martedì 21 febbraio 2017

Temperatura e umidità con pic16F886 e DHT22

Temperatura e umidità con pic16F886 e DHT22

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 componenti
scheda madre lato piste
scheda madre lato piste


sensore con scheda lato componenti
sensore con scheda lato componenti


sensore con scheda lato piste
sensore con scheda lato piste


sensore su scheda
sensore su scheda


LCD e scheda
LCD e scheda


LCD collegato alla scheda
LCD collegato alla scheda


progetto funzionale pic16f886 dht22 lcd
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();
     }
}