Hi I know there are plenty of DHT libraries available to use, but I need to build mine for being able to port it to other embedded systems, the thing is that I can't seem to understand this one wire communication protocol.
I understand that the DHT sends 40 bits, but before you need to negative pulse of at least 1 ms for it to notice you are polling data.
Before the data transmission begins the aduino should recieve a logic low of 80 us followed by a logic high of 80 us. This is where it gets all wrong, because I am getting a pulses of around 300 us. Can someone point me to a datasheet that is actually translated? Can someone explain a little bit more about this protocol?
cheche_romo:
Can someone point me to a datasheet that is actually translated?
Google "DHT22 datasheet". Click on first link.
Why not start with the existing libraries when building your own?
I have read the datasheet, I have also used the libraries and got it to work, the thing I don't understand is why when I try implementing it, timings are off from the datasheet but the library get's it to work.
Well, based on the information given all I can say about this is "you're probably doing something wrong".
You probably best post this question on a forum that deals with these other embedded systems, as it doesn't make sense anyway for you to try and implement it on AVR first, if that's not your actual target.
Arduino is also a target, this is a cross platform library I am building, the reason to write these libraries again is to create the same API for al the devices I intend to use, I prefer to later on add or edit some lines on these libraries that having to deal with n separate libraries to achieve something, these libraries will enable classes with a higher level on abstraction and with portability between embedded systems. But I think this is way of topic from the question.
Where can I find some good documentation for these DHT sensors? If possible of the AM2302 specifically.
Everything you need to know is in the datasheet... Mind that the DHT11 and DHT22 use a slightly different protocol.
So I finally got it to work, I will share my code in case anyone in the future is trying the same, the thing with the datasheet is that it specifies some timing in microseconds, but the device does not actually need to measure the microseconds, the important thing is the relative timing to the previous low pulse, so I implemented it with a counter, counted all the times and then rebuild the data.
#define PIN 19
void setup() {
// put your setup code here, to run once:
pinMode(18,OUTPUT);
digitalWrite(18,HIGH);
pinMode(20,OUTPUT);
digitalWrite(20,LOW);
pinMode(21,OUTPUT);
digitalWrite(21,LOW);
Serial.begin(115200);
pinMode(PIN,INPUT_PULLUP);
delay(2000);
}
uint32_t last_read = 0;
float T = NAN;
float RH = NAN;
uint8_t DataPolling();
static constexpr uint8_t NoError = 0;
static constexpr uint8_t Error1 = 1;
static constexpr uint8_t Error2 = 2;
static constexpr uint8_t Error3 = 3;
static constexpr uint8_t Error4 = 4;
static constexpr uint8_t Error5 = 5;
void loop() {
// put your main code here, to run repeatedly:
if(digitalRead(PIN))
{
if(millis() - last_read > 2000 || last_read == 0)
{
last_read = millis();
uint8_t read_state = DataPolling();
switch(read_state)
{
case NoError:
{
}
break;
case Error1: Serial.println("Device did not ack initial signal"); break;
case Error2: Serial.println("Sync Error, Low state too long."); break;
case Error3: Serial.println("Sync Error, High state too long."); break;
case Error4: Serial.println("Checksum error"); break;
default: break;
}
}
}
}
uint8_t DataPolling()
{
pinMode(PIN,OUTPUT);
digitalWrite(PIN,0);
delayMicroseconds(1100);
pinMode(PIN,INPUT_PULLUP);
// Wait maximum 200 ms for device to acknowlegde the start signal
uint32_t T = micros();
while(digitalRead(PIN))
{
if(micros()-T>200)
{
return Error1;
}
}
// measure low time, it must be 80 ms, wait max 85 ms
T = micros();
while(digitalRead(PIN) == 0)
{
if(micros()-T>85)
{
return Error2;
}
}
// measure high time, it must be 80 ms, wait max 85 ms
T = micros();
while(digitalRead(PIN) == 1)
{
if(micros()-T>85)
{
return Error3;
}
}
// Read 40 bits
uint32_t Times[80];
uint8_t count = 0;
bool state = 0;
uint32_t counter = 0;
while(count<80)
{
while(digitalRead(PIN) == state){counter++;}
state = !state;
Times[count] = counter;
count++;
counter = 0;
}
uint8_t buffer[5] = {0,0,0,0,0};
for(uint8_t i = 0; i < 40; i++)
{
if(Times[(2*i)]<Times[(2*i)+1])
{
buffer[i/8] |= (1u<<(7-(i%8)));
}
}
if(((buffer[0] + buffer[1] + buffer[2] + buffer[3]) & 0xFF) == buffer[4])
{
return NoError;
}
return Error4;
}
That code uses close to 350 bytes of RAM! I'm sure that can be done much more efficiently. That's a LOT of memory for a microcontroller. Most of the ATtiny chips for starters won't be able to run this due to lack of memory.