Il progetto consiste nel rilevare temperatura e umidità relativa (RH) dell’ambiente circostante.
Il microcontrollore PIC16F886 dialoga con il sensore DHT22 e visualizza le due grandezze sul
display LCD 16x2.
Senza soffermarsi sulle caratteristiche dei due componenti principali, verranno di seguito descritti
lo schema elettrico e il codice caricato sul microcontrollore.
Partiamo dallo
schema elettrico
Tutti i particolari descritti in seguito, necessari alla realizzazione del circuito, si possono facilmente
reperire:
Le due resistenze (10kΩ, 100Ω) servono per resettare il micro.
Il diodo 1N4148 entra in gioco quando usiamo ICSP.
I cinque condensatori da 100nF filtrano i disturbi provenienti dall’alimentazione.
Il clock è generato dall’oscillatore interno impostato a 8Mhz. Questa soluzione permette di
risparmiare tre componenti (il quarzo da 8 Mhz e i due condensatori da 22pF) e guadagnare due pin I/O.
Il modulo LCD (controller HD44780) è collegato al micro con un BUS a 6 fili. La resistenza da 100Ω
limita la corrente per il circuito di retroilluminazione e il trimmer da 10kΩ si occupa di regolare
il contrasto.
Il sensore DHT22 è collegato al micro con un solo filo e la resistenza di pull-up da 4,7kΩ garantisce
“l’uno logico” sulla linea dati.
Come si nota dallo schema non è previsto nessun circuito d’alimentazione, infatti è possibile alimentare
tutto tramite la porta USB del PC. Questa scelta deriva da un possibile ampliamento del progetto
(comunicazione col PC).
scheda madre lato componenti |
scheda madre lato piste |
sensore con scheda lato componenti |
sensore con scheda lato piste |
sensore su scheda |
LCD e scheda |
LCD collegato alla scheda |
progetto funzionante |
Finalmente siamo arrivati alla parte più importante del progetto....... , la creazione del codice
che darà vita all'hardware.
Il firmware è stato realizzato con mikroc pro ed è stato caricato sul pic utilizando il programmatore
PICKIT3 e come software MPLAB IPE.
Ecco il codice:
/*******************************************************************************
MCU : pic16f886
osc : oscillatore interno impostato a 8 Mhz
realizzato da : Ciro Marinelli
data : 19/12/2016
NOTE:
*******************************************************************************/
//*****configura connessioni LCD************************************************
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
//*****configura connessioni sensore********************************************
sbit Data at RA5_bit;
sbit DataDir at TRISA5_bit;
//*****dichiarazione variabili globali******************************************
unsigned char Check, T_byte1, T_byte2, RH_byte1, RH_byte2, Ch ;
unsigned int Temp, RH, Sum, n=0 ;
//*****funzione inizio comunicazione col sensore********************************
void StartSignal()
{
DataDir = 0; // imposta RA5 come output
Data = 0; // imposta RA5 a zero
Delay_ms(20); // attendi 20 millisecondi
Data = 1; // imposta RA5 a uno
Delay_us(30); // attendi 30 microsecondi
DataDir = 1; // imposta RA5 come input
}
//*****funzione risposta sensore************************************************
void CheckResponse()
{
Check = 0;
delay_us(40);
if (Data == 0)
{
delay_us(80);
if (Data == 1)
{
Check = 1;
delay_us(40);
}
}
}
//*****funzione leggi dati******************************************************
char ReadData()
{
char i, j;
for(j = 0; j < 8; j++)
{
while(!Data); //Attendo che PORTA.F5 va alto
delay_us(30);
if(!Data)
{
i&= ~(1<<(7 - j));
}
else
{
i|= (1 << (7 - j));
while(Data); //Attendo che PORTA.F5 va basso
}
}
return i;
}
//*****funzione DHT22***********************************************************
void DHT22(void)
{
StartSignal();
CheckResponse();
if(Check == 1)
{
RH_byte1 = ReadData();
RH_byte2 = ReadData();
T_byte1 = ReadData();
T_byte2 = ReadData();
Sum = ReadData();
if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF))
{
Temp = T_byte1;
Temp = (Temp << 8) | T_byte2;
RH = RH_byte1;
RH = (RH << 8) | RH_byte2;
if(n)
{
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
n=0;
}
Lcd_Out(1, 2, "Temp : . C ");
Lcd_Out(2, 2, "RH : . % ");
if (Temp > 0X8000) // verifico se la temperatura è negativa
{
Lcd_Out(1, 8, "-");
Temp = Temp & 0X7FFF;
}
LCD_Chr(1, 9, 48 + ((Temp / 100) % 10));
LCD_Chr(1, 10, 48 + ((Temp / 10) % 10));
LCD_Chr(1, 12, 48 + (Temp % 10));
LCD_Chr(1, 14, 223);
LCD_Chr(2, 9, 48 + ((RH / 100) % 10));
LCD_Chr(2, 10, 48 + ((RH / 10) % 10));
LCD_Chr(2, 12, 48 + (RH % 10));
}
else
{
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, "Check sum error");
n=1;
}
}
else
{
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1, 1, "il sensore");
Lcd_Out(2, 1, "non risponde");
n=1;
}
delay_ms(2000);
}
//*****funzione impostazioni iniziali PIC***************************************
void init_pic(void)
{
OSCCON = 0X70; // imposto l'oscillatore interno a 8MHz
trisa = 0x00; // imposta porta come output
trisb = 0x00; // imposta portb come output
trisc = 0x00; // imposta portc come output
porta = 0x00; // azzera porta
portb = 0x00; // azzera portb
portc = 0x00; // azzera portc
ansel=0x00; // disabilito gli ingressi analogici
anselh=0x00; //
c1on_bit=0x00; // disabilito i comparatori
c2on_bit=0x00; //
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
delay_ms(2000);
}
//*****funzione principale******************************************************
void main()
{
init_pic();
while(1)
{
DHT22();
}
}