Tuesday, January 22, 2013

Getting data from the sensor to the internet

  • these pages describe how to get data from the sensor to the internet where you can watch it on some site with a normal browser
  • you can even add a warning function sending you an SMS
  • the hardware is based on an arduino running on a normal computer with internet access, the software is based on the arduino programming environment, python with serpy and pdata and google drive
  • here is a little sketch of what we are building

Part I: Setting up the arduino as a analog to digital converter


  • get an arduino and a USB cable for it
  • download the arduino programming environment from:
    http://arduino.cc/en/Main/Software and follow the installation instructions for your OS, especially read the instructions on how to install the arduino driver, this sometimes it tricky
  • start the arduino software; go to Tools - Board on the menu and click on the type of arduino you want to use (I use an uno)
  • open Tools - Serial Port, you will see some serial ports that are available, if you now plug in your arduino and open once more Tools - Serial Port, you will see which serial port your arduino occupies
  • you will now need to put code on the arduino that reads a sensor and transmits the data to your computer:

    const int sensorPin = 0;    // select the input pin for the sensor
    const int ledPin = 13; // the pin with the LED built in
    int incomingByte;      // a variable to read incoming serial data into
    int sensorValue;

    void setup() {
      // initialize serial communication:
      Serial.begin(9600);
      // initialize the LED pin as an output:
      pinMode(ledPin, OUTPUT);
    }

    void loop() {
      // see if there's incoming serial data:
      if (Serial.available() > 0) {
        // read the oldest byte in the serial buffer:
        incomingByte = Serial.read();
        // if it's a capital H (ASCII 72), turn LED on and measure:
        if (incomingByte == 'H') {
          digitalWrite(ledPin, HIGH);//turn LED on
          sensorValue = analogRead(sensorPin);
          Serial.println(sensorValue,DEC); //format in DEC -
          digitalWrite(ledPin, LOW);//turn LED off!
        }
      
       
      }
  • compile the code first, then upload it on the arduino
  •  now start the serial monitor - press H and enter in the monitor interface:
  • I connected the input port A0 with the ground or the 5V to get a reading of 0 or 1023 respectively - see this photo:
  • now the arduino is ready to talk to your computer - you just implemented and tested a little serial inferface; the computer sends an 'H' and the arduino will respond with a number between 0 and 1023, which is the value of 0 to 5V at the input port A0 digitized with 10bit


Part II: Getting python up and reading the data from the arduino

  • you will need to download python - for this tutorial I will rely on a python 2.7 distribution, which you can download here (python 3 will show you some errors that you can however fix)
  • download python  http://www.python.org/download/releases/2.7.3/
  • we need the pyserial module to talk to the arduino via the serial interface (its USB cable)
  • the pyserial documentation, installation instructions and download is at: http://pyserial.sourceforge.net/, for windows you can directly download a prepackaged .exe (http://sourceforge.net/projects/pyserial/files/pyserial/2.4/)
  • now you can do a first test  - see if you get some data from the arduino
  • python comes with IDLE, usually if you want to open a file with the extension .py, you will get the option to open it with idle
  • so - save the following text snippet as test.py:
    from __future__ import print_function
    import serial
    import time

    upperVoltage=5.0 # this is the upper volate of the arduino - corresponding to 5V
    voltageStep=upperVoltage/1023 #voltage step in 10 bit AD conv
    ser=serial.Serial('COM13',9600, timeout=1) # your com port goes here
    dummy=1;

    while dummy==1: #this means the while loop runs forwever
       a=time.localtime()
       while a.tm_sec!=0: #check if the seconds of your time are zero (every minute)
           a=time.localtime()#unless the minute has passed


       print(ser.write("H"))#send an H to the arduino
       time.sleep(1.5) #wait some time...
       msg=ser.readline()#read the serial input - its a string
       msg=msg.strip('\r\n')#get signs off the string
       print(msg) #print into terminal
       msgInt=int(msg) #convert str to integer
       #roound(x,1) means ronding on the first digit after decimal dot
       msgVolt=msgInt*voltageStep # the voltage of the arduino reader
       msgStr=str(msgVolt)#convert float to str
       data=open("test.txt", "a") #open text file in append mode
       print(a.tm_mon, a.tm_mday, a.tm_hour, a.tm_min, msgStr, file=data)
       #write into file
       data.close() #close file
       print(msgStr)#print the value written into the file
       print('done')
    ser.close()# just to show you how to close the port - the while runs forever
  • open the file with IDLE (in win klick on it and choose open with idle)
  • test the script - if it runs all right, you should get a terminal output that looks like this (although maybe with other numbers):
  • most likely its not gonna work the first time - type the parts of your code line for line into the python shell and check what step is wrong...don't give up!
  • so, that was ok, right? you should have also a file in the directory of your .py program, which is called test.txt- it will show some output like this:
    1 22 17 56 3.28445747801
    1 22 17 57 3.28445747801
    1 22 17 58 5.0
    1 22 17 59 5.0
    1 22 18 0 5.0
    1 22 18 1 5.0
    1 22 18 2 5.0
    1 22 18 3 5.0
    1 22 18 4 5.0
    1 22 18 5 4.99511241447
     
  • the format is month, day, hour, minute, then the value of your sensor in volts

Part III: get a google account and let them work for you

  • sounds good, right? google has some pretty nice features and interfaces easily with python
  • get a gmail account, if you don't already have one
  • go on google drive and create a new spreadsheet
  • the URL in your browser contains the unique key of the spreadsheet, it goes from key= to #:
    https://docs.google.com/spreadsheet/ccc?key=0AhU9bTOO3AfDdF9MQYRTOEKSNWncxcHplbGRFdEE#gid=0
  • this one has the key 0AhU9bTOO3AfDdF9MQYRTOEKSNWncxcHplbGRFdEE
  • now name the first two columns of your spreadsheet: - first time, second voltage
  • you are ready for some new python stuff, download the gdata from google:
    http://code.google.com/p/gdata-python-client/downloads/list
  • after installing it (see instructions in the zip file) you should be able to type "import gdata" into the python shell without error message
  • we now extend your old python code that was writing into a file to write into the google spreadsheet that you just created

  • from __future__ import print_function
    import serial
    import time
    import gdata.spreadsheet.service


    upperVoltage=5.0 # this is the upper volate of the arduino - corresponding to 5V
    voltageStep=upperVoltage/1023 #voltage step in 10 bit AD conv
    ser=serial.Serial('COM13',9600, timeout=1)#your com port needs to go here
    dummy=1;

    while dummy==1: #this means the while loop runs forwever
       a=time.localtime()
       while a.tm_sec!=0: #check if the seconds of your time are zero (every minute)
           a=time.localtime()#unless the minute has passed


       print(ser.write("H"))#send an H to the arduino
       time.sleep(1.5) #wait some time...
       msg=ser.readline()#read the serial input - its a string
       msg=msg.strip('\r\n')#get signs off the string
       print(msg) #print into terminal
       msgInt=int(msg) #convert str to integer
       #roound(x,1) means ronding on the first digit after decimal dot
       msgVolt=msgInt*voltageStep # the voltage of the arduino reader
       msgStr=str(msgVolt)#convert float to str
       data=open("test.txt", "a") #open text file in append mode
       print(a.tm_mon, a.tm_mday, a.tm_hour, a.tm_min, msgStr, file=data)
       #write into file
       data.close() #close file
       print(msgStr)#print the value written into the file
       print('done')

       #the next section of the code will write into your google spreadsheet
       #make sure gdata is imported (see top)
      
       email = 'you@gmail.com'
       password = 'yourpasswd'
       # Find this value in the url after 'key=' before '#'
       spreadsheet_key = 'yourkey'
       # All spreadsheets have worksheets. I think worksheet #1 by default always
       # has a value of 'od6'
       worksheet_id = 'od6'

       spr_client = gdata.spreadsheet.service.SpreadsheetsService()
       spr_client.email = email
       spr_client.password = password
       spr_client.source = 'test'
       spr_client.ProgrammaticLogin()

       # Prepare a python dictionary to write
       dict = {}
       dict['time'] =time.strftime('%m/%d/%Y %H:%M:%S')# time needs to be in the
       #spreadsheet
       dict['voltage'] = msgStr #voltage needs to be in the spreadsheet
       print (dict)

       entry = spr_client.InsertRow(dict, spreadsheet_key, worksheet_id)
       if isinstance(entry, gdata.spreadsheet.SpreadsheetsList):
         print ("Insert row succeeded.")
       else:
         print ("Insert row failed.")
      
    ser.close()# just to show you how to close the port - the while runs forever
  •  special thanks to Matt for showing how to put python and google together
    http://www.mattcutts.com/blog/write-google-spreadsheet-from-python/
  • the spreadsheet now looks like this:
     
  • the first row contains the date and time, the second the voltage you read from the arduino
  • in the menu you will find Insert and then chart - use this to make your chart:
  • the chart looks like this:
  • the chart has a menu with the item publish chart. you will get text that you can copy paste into any html website and have your chart available to the public (if you want)
  • of course you can also do this on google site (has a insert chart menu point) - but you cannot do it in blogger....:(