Articoli

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):

  1. prevede la lettura della temperatura ma non ha influenza sul funzioamento,
  2. scrive su LCD “Manual” 
  3. pulsanti vanno ad integrare o diminuire la potenza erogata per step di 25%

CASO UNO (AutoMode)

  1. Prevede la lettura della temperatura e ne fa una comparazione con la variabile Set Temp impostata
  2. Scrive su LCD “Auto”
  3. I pulsanti vanno ad integrare o diminuire la temperatura settata in un range da +25 a -20 °C
  4. 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:

  1. tester
  2. bromografo, cloruro ferrico, soda caustica
  3. trapano con punta da 0,8mm
  4. saldatore, stagno, succhiastagno
  5. cavetteria varia
  6. buona pazienza.