RasPI-Surv: a Raspberry-based scalable SMS remote controlled video surveillance system

Good morning dear security systems fanatics Garretlabs fans!

Today you will be very interested in my new post, I’m sure.

Because today we talk about a high-scalable videosurveillance system called RasPI-Surv, based on:

  • A system controller based on Raspberry PI
  • A practical (and modifications-friendly) command/telemetry interface via SMS messages, using the very well known SIM-900 module from ITEAD.
  • A set of wireless video cameras with good motion detection feature
  • A internet router/modem with wireless access point
  • A Google Mail account (it will be your “house account”), to be accessed via IMAP.

I engineered this system after a very strange request from one of my strangest friends. 🙂

He was looking for a “internal” videosurveillance system with motion detection to be used only during his vacation periods…and after the vacation periods he wanted to disable the system and put all cameras and controller inside a box! 😉

In other words he wanted a “portable” internal video surveillance system, without in-the-wall connections, without fixed positions for the cameras, so a very dynamic system with the opportunity to move the cameras and the controller inside his house. Plus, he wanted a powerful and portable alarm siren to be placed in his house, without external components (please note that this DIY solution is not accepted by italian laws, so in our country the alarm device must be always placed by a devoted an credited technician).

A practical example of the siren 12V powered could be THIS  …but you can buy another model following your needs.

Thinking for a smart solution, I studied a system with two day-night wireless IP Cameras from HooToo with pan and tilt features (http://www.hootoo.com/hootoo-ht-ip211hdp-indoor-wireless-network-camera-with-ir-cut-black.html) and two day-night D-Link fixed cameras (http://www.dlink.com/it/it/home-solutions/view/network-cameras/dcs-932l-day-night-cloud-camera). But you could add/remove wireless IP cameras with motion detection featire (also of different brands), in order to add/remove “eyes” to your system.

So, this is a very scalable solution. 😉

Firstly I placed the cameras near a wall power socket (ok, they are wireless..but unfortunately they need power… 😦 ), then I connected all cameras to the internet modem/router following their own user guides.

Finally I enabled their motion detection feature with the email sending (using the “house Google Mail account”) of the captured frame when a motion is detected.

Note that for some camera, a fast tramsition from day to night vision and viceversa (i.e. a sun ray refled by a passing car in the street) could be recognized as motion (so as a false alarm by the system 😦 )…so the best way to place the camera is in front of closed external doors without glasses and of closed windows with the rolling shutter completely closed.

Well… do you placed the alarm siren and cameras? Have you configured your cameras in order to connect to your modem/router and to send an email using your Google mail account when a motion is detected? Very well… we can go ahead with the system idea.

This is the overview schema of the system (as always drawn by hand by me, sorry for the bad photo! 😉 ):

wpid-2014-11-10-08.37.09.jpg.jpeg

…In practice at this moment we have all cameras connected to our modem/router and a alarm siren connected to the power thru a relay commanded by the Raspberry PI. So, we must to setup the Raspberry PI in order to execute the following operations/requirements:

  • Periodically it should check the SENT folder of your Google Mail account, in order to verify if one of your IP cameras detected one motion (and so they sent an email using your “home account”). The cycle should be fast because one burglar can be very fast to open a window and to move in your house… 😦
  • If one or more email arrived from your cameras, it should activate the relay in order to power ON the alarm siren
  • In this case it shoud send an SMS to your mobile phone in order to advise you that the siren has been powered ON
  • It should manage a set of SMS commands in order to: force the power OFF of the alarm siren, enable and disable the check of the sent emails, cancel the SMS memory of the SIM900 module, reset or reboot the system etc.
  • It should send a set of SMS in order to advise you that there is some problem (i.e. the internet connection is down, so the Google Mail mailbox can’t be accessed).

Well. It is’nt so difficult to implement it all. If you you read first these previous posts from Garretlabs: THIS ONE (it uses a GSM dongle and the software gammu in order to receive/send the SMS messages, plus to command the GPIO pins of Raspberry using Python) and also THIS ONE (it uses the SIM900 module and the AT commands in order to receive/send the SMS messages).

This is the Fritzing schema of the controller Raspberry PI+SIM900 module used to command the relay for the alarm siren:

Video surveillance controller (finale per uso con SIM900) v2_bb

I propose you the complete code of my project…. so you can now start playing with the RasPI-Surv system

 

#! /usr/bin/env python

import RPi.GPIO as GPIO
import imaplib, re, time, serial, subprocess

#class from http://segfault.in/2010/07/playing-with-python-and-gmail-part-1/ and http://segfault.in/2010/08/playing-with-python-and-gmail-part-2/
class pygmail(object):
    def __init__(self):
        self.IMAP_SERVER='imap.gmail.com'
        self.IMAP_PORT=993
        self.M = None
        self.response = None
        self.mailboxes = []

    def login(self, username, password):
        self.M = imaplib.IMAP4_SSL(self.IMAP_SERVER, self.IMAP_PORT)
        rc, self.response = self.M.login(username, password)
        return rc

    def get_mailboxes(self):
        rc, self.response = self.M.list()
        for item in self.response:
            self.mailboxes.append(item.split()[-1])
        return rc

    def get_mail_count(self, folder='Inbox'):
        rc, self.response = self.M.select(folder)
        return self.response[0]

    def get_unread_count(self, folder='Inbox'):
        rc, self.response = self.M.status(folder, "(UNSEEN)")
        unreadCount = re.search("UNSEEN (\d+)", self.response[0]).group(1)
        return unreadCount

    def get_imap_quota(self):
        quotaStr = self.M.getquotaroot("Inbox")[1][1][0]
        r = re.compile('\d+').findall(quotaStr)
        if r == []:
            r.append(0)
            r.append(0)
        return float(r[1])/1024, float(r[0])/1024

    def get_mails_from(self, uid, folder='Inbox'):
        status, count = self.M.select(folder, readonly=1)
        status, response = self.M.search(None, 'FROM', uid)
        email_ids = [e_id for e_id in response[0].split()]
        return email_ids

    def get_mail_from_id(self, id):
        status, response = self.M.fetch(id, '(body[header.fields (subject)])')
        return response

    def rename_mailbox(self, oldmailbox, newmailbox):
        rc, self.response = self.M.rename(oldmailbox, newmailbox)
        return rc

    def create_mailbox(self, mailbox):
        rc, self.response = self.M.create(mailbox)
        return rc

    def delete_mailbox(self, mailbox):
        rc, self.response = self.M.delete(mailbox)
        return rc

    def logout(self):
        self.M.logout()

#end library/class

##############################################################################
#Functions to PowerON OFF the relay
##############################################################################
#poweron the relay
def PowerONRelay():
    GPIO.setup(22,GPIO.OUT);
    GPIO.output(22,GPIO.HIGH);
    return;

#poweroff the relay
def PowerOFFRelay():
    GPIO.setup(22,GPIO.OUT);
    GPIO.output(22,GPIO.LOW);
    return;

##############################################################################
#Functions to manage SMS
##############################################################################
#check unread arrived messages
def CheckNewUnreadMessage(ser):
    print "Check for new messages..\n";
    ser.write("at\r");
    time.sleep(3);
    line=ser.read(size=64);
    #print line;
    ser.write('AT+CMGL="REC UNREAD"\r')
    time.sleep(3);
    response=ser.read(size=200);
    print response;
    return response;

#function to send confirmation SMS
def SendSMS(ser,value):
    #send SMS about the action
    ser.write("at\r");
    time.sleep(3);
    line=ser.read(size=64);
    print line;
    ser.write('AT+CMGS="+391234567890"\r'); #here put your phone number :-)
    time.sleep(3);
    if (value==1):
        ser.write('ALARM ON!\r');
    elif (value==0):
        ser.write('ALARM OFF!\r');
    elif (value==3):
        ser.write('ALARM enabled!\r');
    elif (value==4):
        ser.write('ALARM disabled!\r');
    elif (value==11):
        ser.write('ALARM commanded OFF (was ON)!\r');
    elif (value==20):
      ser.write('Deleted SIM memory!\r');
        elif (value==50):
      ser.write('INTERNET DOWN!\r');
    elif (value==51):
      ser.write('INTERNET UP!\r');
    elif (value==60):
      ser.write('Warning: GMAIL temporary DOWN!\r');
    time.sleep(3);
    ser.write(chr(26));
    return;

#function to delete messages...(GSM900 stores only 30 messages..)
def DeleteAllMsg(ser):
    ser.write("at\r");
    time.sleep(3);
    line=ser.read(size=64);
    print line;
    print "Deleting memory....";
    ser.write('AT+CMGD=1,4\r');
    time.sleep(3);
    return;    

###############################################################################
#main program for alarm check
###############################################################################
#global variables
initials_sent_emails=0
ALARM_enabled=True
ALARM_ON=False
actual_sent_emails=0;
ALARM_ON_cycles=0;
INTERNET_UP=True;
GMAIL_UP=True;
################################################################################
#functions to enable/disable/stop alarm (sent VIA SMS)
################################################################################
def enable_ALARM():
         global ALARM_enabled
         ALARM_enabled=True
         

def disable_ALARM():
         global ALARM_enabled
         ALARM_enabled=False
         

def stop_ALARM():
        global initials_sent_emails
        global actual_sent_emails
        #ALARM_ON=False
        initials_sent_emails=actual_sent_emails
        #ALARM_ON_cycles=0
        #TODO here send SMS telemetry

################################################################################
#MAIN program
################################################################################

#0: power ON the SIM900 module and waits for SIM registration
GPIO.setmode(GPIO.BCM)
GPIO.setup(17,GPIO.OUT)
GPIO.output(17,GPIO.HIGH)
print "Registering the sim...\n";
time.sleep(15); #wait for sim to register to the net
#0a: open serial link on /dev/ttyAMA0. It is open only one time:it remains open for all operation time.
#No more open+close action is now requested.
print "Opening communications serial...\n";
ser=serial.Serial('/dev/ttyAMA0',9600,timeout=1);
ser.open();


#1: first login to Gmail
g = pygmail()
g.login('your.home.mailbox@gmail.com', 'yourpassword')
print g.response

#2: list mailboxes
g.get_mailboxes()
for item in g.mailboxes:
  print item

#3: get number of sent emails at power ON of alarm controller...
g.get_mail_count('[Gmail]/Posta inviata')
print g.response
sent_number=g.response[0]
initials_sent_emails=int(sent_number) #actual number of sent messages
print initials_sent_emails

#4:logout from gmail
g.logout();


#Here we add the infinite loop (once per 10 seconds?) which:
#a. checks the number of sent emails (login+get_mails_count+logout)
#b. if the number is > initials_sent_emails sets (&& the alarm is ARMED) the alarm relay ON, else sets the alarm relay OFF
#b2. if this is the first time the alarm is ON, send SMS to communicate the ALARM is correctly ON!
#c. checks if a NEW SMS is arrived in order to enable/disable ALARM relay, and update the global variable
#d: waits for 10 seconds (TBC)
while (True):

       #a0: check for internet status
    ip="www.google.it";
        ret=subprocess.call("ping -c 1 %s" %ip,
        shell=True,
        stdout=open('/dev/null','w'),
        stderr=subprocess.STDOUT)
    if (ret==0):
         print "INTERNET UP!"
        if(INTERNET_UP==False):
            INTERNET_UP=True;
            SendSMS(ser, 51);
    else:
        print "INTERNET DOWN!"
        if (INTERNET_UP==True):
            INTERNET_UP=False;
            SendSMS(ser, 50);

    
       #a: check new sent messages
    if (INTERNET_UP==True):
            print 'Check new sent messages...'
        try:
                g.login('your.home.mailbox@gmail.com', 'yourpassword')
                g.get_mail_count('[Gmail]/Posta inviata')
                actual_sent_emails=int(g.response[0])
                g.logout();
            GMAIL_UP=True
        except imaplib.IMAP4.error, err:
            print 'GMAIL IMAP temporary unavailable!!!'
            if (GMAIL_UP==True):#the first time it sends an sms...
                SendSMS(ser,60)
                GMAIL_UP=False        

        #b/b2: alarm management
        print 'Alarm management...'
        if(ALARM_enabled==1 and actual_sent_emails>initials_sent_emails):
                print 'ALARM ON!!!'
                ALARM_ON=True
                ALARM_ON_cycles=ALARM_ON_cycles+1;
                #here we command the relay ON
                PowerONRelay();
                if (ALARM_ON_cycles==1):
                        SendSMS(ser,1);
                
        else:
                if(ALARM_ON==True):
                        SendSMS(ser,0); #if the alarm is already OFF, dont send messages...
                ALARM_ON=False
                ALARM_ON_cycles=0;
                #here we command the relay OFF
                PowerOFFRelay();
                print 'ALARM OFF!'

        #c: new SMS arrived management
        print 'SMS management'
    message=CheckNewUnreadMessage(ser);
    if(message.find("enablealarm")<>-1):
        enable_ALARM();
        #send message to my phone that Relay is ON
            SendSMS(ser, 3);
        print "Alarm enabled commanded\n";    
    elif (message.find("disablealarm")<>-1):
        disable_ALARM();
        SendSMS(ser, 4);
        print "Alarm disabled commanded\n";
    elif (message.find("alarmoff")<>-1):
        stop_ALARM();
        #send message to my phone that telemetries are OFF
          SendSMS(ser, 11);
        print "Deactivated alarm\n";
        elif (message.find("delsms")<>-1):
        DeleteAllMsg(ser);
        SendSMS(ser,20);

       
        #d: basic cycle time
        print 'Wait for new cycle...'
        time.sleep(2);

 

Weeeeeeell….I Hope the code is well commented,so it is not so unreadable! 😉

As you see, I used a very nice Python library in order to connect to Google Mail using IMAP. You can download it from Segfault.in, and you can find good examples in the following pages: http://segfault.in/2010/07/playing-with-python-and-gmail-part-1/  and http://segfault.in/2010/08/playing-with-python-and-gmail-part-2/.

…Anyway, if you want to request some detail…I am here for you! 🙂

And as usual, if you want to comment/modify/correct/redistribute/relink my code and my idea, you ‘re free to do it (…and thanks for the your pingbacks and for credits in your blogs etc. 😉 )!

Bye bye geek guys and girls… it’s time for me to go to install and test the system in my friend’s house (also if it’s too late for his vacation time..ah ah!!!)! 🙂

 

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! 😉

 

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! 🙂

 

Raspberry and the remote controlled relay: a low-level approach (a.k.a. “AT modem commands: the usual suspects”).

Hi my dear microelectronics F&M (female & male) friends! 😉
Here we are again with the remote controlled 220V relay using a Raspberry PI. In my previous post I used a Huawei 3G dongle with the famous gammu daemon as SMS receiver.
But… do you remember the end of the post? I was talking about a thriller/horror movie by the great Lucio Fulci.
So, the horror turned to real, since gammu-smsd, after 20-25 minutes of correct activity, decided to die himself, without any clear cause. Or better, it continued running in background but when a SMS arrived, the daemon did nothing.
I tried to “reanimate” it in several ways, removing the screensaver and the blank screen from the Raspberry, writing a script which stop/restart the daemon every 5 minutes etc. But nothing changed. 😦
I noticed also after the above mentioned 20-25 minutes, the daemon start/restart (using sudo /etc/init.d/gammu-smsd start/restart) fails.
Only a reboot works in this case….but NO PANIC please! 🙂

I think there is some problem in gammu-smsd (related to Raspbian memory management? Hmmmm…I dont want investigate it because I want to live again 😉 ).
So….I decided to try another approach, using a more simple hardware and writing myself a more simple (= with a simple maintance and debug phases) software.
I bought the ITEAD GSM Sim900 module for Raspberry PI from my usual store (Robot Italy). Price: 37 euros. I think it is a good price for a GSM/GPRS phone without keys and display! 😉
I placed my SIM in the module, then I placed the module on the Raspberry.
The module reports the unused GPIOs on the higher side, so I connected the three wires used to command the relay (Vcc, GND and command) directly to the SIM900 module.
Note that the Vcc available on the SIM900 module is 3.3V , but I noticed that my relay module works well also using 3.3V instead the requested 5V. 🙂
Note also that GPIO18 used to command the relay in my previous post, is used now by SIM900 module as software reset, so I modified my relay ON/OFF scripts in order to use GPIO22.

This is the schema of SIM900 module used GPIOs:Mappatura RasPi GPIO-ITEAD SIM900
Ok, let’s go powering the Raspberry board (with a 2A minimum power supplier, since the SIM900 can use also peaks of current of 1A).
But firstly I needed the right soundtrack for this activity, and the right soundtrack in this case is “The City Sleeps”, a powerful and aggressive crossover-progressive rock cd, in my opinion the best work of Touchstone, the band of my friend Kim Seviour.

Let’s return to us… now the Raspberry boots up but the SIM900 module is powered off (no green led is ON on the surface).
There are two ways to power it on:

  • the first approach is to simply press the power on button :-). Too simple for me.;-)
  • the second way is to set the GPIO17 high….well, you know this is my preferred solution. 😉

