Archivi tag: logging

Tutorial: data logging con Arduino – Parte 2

Nel precedente articolo abbiamo dato una prima ossatura al nostro data logger.
Questa volta andremo ad inserire nel nostro sketch l’LDR e andremo a mediare i nostri valori dando un output più preciso possibile.

Lo schema di massima del collegamento è il seguente:

ldr_nightlight_breadboard fetch.php

Un primo sketch di massima potrebbe essere questo:

int photocellPin = 1;     // LDR connesso al pin analogico 1
int photocellReading;     // variabile di conversione photocellReading = analogRead(photocellPin);  
 Serial.print("Luce = ");
Serial.print(photocellReading);     // scriviamo sulla seriale la quantità di luce percepita

if (photocellReading < 10) {
  Serial.println(" - Scuro");
} 
else if (photocellReading < 200) {
  Serial.println(" - Poca luce");
} 
else if (photocellReading < 500) {
  Serial.println(" - Luce");
} 
else if (photocellReading < 800) {
  Serial.println(" - Luminoso");
} 
else {
  Serial.println(" - Molto luminoso");
}

Minore è il valore percepito più sarà buio.
In questo caso il valore letto è stato spalmato su 5 print, ottimo per il debug sulla seriale.

Ora bisogna riorganizzare la nostra basetta e montare assieme LDR, LED e LM35 (sembra uno scoglilingua!) per ottenere questo:

wiringok

 

Ora riorganizziamo lo sketch iniziale ed introduciamo media su 20 letture consecutive per poi ottenere questo sketch finale:

#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 tempPin=0; //pin del sensore di temperatura
  int ldrPin=1; //pin del sensore di luce

  int campioni=20; //20 campioni
  int ii=0;
  float  tempc1=0; // variabile per la temperatura
  long unsigned int light=0; //variabile per la luce
  float samples1[campioni]; // array di campioni per la temperatura e luce
  int samples2[campioni];  

  //aspettiamo 3secondi
  delay(2900);

  for(ii = 0; ii <= campioni-1 ; ii++)
  {
    //nell'II-esimo elemento dell'array Samples1 inseriamo il valore convertito della temperatura
    samples1[ii] = (( 5.0 * analogRead(tempPin) * 100.0) / 1024.0);
    //sommiamo le temperature di volta in volta in un altra variabile
    tempc1 = tempc1 + samples1[ii];

    //non abbiamo bisogna di convertire il valore della quantità di luce, la recuperiamo direttamente
    samples2[ii] = analogRead(ldrPin);
    light=light + samples2[ii];
  }

  //dividiamo la sommatoria per N
  tempc1 = tempc1/campioni; 
  light = light /campioni;

  //stampiamo sul nostro monitor seriale per eventuale debugging
  Serial.print(tempc1);
  Serial.println(" C");
  Serial.print(light);
  Serial.println(" light"); 

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

  //Scriviamo: LUCE - TEMPERATURA - ORA:MINUTI:SECONDI
  if (dataFile) {
    dataFile.print(light);
    dataFile.print(" - ");
    dataFile.print(tempc1);
    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);
    }
  } 
}

Perchè mediare?

Nello sketch finale ho inserito questo codice:

  for(ii = 0; ii <= campioni-1 ; ii++)
  {
    //nell'II-esimo elemento dell'array Samples1 inseriamo il valore convertito della temperatura
    samples1[ii] = (( 5.0 * analogRead(tempPin) * 100.0) / 1024.0);
    //sommiamo le temperature di volta in volta in un altra variabile
    tempc1 = tempc1 + samples1[ii];

    //non abbiamo bisogna di convertire il valore della quantità di luce, la recuperiamo direttamente
    samples2[ii] = analogRead(ldrPin);
    light=light + samples2[ii];
  }

  //dividiamo la sommatoria per N
  tempc1 = tempc1/campioni; 
  light = light /campioni;

I motivi principali sono due:

  1. una precisione leggermente migliore della lettura fatta col codice del primo articolo
  2. in realtà, la media via software può essere evitata se venisse introdotto un piccolo circuito tra sensori e pin.

Campionare 20 volte successivamente, mi permette di evitare di introdurre altra circuiteria.
Questo workaround ci permette di non avere valori sballati dovuti ad un effetto collaterale, a livello hardware, del “Sample and Hold

Sul nostro file datalog.txt avremo finalmente i valori nel formato che ci eravamo prefissi di avere…