Arduino + Raspberry= Weather station with webcam (Part Three: the webcam)

Well boys and girls!

Here we are again…and this time we will SEE something with our project.:-)

I know that finally your voyeuristic tendencies (I know…I know) will be satisfied! 😉

Ok, do you remember the previous posts about meteo station? If not, go to the PART ONE and PART TWO!

Now, it’s time to connect ….the webcam! TA-DA!

I chose a very popular webcam by Logitech (…why? simply because it is cheap and it is natively supported by Debian and Raspbian!): the model is the well known C170, and I bought it on Amazon.it for approx. 19 euros.

The famous :-) Logitech C170

The famous 🙂 Logitech C170

The connection to Raspberry is very simple: connect it to one USB port of Raspi before the board power on, then after the Raspi boot sequence  it should be automatically mapped on /dev/video0 device.

I will use mjpg-streamer to remotely view the webcam stream, so we must to execute some preliminary (but necessary) step.

Firstly we must install SVN client, since mjpg-streamer is not in the Raspbian repository.

#sudo apt-get install subversion

Secondly we must download the mjpg-streamer sources in the Raspberry disk.

#svn co https://mjpg-streamer.svn.sourceforge.net/svnroot/mjpg-streamer mjpg-streamer

The last argument is the local folder where the sources will be saved.

IMPORTANT NOTE: some day ago the svn repository for mjpg-stream should be changed, so svn command should return an error reporting also the NEW svn repository path. You should relaunch svn command using the new/right svn repository path.

After this we must also install libjpeg8-dev and imagemagick.

#sudo apt-get install libjpeg8-dev
#sudo apt-get install imagemagick

After this, we must compile mjpg-streamer entering the folder /home/pi/mjpg-streamer (the sources location) and launch the old (very old 🙂 ) make command.

Cross the fingers ;-)….. and voilà, les jeux sont faits! 🙂

In order to remotely view (i.e. inside Firefox or IE) we must now activate the webserver provided by mjpg-streamer.

The command line (a little difficult to read but it works very well in my case) is:

# ./home/pi/mjpg-streamer/mjpg_streamer -i "/home/pi/mjpg-streamer/input_uvc.so -d /dev/video0 -r 320x240 -f 28" -o "/home/pi/mjpg-streamer/output_http.so -p 8090 -w /home/pi/mjpg-streamer/www" &

Well, only some clarification:

-i defines the input stream string

-d defines the video device (as mentioned, we use /dev/video0)

-r defines the video resolution (320 x 240)

-f defines the frame rate (28 frames/minute)

-o defines the output mode configuration (in this case the http is used)

-p defines the http port (in my case 8090)

-w defines the root for the webserver (where the webpages are placed)

Finally, note that the command should be launched in background (using the “&”).

Note also that some error will appear at command launch because C170 webcam doesn’t support all mjpg-streamer features (i.e. zoom), but NO PANIC. It should work correctly (I hope 😉 ).

Now…the test: type in your browser the following address http://192.168.0.x:8090 (where x is the address of your Raspberry) and you should see the demo page of mjpg-streamer with inside the stream image of your webcam. The live stream can be viewed in the subpages “Stream” or “Javascript”. For my meteo station I modified one of the demo pages in order to add the refresh of meteo data arriving from Arduino….but you will see this in the next episodes! 😉

This is rear garden of my house using mjpg-streamer…it’s a very strange view (from the ground) for my C170:

Well...the meteo data on the left of frame will be argument of the next posts! ;-)

Well…the meteo data on the left of frame will be argument of the next posts! 😉

What’s Montecchio? Ehmmm…that’s the name of the place where I will install the meteo station when it will be ready! 😉

OK, last recommendation: if you want to start automatically the mjpg-streamer webserver, you have to add the above command line to /etc/rc.local, as usual.

…Wellllll! 🙂

All good today, without pain. Strange, very strange…. 😉

So, the work on meteo station is more or less terminated: the only things to activate  for full functionalities are

  • the web page containg at the same time the webcam stream asnd the meteo data took from Arduino via I2C
  • the internet access of Raspberry using a 3G dongle with the aid of a Dynamic DNS service.

…But I ensure you that the difficult parts are already passed without (so high) difficulties.

So, see you soon geeks…keep always in touch with Garretlabs! 🙂

 

Advertisements

Arduino + Raspberry= Weather station with webcam (Part One: the I2C link)

Hi geek boys and girls!

After few more technical and obscure posts, finally I give some (original? I don’t think so…but it’s funny!) creative idea for your *ware open source projects.

With this post I would like to start building a open source meteo weather station.

In order to do this task I think you could connect together, such as a great cup of Mojito 🙂 :

  • A set of sensors (i.e. humidity, barometric pressure, temperature)
  • One little camera (i.e. we could start with an inexpensive webcam…if the weather conditions would permit its use!)
  • One Arduino UNO (or one Intel Galileo ;-))
  • One Raspberry PI Model B
  • One GSM module, or more simply, one less expensive USB internet key (to access via internet to your station)

Ok, first question: why Raspberry AND Arduino (and not only one board)?

Well… I would like to use Arduino to manage all sensors (especially if they would be analog sensors, since Raspberry doesn’t have analog inputs), and I would like to use Raspberry to manage the webcam and the communication with the external world via the GSM module (since it has  high-level functiona).

So I will use Arduino as acquisition board and Raspberry as data collector and as webserver.

Raspberry and Arduino can talk to each other using some different approaches, but I would like to use the I2C protocol, because it’s very simple and very well supported by Raspbian distribution and by native Arduino libraries.

I found this interesting post by Peter Mount in order to safely connect Arduino (as slave) and Raspberry (as master) using I2C.

In order to activate the I2C bus on Raspberry Peter reports five step on Raspbian:

  1. Open /etc/modprobe.d/raspi-blacklist.conf and comment the line reporting  i2c-bcm2708 (so, I2C is removed from blacklist)
  2. Add i2c-dev to the /etc/modules in order to activate the I2C driver at boot
  3. Install i2c-tools using thje well known apt-get install command
  4. Add the “pi” user to the i2c group (using the adduser pi i2c command) in order to let the user “pi” can access to I2C
  5. Reboot the Raspberry board.

In order to phisically connect Arduino and Raspberry via I2C:

  1. Connect SDA Raspberry pin (GPIO0) to SDA Arduino UNO pin (Digital IO 4)
  2. Connect SCL Raspberry pin (GPIO1) to SCL Arduino UNO pin (Digital IO 5)
  3. Connect the ground pins fo the two boards

Remember that Raspberry uses 3.3V as base voltage and Arduino UNO uses 5V…so pay attention: OR if you use a voltage converter in the I2C connection OR you are sure that you are using Arduino as slave I2C device and Raspberry as master I2C device. The first one choice is the best…but I love the risks (the risk in this cas is to have a “Raspberry flambé” 😉 ).

Ok, let’s go ahead. I used a little analog temperature sensor (the one provided in all starter kits by Analog Devices! 😉 ) connected to Arduino UNO (in the Analog input A0)  and then I modified the code provided on the Peter Mount blog in order to read the ambient temperature using Arduino and send it to Raspberry via I2C bus.

This is the simple circuit I used (zoom to better view the links):

20140411_084154

The code on Raspberry is the following (it’s directly taken from Peter Mount Blog, except for only one correction: I defined file as FILE* since declared as int raised a segmentation fault on fclose call….):

#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

// The Arduino board i2c address
#define ADDRESS 0x04

//For V1 Model B you need i2c-0
//For V2 you need i2c-1(...in my case I have a V2 Raspberry Pi! :-) )
static const char *devName = "/dev/i2c-1"; //)

