Tutorial: data logging con Arduino – Parte 1

Questo tutorial, diviso in due parti, servirà a realizzare un piccolo e semplice modulo ultra-low cost per il data logging ambientale.
In particolare andremo a campionare temperatura e quantità di luce, scrivendo i dati in un log file memorizzato su SD-Card.
Verrà utilizzata la piattaforma open hardware e software “Arduino”.
Info: arduino.cc

Hardware:
Per iniziare, avremo bisogno di una scheda Arduino Uno o Duemilanove (ma anche Mega, 2560, mini, nano etc etc).
Info: http://arduino.cc/it/main/boards
(Costo: ~25€ – Aiutiamo il progetto acquistando board 100% Made in Italy!)

ArduinoUno_R3_Front

Questa piccola schedina, è un piccolo computer in miniatura, dove già c’è tutto il necessario per programmarla senza troppi fronzoli software o hardware (come programmatori costosi).

Avremo bisogno, inoltre di qualche sensore:
Nel nostro caso andremo ad utilizzare un LM35 (questo potete comprarlo anche dai cinesi, costo: 1.50€) ed un LDR (light dependet resistor, costo0.30€)
L’LM35 si presenta in un package simil transistor (TO-92) a tre pin.
Il pinout (piedinatura), da sinistra verso destra con la parte piatta rivolta verso l’osservatore è: +5V, output, GND.

L’LDR è a tutti gli effetti un resistore variabile (tipo potenziometro), la sua resistenza cambia con la quantità di luce che si riflette su di esso.
Non ha polarità, può essere innestato a piacimento: la tensione entra da un capo ed esce alterata dall’altra. Da accoppiare con una resistenza da 500 Ohm (costo: gratis)

LDR1

Per comodità ho usato un modulo (shield) aggiuntivo all’arduino che mi permette di avere:
1. Un RTC DS1307 (Real Time Clock), mantiene il tempo meglio del vostro orologio.
2. Un card reader, i nostri output li andremo a scrivere su file.
3. Led, non avendo monitor i led saranno le nostre spie.
4. Fori per saldare i sensori o per usare una breadboard

La shield vien venduta in kit di montaggio, significa che dovremo metter mano al saldatore (che male non fa).
Sul sito del produttore vi è un ampio tutorial fotografico su come assemblarla:
http://www.ladyada.net/make/logshield/solder.html

4589675367_2192d37442

(opzionale, costo: 19.50$ http://www.ladyada.net/make/logshield/)

Wiring:
Entrambi i sensori lavorano su una tensione di 5v, l’output di ognuno ha una tensione di uscita linearmente proporzionale alla temperatura o alla quantità di luce percepita.
Arduino (il programmatore) ha il compito di leggere la tensione sui pin analogici, campionarla e renderla disponibile.

Per approfondimenti circa dettagli di funzionamento e parametri costruttivi dei sensori:
https://www.national.com/ds/LM/LM35.pdf
http://www.biltek.tubitak.gov.tr/gelisim/elektronik/dosyalar/40/LDR_NSL19_M51.pdf

Il wiring può esser fatto utilizzando una semplice breadboard oppure una millefori.

wiringok

Il risultato finale deve essere più o meno così

dscn6890
Coding:

Premesse:
Arduino, non è solo hardware ma anche: software, documentazione e community.
Sul sito ufficiale (arduino.cc) è possibile scaricare l’IDE che permette di programmare la propria Arduino via USB.
Il linguaggio di programmazione è (simil) C.
All’interno dell’ide, vi sono molti codici di prova già funzionanti, essa include gran parte delle librerie di cui avremo bisogno.
Altre sono presenti nei siti dei corrispettivi produttori hardware o dai siti personali di utenti che hanno condiviso le proprie.
Installare librerie di terze parti è molto semplice (un paio di copy&paste): google ci aiuterà non poco.

Nel nostro caso andremo ad utilizzare le librerie RTC ed SD suggerite sulla pagina di adafruit relative alla logger shield utilizzata: http://www.ladyada.net/make/logshield/download.html

E’ importante documentarsi sempre e approfonditamente sull’hardware su cui andremo a lavorare.
Datasheet, reference, librerie, documentazione varia e google vanno sempre consultati quando abbiamo hardware tra le mani.

Scrivere sulla riga di ricerca di Google: “PAROLA arduino”, risolverà gran parte dei nostri problemi.
Cercare: “lm35 arduino” o “ldr arduino” sia su google testo che immagini ci darà tantissima documentazione… per non parlare poi del forum ufficiale.

Se prendiamo in considerazione Arduino Uno/Duemilanove con controller Atmega328, avremo 32kb di memoria flash per il codice (parte statica) e 2kb per i dati (parte dinamica).
Seppur il compilatore (avr-gcc) ottimizza il codice, dobbiamo cercare di minimizzare al massimo l’uso della memoria.
Esempio: se dobbiamo contare da 1 a 50 usiamo uno short invece di un int, usiamo piccole matrici, facciamo tanto swapping su memorie esterne, dimentichiamo l’allocazione dinamica (esiste ma…).
Con l’esperienza capiremo che i codici scritti per arduino sono davvero molto leggeri: per muovere un braccio meccanico useremo al più 20righe di codice e un paio di variabili.
Il costo computazionale è tipicamente molto basso… sarebbe da pazzi pensare di usare un microcontroller a 16mhz per calcoli metereologici!

Il corpo dei codici da caricare (flashing) in Arduino è sempre formato da almeno due void function: setup e loop.
Setup: serve solo ad inizializzare alcuni valori, come ad esempio la modalità di funzione di alcuni pin, inizializzazione della seriale etc
Entra in esecuzione una sola volta: all’inizio, appena diamo alimentazione.
Loop: è un loop. Un ciclo infinito, il cuore del nostro codice.

La lettura analogica dell’lm35 verrà fatta sul pin 0 (zero) della nostra Arduino.
Senza troppo addentrarci in tecnicismi, diremo banalmente che la tensione di uscita del nostro transistor è la temperatura captata in quell’istante.
Info: http://www.ladyada.net/learn/sensors/tmp36.html
L’lm35 misura temperature in Celsius su un range di -55° +150° con un accuratezza di 0.5°.
Gli input analogici di arduino hanno una risoluzione di 10bit, ciò significa che avremo 2^10=1024 valori discreti.
Ci sono molte tecniche (hardware e software) per leggere la temperatura in modo accurato, ma il modo più semplice è convertire la tensione di uscita in gradi Celsius con questa formula:
temperaturaCelsius = (5.0 * sensor * 100.0)/1024.0;

(Tensione di alimentazione del lm35 * tensione in output dall’lm35 * offset 100) / su 1024 valori

Obiettivo finale:
L’idea è quella di realizzare un log file di testo con questa struttura:
LUCE – TEMPERATURA – ORARIO

• La campionatura, viene fatta ogni 3 secondi.
• Le letture dell’ldr e dell’lm35 vengono mediate su 20letture consecutive (senza delay).
• Stampa su porta seriale ad ogni scrittura per debugging.

Tentativo_1:
In questa primo sketch (sketch=programma=codice=algoritmo), leggeremo la temperatura dall’lm35 e andremo a scrivere sulla sd temperatura e orario.
L’orario verrà di volta in volta *chiesto* al nostro RTC.

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

const int chipSelect = 10;
short i=0;

void setup()
{
  //seriale aperta a 9600 baud
  Serial.begin(9600);
  Serial.println("Initializing SD card...");

  //inizializziamo i pin 3 e 4 per i led rosso-verde
  //pin 10 riservato al card reader
  pinMode(10, OUTPUT);
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT); 

  //se il modulo sd non viene correttamente inizializzato
  if (!SD.begin(chipSelect)) {
    //messaggio di errore sul nostro monitor seriale
    Serial.println("Card failed, or not present");

    for (i=0;i<10;i++) {
      //blinking del led rosso
      digitalWrite(3, HIGH);   
      delay(100);              
      digitalWrite(3, LOW);     
      delay(100);
    }
    return;
  }

  //se correttamente inizializzata...
  Serial.println("card initialized.");
  //blinking led verde
  digitalWrite(4, HIGH);   
  delay(500);              
  digitalWrite(4, LOW);

  //inizializziamo l'RTC
  Wire.begin();
  RTC.begin();
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop()
{
  //chiediamo il tempo all'RTC
  DateTime now = RTC.now();
  int analogPin=0;
  int sensor =0;  

  //aspettiamo 3secondi
  delay(2900);

  //leggiamo e convertiamo la temperatura dal pin 0 di arduino
  sensor = analogRead(analogPin);
  sensor = (5.0 * sensor * 100.0)/1024.0;

  //stampa sulla seriale
  Serial.print("Temperatura: ");
  Serial.println(sensor);

  //apriamo in scrittura il file sulla sd
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  //Scriviamo: TEMPERATURA - ORA:MINUTI:SECONDI
  if (dataFile) {
    dataFile.print(sensor);
    dataFile.print(" - ");
    dataFile.print(now.hour(), DEC);
    dataFile.print(":");
    dataFile.print(now.minute(), DEC);
    dataFile.print(":");
    dataFile.println(now.second(), DEC);
    //chiudiamo il file
    dataFile.close(); 

    //blinking led verde
    digitalWrite(4, HIGH);   
    delay(100);              
    digitalWrite(4, LOW);
  }  
  else {

    //errore nell'apertura del file o card rimossa
    Serial.println("error opening datalog.txt");
    for (i=0;i<10;i++) {
      //blinkig led rosso
      digitalWrite(3, HIGH);   
      delay(100);              
      digitalWrite(3, LOW);     
      delay(100);
    }
  } 
}

Dopo il caricamento, apriamo il nostro monitor seriale (all’interno dell’ide c’è il proprio monitor seriale, ma possiamo utilizzare anche putty) a 9600baud sulla stessa porta USB su cui è attaccato il nostro arduino e avremo un output più o meno di questo tipo:

26 - 21:15:36
25 - 21:17:15
25 - 21:17:19
25 - 21:17:22

Ogni volta verrà scritto un nuovo record nel nostro file che può essere elaborato in qualsiasi modo.
In questo caso ho importato i dati su un foglio Excel:

capturesg

Nel prossimo articolo uniremo alla temperatura anche la quantità di luce…

[Articolo comparso anche su: http://students.uniparthenope.it/]

Un pensiero su “Tutorial: data logging con Arduino – Parte 1

  1. Renato

    Interessante poichè vorrei realizzare un data loggin per la registrazione di correnti elettriche in un sistema trifase.
    Buona giornata.
    P.S.
    Qualcuno ha il mio stesso problema ?

    Rispondi

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.