The python code (remember you must before install python extensions devoted to GPIO commanding, following my previous post!) is the following:

#poweron the RPI GSM SIM900 module
def PowerON_SIM900_module():
    GPIO.setup(17,GPIO.OUT)
    GPIO.output(17,GPIO.HIGH)
    return;

Raspberry talks with SIM900 module via a serial link mapped on /dev/ttyAMA0, but Raspberry locks this port at startup. The document reporting the correct actions to free the serial port (before to try to talk with the module) are in ITEAD provided C library…but they are written in chinese! 😦
So I googled aroud a lot before to find the solution to this problem, damn! 😦
This is the correct procedure in order to “unlock” /dev/ttyAMA0 port (application note taken from ITEAD blog, related to another ITEAD product):

In /etc/bootline.txt change:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline rootwait

to:

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline rootwait

and in /etc/inittab comment out or delete the following line (in my case it is the last line):

# T0: 23: respawn :/ sbin / getty-L ttyAMA0 115200 vt100

Well…after this, a reboot is necessary.

The Itead GSM module...with "The City Sleeps" of Touchstone!

The Itead GSM module…with “The City Sleeps” of Touchstone!

Now, I tried using the examples provided in the official C library from ITEAD, but I encountered some error (very strange errors, such as “SIM not registered, some unpredictable error code and so on…), so I decided to talk directly to SIM900 module using AT commands.

Firstly I installed the old, well known minicom software then I connected minicom to SIM900 module with the following (the “old style values”) parameters: port: /dev/ttyAMA0, speed: 9600 bps, no flow control, no parity, 8 bit per word, 1 stop bit.

I sent some famous AT commands, such as “AT” (in order to verify if the momdem is responding), “AT+CMGS” (in order to send to my phone a text SMS), etc. and I verified that all worked well.

Quasi-incredible! 🙂

At this point I decided to implement (in Python, of course) the main code, which: receives the SMS message (many thanks to this tutorial for inspiration of this part), parses them and, if a valid command is received, it powers ON/OFF the relay. Plus, the script can send to my phone  a SMS reporting the action (Power ON/OFF) executed.

I used only three AT simple commands:

  • AT (in order to verify if the communication between module and Raspberry is OK)
  • AT+CMGS (used to send SMS messages)
  • AT+CMGL= “REC UNREAD” (used to read received unread messages)

Note that I added some delay, since I noticed that in some case the modem is a little slow to execute the AT commmands and to reply. This is the complete Python code.

But first don’t forget to install the python extension for serial communication using sudo apt-get install python-serial.

#! /usr/bin/env python

import serial
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

#poweron the RPI GSM SIM900 module
def PowerON_SIM900_module():
    GPIO.setup(17,GPIO.OUT)
    GPIO.output(17,GPIO.HIGH)
    return;

def PowerONRelay():
    GPIO.setup(22,GPIO.OUT);
    GPIO.output(22,GPIO.HIGH);
    #send message to my phone that Relay is ON
    SendSMS(1);
    return;

def PowerOFFRelay():
    GPIO.setup(22,GPIO.OUT);
    GPIO.output(22,GPIO.LOW);
    #send message to my phone that Relay is OFF
    SendSMS(0);
    return;


def SendSMS(value):
   #send SMS about the action
   ser=serial.Serial('/dev/ttyAMA0',9600,timeout=1);
   ser.open();
   ser.write("at\r");
   time.sleep(3);
   line=ser.read(size=64);
   print line;
   ser.write('AT+CMGS="+39123456"\r');
   time.sleep(3);
   if (value==1):
       ser.write('Relay powered ON!\r');
   elif (value==0):
       ser.write('Relay powered OFF!\r');
   time.sleep(3);
   ser.write(chr(26));
   ser.close();
   return;

def CheckNewUnreadMessage():
   print "Check for new messages..\n";
   ser=serial.Serial('/dev/ttyAMA0',9600,timeout=1);
   ser.open();
   ser.write("at\r");
   time.sleep(3);
   line=ser.read(size=64);
   #print line;
   ser.write('AT+CMGL="REC UNREAD"\r')
   time.sleep(3);
   response=ser.read(size=200);
   print response;
   ser.close();
   return response;

#main loop
   PowerON_SIM900_module();
   print "Registering the sim...\n";
   time.sleep(15); #wait for sim to resgister to the net
   print "Started main loop\n";
   while True:
      message=CheckNewUnreadMessage();
      if(message.find("poweron")<>-1):
          PowerONRelay();
          print "PowerON commanded\n";
      elif (message.find("poweroff")<>-1):
          PowerOFFRelay();
          print "PowerOFF commanded\n";
     time.sleep(5);

As you see from the code, the new, unread SMS messages are checked every 5 seconds.

If a new message is found, it is copied in the message variable. If the message contains the poweron keyword the relay is powered ON. Else,  if it contains the poweroff keyword, the relay is powered OFF.

In both cases a SMS is sent to my phone (well… this is not my real number, also if I know you would like to know it! 😉 )

In order to auto-start the script after the Raspberry boot, you should add this command to /etc/rc.local (prior, remember to “executabilize” 😀  your script using the old chmod +x name_of_your_script.py ):

sudo /home/pi/name_of_your_script.py &

IMPORTANT NOTE: Add the “&” in order to launch in background the Python script, or you won’t be able to stop it neither using CTRL+C or swithcing shell . I will re-take the control of your Raspberry only via remote connection (using ssh)! 🙂

Now, rebooting the Raspberry, you will be able to receive/send SMS message using AT commands, power ON/OFF a 220V relay…and the most important thing: I tested the system for 3+ hours, and it worked well all time!!!

So ….I think we executed today another litlle step in my and in your “knowledge database system” called BRAIN. 🙂

Now I will take a relax time with the aid of the new Touchstone cd: “Oceans of Time”. It’s an kick-ass prog-rock album, of highest level guaranteed (as we say in Italy, it’s “Lemon guaranteed”, that is “Garantito al limone”).

Bye bye Raspberry freaks, it’s rock time for me! 😉

 

Raspberry PI: A remote controlled relay using SMS messages

Hi my dear female & male microelectronics geeks!

This time I will build an interesting object: a remote controlled relay using a Raspberry PI as SMS messages receiver and parser (and -obviously- as relay phisical controller).

I will use this stand-alone (sub)system with my meteo station system. If you want to read more about the meteo station, in the previous posts I described the I2C communication between the acquisition board (Arduino UNO) and the station controller, the model (hardware and software) of the acquisition board.
In this post we will PLAY WITH THE HIGH VOLTAGE, so… pay attention,please. 🙂
Rememeber that when we use the high voltage..the only safe thing you can consider is the GROUND, so… again, pay attention please! 🙂

Why high voltage? Well… it’s simple.
Because I would like to power on/off my meteo station via remote commands (since at the end of this “technical adventure” I will install my meteo station in a very beautiful place, but a little far from my home).
In order to do that, I would like to use a simple (sub)system, consisting of one Raspberry PI (for this purpose you can use also the less expensive model A, but in my project I will use again a Model B.Yeah, you know I love this board …but I assure you I’m preparing some surprise also with my new Olinuxino A20! 😉 ), one Itead 2-way Relay Module (bought as usual from Robot Italy), one multiple power connector bought (…from my father) at the cheapest general-purpose shop in my little city (it is called “Risparmio Casa”, in English it should be something like “Savings -for the- House”), and, last but not least, one USB 3G dongle (I used an old Huawey K3715 compatible E169, marketed by Vodafone, with a TIM sim inside) which I will use as “mobile phone” in order to receive SMS messages.

In this case I will not use it as “internet 3G dongle” because:

  1.  I want to command the power on/off even if the 3G signal is not present
  2.  Sending single SMS messages is cheaper than a flat 3G connection (in Italy, I don’t know if the situation is the same in other countries)
  3. The power consuption is lower if the dongle is not connected to 3G

Ok, let’s go with the experiment! 😉

Commanding the relay using Python

I took the inspiration for this step , from this post of the italian blog “Raspibo.org”
Let’s install something!

#sudo apt-get update
#sudo apt-get install python-rpi.gpio
#sudo apt-get install python3-rpi.gpio

Well, after this you can connect Raspberry and the Itead relay module .

GPIO18 will be used as command signal for relay, plus you will connect the Raspberry 5V/GND pins to the module Vcc/Gnd pins. This is the Fritzing schema:

Arduino rele controller_bb

Then you can modify the multiple power connector in the following mode: remove a part of external protection from the cable (pay attention in this operation, please!), then cut the 220V brown wire and connect the terminals to COM and NO pins of the relay module. NC shall be not connected. Blue and yellow/green wires shall arrive directly to the power connector.

Ok, now we can test the relay (with the 220V power NOT connected, for the moment).

Firstly we must write a script in order to initialize to LOW the GPIO18 pin at Raspberry startup. The script will be:

#!/usr/bin/env python
import Rpi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT, initial=GPIO.LOW)

 Then, you can save it where you want, and you must to change the mode in order to declare the script as executable:

#chmod +x initialize_GPIO18_script.py

…But the very important thing is to add the following line to /etc/rc.local:

sudo /path_to_initialize_GPIO18_script/initialize_GPIO18_script.py

and execute a reboot of the board.

After the reboot, the GPIO18 will be correctly initialized, so you could test the relay functionality. In order to close the relay you will write the following script:

#!/usr/bin/env python
import Rpi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.output(18, GPIO.HIGH)

and in order to open the relay you will write the following script:

#!/usr/bin/env python
import Rpi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.output(18, GPIO.LOW)

Note that all the executions of GPIO-related scripts will be possible only using “sudo” before the commands.

