Arduino + Raspberry= Weather station with webcam (Part Four: the internet connection…. and the conclusion!)

…Gooooood morning Vietnam!!!!

Ehmmm…good morning my dear geeks! 😉

A little lapsus is acceptable today, since today we finish the Weather Station project based on Raspberry and Arduino! 🙂 🙂

First thing: if you lost my previous three post on this marvelous project, please, read them: One, two, three! They contain not only the steps to build the weather station, but also general concepts about data acquisition, I2C connection, webcam integration and so on… 😉

Ok, today firstly we connect our weather station to internet. In order to do it we must use a 3G dongle (or a 3G expansion card for Raspberry). Note that the well known SIM900 Raspberry Addon (see my posts on it) is not suitable since it is a GPRS card.

 

The internet connection

For this purpose I used an old 3G dongle by Vodafone (with a SIM card by TIM inside). This dongle is a HUAWEI K3715 (a.k.a E 180).  With an infinite luck 🙂 I noticed that this dongle is automatically recognized as USB modem by Raspbian…. this is not the case of (for example) the HUAWEI E1820 (another dongle that I have at home).

So, the dongle is mapped by Raspbian at /dev/ttyUSB0 (you can verify it with dmesg or lsusb commands).

Let’s go on.

Firstly we must install screen (the AT commands wrapper) and wvdial (the PPP dialer) applications.

#sudo apt-get install screen
#sudo apt-get install wvdial

After this you must modify the /etc/wvdial.conf in order to match your 3G dongle.

In my case (TIM service provider, with HUAWEI K3715 dongle) the file is:

[Dialer defaults]
Init = AT
Init4 = AT0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,"IP","ibox.tim.it"
Phone = *99***1#
ISDN = 1
Username = a
Password = a
Modem = /dev/ttyUSB0
Baud = 460800
Stupid Mode = on

Some mysterious initialization is created ” by default” by wvdial. 🙂

