Last active
February 10, 2021 11:16
-
-
Save eleanor-em/292cfefd0b9c8fb85adb731d17e5bfd0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Based on code by Caroline Dunn: https://github.com/carolinedunn/pico-weather-station | |
**/ | |
#include <stdio.h> | |
#include <math.h> | |
#include "pico/stdlib.h" | |
#include "hardware/gpio.h" | |
#include <string.h> | |
const uint LED_PIN = PICO_DEFAULT_LED_PIN; | |
const uint DHT_PIN = 15; | |
typedef struct { | |
float humidity; | |
float temp_celsius; | |
} dht_reading; | |
uint32_t wait_for(uint8_t expect) { | |
uint32_t then = time_us_32(); | |
while (expect != gpio_get(DHT_PIN)) { | |
sleep_us(10); | |
} | |
return time_us_32() - then; | |
} | |
inline float word(uint8_t first, uint8_t second) { | |
return (float) ((first << 8) + second); | |
} | |
inline void blink() { | |
gpio_put(LED_PIN, 1); | |
sleep_ms(50); | |
gpio_put(LED_PIN, 0); | |
} | |
// helper function to read from the DHT | |
// more: https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf | |
uint8_t read_from_dht(dht_reading *result) { | |
uint8_t data[5] = {0, 0, 0, 0, 0}; | |
// request a sample | |
gpio_set_dir(DHT_PIN, GPIO_OUT); | |
gpio_put(DHT_PIN, 0); | |
sleep_ms(10); | |
gpio_put(DHT_PIN, 1); | |
sleep_us(40); | |
// wait for acknowledgement | |
gpio_set_dir(DHT_PIN, GPIO_IN); | |
wait_for(0); | |
wait_for(1); | |
wait_for(0); | |
// read sample | |
for (uint8_t bit = 0; bit < 40; ++bit) { | |
wait_for(1); | |
uint8_t count = wait_for(0); | |
data[bit / 8] <<= 1; | |
if (count > 50) { | |
data[bit / 8] |= 1; | |
} | |
} | |
// checksum | |
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { | |
result->humidity = word(data[0], data[1]) / 10; | |
// if the highest bit is 1, temperature is negative | |
result->temp_celsius = word(data[2] & 0x7F, data[3]) / 10; | |
if (data[2] & 0x80) { | |
result->temp_celsius = -result->temp_celsius; | |
} | |
// double-blink if checksum was OK but something else went wrong | |
if (isnan(result->temp_celsius) || isnan(result->humidity) | |
|| result->temp_celsius == 0) { | |
blink(); | |
sleep_ms(50); | |
blink(); | |
return 2; | |
} else { | |
blink(); | |
return 0; | |
} | |
} else { | |
return 1; | |
} | |
} | |
int main() { | |
stdio_init_all(); | |
gpio_init(LED_PIN); | |
gpio_init(DHT_PIN); | |
gpio_set_dir(LED_PIN, GPIO_OUT); | |
while (1) { | |
sleep_ms(2000); | |
dht_reading reading; | |
uint8_t status = read_from_dht(&reading); | |
if (status == 0) { | |
float fahrenheit = (reading.temp_celsius * 9 / 5) + 32; | |
printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n", | |
reading.humidity, reading.temp_celsius, fahrenheit); | |
} else if (status == 1) { | |
printf("Bad data (failed checksum)\n"); | |
} else if (status == 2) { | |
printf("Bad data (nonsense result)\n"); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment