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:
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:
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:
- una precisione leggermente migliore della lettura fatta col codice del primo articolo
- 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…