int main(int argc, char** argv) {
 if (argc == 1) {
   printf("Supply one or more commands to send to the Arduino\n");
   exit(1);
   }

 printf("I2C: Connecting\n");
 FILE* file;
 if ((file = open(devName, O_RDWR)) < 0) {
   fprintf(stderr, "I2C: Failed to access %d\n", devName);
   exit(1);
   }

 printf("I2C: acquiring buss to 0x%x\n", ADDRESS);
 if (ioctl(file, I2C_SLAVE, ADDRESS) < 0) {
   fprintf(stderr, "I2C: Failed to acquire bus access/talk to slave 0x%x\n", ADDRESS);
   exit(1);
   }

 int arg;
 for (arg = 1; arg < argc; arg++) {
   int val;
   unsigned char cmd[16];
   if (0 == sscanf(argv[arg], "%d", &val)) {
     fprintf(stderr, "Invalid parameter %d \"%s\"\n", arg, argv[arg]);
     exit(1);
     }

   printf("Sending %d\n", val);
   cmd[0] = val;
   if (write(file, cmd, 1) == 1) {
    // As we are not talking to direct hardware but a microcontroller we
    // need to wait a short while so that it can respond.
    // 1ms seems to be enough but it depends on what workload it has
    usleep(10000);
    char buf[1];
    if (read(file, buf, 1) == 1) {
      int temp = (int) buf[0];
      printf("Received %d\n", temp);
      }
   }

   // Now wait else you could crash the arduino by sending requests too fast
   usleep(10000);
  }
  fclose(file);
  return (EXIT_SUCCESS);
}

 

The code on Arduino UNO  is very simple and it is derived from the code taken from Peter Mount Blog:

#include <Wire.h>

#define SLAVE_ADDRESS 0x04

int number = 0; //command identifier (sent by Raspberry)
double temp; //variable used to store the temperature
const int sensorPin = A0; //pin where we read the temperature from the sensor
 
void setup() {
 // initialize i2c as slave
 Wire.begin(SLAVE_ADDRESS);
 // define callbacks for i2c 
 Wire.onReceive(receiveData);
 Wire.onRequest(sendData);
}
 
void loop() {
 delay(100);
 temp = GetTemp();
}
 
// callback for received data from I2C
void receiveData(int byteCount){
 while(Wire.available()) {
 number = Wire.read();
 
 //"2" is the command sent by Raspberry Pi in order to have the 
 // temperature as answer on I2C from Arduino
 if(number==2) { 
     number = (int)temp; //Arduino in this case sends the integer value of temperature
  }
 }
}
 
// callback for sending data on I2C
void sendData(){
 Wire.write(number);
}

float GetTemp(){
 // read the value on AnalogIn pin 0 
 // and store it in a variable
 int sensorVal = analogRead(sensorPin);

 // convert the ADC reading to voltage
 double voltage = (sensorVal/1024.0) * 5.0;
 
 // convert the voltage to temperature in degrees C
 // the sensor changes 10 mV per degree
 // the datasheet says there's a 500 mV offset
 // ((voltage - 500mV) times 100)
 double temperature = (voltage - .5) * 100;
 return temperature;
}

Ok… we can now download the cvode on Arduino and we can compile the client software on Raspberry Pi using the good old command:

gcc -o TakeTemp main.c

So, once powered on Arduino and verified using the Raspberry command

i2cdetect -y 1

that Arduino is correctly detected with I2C address 0x04, write in the Raspberry command line

./TakeTemp 2

Note that “2” is the I2C command used to receive from Arduino the acquired temperature (see the Arduino code above).

…If all will work correctly, you will read as output the integer value of the sensor temperature, acquired by Arduino and sent to Raspberry via I2C!

Yeah geek guys (and obviously geek gals)…”this is one small step for the human race”, but it’s also a good start to develop an open source meteo station. 😉

And now… a good relax!:-) That’s all folks (for this time)! 😉

…Bye bye!