Anyway, note that important lines for your configuration are: Init3 (where I placed my access point ibox.tim.it),  Username and Password (mandatory for wvdial, but with TIM you can insert a dummy user, I placed “a” in both cases), the Modem path and the Phone number (also *99# can work well with  my dongle).

After having saved the configuration file you can launch:

#sudo wvdial

…If all works well you will see the PPP connection steps, the IP address assignment etc. So, opening the browser you could surf on Internet! 🙂

 

The Dynamic DNS

Well, at this point you can surf the Internet, but it’s important to access to your Weather Station FROM Internet.

Since you have a dynamic IP assignment, you must use a service called Dynamic DNS in order to access to your Raspberry using always the same name (for example: mystation.dyndns.org).

In order to do it, firstly you must register to a Dynamic DNS site (I use always http://dyn.com/dns/). Note that Dyn.com is a pay service (but you have 30 days to try it)… and the price is effordable  (25 $ for year, and you can register up to 30 domains).

After this you must install on Raspberry a dynamic DNS client application. I used ddlclient.

#sudo apt-get install ddlclient

The configuration of the app is done launching:

#sudo dpkg-reconfigure ddlclient

You should insert the following parameters:

  • Name of service: http://www.dyndns.com
  • User: the username with wich you registered on Dyn.com (i.e. myuser)
  • Password: the password with wich you registered on Dyn.com (i.e. mypassword)
  • Interface on wich activate the client: ppp0 (it is the PPP on the USB 3G dongle)
  • activate ddlclient when ppp0 starts: Yes
  • Domain: the domain you registered on Dyn.com (i.e. mystation.dyndns.org)

Ok, at this point add to /ect/rc.local the following line, in order to automatically start the internet connection at Raspbian boot:

sudo wvdial &

Weeeeeelllll… this was a ordeal! 🙂

 

The web access from Internet

Do you remember that in my previous post I added the mjpg-streamer web server in rc.local?

So, if all works well, now you will see what your webcam images opening a browser from you Internet connected tablet, phone or pc and writing on the address bar:

http://mystation.dyndns.org:8090

But….what happens if the internet connection goes down? You should try to automatically relauch wvdial (or reboot), or you cannot (NEVERMORE) access to your station.

In order to do it I wrote a little .sh script that checks the internet connectivity.

This is the script:

#! /bin/bash
# Sending the output of the wget in a variable and not what wget fetches
RESULT=`wget --spider http://www.google.it 2>&1`
FLAG=0

# Traverse the string considering it as an array of words
for x in $RESULT; do
    if [ "$x" = '200' ]; then
        FLAG=1 # This means all good
        echo  "Internet OK, Google responded!"
    fi
done

if [ $FLAG -eq '0' ]; then
    # Probably internet key TIM is down...
    echo "Internet down"
    #....triyng to reconnect TIM key
    sudo reboot
fi

It checks if Google is accesible (using wget) from your station, and if not, it forces a reboot. This script must be lauched every X minutes in order to reboot the system if the Internet connection is down (so, to retry the PPP connection process). So, I added it to the crontab:

#sudo crontab -e

And at the end of crontab I added the following line (then I rebooted the board):

*/5 * * * * /home/pi/internet_conn_check/internet_check_daemon_v1.sh

The script is launched every 5 minutes. If the Internet is down, a reboot of the station is commanded. 🙂

 

Mixing meteo data with webcam video

We are at the final steps, boys and girls, so you must do the last effort! 😉

In order to “see” the Arduino meteo data mixed with the webcam images, we must now modify:

  • The Raspberry acquisition application
  • A webpage using Javascript

In the step TWO of my Weather Station project I created on Raspberry a C application to acquire data from Arduino. It was printing the meteo data as output on the shell.

Well, this time I modify the program in order to save the meteo data in a text file. This is the way to communicate to the Weather Station webpage the actual meteo data (i.e. the webpage will read this file and it will display the meteo data mixed with the ).

I know this is a “rough” method, but it is only an idea: you can use your preferred approach. 😉

This is the modified C acquisition program for Raspberry.

 #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>
#include <time.h>
 
// The PiWeather board i2c address
#define ADDRESS 0x04

//commands
#define TEMP 1
#define HUMI 2
#define PRES 3
#define DEW 4

// The I2C bus: This is for V2 pi's. For V1 Model B you need i2c-0
static const char *devName = "/dev/i2c-1";
 
int main(int argc, char** argv) {
 
  printf("I2C: Connecting\n");
  int 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 command;
  FILE* meteo_data_file;

while (1)
{
  //open file for web page display
  meteo_data_file=fopen("../mjpg-streamer/www/meteo_data_file.txt","w");
  time_t mytime;
  mytime = time(NULL);
  fprintf(meteo_data_file,"%s\n<br>",ctime(&mytime));

  for (command= 1; command<=4; command++) {
    int val;
    unsigned char cmd[16];
 
    //printf("Sending %d\n", val);
 
    cmd[0] = command;
    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[5];
      if (read(file, buf, 4) == 4) { //read 4 byte from i2c (a float)
        float value_received;
    
    //convert 4 bytes received into a float
    memcpy((char*)&value_received,buf,4);
/*disable printf on shell... 
     if (command==TEMP)   
        printf("Temperature (°C)= %f\n", value_received );
    if (command==HUMI)   
        printf("Humidity (%)= %f\n", value_received );
    if (command==PRES)   
        printf("Pressure (hPa)= %f\n", value_received );
    if (command==DEW)   
        printf("Dew Point (°C)= %f\n", value_received );
*/
        //write the file used to display values on the webpage
          if (command==TEMP)   
                fprintf(meteo_data_file,"Temperature (C)= %f\n<br>", value_received );
        if (command==HUMI)   
                fprintf(meteo_data_file,"Humidity (perc)= %f\n<br>", value_received );
        if (command==PRES)   
                fprintf(meteo_data_file,"Pressure (hPa)= %f\n<br>", value_received );
        if (command==DEW)   
                fprintf(meteo_data_file,"Dew Point (C)= %f\n<br>", value_received );
      }
    }
 
    // Now wait else you could crash the arduino by sending requests too fast
    usleep(10000);
  }
 //close meteo data file
 fclose(meteo_data_file); 
//one sensors reading every 5 seconds
 usleep (5000000);
} 
  close(file);
  return (EXIT_SUCCESS);
}

FIRST NOTE: I placed the executable as you see from the code, I placed the acquisition executable in /home/pi/ and mjpg-streamer in /home/pi/mjpg-streamer.

SECOND NOTE: I save the meteo_data_file.txt in the /mjpg-streamer/www folder, since I found some difficulty to access other directories from inside the webpage javascript.

Compile with the old command:

gcc -o acquisition_task acquisition_task.c

Then add it to the /etc/rc.local in order to autostart it at boot time.

sudo /home/pi/acquisition_task &

Now, the final step: the webpage meteo.html, which mixes the webcam output with the meteo data.

NOTE: This file must be placed in the /mjpg-streamer/www folder!

Note that I modified one of example provided by mjpg-streamer in order to read and display (using a refresh button) the file containing the actual meteo data. 😉

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
    <title>MJPG-streamer</title>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <link rel="stylesheet" href="style.css" type="text/css" />
    <script type="text/javascript" src="jquery.js"></script>    
    <script type="text/javascript" src="jquery.rotate.js"></script>
    <!--[if IE 6]>
    <link rel="stylesheet" href="fix.css" type="text/css" />
    <![endif]-->
    <script type="text/javascript">
    
    var phi = 0, flipped = 0, mirrored = 0;

    function setXformClass () {
        $('.xform').each(function(idx,el) {
            el.className = "xform x" +(flipped ? "-flipped":"") + (mirrored ? "-mirrored" : "") + "-rotated-" + phi;
        });
    }
    $(document).ready(function() {
        // set rotation angle phi and toggle rotate class
        $('#rotate').click(function() {
            phi = (phi + 90) % 360;
            setXformClass();
            if (phi % 180) {
                $('.xform-p').addClass('rotated');
            } else {
                $('.xform-p').removeClass('rotated');
            }
        });
        // toggle mirror class component
        $('#mirror').click(function() {
            mirrored = ! mirrored;
            setXformClass();
        });
        // toggle flip class component
        $('#flip').click(function() {
            flipped = ! flipped;
            setXformClass();
        });

//ML:::::when I click on refresh_meteo_data...I print the values of the file!    
$("#refresh_meteo_data").click(function() {
        $.ajax({
            url : "meteo_data_file.txt",
            dataType: "text",
            success : function (data) {
                $(".text").html(data);
            }
        });
    });
    });
    </script>
  </head>

  <body>

    <div id="sidebar">
    <br><br>
    <div class="button" align="center">
            <input type="button" id="refresh_meteo_data" value="Refresh Meteo Data!!" />
    </div>
    <br>
    <div class="text" align="center">
            ...No meteo data acquired at the moment! <br />
    </div>

    </div>

    <div id="content">
      <h1>Garretlabs Meteo Lab</h1>
      <h2>version 1.0 (released by Marco Lastri)</h2>
      <h2>https://garretlabs.wordpress.com</h2>

    <p id="xform">
        <button id="rotate"><div class="btnface"></div></button>
        <button id="mirror"><div class="btnface"></div></button>
        <button id="flip"><div class="btnface"></div></button>
    </p>
    <p class="xform-p"></p>
    <p id="streamwrap" class="xform-p">
        <img id="streamimage" class="xform" src="/?action=stream" />
    </p>

    <p>&copy; The <a href="http://mjpg-streamer.sf.net">MJPG-streamer team</a> | Design by <a href="http://andreasviklund.com">Andreas Viklund</a></p>

</body>
</html>

Ok, I simply added a button “Refresh meteo data” in the sidebar, and I added  a callback which, on each button click, reads the file “meteo_data_file.txt” and prints it on the sidebar of the webpage. I didn’t modify the final line, which reports the original team of mjpg-streamer….it’s a beautiful software and I want to remember once again!

….The final goal!!!

Well, the Garretlabs Weather Station is now ready.

When you open from your tablet, pc etc. the page:

http://mydomain.dyndns.org/meteo.html

you would see (if all works correctly) the following page:

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

Then you can click the button “Refresh Meteo Data” you should see the last acquired meteo data values.

Well… it has been a very long and hard work, but now I can place my final Weather Station at Montecchio, a beautiful place near Firenzuola (in the country of Florence, but it is a very special mountain site).

wpid-20140618_182808.jpg

wpid-20140618_182751.jpg

wpid-20140618_183520.jpg

So…. now I can take my grappa, listening a good progressive rock album (or viewing a  70’s italian horror movie).

I think to deserve a little piece of relax, and you? 🙂

Bye bye babes! 😉

 

Advertisements

2 thoughts on “Arduino + Raspberry= Weather station with webcam (Part Four: the internet connection…. and the conclusion!)

  1. Hello Garret, thanks for this article, it’s a great starting point for many projects. I’ve a question for you: now, on 2015, with the TIM connection and the APN ibox.tim.it, you can reach your raspberry from internet. I’ve a TIM sim, i connect my RB to internet without problems, but the IP in private (10.x.x.x) e then NATted; also with an DDNS services I cannot hit mi RB, because I see only the public ip behind NAT.
    Do you know another Tim APN for obtain a public IP.
    Thanks in advance and sorry for my bad english.

    Lorenzo

    • Hi dear Lorenzo, I see you write from Italy… since I’m also italian (from Florence), I’m very happy to read your comment! 🙂
      You english is very good, don’t worry!
      So…I fronted (and resolved) the problem of TIM public IP address exactly one year ago. Take a look to my prevoius post https://garretlabs.wordpress.com/2014/06/25/arduino-raspberry-weather-station-with-webcam-part-four-the-internet-connection-and-the-conclusion/.
      In this post I described the connection to ibox.tim.it via DynDNS service and a Raspi Dynamic DNS client.
      At that time it worked perfectly…unfortunately in December 2014 we removed the meteo station in order to execute some work of restructuration on the building, and at the moment it is still in a box. 😦
      But I cannot now verify on the fly if TIM changed something on his protocol during these last 5 months… 😦
      Bye bye, and keep in touch!
      Marco

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s