esco un pò dai soliti progetti di cnc o fresatura per dedicarmi ad un progettino che avevo in mente da un pò di tempo. Sto parlando di un datalogger con Arduino
Mi serviva un dispositivo per poter registrare a intervalli regolari di tempo 2 temperature, quella dell'acqua della piscina e quella esterna per monitorare quanto l'escursione notturna e l'evaporazione abbassa la temperatura della vasca.
Il tutto è nato dal fatto che quest'anno per contrastare i bagni freddi a temperature intorno i 26° ho comprato una copertura isotermica per trattenere i raggi UV e per evitare l'evaporazione notturna.
I risultati sono stati da subito eccezionali, l'acqua nei giorni scorsi ha toccato temperature intorno ai 33° ma ha anche fatto un bel caldo per cui il datalogger mi serve appunto per verificare con e senza copertura isotermica quanto cambiano le cose.
Questo è il mio primo progetto in assoluto dove ho scritto anche codice per Arduino per cui accetto volentieri commenti e critiche perchè possa migliorarmi. Alcune parti di codice sono ridondate, ho sprecato un pò di ram ma per il mio scopo va più che bene.
Ringrazio Mauro Alfieri, logicaprogrammabile.it e maffucci.it per i loro esaustivi post che mi hanno illuminato e aiutato a completare questo progetto.
I componenti per il progetto sono:
- Scheda Arduino Uno
- Modulo Real Time Clock I2C DS1307
- Lettore SD Card Reader/Writer PIC + SD Card
- Sonda di Temperatura DS18B20 da 1m Waterproof
- Sensore di temperatura LM35
- Lcd 16x2 QC1602A
Purtroppo non sono riuscito a documentare tutti i passaggi, forse perchè ero troppo preso e concentrato ma posso dirvi dove ho recuperato le informazioni.
Risorse dalle quali mi sono ispirato per gli schemi dei collegamenti:
In prima battuta ho cablato tutti i moduli su una breadboard e scritto lo Sketch per intero
Questo è lo sketch:
//includo la libreria per la //comunicazione su bus I2C #include#include #include #include #include const int chipSelect = 4; int counter = 0; int minute_interval = 10; // in minuti int log_interval = minute_interval*60; // ricavo i secondi File dataFile; int DS18B20_Pin = 9; OneWire ds(DS18B20_Pin); // initialize the library with the numbers of the interface pins LiquidCrystal lcd(8, 7, 5, 6, 3, 2); //LM35 int pinoSensor = 0; int valorLido = 0; float temperaturaExt = 0; void setup() { Serial.begin(9600); pinMode(chipSelect, OUTPUT); lcd.begin(16, 2); Wire.begin(); //inizia la comunicazione con il DS1307 Wire.beginTransmission(0x68); Wire.write((byte)0x00); Wire.endTransmission(); Wire.requestFrom(0x68, 7); // estrapolazione dei 7 byte dei registri byte secondi = Wire.read(); byte minuti = Wire.read(); byte ora = Wire.read(); byte giorno_sett = Wire.read(); byte giorno_mese = Wire.read(); byte mese = Wire.read(); byte anno = Wire.read(); String o = String(ora, HEX); char ORA[10]; sprintf(ORA, "%02d", o.toInt()); String m = String(minuti, HEX); char MINUTI[10]; sprintf(MINUTI, "%02d", m.toInt()); String s = String(secondi, HEX); char SECONDI[10]; sprintf(SECONDI, "%02d", s.toInt()); String g = String(giorno_mese, HEX); char GIORNO[10]; sprintf(GIORNO, "%02d", g.toInt()); String me = String(mese, HEX); char MESE[10]; sprintf(MESE, "%02d", me.toInt()); String a = String(anno, HEX); char ANNO[10]; sprintf(ANNO, "%02d", a.toInt()); lcd.setCursor(0, 0); lcd.print("Initialize SD"); Serial.print("Initializing SD card..."); //Serial.println("CS pin "+chipSelect); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); // don't do anything more: return; } Serial.println("card initialized."); dataFile = SD.open("piscina.log", FILE_WRITE); if (dataFile) { dataFile.print(GIORNO); dataFile.print("/"); dataFile.print(MESE); dataFile.print("/"); dataFile.print(ANNO); dataFile.print(";"); dataFile.print(ORA); dataFile.print(":"); dataFile.print(MINUTI); dataFile.print(":"); dataFile.print(SECONDI); dataFile.print(";"); dataFile.print("accensione"); dataFile.println(""); dataFile.close(); } else { Serial.println("error opening dati.log"); } delay(1000); } void loop() { counter++; // LM35 temperatura esterna valorLido = analogRead(pinoSensor); temperaturaExt = (valorLido * 0.00480); temperaturaExt = temperaturaExt * 100; //inizzializza la trasmissione partendo //dall'indirizzo 0x00 Wire.beginTransmission(0x68); Wire.write((byte)0x00); Wire.endTransmission(); Wire.requestFrom(0x68, 7); //regupero i 7 byte relativi ai //corrispondenti registri byte secondi = Wire.read(); byte minuti = Wire.read(); byte ora = Wire.read(); byte giorno_sett = Wire.read(); byte giorno_mese = Wire.read(); byte mese = Wire.read(); byte anno = Wire.read(); String o = String(ora, HEX); char ORA[10]; sprintf(ORA, "%02d", o.toInt()); String m = String(minuti, HEX); char MINUTI[10]; sprintf(MINUTI, "%02d", m.toInt()); String s = String(secondi, HEX); char SECONDI[10]; sprintf(SECONDI, "%02d", s.toInt()); String g = String(giorno_mese, HEX); char GIORNO[10]; sprintf(GIORNO, "%02d", g.toInt()); String me = String(mese, HEX); char MESE[10]; sprintf(MESE, "%02d", me.toInt()); String a = String(anno, HEX); char ANNO[10]; sprintf(ANNO, "%02d", a.toInt()); // prima riga lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); String orario; float temperature = getTemperature(); int temperatura = int(temperature); lcd.print(ORA); lcd.print(":"); lcd.print(MINUTI); lcd.print(" "); lcd.print(temperature,1); lcd.print(" "); lcd.print(temperaturaExt,1); String frase = "..."; if(temperatura <20 ){ frase = "troppo fredda.."; } if(temperatura >=20 && temperatura <27 ){ frase = "da temerari.."; } if(temperatura >=27 && temperatura <29 ){ frase = "Da bagno...corto"; } if(temperatura >=29 && temperatura <30 ){ frase = "Da bagno!"; } if(temperatura >=30 && temperatura <32 ){ frase = "Da super bagno!"; } if(temperatura >=32 && temperatura <33){ frase = "Tuffati dai!"; } if(temperatura >=33){ frase = "Butta la pasta.."; } // Seconda riga dalla posizione zero lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(frase); // log su SD if(counter==log_interval){ counter = 0; } if(counter==1){ dataFile = SD.open("piscina.log", FILE_WRITE); if (dataFile) { dataFile.print(GIORNO); dataFile.print("/"); dataFile.print(MESE); dataFile.print("/"); dataFile.print(ANNO); dataFile.print(";"); dataFile.print(ORA); dataFile.print(":"); dataFile.print(MINUTI); dataFile.print(":"); dataFile.print(SECONDI); dataFile.print(";"); dataFile.print(temperature,1); dataFile.print(";"); dataFile.print(temperaturaExt,1); dataFile.print(";"); dataFile.print(frase); dataFile.println(""); dataFile.close(); Serial.println("log su SD.."); lcd.setCursor(15, 0); lcd.print("*"); }else{ lcd.print(" "); lcd.setCursor(0, 1); lcd.print("errore SD file"); } counter = 1; } Serial.println(""); Serial.print("Temperatura esterna: "); Serial.println(temperaturaExt,1); Serial.print("Temperatura acqua: "); Serial.println(temperature,1); delay(1000); } float getTemperature(){ //returns the temperature from one DS18B20 in DEG Celsius byte data[12]; byte addr[8]; if ( !ds.search(addr)) { //no more sensors on chain, reset search ds.reset_search(); return -1000; } if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return -1000; } if ( addr[0] != 0x10 && addr[0] != 0x28) { Serial.print("Device is not recognized"); return -1000; } ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end byte present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for (int i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } ds.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float tempRead = ((MSB << 8) | LSB); //using two's compliment float TemperatureSum = tempRead / 16; return TemperatureSum; }
Poi ho comprato una scatolina che potesse contenere i vari componenti e l'ho forata con la mia cnc laser autocostruita
Dalla scatola ho fatto uscire la sonda LM35 per misurare la temperatura esterna
Infine ho fatto una prolunga alla sonda che poi ho immerso in acqua
I datalogger scrive su un file ogni 10 minuti i valori della temperatura esterna e dell'acqua della piscina. Tali dati li ho poi messi su un foglio di calcolo di google per disegnarne un grafico.
Infine ho sviluppato in php e javascript una semplice interfaccia per consultare i dati raccolti.
![]() |
Nessun commento:
Posta un commento