i ventured an implementation for DHT22 (AM2302) with a maple mini clone on libmaple core
no external pull-up resistors used
Code: Select all
#include <Arduino.h>
uint16_t pulse[80];
uint8_t data[5];
bool debug=false;
const uint8_t dht_data_pin = PB7;
uint8_t tog = 0;
bool timeout = false;
uint16_t expectPulse(uint8_t val);
void prtemp();
void timer_handler();
void dht_read();
float get_humidity();
float get_temp();
bool check_parity();
void sleep(uint16_t ms);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin();
// vrefint
adc_reg_map *regs = ADC1->regs;
regs->CR2 |= ADC_CR2_TSVREFE; // enable VREFINT and temp sensor
regs->SMPR1 = ADC_SMPR1_SMP17; // sample rate for VREFINT ADC channel
//initialise microsecond timer
Timer1.init();
Timer1.pause();
Timer1.setPrescaleFactor(72-1); // 1 us
Timer1.setOverflow(0xffff); //timeout 65.535 ms
Timer1.attachInterrupt(0, timer_handler);
Timer1.refresh();
pinMode(dht_data_pin, INPUT_PULLUP);
}
void timer_handler() {
timeout = true;
Timer1.pause();
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
sleep(100);
digitalWrite(LED_BUILTIN, LOW);
prtemp();
dht_read();
float hum = get_humidity();
float temp = get_temp();
Serial.print("dht humidity (RH%):");
Serial.println(hum);
Serial.print("dht temp (C):");
Serial.println(temp);
sleep(10000);
}
void sleep(uint16_t ms) {
for(int i=0; i<ms; i++)
asm("wfi");
}
float get_humidity() {
uint16_t hum = data[0] << 8 | data[1];
return hum / 10.0;
}
float get_temp() {
int temp = (data[2] & 0x7f) << 8 | data[3];
if(data[2] >> 7 == 1)
temp *= -1;
return temp / 10.0;
}
bool check_parity() {
uint8_t sum = data[0] + data[1] + data[2] + data[3];
return sum == data[4];
}
/* note the timings used here is based on DHT22 AM2302
*/
void dht_read() {
pinMode(dht_data_pin, OUTPUT_OPEN_DRAIN);
digitalWrite(dht_data_pin, LOW);
delay(1); //start conversion 1ms low pulse
digitalWrite(dht_data_pin, HIGH);
pinMode(dht_data_pin, INPUT_PULLUP);
expectPulse(HIGH); //30us
if(timeout) {
Serial.println("timeout waiting for response low");
return;
}
expectPulse(LOW); //80us
if(timeout) {
Serial.println("timeout waiting for response high");
return;
}
expectPulse(HIGH); //80us
if(timeout) {
Serial.println("timeout waiting for data");
return;
}
/* next data pulses
* low pulse 50 us
* '0' high pulse 26 us
* '1' high pulse 70 us
*/
for(uint16_t i=0; i<80; i+=2) {
pulse[i] = expectPulse(LOW);
if(timeout) {
Serial.print("timeout reading data ");
Serial.print(i/2);
Serial.println("low");
return;
}
pulse[i+1] = expectPulse(HIGH);
if(timeout) {
Serial.print("timeout reading data ");
Serial.print(i/2);
Serial.println("high");
return;
}
}
//decode pulses
for(uint16_t i=0; i<40; i++) {
uint16_t lowcount = pulse[2*i];
uint16_t highcount = pulse[2*i + 1];
if(debug) {
Serial.print(i);
Serial.print(":");
Serial.print(lowcount);
Serial.print(",");
Serial.println(highcount);
}
data[i / 8] <<= 1;
if (highcount > lowcount) {
// High cycles are greater than 50us low cycle count, must be a 1.
data[i / 8] |= 1;
}
}
}
uint16_t expectPulse(uint8_t val) {
//start the counter
Timer1.refresh();
timeout = false;
Timer1.resume();
while(digitalRead(dht_data_pin) == val && !timeout);
Timer1.pause();
return Timer1.getCount();
}
void prtemp() {
uint16_t vrefint = adc_read((adc_dev *)ADC1, 17);
Serial.print(F("Vref int (1.2v):"));
Serial.print(vrefint);
Serial.println();
uint16_t vtemp = adc_read((adc_dev *)ADC1, 16);
Serial.print(F("temp sensor:"));
Serial.print(vtemp);
Serial.println();
uint16_t mv = (1200 * vtemp) / vrefint;
Serial.print(F("mvolt:"));
Serial.print(mv);
Serial.println();
// specs 5.3.19 temp sensor characteristics
// V 25 deg ~ 1.43v
// slope 4.3 mv/C
float temp = (mv - 1430) * 1.0 / 4.3 + 25.0;
Serial.print(F("temp:"));
Serial.print(temp);
Serial.println();
}
results looks like such
Code: Select all
Vref int (1.2v):1496
temp sensor:1831
mvolt:1468
temp:33.84
dht humidity (RH%):81.60
dht temp (C):30.40
Vref int (1.2v):1504
temp sensor:1835
mvolt:1464
temp:32.91
dht humidity (RH%):81.70
dht temp (C):30.40
Vref int (1.2v):1495
temp sensor:1830
mvolt:1468
temp:33.84
dht humidity (RH%):81.70
dht temp (C):30.40
Vref int (1.2v):1494
temp sensor:1830
mvolt:1469
temp:34.07
dht humidity (RH%):81.70
dht temp (C):30.30
i added some codes to read the temperature off the stm32 internal temperature sensor for comparison. they looked quite well

the difference between this vs adafruit's code is that i used a hardware timer TIM1 as my microsecond timer.
i did not use a library here, it is self contained in the sketch.
This is quite possibly portable to STM core as well. the main things used are
Code: Select all
pinMode(dht_data_pin, OUTPUT_OPEN_DRAIN);
pinMode(dht_data_pin, INPUT_PULLUP);
digitalRead();
digitalWrite();
using digitalRead() and digitalWrite() APIs possibly lose several microseconds in terms of the pulse timing measurements.
but fortunately it works quite well.
and the hardware timer declaration and interrupt (which is used to check timeout), the declarations would likely look a little different.
i'd likely try doing a STM core based sketch at a different sitting.
note that adafruit's library is more complete and has more features e.g. F / C conversion and heat index computation.
i've a feeling Adafruit's library probably works just as well except that Adafruit used a variable counting loop instead as hardware timer is mcu dependent.