Well… if your scripts work well, open the relay (=led powered off on the Itead module): this is the safer state.

Now it’s the moment to connect the multiple power connector to the 220Volts plug on the wall….but, REMEMBER THAT THIS OPERATION CAN BE DANGEROUS AND YOU MUST USE ALL AVAILABLE PROTECTIONS in order to reduce risks. Remember that you are now playing with HIGH VOLTAGE, so PAY ATTENTION.

To test the relay behavior now you connect a lamp (or something else) to the multiple power connector and use the above scripts to power on/off it.

…..Aufffff, I hope all worked well, and you haven’t burnt your home! 😉


Connecting the USB 3G dongle and configuring it in order to receive (and send) SMS messages

Ok, now a little more relaxed activity: we must receive SMS messages using a 3G dongle and we must to parse them in order to command the relay.

I’ve done the following steps in order to make all things work without problems (after maaaaaaaany experiments, overall tied to the files/directories permissions and to users execution policies…. 😦 ).

1. Power Off your Raspberry
2. Connect the USB 3G dongle, then power on the Raspberry. My dongle is correctly recognized by Raspbian as 3G modem on /dev/ttyUSB0 [IMPORTANT NOTE: some USB dongle -i.e. Huawey E1820- is recognized by Raspian as CD-ROM… so you should use some “howto” regarding the utility usbmodeswitch in order to correctly recognize the modem inside the dongle]
3. Install gammu and gammu-smsd. Gammu is used to send SMS message, gammu-smsd is the daemon used to receive the SMS.

#sudo apt-get install gammu 
#sudo apt-get install gammu-smsd

4. Configure the file /etc/gammu-smsdrc in the following way:

port = /dev/ttyUSB0
connection= at19200
[...]
logfile = /home/pi/log-gammu.txt
service = file 
RunOnReceive = sudo /home/pi/Script_relay/sms_relay.py
[...]
inboxpath= /home/pi/Script_relay/inbox_sms/

5. Save the file, then add the user “gammu” to “sudoers” group of your Raspberry, using the tool visudo:

#sudo visudo

It will open /etc/sudoers.rc…so you append the following line to the file :

gammu ALL=(ALL) NOPASSWD: ALL

[NOTE: you can report /home/pi/Script_relay/sms_relay.py instead of ALL, for security reasons]

6. Save the file and Reboot you Raspberry. The gammu-smsd daemon starts automatically at the end of boot process.
7. Verify that in /home/pi/gammu-log.txt there arent’t strange errors (tied to communication between Raspi and the dongle). I encountered these errors when I installed gammu-smsd without the dongle already connected. Anyway, in this case you can remove the installation and you can reinstall gammu-smsd:

#sudo apt-get –purge autoremove gammu-smsd
#sudo apt-get gammu-smsd

8. Create the filesystem used by the gammu-smsd configuration:

#mkdir /home/pi/Script_relay
#mkdir /home/pi/Script_relay/inbox_sms
#chmod 777 /home/pi/Script_relay/inbox_sms

[NOTE: I imposed the simple mode 777 in order to permit to “gammu” user to save the SMS messages in this folder -and it’s work-, but you can use some more secure access]

9. Create the code for /home/pi/Script_relay/sms_relay.py in the follwing way:

#!/usr/bin/env python
import Rpi.GPIO as GPIO
import sys
GPIO.setmode(GPIO.BCM)
#note we don't initialize the initial value of GPIO18, we use the current status
GPIO.setup(18, GPIO.OUT)
#the filename of the SMS is passed as argument to the script from the RunOnReceive gammu-smsd option 
filename=str(sys.argv[1]) 
complete_filename="/home/pi/Script_relay/inbox_sms/"+filename 
sms_file=open(complete_filename,"r") 
message=sms_file.read(160) #note that a not-parted SMS can be maximum 160 characters 
if (message.find("poweron")<>-1): 
     GPIO.output(18, GPIO.HIGH) 
elif (message.find("poweroff")<>-1): 
     GPIO.output(18, GPIO.LOW)

That’s all folks!

If all worked correctly, sending now to the dongle telephone number a SMS containing the keyword poweron you will see that the relay will be powered on, and sending an SMS containg the keyword poweroff you will see that the relay will be powered off.

…It’s a magical thing, don’t you think that? 😉

wpid-20140520_063754.jpg

Finally…the complete relay controller

Possible improvements to the project (I give you them as exercises 🙂 )

1. Send a SMS message to a number (it should be the number of the phone which commanded the power on/off)when the relay has been powered on/off. You should modify the sms_relay.py adding a call to the gammu command line tool (find one of the many examples on internet for the usage). Note that the tool must be configured (his configuration file is /home/pi/.gammurc) with the following data:

port = /dev/ttyUSB0
connection= at19200

…But for this functionality there is a little (=big 😦 ) problem: gammu-smsd blocked the /dev/ttyUSB0, so….what could be a possible solution?

2.  Add to the /etc/gammu-smsdrc file one filter in order to accept SMS message only from YOUR phone. This is not difficult, there is a configuration parameter to add in the file (with the “white-listed” numbers)… you can find it in the gammu-smsd user guide! 🙂

 

Ok boys and girls, today we used the high voltage… you know that for a software and/or microelectronics engineer this is like a bungee-jumping. 😀

So, now I need only a good grappa an an italian horror (or thriller) movie of the ’70-’80 on my television.

Do you like Lucio Fulci movies?

