After few years of „JAVA lazy programming“ with IOIO board, I decided to move to the next level and try Arduino and C. And what is the most obvious „hello world“ project for Arduino? Thermometer. But just display the temperature is little boring. After seeing this beautiful example from plotly:

Real-time Graphing and Data Logging

it was clear, that I need to be online, with some charts and other things making the geek happy.
Components were

  • Arduino Nano
  • Ethernet shield
  • pair of DHT22
  • LCD screen (used in Nokia 5110/3110)

As the ethernet shield is based on ENC28J60 chip, I cannot used the default Ethernet Arduino lib, so I tried UIPEthernet, which is copy/paste replacement.
But only UIPEthernet + plotly_streaming_ethernet takes 28 066 bytes of memory! So no space for display and temperature sensor.

Another option was Ethercard which is simplier and smaller, but cannot work with plotly streaming API.
I decides to send data to my sql database first and then to the plotly service via their REST API – final complete sketch has 21 910 bytes (EtherCard + DHT + LCD5110_Basic)


Complete sketch, just replace
%WRITE_SCRIPT% and %DOMAIN% with your values.
Eventualy change pinout
#define DHTPIN 8
#define DHTPIN_OUT 9
#define BACKLIGHT = 7;


#include <EtherCard.h>
#include "DHT.h"
#include <LCD5110_Basic.h>


#define DHTPIN 8
#define DHTPIN_OUT 9
#define DHTTYPE DHT22
#define BACKLIGHT = 7; 

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[700];
char myIpString[24];

extern uint8_t MediumNumbers[];

extern uint8_t SmallFont[];
static uint32_t timer;

DHT dht(DHTPIN, DHTTYPE);
DHT dht_out(DHTPIN_OUT, DHTTYPE);
LCD5110 myGLCD(6,5,4,2,3);

const char website[] PROGMEM = "%DOMAIN%";

int dstart = 0; 
int dlen = 0; 
char tbuff[12];
char cbuff[]="serial=0&temperature=00&humidity=00&oustsidetemp=00&oustsidehum=00";


// called when the client request is complete
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
  memset( &tbuff, 0, sizeof(tbuff)); 
}

void setup () {
  Serial.begin(57600);
  Serial.println(F("\n[setup]"));

  if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0) 
    Serial.println(F("Failed to access Ethernet controller"));
  if (!ether.dhcpSetup())
    Serial.println(F("DHCP failed"));

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);  
  ether.printIp("DNS: ", ether.dnsip);  

  if (!ether.dnsLookup(website))
    Serial.println("DNS failed");
    
  pinMode(7,OUTPUT);
    
  sprintf(myIpString, "%d.%d.%d.%d", ether.myip[0], ether.myip[1], ether.myip[2], ether.myip[3]);  
  ether.printIp("SRV: ", ether.hisip);
  myGLCD.InitLCD();
  dht.begin();
  dht_out.begin();
  
}

void loop () {
 
  ether.packetLoop(ether.packetReceive());
  
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  if(pos)
  {
  char* data = (char *) Ethernet::buffer + pos;
  Serial.println("----------------");
  Serial.println("data received:");
  Serial.println(data);
  Serial.println("----------------");
  if (strncmp("GET /?on",data,8) == 0) {
  digitalWrite(7, LOW); 
  Serial.println("LED ON:");
  }
  if (strncmp("GET /?off",data,9) == 0) {
  digitalWrite(7, HIGH); 
  Serial.println("LED OFF:");
  }
  }
  
  if (millis() > timer) {
    
  float h = dht.readHumidity();
  float ho = dht_out.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  float to = dht_out.readTemperature();

     myGLCD.clrScr();
 
     myGLCD.setFont(SmallFont);
     myGLCD.print("------------", CENTER, 17);
      
     myGLCD.print("Teplota",LEFT,0);
     myGLCD.print("Venkovni",LEFT,15);
     myGLCD.print("Vlhkost",LEFT,24);
     myGLCD.print("Venkovni",LEFT,34);
     myGLCD.printNumF(t, 1, RIGHT, 0);
     myGLCD.printNumF(to, 1, RIGHT, 15);
     myGLCD.printNumI(ho, RIGHT, 34);
     myGLCD.printNumI(h, RIGHT, 24);
     
 
    timer = millis() + 50000;
    Serial.println();
    Serial.print("<<< REQ ");
  
 
  dtostrf(t,2,2,tbuff); 
  dstart = 21;
  //start of replace 
  dlen = 2; 
  
  for (int i=0+dstart; i <= dstart+dlen-1; i++)
  { 
  cbuff[i] = tbuff[i-dstart];
  }
  
  dtostrf(h,2,3,tbuff);
  dstart = 33;
  dlen = 2;
  
  for (int i=0+dstart; i <= dstart+dlen-1; i++)
  { 
  cbuff[i] = tbuff[i-dstart];
  } 
  
  memset( &tbuff, 0, sizeof(tbuff)); 

  // Outside values
  dtostrf(to,2,2,tbuff); 
  dstart = 49;
  dlen = 2; 
  
  for (int i=0+dstart; i <= dstart+dlen-1; i++)
  { 
  cbuff[i] = tbuff[i-dstart];
  }
  
  dtostrf(ho,2,3,tbuff);
  dstart = 64;
  dlen = 2;
  
  for (int i=0+dstart; i <= dstart+dlen-1; i++)
  { 
  cbuff[i] = tbuff[i-dstart];
  } 
    Serial.println();
    Serial.print("Buffer");
    Serial.println();
    Serial.print(cbuff);
    Serial.println();
  
    ether.browseUrl(PSTR("/%WRITE_SCRIPT%.php?"),cbuff, website, my_callback);
   
}

myGLCD.setFont(SmallFont);
myGLCD.print(myIpString, CENTER, 46);

}

