To be able to test my DHT library in an easy way I decided to write a DHT simulator a few weeks ago.
This weekend I found some time to read through the specs and wrote the sketch below
I used two potmeters:
one to simulate humidity 0.0 ... 100.0 %
one to simulate temperature -20.0 ... 184.6 C
You can use this code (small changes) to create a virtual DHT22 sensor based upon any other temperature sensor - analog or digital e.g. LM35, thermocouple, DHT11 + DS18B20 etc. Even non-temperature sensors - e.g. flex-sensor and a bi-metal; pressure-sensor or volume sensor - and some physics formula's can be used to create virtual temperature sensors.
The code is tested on an UNO and a Duemilanove 16 MHZ - connect datapin & GND - and has run for several hours now without flaws.
I am especially interested if anyone can confirms it works on a ATTINYxx (for making virtual DHT22's with e.g analog sensors)
Use the code at your own risk, have fun, and as always remarks and ideas are welcome!
//
// FILE: DHT_simulator.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.01
// PURPOSE: simulator to test DHT lib
// DATE: 2014-06-14
// URL:
//
// Released to the public domain
//
// TODO
// - robustness
// - timeout loops
const int dataPin = 5;
byte b[5];
void setup()
{
Serial.begin(115200);
Serial.print("Start ");
Serial.println(__FILE__);
pinMode(dataPin, INPUT_PULLUP);
}
void loop()
{
// T = -200 .. 1800
analogRead(A2);
int T = analogRead(A2) * 2 - 200;
// H = 0 .. 1000
analogRead(A0);
int H = analogRead(A0);
if (H > 1000)
{
H = 1000;
}
// Serial.print(H);
// Serial.print("\t");
// Serial.println(T);
// WAKE UP SIGNAL DETECTED
if (digitalRead(dataPin) == LOW)
{
uint32_t start = micros();
// wait until signal goes high
// todo timeout on blocking loop
while (digitalRead(dataPin) == LOW)
{
if (micros() - start > 1500) return;
}
if (micros() - start > 500) // serious request...
{
DHTsend(H, T);
Serial.print(H);
Serial.print("\t");
Serial.println(T);
}
}
}
void DHTsend(int H, int T)
{
pinMode(dataPin, OUTPUT);
// SEND ACK
digitalWrite(dataPin, LOW);
delayMicroseconds(80); // 80 us
digitalWrite(dataPin, HIGH);
delayMicroseconds(80); // 80 us
// PREPARE DATA
b[0] = H / 256;
b[1] = H & 255;
b[2] = 0;
if (T < 0)
{
T = -T;
b[2] = 0x80;
}
b[2] |= T / 256;
b[3] = T & 255;
// CRC
b[4] = b[0] + b[1] + b[2] + b[3];
// SEND DATA
for (int i = 0; i < 5; i++)
{
DHTsendbyte(b[i]);
}
// END OF TRANSMISSION SIGNAL
digitalWrite(dataPin, LOW);
delayMicroseconds(50); // 50 us
pinMode(dataPin, INPUT_PULLUP);
// DEBUG
// for (int i = 0; i < 5; i++)
// {
// Serial.print(b[i]);
// Serial.print(" ");
// }
// Serial.println();
}
// timing manual tuned
void DHTsendbyte(byte b)
{
byte mask = 128;
for(int i = 0; i < 8; i++)
{
digitalWrite(dataPin, LOW);
delayMicroseconds(45); // 50 us
digitalWrite(dataPin, HIGH);
if (b & mask) delayMicroseconds(60); // 70 us
else delayMicroseconds(24); // 26 us
mask >>= 1;
}
}
to be continued.