A relaxing movie now...

A relaxing movie now…”The New York ripper” by Lucio Fulci

I know he is very famous all around the world (…except than in Italy 😦 ).

My Fulci preferred movie is “The New York Ripper” (italian title: “Lo Squartatore di New York”)…. I need a very relaxing night, after this dangerous and stressing post! 😉

Bye bye, see you soon!

Olinuxino A20 micro: a new toy in Garretlabs!

…Yeahhhh!!!! 🙂

I’m always happy when my lab “boards family” grows…. and this time I bought a very interesting single board computer from Olimex, a Bulgarian company: one Olinuxino A20 micro (without NAND flash).

This is the toy (photo from Olimex blog):

a20

As usual I bought the board from my favourite online shop: Robot Italy (this is not a commercial spot…but I would like to have some little discount from this company!).

With the board I ordered also the ad-hoc plexiglas box, some 40-pins flat cable (in order to connect some GPIO) and the SATA cable to connect a 2.5” hard disk to the board.

The board arrived in one day with Bartolini express courier (Robot Italy is very fast to ship), and these are my very first impressions about the board:

  1. The packaging is very beautiful (as we say -literally- in Italy: ” also the eye wants his part” 😉 )
  2. The board has a very solid appearance, and it seems very well designed and built
  3. The ad-hoc plexiglass box prefectly fits, and it’s very “chic”  (see point 1)

I downloaded the official Debian image from Olimex, I wrote it on a Kingston microSD (class 4) using the open source Win32 Disk Imager. Note that Olimex recommends to use a class 10 microSD…but I wanted to try with a cheaper choice. 😉

After this, I connected the HDMI cable to my 37” Panasonic TV, I connected to one USB connector the radio transmitter for my wireless cheap Trust keyboard + mouse (only 19 euros… but it’s a very good choice to be used on the sofa in order to seek youtube videos…. with the fingers by the chips and assorted fried food 😀 ) and I powered the board with the miniUSB connector.

Pushed the power ON button, first boot….a moment of real suspence….and all worked correctly!  …YES! 🙂

keep-calm-and-try-olinuxino

Ok, I tried some program preinstalled in the Debian image (such as Midori browser) and I noticed that all seems faster than same programs running on the Raspberry PI (ok, I know it’s obvious but I want to evidentiate this concept).

After this first boot I connected a wifi dongle (this dongle from Robot Italy, as usual) to the other USB connector and I rebooted the board.  The dongle is supported by Debian but, after the connection to my home WPA2 protected wifi network, I observed some problem tied to lost ping packets (approx 25% of the total number) .:-(

Mhhhhh… it could be tied to a too high power consuption, so in the next days I will try using a 6-16 volts external power supplier instead the miniUSB source (as recommended by Olimex in the user manual, in order to have the maximum efficiency with external peripherals).

For the moment that’s all, folks. After the first few steps with this board, Olinuxino A20 seems to be a great study opportunity for my natural born curiosity. 🙂

….Bye bye geeks!!!!

Arduino + Raspberry= Weather station with webcam (Part Two: the meteo data acquisition)

Hi geek boys and girls!

I hope you passed a very nice Easter holidays. Unfortunately I had the flu during these days…so no great funny time for me! 😦

…But I spent some time developing my weather station (I wrot the code for meteo data acquisition, and then I succesfully connected to the Raspberry a webcam and also a internet dongle for the remote access to the weather station).

 

In this post I will talk about the meteo data acquisition from Arduino and the consequent data trasmission from Arduino to Raspberry via I2C (see my previous post in order to activate the I2C link).

I decided, after some unfruitful (or simply too diffcult to implement) experiment with analog sensors, to use only digital sensors to acquire with Arduino temperature, barometric pressure and relative umidity. So I bought these sensors from Robot Italy (my preferred online store for embedded resources… as you know I love all italian products/services 😉 ):

 

This is the final circuit I’ve realized after some very basic integration test (click on the image for the zoom):

Centralina_meteo_v2_bbNote that I used a resistor of 4.7 KOhm instead 5 KOhm, as suggested on the DHT11 datasheet.

Ok, now it’s time to code some litttle skecth. Let’s start with Arduino.

In order to communicate with DHT11 and with MPL115A1 I used two well known libraries.

I took the DHT11 library from Arduino Playground and I took the MPL115A1 lib from the github of SMacarena (great appreciation for these very good works, and my sincere thanks to the authors 😉 ).

After some cut/paste/washing/ironing/rewashing and some other (not too many,you know me! ;-)) tests, this is the final Arduino code for the meteo data acquisition from sensors:

 

#include <SPI.h>
#include <MPL115A1.h>
#include <dht11.h>
#include <Wire.h> //I2C library

#define __DEBUG__ //note: I used for debug a ht1632c led display
                  //If you can't/don't use it, undef this macro! :-)
#ifdef __DEBUG__
#include <ht1632c.h>

//debug display
ht1632c dotmatrix = ht1632c(&PORTD, 7, 6, 4, 5, GEOM_32x16, 2);
#endif

//i2c settings
#define SLAVE_ADDRESS 0x04
int number_command = 0;
float value_to_send=0.0;

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

//out pint for DHT11 sensor
#define DHT11PIN 2

//sensors
MPL115A1 Pressure_sensor;
dht11 DHT11_sensor;

//current atmo values
float current_pressure=0.0;
float current_humidity=0.0;
float current_temperature=0.0;
double current_dewpoint=0.0;