The „receiver“ script, saving the results to the mySQL (PoC)

<?php
    // Connect to MySQL
    include("dbconnect.php");

    if(is_numeric($_GET["temperature"])&&is_numeric($_GET["humidity"])&&is_numeric($_GET["oustsidetemp"])&&is_numeric($_GET["oustsidehum"]))
    {
    // Prepare the SQL statement
    $SQL = "INSERT INTO temperature (sensor,celsius,humidity,oustsidetemp,oustsidehum) VALUES ('".$_GET["serial"]."', '".$_GET["temperature"]."', '".$_GET["humidity"]."', '".$_GET["oustsidetemp"]."', '".$_GET["oustsidehum"]."')";    

    // Execute SQL statement
    $result = mysql_query($SQL);
    if (!$result) 
    {  
    die('Invalid query: ' . mysql_error());
    }

   }
?>

Very very very UGLY code for posting, just need to check the functionality

<?php
      // Connect to MySQL
     include("dbconnect.php");
     $url = 'https://plot.ly/clientresp';
    
     
   $result = mysql_query("SELECT * FROM temperature ORDER BY id ASC");

   
      $x = "[" ;
      $y = "[" ;
      $h = "[" ;
      $yo = "[" ;
      $ho = "[" ;
    // process every record
    $i = 0;
    while( $row = mysql_fetch_array($result) )
    {
    if($i!=0)
    { 
    $x = $x."," ;
    $y = $y."," ;
    $h = $h."," ;
    $yo = $yo."," ;
    $ho = $ho."," ;
    }
         $x = $x."\"".$row["event"]."\"";
         $y = $y.$row["celsius"];
         $h = $h.$row["humidity"];
         $yo = $yo.$row["oustsidetemp"];
         $ho = $ho.$row["oustsidehum"];
         $i++  ;
    }
    $x = $x."]" ;
    $y = $y."]" ;
    $h = $h."]" ;
    $yo = $yo."]" ;
    $ho = $ho."]" ;
   // var_dump($x);

    $data = array('un' => '%PLOTLYNICK%', 'key' => '%PLOTLYKEY%', 'origin' => 'plot', 'platform' => 'rest', 'args' => '[{"x":'. $x .' , "y": ' .$y. ',"name": "Temperature", "type": "scatter", "mode": "lines"},{"x":'. $x .' , "y": ' .$yo. ',"name": "Temperature ouside", "type": "scatter", "mode": "lines"},{"x":'. $x .' , "y": ' .$h. ',"name": "Humidity", "type": "scatter", "mode": "lines"},{"x":'. $x .' , "y": ' .$ho. ',"name": "Humidity ouside", "type": "scatter", "mode": "lines"}]', 'kwargs' =>'{"filename": "Arduino nano test", "fileopt": "overwrite", "layout": {"title": "Temperature and Humidity", "xaxis": {"title": "Date"}, "yaxis": {"title": "Values (C) (%)"}}}');
     // use key 'http' even if you send the request to https://...
    $options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ),
    );
    $context  = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
     var_dump($result);
//    $obj = json_decode($json);
//    $graphUrl = $obj->{"url"}; 
    
//    $obj = json_decode($json);
//    print $obj->{'error'};
 
?>
Arduino

Arduino

It was working, but since ESP8266 came to the market, this is old and little overkill as now, the single ESP8266 could measure temperature and send it to thingspeak.
http://www.instructables.com/id/Low-cost-WIFI-temperature-data-logger-based-on-ESP
Its time to make it more wireless, smaller and more fancy.

The new PoC with Wifi + BMP180 Barometric Pressure/Temperature sensor is coming 🙂