Controller per Peltier Con Arduino – Parte IV – Lo Sketch
Pronti per lo sketch?
Arrivati a questo punto, dal momento che abbiamo tutta la circuiteria impostata, iniziamo a mettere mano al codice.
Non spiegherò come collegare arduino al pc, installare librerie etc.etc., tutte cose che le trovate in giro nel net e fanno parte dell’ABC di questo dispostivo.
Partiamo dalle Librerie: le librerie che ci servono sono 3:
- Quella dello Schermo LCD 12c che potete scaricare a questo LINK
- Quella del Termistore NTC che potete scaricare a questo LINK
Scaricate ed installate queste librerie possiamo iniziare, richiamando tutte le librerie che ci necessitano
LA LOGICA CON CUI HO CREATO IL FIRMWARE
Il firmware è creato in questo modo, lo spiego testualmente ma poi troverete ulteriori righe di testo all’interno del codice.
Partiamo dallo stato iniziale. Si accende il dispositivo, e viene immediatamente rilevata la temperatura. Inquesta fase ci si trova in modalità Manual (quindi “Manual” scritto sull’LCD e LED spento), con la potenza erogata pari a 0% Questo si rende necessario per evitare di accendere e far schizzare la peltier a palla.
Bene, la peltier viene gestita in PWM tramite il comando MAP che definisce una rimappatura dei valori. Il PWM consente valori da 0 a 255, mentre le percentuali vanno da 0 a 99. Col comando MAP si riesce a rimappare proporzionalmente i due valori, in moco che se, esempio, io inserisco 10% di utilizzo, il Pin3 scrive un valore pari a 25, e via di seguito
I pulsanti invece vengono gestiti con un contatore che scrive un valore temporaneo quando viene letto un cambio di stato sui pin a cui sono collegati. In questo modo si va a creare un contatore che permette di integrare o diminuire i valori (esempio Settare la temperatura o la potenza erogata), aumentando o diminuendo ad ogni pressione il valore memorizzato nel contatore. Questa routine avviene per tutti e tre i bottoni, dove i pulsanti UP & DOWN aumentano o diminuiscono i valori di Temperatura (se AutoModo ON) o potenza (se AutomodoOFF), mentre il terzo pulsante chiamato AUTOMODO consente di utilizzare la proprietà dello Switch Case.
Infatti proprio tramite Switch CAse ho creato due blocchi di istruzioni differenti, dove :
CASO ZERO (Manual Mode):
- prevede la lettura della temperatura ma non ha influenza sul funzioamento,
- scrive su LCD “Manual”
- pulsanti vanno ad integrare o diminuire la potenza erogata per step di 25%
CASO UNO (AutoMode)
- Prevede la lettura della temperatura e ne fa una comparazione con la variabile Set Temp impostata
- Scrive su LCD “Auto”
- I pulsanti vanno ad integrare o diminuire la temperatura settata in un range da +25 a -20 °C
- Vengono effettuate operazioni condizionali dal risultato della differenza tra temperatura settata e temperatura letta. In questo modo, esempio se io setto -10°C e la temperatura letta è 5°C, la peltier lavorerà al massimo (99%). A mano a mano che la temperatura letta si avvicinerà alla tempreatura settata (supponiamo letti -9, impostati -10) allora inizierà a scendere la potenza erogata fino a stabilizzare, dopo una decina di minuti, la temperatura.
Ok, trovavo opportuna questa spiegazione. Ecco il codice, completo di righe di commento. A margine, troverete il file .ino da scaricare per provare il vostro controller. Fatto questo, inizieremo a costruirne uno insieme passo dopo passo.
// carico le librerie necessarie #include <LiquidCrystal_I2C.h> #include <LiquidCrystal_I2C.h> #include <Thermistor.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,16,2); /* ---------------------------------MYKOOLER Un progetto di Michele Lavino Written by Fabio Mortari Inizio spiegando come dovrebbe girare. * Prima di tutto, abbiamo lo stato iniziale del programma * dove * a) la peltier ? a 0 * b) la funzione MODE ? su MANUAL * dopodich? se proseguo su MANUAL la peltier si attiver? solo * ed esclusivamente cliccando su UP. * Diversamente, posso andare su AUTO, e il software entrer? in un altro * caso - case switch. * Quindi la struttura dovrebbe essere questa: due blocchi Switch * case 1 Manual e case 2 Auto, dove MANUAL contiene tutte le informazioni * inerenti ai ,)bottoni, mentre il 2 Auto contiene tutte le istruzioni per l'automatismo * Questo porta ovviamente a dover dichiarare prima tutte le variabili * che verranno dichiarate Inoltre bisogna impostare i pin * Per far questo, i pin che metterei sono i seguenti * a) pin 3 - pilotaggio della peltier via Mosfet * b) pin 4 - Pulsante UP * c) pin 5 - pulsante Down * d) pin 6 - Led di stato Manual/Auto * e) pin Analog (0) - sensore di temperatura * Dopo aver dichiarato queste, ho bisogno di andare a impostare le variabili di stato. Essendo che la temperatura ? la prima cosa che vogliamo leggere * inizio col definire la variabile di temperatura */ Thermistor senstemp(0); //int senstemp = A0; // questo ? la dichiaraione del pin associato a Senstemp che andr? associata ad analogread(0), cio? il risultato della lettura si chiamer? val_Adc float temperatura = 0; // questo ? il "contenitore" del risoltato di conversione tra Volt e Temperatura /* ok. Fatto questo inizio a definire anche dove andremo a leggere o scrivere i valori sui pin, quindi assegniamo un nome ai pin */ const int plt = 3; float difftemp = 0; //difftemp è la differenza tra temperatura e settemp e mi serve per il ciclo while dell'automode /* dichiaro le variabili e le costanti per i bottoni up e down */ const int buttonUp = 5; const int buttonDown = 4; const int AutoMode = 6; //nel pin 6 colleghiamo il pulsante di Auto ON e OFF const int AutoLed = 7; // questo ? il led Auto OnOff /* bene. Abbiamo quindi definito il pin della peltier, i pin dei bottoni up e down, il pin dell'pulsante AuotMode e infine il pin dell'Autoled Adesso ? il momento di iniziare a definire alcune variabili di inizio. Abbiamo detto che la peltier deve essere spenta quindi iniziamo da quella*/ int power = 0; //definisco a quanto deve stare all'avvio il valore di power. Occhio perch? ancora non gli ho assegnato in realt? il funzionamento...lo faremo in seguito int peltier_level = map(power, 0, 99, 0, 255); //peltier level ? la variabile che gestir? il mosfet da 0 a 255. Questo perch? in pratica il pwm ? a 8 bit che sono 255 livelli /* ora, fatto questo andiamo a inserire le variabili al pulsante AUTOMODE Questo pulsante se azionato in case 1, accende il led e inizia le istruzioni di AUTO, diversamente spegne il Led e inizia le istruzioni di MANUAL */ int StatoAutoMode = 0; //in questo modo, l'automode va su manual all'avvio. Quindi ricordiamoci che Automode = 0 va in manual int LastStatoAutoMode = 0; //ultimo stato del pulsante, appunto non premuto al momento dell'avvio quindi restituisce 0 int CountAutoMode = 0; //conteggio del bottone /* fatto questo vado a definire anche le variabili di conteggio per i pulsanti Up & Down, perch? poi ci torneranno utili */ int countUpDown = 0; //il conteggiatore UP E DOWN int lastcountUpDown = 0; //riporter? l'ultimo stato di up e down int statoUp = 0; // stato del pulsante UP, inizialmente non premuto int statoDown = 0; //stato del pulsante DOWN, inizialmente non premuto /* ************ DA QUI INIZIANO LE VARIABILI PER LA GESTIONE DEL VALORE DI RIFERIMENTO - script byhttp://forum.arduino.cc/index.php?topic=215295.0!! */ byte button1=0; byte oldbutton1=0; byte button2=0; byte oldbutton2=0; int settemp = 20; byte button3=0; byte oldbutton3=0; byte button4=0; byte oldbutton4=0; int setpower = 0; int convertipotenza; /* ****** FINE DELLE VARIABILI PER LE IMPOSTAZIONI DELLE TEMPERATURE DI RIFERIMENTO *****/ /* andiamo adesso a sviluppare il setup, cio? a definire i pin entrata e uscita, avviare la lettura seriale etc. */ void setup() { lcd.init(); lcd.backlight(); lcd.setCursor(4,0); lcd.print("Mykooler"); lcd.setCursor(4,1); lcd.print("Vers.1.2"); delay (2000); lcd.clear(); lcd.print("Proj:M.Lavino"); lcd.setCursor(0,1); lcd.print("Dev:F.Mortari"); delay (2000); lcd.clear(); Serial.begin(9600); /* SETUP TEMPERATURA */ temperatura = senstemp.getTemp(); //diciamo che Val_Adc dovr? ospitare i dati letti dal pin analogico (0) per la temp. /* SETUP AUTOMODE */ pinMode (AutoMode, INPUT); //stabilitamo che il pin del pulsante automoed deve attendersi un segnale di input pinMode (AutoLed, OUTPUT); //stabiliamo che il pin del pulsante autoled deve fornire corrente per il led /* SETUP PULSANTI UP E DOWN */ pinMode (buttonUp, INPUT); //stabiliamo che il pin del pulsante UP ? un input e quindi arduino dovr? attendersi un segnale in entrata pinMode (buttonDown, INPUT); //stabiliamo che il pin del pulsante DDOWN ? un input e quindi arduino dovr? attendersi un segnale in entrata /* SETUP PARTE PELTIER */ pinMode (plt, OUTPUT); // siccome la peltier viene comandata da un mosfet che varia il suo stato in base al segnale in entrata, il pin peltier dovr? fornire corrente. } /* adesso andiamo nei blocchi di istruzioni. La prima cosa che vorrei fare ? attendere che qualcuno pigi sul pulsante AUOTMODE e creare i CASE con i blocchi di codice. */ void loop(){ // verifico se Myke ha premuto il pulsante if (digitalRead(AutoMode)) {delay(50); //circuito di attesa di 15ms dopodich? vado a modificare lo stato del bottone autoMode che avevo gi? dichiarato if (LastStatoAutoMode == 0) LastStatoAutoMode = 1; //se l'ultimo stato bottone ? = 0, lo fai diventare 1) else LastStatoAutoMode = 0; if ( CountAutoMode <= 0 ) CountAutoMode = CountAutoMode +1; else CountAutoMode = 0;} /* inizio a dichiarare i due casi: automode On e automode Off */ switch (CountAutoMode) /* NOTA...DA QUI INIZIA IL CASE 1 - DEFINITO AUTOMODE) */ {/*default: digitalWrite (AutoLed, LOW); lcd.print("MODE CHOOSE"); delay(1000); lcd.clear(); break;*/ case 1: digitalWrite (AutoLed, HIGH); /* DA qui iniziano le variabili per i pulsanti up e down rispettivamente ai pin 4 e 5 */ delay (50); /* inizio codice di aumento della variabile settemp */ // ciclo di controllo del pulsante che incrementa il valore settemp button1 = digitalRead(buttonUp); if ((button1 != oldbutton1) && (oldbutton1 == LOW)) //il pulsante e' appena stato premuto { delay(50); //debounce // oldbutton1 = button1; //porta oldbutton1 = button1 (previene cicli ripetitivi) settemp++; if (settemp > 50) {settemp = 0;} } if ((button1 != oldbutton1) && (oldbutton1 == HIGH)) //il pulsante e' appena stato rilasciato { delay(50); //debounce, non indispensabile se e' presente una rete RC oldbutton1 = button1; //porta oldbutton1 = button1 (previene cicli ripetitivi) } //ciclo di controllo del pulsante che decrementa button2 = digitalRead(buttonDown); //legge lo stato del pulsante 2 if ((button2 != oldbutton2) && (oldbutton2 == LOW)) // il pulsante e' appena stato premuto { delay(50); //debounce //oldbutton2 = button2; //porta oldbutton2 = button2 (previene cicli ripetitivi) settemp--; if (settemp <-25) {settemp = 0;} } if ((button2 != oldbutton2) && (oldbutton2 == HIGH)) //il pulsante e' appena stato rilasciato { delay(50); //debounce oldbutton2 = button2; //porta oldbutton2 = button2 (previene cicli ripetitivi) } /* inizio codice peltier */ { //if(Serial.available() > 0) temperatura = senstemp.getTemp(); difftemp = temperatura - settemp; //option = Serial.read(); if (difftemp > 0.7) power = 99 ; else if ((difftemp < 0.69) && (difftemp >0.3)) power = 75; else if ((difftemp <0.29) && (difftemp >0)) power = 50; else if ((difftemp <0) && (difftemp >-1)) power = 15; else if (difftemp <-1) power = 0; if(power > 99) power = 99; if(power < 0) power = 0; peltier_level = map(power, 0, 99, 0, 255); } Serial.print("Power="); Serial.print(power); Serial.print(" Temperatura="); Serial.print(temperatura); Serial.print("difftemp"); Serial.println (difftemp); lcd.print ("T=:"); lcd.print (temperatura); lcd.print (" C"); lcd.setCursor(0,1); lcd.print("Pwr:"); lcd.print (power); lcd.print (" %"); lcd.setCursor(12,0); lcd.print ("Auto"); lcd.setCursor(9,1); lcd.print ("Set.T"); lcd.setCursor(13,1); lcd.print(settemp); analogWrite(plt, peltier_level); delay(200); lcd.clear(); break; /* NOTA...DA QUI INIZIA IL CASE 1 - DEFINITO MANUAL) */ default : temperatura = senstemp.getTemp(); digitalWrite (AutoLed, LOW); //lcd.print ("MANUAL MODE"); { //if(Serial.available() > 0) /* *** DA QUI INCOMINCIANO LE CONDIZIONI PER PWR MANUAL *** */ delay (50); /* inizio codice di aumento della variabile settemp */ // ciclo di controllo del pulsante che incrementa il valore settemp button3 = digitalRead(buttonUp); if ((button3 != oldbutton3) && (oldbutton3 == LOW)) //il pulsante e' appena stato premuto { delay(50); //debounce oldbutton3 = button3; //porta oldbutton1 = button1 (previene cicli ripetitivi) setpower++; if (setpower > 4) {setpower = 4;} } if ((button3 != oldbutton3) && (oldbutton3 == HIGH)) //il pulsante e' appena stato rilasciato { delay(50); //debounce, non indispensabile se e' presente una rete RC oldbutton3 = button3; //porta oldbutton1 = button1 (previene cicli ripetitivi) } //ciclo di controllo del pulsante che decrementa button4 = digitalRead(buttonDown); //legge lo stato del pulsante 2 if ((button4 != oldbutton4) && (oldbutton4 == LOW)) // il pulsante e' appena stato premuto { delay(50); //debounce oldbutton4 = button4; //porta oldbutton2 = button2 (previene cicli ripetitivi) setpower--; if (setpower <0) {setpower = 0;} } if ((button4 != oldbutton4) && (oldbutton4 == HIGH)) //il pulsante e' appena stato rilasciato { delay(50); //debounce oldbutton4 = button4; //porta oldbutton2 = button2 (previene cicli ripetitivi) } /* inizio codice peltier */ if (setpower == (0)) power = 0; else if (setpower == (1)) power = 25; else if (setpower == (2)) power = 50; if (setpower == 3) power = 75; if (setpower == 4) power = 99; //power = setpower; if(power > 99) power = 99; if(power < 0) power = 0; peltier_level = map(power, 0, 99, 0, 255); } lcd.setCursor(0,0); lcd.print ("Manual"); lcd.setCursor(9,0); lcd.print ("T:"); lcd.print (temperatura); lcd.setCursor(0,1); lcd.print("Pwr:"); lcd.print (power); lcd.print ("%"); lcd.setCursor(9,1); lcd.print ("SetP="); lcd.print (setpower); Serial.print(setpower); Serial.print("-"); Serial.println(power); analogWrite(plt, peltier_level); //Write this new value out to the port delay(200); lcd.clear(); break; /* lcd.print (temperatura); lcd.print ("C"); lcd.setCursor(0,1); lcd.print("Pwr:"); lcd.print (power); lcd.print (" %"); lcd.setCursor(10,0); lcd.print ("Manual"); lcd.setCursor(12,1); lcd.print ("Set.P"); Serial.print("Automode"); Serial.println (": Automode Off"); /* NOTA...DA QUI INIZIA IL CASE 1 - DEFINITO MANUAL) */ } }
LINK DOWNLOAD FIRMWARE ARDUINO
Pronti a stampare il PCB che rilascerò al prossimo intervento? Ne costruiremo uno insieme, per cui dotatevi del seguente materiale:
- tester
- bromografo, cloruro ferrico, soda caustica
- trapano con punta da 0,8mm
- saldatore, stagno, succhiastagno
- cavetteria varia
- buona pazienza.
Ciao sto realizzando il vostro progetto con la cella di Peltier,
purtroppo ho dei problemi con lo sketch, nel senso che mi si blocca nella verifica, e quindi non riesco a caricarlo su arduino. Mi potreste aiutare???
Grazie