Hot!C Code to Interface Humidity Sensor (DHT22)

Page: 123 > Showing page 1 of 3
Author
delfindelfin
Senior Member
  • Total Posts : 140
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: online
2019/04/17 08:27:29 (permalink)
0

C Code to Interface Humidity Sensor (DHT22)

This is the continuation of:  www.microchip.com/forums/m1089624.aspx . I decided to make a new post since now I am programming it in C. I have already added a Timer Interrupt to be used as a TimeOut if the Sensor is not sending a signal. But I still have issues, particulary with this line of code:
 
while (PORTCbits.RC2 != 0); // Wait until RC2 is Low 

 
It seems to be trapped in an infinite loop, it never detects PORCbits.RC2 as 0
 
Any ideas?
https://www.dropbox.com/s...50qHlgWQiG2BH5WWa?dl=0

MPLAB X IDE v5.05
XC8 2.00
#1

46 Replies Related Threads

    katela
    Super Member
    • Total Posts : 1186
    • Reward points : 0
    • Joined: 2013/06/11 05:25:18
    • Location: South Africa
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 08:34:31 (permalink)

    Free online Microcontroller Tutorials and Projects for Hobbyists and students. From beginners to advanced. Website: www.studentcompanion.co.za
    YouTube Tutorials: https://www.youtube.com/StudentCompanionSA
    #2
    jack@kksound
    code tags!
    • Total Posts : 3156
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 08:41:50 (permalink)
    0
    I suggest you post your most recent program code (in c) ALL of it.
    #3
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 08:48:52 (permalink)
    0
    This is the last code
     
    #include <string.h>
    #include <stdio.h>

    #include <stdint.h>

    // CONFIGURATION BITS
    #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
    #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
    #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
    #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)

    #define _XTAL_FREQ 8000000

    #include <xc.h>
    #include "lcd.h"

    //// Function Prototyping ///////////////////////////////////////////////////////////////////

    void initiate_humidity_sensor();
    void read_humidity_sensor();

    //// Funtion Initialization /////////////////////////////////////////////////////////////////
    void initiate_humidity_sensor()
    {
        TRISCbits.TRISC2 = 0; // RC5 as Output PIN
      
        PORTCbits.RC2 = 0;
        __delay_ms(18); // RC5 Low for 18 ms
        PORTCbits.RC2 = 1;
        __delay_us(30);
        //__delay_ms(0.03); // RC5 High for 30 us
        
        TRISCbits.TRISC2 = 1; // RC5 as Input PIN
    }

    //// Declaring Global Vaiables (Sensor Output)

    short int humid ;
    short int temp ;
    short int checksum ;

    void read_humidity_sensor()
    {

        short int j;
        
        humid = 0 ;
        temp = 0 ;
        checksum = 0 ;
        
        // Timer Interrupt ///////////////////////////////////////////////////////////////////////
      
        OPTION_REG = 4 ; // Timer0 with external freq and 32 as prescalar
        TMR0 = 250; // Load the time value for 100us delay: TMR0_RegValue = 256-((100us*8MHz)/(32*4)) = 256 - 6.25 = 249.75
        
        TMR0IE = 1; // Enable the TMR0 Interrupt:
        GIE = 1; // Enable Global Interrupt
        PEIE = 1; // Enable the Peripheral Interrupt

        while (PORTCbits.RC2 != 0); // Wait until RC2 is Low
        
        for(j=0;j<20;j+=1)
        {
           
            while (PORTCbits.RC2 != 0); // Wait until RC2 is Low
            while (PORTCbits.RC2 != 1); // Wait until RC2 is high
        
            __delay_us(30);
            
        
            if(j<16){ // Select Data Humidity
                
                humid <<= 1;
                if (PORTCbits.RC2 == 1) humid |= 1;
                
            }
            else if(j<32){ // Select Data Temperature
                if (PORTCbits.RC2 == 1){
                    temp = temp + (1 << (32 - j) );
                }
            }
            else{
                if (PORTCbits.RC2 == 1){ // Select Data Checksum
                    checksum = checksum + (1 << (8 - j) );
                }
            }
                
        }

        TMR0IE = 0; // Diable the TMR0 Interrupt
       
            
    }

    volatile uint8_t recieved_intf = 0;

    void __interrupt() timer_isr()
    {
        if(TMR0IF==1)
        {
            if(PORTCbits.RC2 == 1)
            {
                recieved_intf = 1;
            }
            
            TMR0IF=0; // Clear timer interrupt flag
        }
    }

    void main() {
        
      unsigned int a;
      TRISD = 0x00;
      
      // LCD Initiation ///////////////////////////////////////////////////////////////////////
      
      Lcd_Init();
      Lcd_Clear();
      
      while(1)
      {

        initiate_humidity_sensor();
        read_humidity_sensor();
        
        if(recieved_intf == 1)
        {
            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("Temp:");
            
            Lcd_Set_Cursor(12,1);
            Lcd_Write_Char('C');
        
            Lcd_Set_Cursor(1,2);
            Lcd_Write_String("Humi:");
        
        
            Lcd_Set_Cursor(12,2);
            Lcd_Write_Char('%');
            
        }
        else
        {
            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("No Signal");
            
        }

      
        __delay_ms(50);
                  
      }
        
    }

    post edited by delfindelfin - 2019/04/17 08:49:56

    MPLAB X IDE v5.05
    XC8 2.00
    #4
    jack@kksound
    code tags!
    • Total Posts : 3156
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 09:03:17 (permalink)
    +1 (1)
    After looking at that code my head hurts. I suggest you add LOTS of comments as what you are trying to do is a little obscure. The while() statement you have IS an infinite loop unless the RC2 (not RC5 as you have in some comments) input actually does go low. Also since that particular while() statement occurs a number of times which occurance are you asking about?
    #5
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 10:00:23 (permalink)
    0
    Oh, that is because it is the protocol of the Sensor that sends the data. I attached some images. Technically what I am doing is reading each bit sended by the sensor. The occurence is that everytime the sensor sends a bit of data, it has to go low before send it
     
     
    post edited by delfindelfin - 2019/04/17 10:05:34

    Attached Image(s)


    MPLAB X IDE v5.05
    XC8 2.00
    #6
    1and0
    Access is Denied
    • Total Posts : 8850
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 10:17:01 (permalink)
    +1 (1)
    You are just doing things aimlessly and not learning at all. Take this snippet

    for(j=0;j<20;j+=1)
    {

    while (PORTCbits.RC2 != 0); // Wait until RC2 is Low
    while (PORTCbits.RC2 != 1); // Wait until RC2 is high

    __delay_us(30);


    if(j<16){ // Select Data Humidity

    humid <<= 1;
    if (PORTCbits.RC2 == 1) humid |= 1;

    }
    else if(j<32){ // Select Data Temperature
    if (PORTCbits.RC2 == 1){
    temp = temp + (1 << (32 - j) );
    }
    }
    else{
    if (PORTCbits.RC2 == 1){ // Select Data Checksum
    checksum = checksum + (1 << (8 - j) );
    }
    }

    }

    ask yourself what are the values of j for humidity, temperature, and checksum.  In the other thread, you were shown how to insert bits into a variable efficiently, yet you are doing it for one variable here but not the other. :(
     
    #7
    pcbbc
    Super Member
    • Total Posts : 797
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 10:35:45 (permalink)
    +1 (1)
    Observations:
    1. recieved_intf is set, but never reset.
    2. It's fairly pointless configuring the timer interrupt.  Might as well just poll TMR0IF from main.
    3. I believe we already told you on the previous thread that your shifts are extremely non-performant on an 8-bit device.
    This code:
    temp = temp + (1 << (32 - j) );

    Will take many, many machine cycles to execute as it requires a loop and shifting 1 bit at a time.  Code these shifts the same way as you have humid:
    temp <<= 1;
    if (PORTCbits.RC2 == 1) temp |= 1;

    You have less than 50us to do your processing, which is only 100 machine instructions at 8MHz.  With the overhead of the ISR as well, you are probably missing edges.
    4. You seem to be reading 16 bits for both humid and temp, and 8 bits to checksum for 40 bits total.  And yet your outer loop is only: for(j=0;j<20;j+=1)?  Why?
    5. Line checksum = checksum + (1 << (8 - j) ); does not seem correct for when j >= 32!  But this should be fixed by point 3.
    6. j does not need to be a short int when you can get away with a byte.  Try uint8_t.
    post edited by pcbbc - 2019/04/17 10:37:20
    #8
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 19:54:53 (permalink)
    0
    Why do I have to declare a "volatile" before uint8_t? Why is it pointless configuring the timer interrupt? Why I can't post my whole code and the code indentations?
     


    short int humid ;
    short int temp ;
    short int checksum ;

    void Read_Humid_Sensor()
    {

    volatile uint8_t j;

    humid = 0 ;
    temp = 0 ;
    checksum = 0 ;

    // Timer Interrupt ///////////////////////////////////////////////////////////////////////

    OPTION_REG = 4 ; // Timer0 with external freq and 32 as prescalar
    TMR0 = 250; // Load the time value for 100us delay: TMR0_RegValue = 256-((100us*8MHz)/(32*4)) = 256 - 6.25 = 249.75

    TMR0IE = 1; // Enable the TMR0 Interrupt:
    GIE = 1; // Enable Global Interrupt
    PEIE = 1; // Enable the Peripheral Interrupt

    __delay_us(80); // DHT22 Responds Low for 80 uS
    __delay_us(80); // DHT22 Responds High for 80 uS

    for(j=0;j<40;j+=1)
    {

    while (PORTCbits.RC2 != 0); // Wait until RC2 is Low
    while (PORTCbits.RC2 != 1); // Wait until RC2 is high

    __delay_us(30);


    if(j<16){ // Select Data Humidity

    humid <<= 1;
    if (PORTCbits.RC2 == 1) humid |= 1;

    }
    else if(j<32){ // Select Data Temperature

    temp <<= 1;
    if (PORTCbits.RC2 == 1) temp |= 1;

    }
    else{

    checksum <<= 1;
    if (PORTCbits.RC2 == 1) checksum |= 1;

    }

    }

    TMR0IE = 0; // Diable the TMR0 Interrupt


    }

    volatile uint8_t recieved_intf = 0;

    void __interrupt() timer_isr()
    {
    if(TMR0IF==1)
    {
    if(PORTCbits.RC2 == 1)
    {
    recieved_intf = 1;
    }

    TMR0IF=0; // Clear timer interrupt flag
    }
    }



    }

     
    post edited by delfindelfin - 2019/04/17 20:16:38

    MPLAB X IDE v5.05
    XC8 2.00
    #9
    pcbbc
    Super Member
    • Total Posts : 797
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 21:00:18 (permalink)
    +1 (1)
    delfindelfinWhy do I have to declare a "volatile" before uint8_t?
    You don’t.


    You need to look up the usage of the word volatile in C.
    https://barrgroup.com/Emb...-To/C-Volatile-Keyword
    Volatile should only be necessary on variables that are shared between your interrupt code and mainline.
    It tells the compiler to check the variable every time, rather than rely on the contents it may have read previously (because an interrupt can change it at any time). Consider the following code....
    uint8_t flag;
    void main()
    {
    flag = 0;
    // wait for interrupt...
    while (flag == 0);
    // do some other stuff
    }
    Because there is no volatile the compiler may look at that, see that flag is set to zero initially and never changed, and then just optimise the while condition away. It will then just not bother with the flag == 0 test (assuming it can never be false, or using the value it read for flag into a register) and just loop forever. So even if ISR changes flag, mainline will never exit the loop.

    Why is it pointless configuring the timer interrupt?
    For a number of reasons.

    1. All it does is sets recieved_intf, and that variable is never reset anywhere in your code. So once the interrupt has fired once it can have no further actions on the mainline code (except slow it down).
    2. Even if you did reset recieved_intf, you could just as effectively poll the TMR0IF where you currently check recieved_intf for no change of functionality.
    3. The overhead of the timer interrupt is slowing down your read function, which is already fairly timing critical. An ISR every 100us could easily add 25-50 (12-25us) cycles to either your delay or loop when reading. Do you not see how that would screw up your pulse width timing or edge detection?
    4. You don’t seem to have thought about what you are actually trying to achieve with the interrupt? What do you think it is doing for you, or what do you want it to do?

    Why I can't post my whole code and the code indentations?
    Probably the flipping forum firewall. Try attaching instead.


    Good that you are asking questions. Remember there are no dumb questions.

    But as pointed out on previous thread, you need to think about what happens if there is a protocol error reading from the sensor, or no response at all? Currently your code will lockup in one of the while loops waiting for ever. How are you planning to handle that? Perhaps that was your plan (somehow) with the interrupt?
    post edited by pcbbc - 2019/04/17 21:03:17
    #10
    qhb
    Superb Member
    • Total Posts : 9625
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/17 21:57:40 (permalink)
    +1 (1)
    Why I can't post my whole code and the code indentations?

    If the code posts, but loses the indentation, that means you are using tab characters for the indentation.
    The forum software does not handle tabs, only spaces for indenting.
     
    #11
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 04:45:45 (permalink)
    0
    pcbbc All it does is sets recieved_intf, and that variable is never reset anywhere in your code.

     
    In the last code I reset recieved_intf 
     
    pcbbc What do you think it is doing for you, or what do you want it to do? 

     
    The idea of the interrupt was to check if the sensor was sending the response signal before the actual data, if it is, then we now it is connected and working, but now that I think about it, at the moment of the interrupt, may cost time and as you mention, that part of the code it is fairly timing critical, so probably I should use it in another way, or make sure that the interrupt doesn't last more than 80 us 


    But even without the interrupt, I still have problems with this:
     
     while (PORTCbits.RC2 != 0); // Wait until RC2 is Low 

     
    If I remove that line, the code doens't wait for ever. It never detects the sensor as low 
    post edited by delfindelfin - 2019/04/18 04:49:59

    MPLAB X IDE v5.05
    XC8 2.00
    #12
    qhb
    Superb Member
    • Total Posts : 9625
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 04:58:13 (permalink)
    +1 (1)
    delfindelfin
    pcbbc All it does is sets recieved_intf, and that variable is never reset anywhere in your code.

     
    In the last code I reset recieved_intf

    No you don't.
    In post#22, the only place you write zero to it is in the line the declares the variable, so it only happens once when your code starts running.
     

    pcbbc What do you think it is doing for you, or what do you want it to do? 

     
    The idea of the interrupt was to check if the sensor was sending the response signal before the actual data, if it is, then we now it is connected and working, but now that I think about it, at the moment of the interrupt, may cost time and as you mention, that part of the code it is fairly timing critical, so probably I should use it in another way, or make sure that the interrupt doesn't last more than 80 us



    So it's totally senseless to use an interrupt for the statred purpose, which is what people are trying to tell you.
     

    But even without the interrupt, I still have problems with this:
     
     while (PORTCbits.RC2 != 0); // Wait until RC2 is Low 

     
    If I remove that line, the code doens't wait for ever. It never detects the sensor as low

    There are any number of ways to work around this.
    You can count how often you loop, or set a timer to reach zero after you have waited to long, and just poll the timer overflow flag as part of your loop to see if it has expired yet.
    None of this is magic. You just have to have a clear head about what it is that you are doing.
     
    #13
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:04:11 (permalink)
    0
    There is no post#22 yet ... But you are right, I couldn't post the whole code thanks to the flipping firewall.
     
    What do you mean by "poll the timer overflow flag"? I don't understand the word poll in that context, or any other actually. English is not my native language
    post edited by delfindelfin - 2019/04/18 05:12:10

    MPLAB X IDE v5.05
    XC8 2.00
    #14
    qhb
    Superb Member
    • Total Posts : 9625
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:10:10 (permalink)
    0
    Oops, I meant post#9.
    #15
    rodims
    Super Member
    • Total Posts : 1466
    • Reward points : 0
    • Joined: 2009/02/10 11:08:59
    • Location: 51.9627, 7.6262
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:21:03 (permalink)
    #16
    delfindelfin
    Senior Member
    • Total Posts : 140
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: online
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:21:11 (permalink)
    0
    This may be off topic. But do you know any good forums about C language and Linux? Without counting Stack Overflow that is Question - Answer site

    MPLAB X IDE v5.05
    XC8 2.00
    #17
    pcbbc
    Super Member
    • Total Posts : 797
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:29:41 (permalink)
    +1 (1)
    delfindelfinWhat do you mean by "poll the timer overflow flag"? I don't understand the word poll in that context, or any other actually. English is not my native language
    Not a problem.  That must be hard.    You are doing fine.
     
    Foreign languages are not my strong point (I do try!), and I realise I am very lucky (and very lazy!) to have been born a native English speaker.


    There are 2 ways to use interrupt flags:
     
    1. Polling
    This isn't really an interrupt at all.  You don't set the interrupt enable flag (xxIE) and you don't need an ISR routine.
    You just check the interrupt flag register (xxIF) in your main code, to see if the event you are interested in has happened.  After you have detected it, clear xxIF so you can tell when the event happens again next time.
    Of course, if you do not check regularly enough, you will miss interrupts.
     
    2. As An interrupt
    Here you set the interrupt enable flag (xxIE) and have to provide ISR code to handle the interrupt.
    Under this model the processor stops whatever it is doing when the event happens (assuming GIE=1), and calls your ISR where you are expected to deal with the interrupt, and then clear xxIF.
    With this method you never* miss any events, but you have some overhead of calling the ISR etc.
    * Unless the events happen so fast that the ISR cannot finish process one before the next one occurs.
     
    You code is just using the method 2 to set a variable, which the main code uses like it could have done if it was checking the xxIF flag via "polling" as explained in method 1.
    This is pointless.  Might as well (in this example) use method 1 and be done with it.
     
    Note you can mix and match methods 1 and 2 with different interrupts according to need.
    #18
    pcbbc
    Super Member
    • Total Posts : 797
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 05:41:31 (permalink)
    +1 (1)
    delfindelfinThis may be off topic. But do you know any good forums about C language and Linux? Without counting Stack Overflow that is Question - Answer site
    Separate books?


    For C the go to reference work is always:
    The C Programming Language (2nd Edition) Paperback – 22 Mar 1988
    by Brian W. Kernighan (Author), Dennis Ritchie (Author)
     
    Linux I can't help with, sorry.
    #19
    1and0
    Access is Denied
    • Total Posts : 8850
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/18 06:30:22 (permalink)
    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2019 APG vNext Commercial Version 4.5