void setup() {
  //serial setup
  Serial.begin(115200);
  //initialize pressure sensor
  Pressure_sensor.begin();

  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);

  // define callbacks for i2c communication
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
#ifdef __DEBUG__
  dotmatrix.clear();
  dotmatrix.setfont(FONT_5x8);
#endif
}

void loop() {
  //take & save pressure values
  current_pressure = GetPressure();
  GetTemp_Humidity_DewPoint();

  //print current valueson serial ...debug (remove it if you want)!
  Serial.print(current_pressure);
  Serial.print(" hPa\n");

  Serial.print (current_humidity);
  Serial.print(" % Humidity\n");

  Serial.print (current_temperature);
  Serial.print(" °C\n");

  Serial.print (current_dewpoint);
  Serial.print(" Dew point (°C)\n");
#ifdef __DEBUG__
  dotmatrix.clear();
  char tmp[20] = "";
  //pressure
  sprintf(tmp, "P=%dhPa", (int)current_pressure);
  byte len = strlen(tmp);
  for (int i = 0; i < len; i++)
    dotmatrix.putchar(5*i, 0, tmp[i], ORANGE);

  //temperaure
  sprintf(tmp, "T=%dC", (int)current_temperature);
  len = strlen(tmp);
  for (int i = 0; i < len; i++)
  dotmatrix.putchar(5*i, 8, tmp[i], RED);
  //humidity
  sprintf(tmp, "H=%d%%", (int)current_humidity);
  len = strlen(tmp);
  for (int i = 0; i < len; i++)
     dotmatrix.putchar(32+5*i, 8, tmp[i], GREEN);
  dotmatrix.sendframe();

#endif
  //delay
  delay(5000);
}

//Acquisition functions
//from sensors
float GetPressure()
{
  float hPa = Pressure_sensor.pressure();
  return hPa;
}

void GetTemp_Humidity_DewPoint()
{
  //take & save DHT11 values (temp + rel. humidity)
  int chk = DHT11_sensor.read(DHT11PIN);
  switch (chk) //check errors
  {
    case DHTLIB_OK:
      Serial.println("read OK");

      //read values
      current_humidity=(float)(DHT11_sensor.humidity);
      current_temperature=(float)(DHT11_sensor.temperature);

      //dew point
      current_dewpoint=dewPoint(DHT11_sensor.temperature, DHT11_sensor.humidity);
    break;

    case DHTLIB_ERROR_CHECKSUM:
      Serial.println("Checksum error");
    break;
    case DHTLIB_ERROR_TIMEOUT:
      Serial.println("Time out error");
    break;

   default:
     Serial.println("Unknown error");
   break;
  }
}

//dewpoint function (taken from http://playground.arduino.cc/main/DHT11Lib)
// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//
double dewPoint(double celsius, double humidity)
{
  // (1) Saturation Vapor Pressure = ESGG(T)
  double RATIO = 373.15 / (273.15 + celsius);
  double RHS = -7.90298 * (RATIO - 1);
  RHS += 5.02808 * log10(RATIO);
  RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ;
  RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
  RHS += log10(1013.246);
  // factor -3 is to adjust units - Vapor Pressure SVP * humidity
  double VP = pow(10, RHS - 3) * humidity;
  // (2) DEWPOINT = F(Vapor Pressure)
  double T = log(VP/0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}

//I2C callbacks

// callback for received command
void receiveData(int byteCount)
{
  while(Wire.available()) {
    number_command = Wire.read();

    if(number_command==TEMP) { //request temperature
      value_to_send = current_temperature;
    }
    if(number_command==HUMI) { //request humidity
      value_to_send = current_humidity;
    }

    if(number_command==PRES) { //request humidity
      value_to_send = current_pressure;
    }

    if(number_command==DEW) { //request dewpoint
     value_to_send = current_dewpoint;
    }
  }
}

// callback for sending data via I2C
void sendData()
{
  //convert the float values in a vector of 4 bytes to send via i2c bus
  char vector_to_send[4];
  memcpy(vector_to_send,(char*)&(value_to_send),4);
  Wire.write(vector_to_send,4);
}

 

Write the above skecth on the Arduino UNO and power on it….on the serial shell (and/or on the led display) you will see the vaues taken from the sensors.

Ok, let’s go ahead with the correspondant Raspberry PI code (at the moment it is implemented in an interactive way). It is a little more simple than the Arduino one (it is derived from the original one, but in thsi case I manage the transmission via I2C of float numbers, mapped each one on 4 bytes):

//ML meteo lab station v2.0 Raspi side
#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 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;

  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 -temp, humidity etc.-)
        float value_received;

      //convert 4 bytes received into a float
      memcpy((char*)&value_received,buf,4);
      //print the results
      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 );
     }
   }

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

  close(file);
  return (EXIT_SUCCESS);
}

Compile the Raspberry program with the same old gcc -o meteo_lab meteo_lab.c , then, if Arduino is already powered on, launch the program with ./meteo_lab

You will see on the Raspberry shell the current values for temperature, relative humidity, pressure and dew point temperature acquired (and calculated, in case of the dew point temperature) by our two sensors.

….So, you can monitor in each moment your lab weather condition! 🙂

Ok, I think you are thinking it is not too much….So, in the next posts we will see how to visualize these data (with a good webcam image on the side) on a web page accessed from internet… this is much more interesting or not? 😉

Bye bye geeks, c ya soon!