|
|
View previous topic :: View next topic |
Author |
Message |
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
Problem with DHT11 humidity and temp measurement |
Posted: Fri May 02, 2014 12:39 am |
|
|
I have interfaced DHT11 humidity and temp sensor with pic microcontroller.
Controller used: 16F690. Compiler ver: 4.114. Oscillator: internal oscillator 4Mhz
Below is the code:
main.c
Code: | #include "16F690.h"
#fuses INTRC_IO
#use delay(clock=4000000)
#define DHT_IO PIN_C0
#define RS PIN_B4
#define RW PIN_B6
#define EN PIN_A4
int1 bExit;
unsigned int8 iByteIndex;
unsigned int16 CRC;
unsigned int Humidity;
unsigned int Temperature;
unsigned char DHT_Data[];
void lcd_init();
void lcd_cmd(unsigned char c);
void lcd_data(unsigned char z);
void disp_cmd(unsigned char cmd_value);
void disp_data(unsigned char data_value);
#int_rtcc
void Set_Enable()
{
// This function is called every time Timer0 overflows (255->0). Timer0 is setup
// so that this occurs approx. 15 times per second, or once every 66mS.
if (!bExit)
bExit = True;
}
void DHT_Start(void)
{
// Here we send the 'start' sequence to the DHT sensor! We pull the DHT_IO pin low for 25mS, and
// then high for 30mS. The DHT sensor then responds by pulling the DHT_IO pin low, and then pulling it
// back high.
Output_low(DHT_IO);
delay_ms(25);
Output_high(DHT_IO);
delay_us(30);
// Here we wait while the DHT_IO pin remains low.....
bExit = False;
set_timer0(0);
while (!input(DHT_IO) && !bExit);
// Here we wait while the DHT_IO pin remains high.....
bExit = False;
set_timer0(0);
while (input(DHT_IO) && !bExit);
}
int8 DHT_ReadData(void)
{
// This subroutine reads a byte of data (8 bits) from the DHT sensor...
int8 iIndex;
int8 iValue = 0;
for(iIndex = 0; iIndex < 8 ; iIndex++)
{
bExit = False;
set_timer0(0);
while (!input(DHT_IO) && !bExit);
delay_us(30);
if (input(DHT_IO))
{
iValue = iValue |(1<<(7 - iIndex));
bExit = False;
set_timer0(0);
while (input(DHT_IO) && !bExit);
}
}
return iValue;
}
void main()
{
setup_comparator(NC_NC_NC_NC);
SETUP_ADC(ADC_OFF);
SETUP_CCP1(CCP_OFF);
setup_timer_0(T0_internal | T0_8_bit);
set_timer0(0);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
lcd_init();
disp_cmd(0x80);
printf(disp_data, "Humidity ");
disp_cmd(0xC0);
printf(disp_data, "Measurement ");
delay_ms(2000);
disp_cmd(0x01);
while(1)
{
// Here we send the initialization sequence to "wake up" the DHT sensor, and put it into
// data transmission mode.
DHT_Start();
// Here we read a total of 5 bytes of data (40 bits) from the DHT sensor. For the DHT-11 sensor,
// the integer data is contained in the 1st (Humidity), and 3rd (Temperature) bytes transmitted,
// and the 2nd and 4th decimal bytes are always zero (0). For the DHT-22 sensor, the integer data is
// is contained in the 1st (Humidity), and 3rd (Temperature) bytes transmitted, and the decimal
// data is contained in the 2nd (Humidity), and 4th (Temperature) bytes transmitted. The 5th byte
// contains the CRC byte for both sensor types.
for (iByteIndex = 0; iByteIndex < 5 ; iByteIndex++)
{
DHT_Data[iByteIndex] = DHT_ReadData();
}
// Here we calculate the CRC by adding the 1st four bytes, and looking at only the lower 8 bits.
// This value should match the 5th byte sent by the sensor which is the CRC byte!
CRC = DHT_Data[0] + DHT_Data[1] + DHT_Data[2] + DHT_Data[3];
CRC = CRC & 0xFF;
if (CRC != DHT_Data[4] && !bExit)
// fprintf(PC, "CRC Error, expected: %Lu, and received: %u\n\r", CRC, DHT_Data[4]);
Humidity = DHT_Data[0];
Temperature = DHT_Data[2];
disp_cmd(0xC0);
printf(disp_data, "Humidity: %2u %%", Humidity);
delay_ms(5000);
//fprintf(PC, "Humidity: %ld%%\n\r", Humidity);
//fprintf(PC, "Temperature: %ldC\n\r", Temperature);
}
}
void lcd_init()
{
disp_cmd(0x02); // To initialize LCD in 4-bit mode.
disp_cmd(0x28); // To initialize LCD in 1 lines, 5x7 dots and 4bit mode.
disp_cmd(0x0C);
disp_cmd(0x01);
disp_cmd(0x06);
disp_cmd(0x80);
}
void lcd_cmd(unsigned char c)
{
output_c(c);
output_low(RS);
output_low(RW);
output_high(EN);
delay_ms(15);
output_low(EN);
}
void lcd_data(unsigned char z)
{
output_c(z);
output_high(RS);
output_low(RW);
output_high(EN);
delay_ms(15);
output_low(EN);
}
void disp_cmd(unsigned char cmd_value)
{
unsigned char cmd_value1;
cmd_value1=(cmd_value & 0xF0);
lcd_cmd(cmd_value1); // Send to LCD
cmd_value1 = ((cmd_value<<4) & 0xF0); // Shift 4-bit and mask
lcd_cmd(cmd_value1); // Send to LCD
}
void disp_data(unsigned char data_value)
{
unsigned char data_value1;
data_value1=(data_value & 0xF0);
lcd_data(data_value1);
data_value1 = ((data_value<<4) & 0xF0);
lcd_data(data_value1);
} |
When i power up, it displays humidity measurement for 2 secs and then it displays Humidity: 0%. Why it is not displaying humidity values.
I'm testing in the real hardware. To show the circuit, i have drawn the circuit in proteus and shown here
https://imageshack.com/i/nelh1qwj
Please help |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 02, 2014 12:44 am |
|
|
Quote: | unsigned char DHT_Data[]; |
The error is in the line above. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri May 02, 2014 12:48 am |
|
|
Code: | unsigned char DHT_Data[4];
|
Will it solve my problem? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 02, 2014 1:01 am |
|
|
Quote: | unsigned char DHT_Data[4];
Will it solve my problem?
for (iByteIndex = 0; iByteIndex < 5 ; iByteIndex++)
{
DHT_Data[iByteIndex] = DHT_ReadData();
}
|
You are using array indexes from 0 to 4. That's 5 elements.
So you still have a problem.
You are writing code for a driver, which is at least an intermediate topic.
I'm not trying to beat up on you, but this array stuff should have been
learned a long time ago. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri May 02, 2014 1:03 am |
|
|
I got it now,
Code: | unsigned char DHT_Data[5]; |
Hope now its ok |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri May 02, 2014 7:27 am |
|
|
When i changed to
Code: | unsigned char DHT_Data[5] |
Display always shows 253% all the time.
What could be the problem? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 02, 2014 8:39 am |
|
|
Quote: | #include "16F690.h"
#fuses INTRC_IO
#use delay(clock=4000000)
#int_rtcc
void Set_Enable()
{
// This function is called every time Timer0 overflows (255->0). Timer0 is setup
// so that this occurs approx. 15 times per second, or once every 66mS.
if (!bExit)
bExit = True;
} |
Quote: |
setup_timer_0(T0_internal | T0_8_bit);
|
Quote: | 5.0 TIMER0 MODULE
The Timer0 module is an 8-bit timer/counter.
There are 8 prescaler options for the Timer0 module
ranging from 1:2 to 1:256.
|
Timer0 is clocked at Fosc/4, which is 1 MHz for your program.
To get an interrupt rate of 15 Hz, you would need to do this:
1 MHz / 65536 = 15 Hz (approx.)
But your Timer0 setup doesn't have a prescaler of T0_DIV_256.
It's missing that parameter:
Quote: |
setup_timer_0(T0_internal | T0_8_bit);
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri May 02, 2014 8:41 am |
|
|
A couple of things to think about, related to the timer....
Code: |
bExit = False;
set_timer0(0);
|
What happens if the timer times out between the two instructions?. 1 in 256 probability of this happening (with the current timer programming), and if it does bExit will immediately be TRUE.
You need to set the timer to zero _before_ clearing BExit.
Then your timing is wrong.
You have the timer programmed to use 8bit, and it counts from Fosc/4. The timer will interrupt 3906 times per second, not 15 times per second. BExit is always going to get set TRUE before the line changes. To give 15* per seocnd, you need the /256 prescaler selected. Then it'll give 1000000/(256*256) = 15.25* per second.
setup_timer_0(T0_INTERNAL | T0_8_BIT | T0_DIV_256); |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Fri May 02, 2014 8:43 am |
|
|
Hi,
Quote: | 'What could be the problem?' |
That is kind of an open-ended question, don't you think? It could be any number of problems!
Did you change anything else in your code? You definitely need the 5 elements in your array, so that should not cause your issue! Post any other changes you've made!
Your posted code appears to be based on some DHT11 driver code that I posted a while back. You seem to have made a number of key changes that have disabled that (working) code? You appear to be a bit of a 'newbie' programmer lacking in a lot of basic 'C' programming knowledge', so I'm wondering what motivated you to try to 'improve' the working code?
John |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri May 02, 2014 9:46 pm |
|
|
I didn't change another other part of the code.
Yes ezflyr, I'm using your library to display the humidity on lcd.
my complete code:
Code: | #include "16F690.h"
#fuses INTRC_IO
#use delay(clock=4000000)
#define DHT_IO PIN_C0
#define RS PIN_B4
#define RW PIN_B6
#define EN PIN_A4
int1 bExit;
unsigned int8 iByteIndex;
unsigned int16 CRC;
unsigned int16 Humidity;
unsigned int16 Temperature;
unsigned int16 DHT_Data[5];
void lcd_init();
void lcd_cmd(unsigned char c);
void lcd_data(unsigned char z);
void disp_cmd(unsigned char cmd_value);
void disp_data(unsigned char data_value);
#int_rtcc
void Set_Enable()
{
// This function is called every time Timer0 overflows (255->0). Timer0 is setup
// so that this occurs approx. 15 times per second, or once every 66mS.
if (!bExit)
bExit = True;
}
void DHT_Start(void)
{
// Here we send the 'start' sequence to the DHT sensor! We pull the DHT_IO pin low for 25mS, and
// then high for 30mS. The DHT sensor then responds by pulling the DHT_IO pin low, and then pulling it
// back high.
Output_low(DHT_IO);
delay_ms(25);
Output_high(DHT_IO);
delay_us(30);
// Here we wait while the DHT_IO pin remains low.....
bExit = False;
set_timer0(0);
while (!input(DHT_IO) && !bExit);
// Here we wait while the DHT_IO pin remains high.....
bExit = False;
set_timer0(0);
while (input(DHT_IO) && !bExit);
}
int8 DHT_ReadData(void)
{
// This subroutine reads a byte of data (8 bits) from the DHT sensor...
int8 iIndex;
int8 iValue = 0;
for(iIndex = 0; iIndex < 8 ; iIndex++)
{
bExit = False;
set_timer0(0);
while (!input(DHT_IO) && !bExit);
delay_us(30);
if (input(DHT_IO))
{
iValue = iValue |(1<<(7 - iIndex));
bExit = False;
set_timer0(0);
while (input(DHT_IO) && !bExit);
}
}
return iValue;
}
void main()
{
setup_comparator(NC_NC_NC_NC);
SETUP_ADC(ADC_OFF);
SETUP_CCP1(CCP_OFF);
setup_timer_0(T0_INTERNAL | T0_8_BIT | T0_DIV_256);
set_timer0(0);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
lcd_init();
disp_cmd(0x80);
printf(disp_data, "Humidity ");
disp_cmd(0xC0);
printf(disp_data, "Measurement ");
delay_ms(2000);
disp_cmd(0x01);
while(1)
{
// Here we send the initialization sequence to "wake up" the DHT sensor, and put it into
// data transmission mode.
DHT_Start();
// Here we read a total of 5 bytes of data (40 bits) from the DHT sensor. For the DHT-11 sensor,
// the integer data is contained in the 1st (Humidity), and 3rd (Temperature) bytes transmitted,
// and the 2nd and 4th decimal bytes are always zero (0). For the DHT-22 sensor, the integer data is
// is contained in the 1st (Humidity), and 3rd (Temperature) bytes transmitted, and the decimal
// data is contained in the 2nd (Humidity), and 4th (Temperature) bytes transmitted. The 5th byte
// contains the CRC byte for both sensor types.
for (iByteIndex = 0; iByteIndex < 5 ; iByteIndex++)
{
DHT_Data[iByteIndex] = DHT_ReadData();
}
// Here we calculate the CRC by adding the 1st four bytes, and looking at only the lower 8 bits.
// This value should match the 5th byte sent by the sensor which is the CRC byte!
CRC = DHT_Data[0] + DHT_Data[1] + DHT_Data[2] + DHT_Data[3];
CRC = CRC & 0xFF;
if (CRC != DHT_Data[4] && !bExit)
// fprintf(PC, "CRC Error, expected: %Lu, and received: %u\n\r", CRC, DHT_Data[4]);
Humidity = DHT_Data[0];
Temperature = DHT_Data[2];
disp_cmd(0xC0);
printf(disp_data, "Humidity: %4lu %% ", Humidity);
delay_ms(2000);
//fprintf(PC, "Humidity: %ld%%\n\r", Humidity);
//fprintf(PC, "Temperature: %ldC\n\r", Temperature);
}
}
void lcd_init()
{
disp_cmd(0x02); // To initialize LCD in 4-bit mode.
disp_cmd(0x28); // To initialize LCD in 1 lines, 5x7 dots and 4bit mode.
disp_cmd(0x0C);
disp_cmd(0x01);
disp_cmd(0x06);
disp_cmd(0x80);
}
void lcd_cmd(unsigned char c)
{
output_c(c);
output_low(RS);
output_low(RW);
output_high(EN);
delay_ms(15);
output_low(EN);
}
void lcd_data(unsigned char z)
{
output_c(z);
output_high(RS);
output_low(RW);
output_high(EN);
delay_ms(15);
output_low(EN);
}
void disp_cmd(unsigned char cmd_value)
{
unsigned char cmd_value1;
cmd_value1=(cmd_value & 0xF0);
lcd_cmd(cmd_value1); // Send to LCD
cmd_value1 = ((cmd_value<<4) & 0xF0); // Shift 4-bit and mask
lcd_cmd(cmd_value1); // Send to LCD
}
void disp_data(unsigned char data_value)
{
unsigned char data_value1;
data_value1=(data_value & 0xF0);
lcd_data(data_value1);
data_value1 = ((data_value<<4) & 0xF0);
lcd_data(data_value1);
} |
|
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sat May 03, 2014 8:18 am |
|
|
Display reads the wrong value which is showing constantly 1997 %... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat May 03, 2014 9:15 am |
|
|
Since it's not displaying right, you have to 'break' the program into 2 parts. 'Reading the sensor' and 'displaying the data'.
For starters, I'd fix the variable 'humidity' to a valid number that you expect and see what the LCD shows.
This simple test will confirm the LCD 'driver' code is functioning properly.
Actually you should use several known values, say 0, midpoint, maximum.
recode/recompile/retest/report back.....
hth
jay |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Sat May 03, 2014 12:39 pm |
|
|
I had something to do with similar sensor RHT03.
I did read data successfully.
This is the driver:
Code: |
void RHT03_Init(void)
{
printf("\fRHT03 Initialization. . .");
delay_ms(1500); //When power is supplied to sensor, don't send any instruction to the sensor within one second to pass unstable status
printf("\fRHT03 Initialization done!");
}
void RHT_Start()
{
output_low(RHT_IO); // MCU pull low data bus this process must beyond 1~10ms
delay_ms(15); // this process must beyond 1~10ms
output_float(RHT_IO); // MCU will pulls up and wait 20-40us for RHT03's response.
while(input(RHT_IO)); // Wait for RHT03 pulls low the buss for 80uS as response signal
while(!input(RHT_IO)); // Wait for RHT03 pulls up 80us for preparation to send data
While(input(RHT_IO)); // RHT03 prepares data for being send (80uS)
}
int8 RHT_ReadData(void) //RHT03 is sending data to MCU
{
int8 iIndex;
int8 iValue=0;
for(iIndex = 0; iIndex < 8 ; iIndex++) //filling 8bit variable, bit by bit, according to RHT03 input state,
{
while(!input(RHT_IO)); // every bit's transmission begin with low-voltage-level that last 50us
delay_us(35);
shift_left(&iValue, 1, input(RHT_IO));
while(input(RHT_IO));
}
return iValue;
} |
and this is the code that handle it.
Code: |
#INCLUDE <16F1508.h>
#FUSES INTRC_IO, NOMCLR, NOWDT, PUT, NOBROWNOUT
#USE delay(internal=16M)
#USE rs232(BAUD=9600, UART1,ERRORS)
#define RHT_IO Pin_B6
#Define LED PIN_C7
#Include <C:\Users\Riko\Desktop\Leonid_Silistra\CCS\RHT-03 driver\RHT03.c>
void PrintData(int B1, int B2, int B3, int B4);
void main (void)
{
int8 i;
int8 ByteIndex[5];
RHT03_Init();
While (True)
{
RHT_Start(); //immediately after this line we must call reading of 40bits data
for (i=0;i<5;i++) //5 bytes being read in this loop
{
ByteIndex[i] = RHT_ReadData();
}
if(ByteIndex[0]+ByteIndex[1]+ByteIndex[2]+ByteIndex[3]==ByteIndex[4])
printf("\r DATA Reception Succesful!");
else
printf("\rDATA Garbage!");
PrintData(ByteIndex[0],ByteIndex[1],ByteIndex[2],ByteIndex[3]);
delay_ms(2300); //The process of data reception must last more than 2secs
}
}
void PrintData(int B1, int B2, int B3, int B4)
{
int16 humidity;
int16 temperature;
int1 TempSign; //the sign of the temperature (either minus or plus)
TempSign = bit_test(B3,7); //bit 7 determines if temerature is positive or negative, (=1-negative), (=0 positive)
humidity = make16(B1,B2); //assemble entire byte for humidity
temperature = make16(B3,B4); //assemble entire byte for humidity
temperature &= 0b0111111111111111; //exclude the sign of the temperature so I can convert it to a float value
if(TempSign) //If temperature 15th bit is==1 the temperature value is negative
printf(" T = -%.1f",(float)temperature/10); //Note that I manualy put the minus sign
else
printf(" T = %.1f",(float)temperature/10);
printf(" RH = %.1f",(float)humidity/10);
} |
_________________ A person who never made a mistake never tried anything new. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sun May 04, 2014 9:06 pm |
|
|
hi rikotech8, it displays RHT03 Initialization. . . and then,
RHT03 Initialization done! and stays there itself. |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Mon May 05, 2014 4:12 am |
|
|
Hi hemnath,
If all you can do is report the output messages from a particular program with no ability to understand what is going on, or to troubleshoot any further, then I don't think you've got any future as an embedded developer/programmer.....
Sorry!
John
Ps The driver you are now using is poorly written because there are many places it can hang without any feedback to the user at all. You need to find out where this is happening, and more importantly, why...... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|