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();
adc_reg_map *regs = ADC1->regs;
regs->CR2 |= ADC_CR2_TSVREFE;
regs->SMPR1 = ADC_SMPR1_SMP17;
Timer1.init();
Timer1.pause();
Timer1.setPrescaleFactor(72-1);
Timer1.setOverflow(0xffff);
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];
}
void dht_read() {
pinMode(dht_data_pin, OUTPUT_OPEN_DRAIN);
digitalWrite(dht_data_pin, LOW);
delay(1);
digitalWrite(dht_data_pin, HIGH);
pinMode(dht_data_pin, INPUT_PULLUP);
expectPulse(HIGH);
if(timeout) {
Serial.println("timeout waiting for response low");
return;
}
expectPulse(LOW);
if(timeout) {
Serial.println("timeout waiting for response high");
return;
}
expectPulse(HIGH);
if(timeout) {
Serial.println("timeout waiting for data");
return;
}
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;
}
}
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) {
data[i / 8] |= 1;
}
}
}
uint16_t expectPulse(uint8_t val) {
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();
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.