.: HosiriS :.

Informatica e non solo

Misuriamo la temperatura tramite Arduino

Posted by hosiris su ottobre 3, 2011

Dopo aver introdotto il mio progettino (IHSys) cominciamo con il progettare e realizzare il primo modulo: un misuratore di temperatura.

Al fine di poter realizzare il progetto avremo bisogno di alcuni componenti: Arduino, ArduinoSDK, Sensore DS18B20, resistenza da 4.7k Ohm.
E’ tutto molto limitato perché abbiamo scelto un sensore digitale che ha già incorporati i componenti necassari ad una buona trasduzione.
Le conoscenze purtroppo non saranno così limitate… a meno che non vogliate fare solo copia ed incolla: C per Arduino, Python per la lettura dei dati, SQL per lo store dei dati, PHP e Javascript per la presentazione dei dati😀
Dopo aver letto il datasheet possiamo passare alla realizzazione del circuito:

Così è il mio risultato (non ho i cavi dei vari colori… scusatemi):

Anche questo di facile realizzazione, prevede la presenza di una resistenza di pull-up ed una alimentazione a 5V.
Come possiamo leggere dal datasheet questo tipo di sensore si basa sul sistema di comunicazione 1-wire, per cui ha scolpito in se un codice a 64bit che permette di riconoscerlo sul canale di comunicazione. Allora il nostro primo compito è quello di carpire questo codice.
Scarichiamo la libreria OneWire e scompattiamola nella cartella “libraries” sotto la cartella d’installazione dell’SDK.

Apriamo il nostro bell’SDK ed inseriamo il seguente codice:


#include <OneWire.h>
OneWire ow(2);
void setup(void)
{
  Serial.begin(9600);
  lookUpSensors();
}
 
void lookUpSensors()
{
  byte address[8];
  int i=0;
  byte ok = 0, tmp = 0;

  Serial.println("--Ricerca avviata--");
 
  while (ow.search(address))
  {
    tmp = 0;
 
    if (address[0] == 0x10)
    {
      Serial.println("A questo indirizzo si trova una DS18S20 : ");
      tmp = 1;
    }
    else
    {
      if (address[0] == 0x28)
      {
        Serial.println("A questo indirizzo si trova una DS18B20 : ");
        tmp = 1;
      }
    }
 
    if (tmp == 1)
    {
      if (OneWire::crc8(address, 7) != address[7])
      {
        Serial.println(" (ma CRC8 non valido)");
      }
      else
      {
        for (i=0;i<8;i++)
        {
          Serial.print("0x");
          if (address[i] < 9)
          {
            Serial.print("0");
          }
          Serial.print(address[i],HEX);
          if (i<7)
          {
            Serial.print(",");
          }
        }
        Serial.println("");
        ok = 1;
      }
    }
  }
 
  if (ok == 0)
  {
    Serial.println("Non ho trovato sonde di temperatura");
  }
  Serial.println("--Ricerca terminata--");
}
 
void loop(void)
{
}

Caricate il codice ed eseguitelo, aprendo il monitor leggeremo un codice (a meno di errori) che sarà proprio l’indirizzo del sensore, per cui copiamolo e memorizziamolo dove non può essere perso😛.
Adesso passiamo alla parte bella: vediamo che cosa ci dice il sensore.
Apriamo un nuovo progetto nell’SDK e scriviamo:


#include <OneWire.h>
OneWire  source(2);
 
//Scriviamo qui il codice che abbiamo salvato
byte sensor[8] = {0x28,0xCE,0x47,0x31,0x02,0x00,0x00,0xA2};
 
void setup(void) {
  Serial.begin(9600);
}
 
void writeTimeToScratchpad(byte* address){
  source.reset();
  source.select(address);
  source.write(0x44,1);
  delay(1000);
}
 
void readTimeFromScratchpad(byte* address, byte* data){
  source.reset();
  source.select(address);
  source.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = source.read();
  }
}
 
float getTemperature(byte* address){
  byte data[12];
 
  writeTimeToScratchpad(address);
  readTimeFromScratchpad(address,data);
  
  return ((data[1] << 8 ) + data[0]) * 0.0625;
}
 
void loop(void) {
  float temp;
  temp = getTemperature(sensor);

  Serial.println(temp);
  delay(3600000);
}

Carichiamo il tutto nella EEPROM ed apriamo il monitor seriale attendiamo un po’ e vedremo apparire i valori delle temperature; io ho impostato il valore di un’ora, se volete qualcosa di più celere modificate il valore del delay.

Per poter elaborare i dati ho deciso di caricarli su un db di tipo SQLite, quindi ho sfruttato uno script creato da Allanon per la lettura dei dati da seriale tramite python. Modificandolo opportunamente otteniamo il seguente risultato:


#!/usr/bin/env python

from serial import Serial
from sys import exit
import sqlite3
import datetime
import os.path

filename = 'data.sqlite'
backup = 'data.bak'
create_query = '\
CREATE TABLE "data" \
(\
"year" INTEGER, "month" INTEGER, "day" INTEGER, \
"hour" INTEGER, "minute" INTEGER, "seconds" INTEGER, "milli" INTEGER, \
"Tint" INTEGER, "Tdec" INTEGER\
);'

if (not os.path.exists(filename)):
    con = sqlite3.Connection(filename)
    cur = con.cursor()
    cur.execute(create_query)
    cur.close()
    con.commit()
    con.close()

s = Serial('/dev/ttyUSB0', 9600)
while True:
    try:
        con = sqlite3.Connection(filename)
        cur = con.cursor()
        
        read = s.readline();

        tmp = read.replace("\r\n", "")
        readed = tmp.split(".");
        now = datetime.datetime.now()
        to_db = [now.year, now.month, now.day, now.hour, now.minute, now.second, now.microsecond, int(float(readed[0])), int(float(readed[1]))]
        print to_db
        cur.execute('INSERT INTO data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);', to_db)
        cur.close()
        con.commit()
        con.close()
    except KeyboardInterrupt:
        print "Bye"
        exit(0)

Il codice è semplice, non fa altro che leggere i dati ed elaborarli togliendo ciò che non serve. Il db viene chiuso dopo ogni insert, per cui è possibile elaborare il file nei tempi “morti”.

Fin qui possiamo già essere soddisfatti.. abbiamo i nostri dati caricati e su questi possiamo scegliere di fare qualsiasi tipo di elaborazione con qualsiasi mezzo. Essendo un modulo di IHSys dovrà permettermi di leggere queste info con qualsiasi messo e da qualsiasi canale, quindi ho scelto di rileggere i dati dal db tramite PHP e presentarli tramite Javascript.


<html>
        <head>
                <script src="js-class.js"></script>
                <script src="bluff-src.js"></script>
        </head>
        <body>

<?php
$dbname = "data.sqlite";
$datatable = "data";

$conn = new SQLite3($dbname);
$query = "
        SELECT *
        FROM $datatable
";
$results = $conn->query($query);
i
?>
                <div id="data">
                        <pre>
<?php
$sum = 0;
$count = 0;
$temp = array();
$label = array();
while ($row = $results->fetchArray()) {
        $row[1] = (strlen($row[1]) == 2) ? $row[1] : ((strlen($row[1]) == 1) ? "0".$row[1] : "00".$row[1]);
        $row[2] = (strlen($row[2]) == 2) ? $row[2] : ((strlen($row[2]) == 1) ? "0".$row[2] : "00".$row[2]);
        $date = $row[2]."-".$row[1]."-".$row[0];
        $row[3] = (strlen($row[3]) == 2) ? $row[3] : ((strlen($row[3]) == 1) ? "0".$row[3] : "00".$row[3]);
        $row[4] = (strlen($row[4]) == 2) ? $row[4] : ((strlen($row[4]) == 1) ? "0".$row[4] : "00".$row[4]);
        $row[5] = (strlen($row[5]) == 2) ? $row[5] : ((strlen($row[5]) == 1) ? "0".$row[5] : "00".$row[5]);
        $hour = $row[3].":".$row[4].":".$row[5];

        echo "Data: ".$date."\tOra: ".$hour;

        $T = $row[7] + ($row[8]/100);
        $T = (strlen(substr($T, 3)) >= 2) ? $T : ((strlen(substr($T, 3)) == 1) ? $T."0" : $T.".00");
        echo "\tTemp: ".$T."°C\r\n";

        $sum += $T;
        $label[$count] = $row[3];
        $temp[$count] = $T;
        $count++;
}
$Tavg = $sum/$count;
echo "\n\t\tAvg Temp: ".$Tavg."°C";
echo "\n\t\tMin Temp: ".min($temp)."°C";
echo "\n\t\tMax Temp: ".max($temp)."°C";
?>
                        </pre>
                </div>

                <canvas id="temperature" width="400" height="300"></canvas>
                <script>
                        var g = new Bluff.Line('temperature', '1000x500');
                        g.hide_dots = true;
                        g.hide_legend = true;
                        g.marker_font_size = 10;
                        g.title = 'Temperature';
                        g.tooltips = true;

                        g.theme_greyscale();

                        var tarray = new Array();
                        var darray = new Array();
                        <?php
                        for ($i=0; $i<$count; $i++) {
                        ?>
                                tarray[<?php echo $i;?>] = "<?php echo $temp[$i]?>";
                                darray[<?php echo $i;?>] = "<?php echo $label[$i]?>";
                        <?php
                        }
                        ?>

                        //g.data("Temp", [10, 12, 18, 20, 22, 26]);
                        g.data("Temp", tarray);
                        g.minimum_value = 15;
                        g.maximum_value = 35;
                        g.y_axis_increment = 1;

                        g.labels = darray;

                        g.draw();
                </script>
        </body>
</html>

Non facciamo altro che leggere i dati dal db usando le librerie SQLite3. Prima li presentiamo in forma tabellare tramite PHP e ne calcoliamo dei dati: temperatura media, minimo e massimo del periodo.
Poi tramite le librerie Bluff presentiamo i dati in forma di grafico:

Certo ancora il sistema è rozzo, ma è un inizio: in previsione ho la possibilità di scegliere il periodo da visualizzare, migliorare il sistema di analisi, … mi verrà in mente altro per renderlo migliore😀

Per chi volesse scaricare questi sorgenti, qui potete trovare il pacchetto

Una Risposta to “Misuriamo la temperatura tramite Arduino”

  1. […] Misuriamo la temperatura tramite Arduino ::: HosiriS […]

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

 
%d blogger cliccano Mi Piace per questo: