mirror of
https://github.com/stasenso/Thermometr_pico.git
synced 2026-06-26 21:42:42 +03:00
Add DHT22 PIO reader and simplify display output
This commit is contained in:
+7
-2
@@ -38,6 +38,7 @@ target_link_libraries(display_engine PUBLIC
|
|||||||
hardware_spi
|
hardware_spi
|
||||||
hardware_dma
|
hardware_dma
|
||||||
hardware_timer
|
hardware_timer
|
||||||
|
hardware_pio
|
||||||
pico_multicore
|
pico_multicore
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ target_link_libraries(display_engine PUBLIC
|
|||||||
target_compile_definitions(display_engine PUBLIC
|
target_compile_definitions(display_engine PUBLIC
|
||||||
# EN: Select the display controller backend: ST7789 or ILI9341.
|
# EN: Select the display controller backend: ST7789 or ILI9341.
|
||||||
# RU: Выберите бэкенд контроллера дисплея: ST7789 или ILI9341.
|
# RU: Выберите бэкенд контроллера дисплея: ST7789 или ILI9341.
|
||||||
DISPLAY_TYPE=DISPLAY_TYPE_ST7789
|
DISPLAY_TYPE=DISPLAY_TYPE_ILI9341
|
||||||
# EN: Select the SPI peripheral connected to the display: spi0 or spi1.
|
# EN: Select the SPI peripheral connected to the display: spi0 or spi1.
|
||||||
# RU: Выберите SPI-периферию, к которой подключён дисплей: spi0 или spi1.
|
# RU: Выберите SPI-периферию, к которой подключён дисплей: spi0 или spi1.
|
||||||
DISPLAY_SPI_PORT=spi1
|
DISPLAY_SPI_PORT=spi1
|
||||||
@@ -58,6 +59,10 @@ target_compile_definitions(display_engine PUBLIC
|
|||||||
DISPLAY_PIN_BL=10 # BL / LED / LEDK
|
DISPLAY_PIN_BL=10 # BL / LED / LEDK
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(my_app src/main.c)
|
add_executable(my_app
|
||||||
|
src/main.c
|
||||||
|
src/dht22.c
|
||||||
|
)
|
||||||
target_link_libraries(my_app PRIVATE display_engine)
|
target_link_libraries(my_app PRIVATE display_engine)
|
||||||
|
pico_generate_pio_header(my_app ${CMAKE_CURRENT_LIST_DIR}/src/dht22.pio)
|
||||||
pico_add_extra_outputs(my_app)
|
pico_add_extra_outputs(my_app)
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
#include "dht22.h"
|
||||||
|
|
||||||
|
#include "dht22.pio.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#define DHT22_START_LOW_US 1200u
|
||||||
|
#define DHT22_PREPARE_US 30u
|
||||||
|
#define DHT22_WORD_TIMEOUT_US 2000u
|
||||||
|
|
||||||
|
static bool wait_for_rx_word(PIO pio, uint sm, uint32_t *out, uint32_t timeout_us) {
|
||||||
|
uint64_t deadline = time_us_64() + timeout_us;
|
||||||
|
while (pio_sm_is_rx_fifo_empty(pio, sm)) {
|
||||||
|
if (time_us_64() > deadline) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out = pio_sm_get(pio, sm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dht22_init(dht22_t *dev, PIO pio, uint sm, uint pin) {
|
||||||
|
dev->pio = pio;
|
||||||
|
dev->sm = sm;
|
||||||
|
dev->pin = pin;
|
||||||
|
dev->offset = pio_add_program(pio, &dht22_program);
|
||||||
|
|
||||||
|
pio_gpio_init(pio, pin);
|
||||||
|
|
||||||
|
pio_sm_config c = dht22_program_get_default_config(dev->offset);
|
||||||
|
sm_config_set_in_pins(&c, pin);
|
||||||
|
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / 1000000.0f);
|
||||||
|
sm_config_set_in_shift(&c, false, true, 8);
|
||||||
|
|
||||||
|
pio_sm_init(pio, sm, dev->offset, &c);
|
||||||
|
pio_sm_set_enabled(pio, sm, false);
|
||||||
|
|
||||||
|
gpio_init(pin);
|
||||||
|
gpio_pull_up(pin);
|
||||||
|
gpio_set_dir(pin, GPIO_IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
dht22_status_t dht22_read(dht22_t *dev, int16_t *temperature_x10, uint16_t *humidity_x10) {
|
||||||
|
if (!gpio_get(dev->pin)) {
|
||||||
|
return DHT22_BUS_STUCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_set_dir(dev->pin, GPIO_OUT);
|
||||||
|
gpio_put(dev->pin, 0);
|
||||||
|
sleep_us(DHT22_START_LOW_US);
|
||||||
|
|
||||||
|
gpio_set_dir(dev->pin, GPIO_IN);
|
||||||
|
gpio_pull_up(dev->pin);
|
||||||
|
sleep_us(DHT22_PREPARE_US);
|
||||||
|
|
||||||
|
pio_sm_set_enabled(dev->pio, dev->sm, false);
|
||||||
|
pio_sm_clear_fifos(dev->pio, dev->sm);
|
||||||
|
pio_sm_restart(dev->pio, dev->sm);
|
||||||
|
pio_sm_set_enabled(dev->pio, dev->sm, true);
|
||||||
|
|
||||||
|
uint8_t data[5] = {0};
|
||||||
|
for (uint i = 0; i < 5; ++i) {
|
||||||
|
uint32_t word = 0;
|
||||||
|
if (!wait_for_rx_word(dev->pio, dev->sm, &word, DHT22_WORD_TIMEOUT_US)) {
|
||||||
|
pio_sm_set_enabled(dev->pio, dev->sm, false);
|
||||||
|
return DHT22_TIMEOUT;
|
||||||
|
}
|
||||||
|
data[i] = (uint8_t)word;
|
||||||
|
}
|
||||||
|
|
||||||
|
pio_sm_set_enabled(dev->pio, dev->sm, false);
|
||||||
|
|
||||||
|
uint8_t checksum = (uint8_t)(data[0] + data[1] + data[2] + data[3]);
|
||||||
|
if (checksum != data[4]) {
|
||||||
|
return DHT22_CHECKSUM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t raw_h = (uint16_t)((data[0] << 8) | data[1]);
|
||||||
|
uint16_t raw_t = (uint16_t)((data[2] << 8) | data[3]);
|
||||||
|
|
||||||
|
*humidity_x10 = raw_h;
|
||||||
|
if (raw_t & 0x8000u) {
|
||||||
|
*temperature_x10 = -(int16_t)(raw_t & 0x7fffu);
|
||||||
|
} else {
|
||||||
|
*temperature_x10 = (int16_t)raw_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DHT22_OK;
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef DHT22_H
|
||||||
|
#define DHT22_H
|
||||||
|
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
#include "pico/types.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DHT22_OK = 0,
|
||||||
|
DHT22_TIMEOUT,
|
||||||
|
DHT22_CHECKSUM_ERROR,
|
||||||
|
DHT22_BUS_STUCK
|
||||||
|
} dht22_status_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PIO pio;
|
||||||
|
uint sm;
|
||||||
|
uint pin;
|
||||||
|
uint offset;
|
||||||
|
} dht22_t;
|
||||||
|
|
||||||
|
dht22_status_t dht22_read(dht22_t *dev, int16_t *temperature_x10, uint16_t *humidity_x10);
|
||||||
|
void dht22_init(dht22_t *dev, PIO pio, uint sm, uint pin);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
.program dht22
|
||||||
|
|
||||||
|
; Capture 40 bits from DHT22 by sampling each high pulse around 35us after rising edge.
|
||||||
|
.wrap_target
|
||||||
|
wait 0 pin 0
|
||||||
|
wait 1 pin 0
|
||||||
|
|
||||||
|
set y, 4
|
||||||
|
byte_loop:
|
||||||
|
set x, 7
|
||||||
|
bit_loop:
|
||||||
|
wait 0 pin 0
|
||||||
|
wait 1 pin 0
|
||||||
|
nop [31]
|
||||||
|
nop [2]
|
||||||
|
in pins, 1
|
||||||
|
jmp x-- bit_loop
|
||||||
|
jmp y-- byte_loop
|
||||||
|
.wrap
|
||||||
+31
-23
@@ -2,46 +2,54 @@
|
|||||||
#include "display/display.h"
|
#include "display/display.h"
|
||||||
#include "display/render/context.h"
|
#include "display/render/context.h"
|
||||||
#include "Font/font_data.h"
|
#include "Font/font_data.h"
|
||||||
|
#include "dht22.h"
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#define WIDTH 320
|
||||||
|
#define HEIGHT 240
|
||||||
|
#define DHT22_PIN 13
|
||||||
|
#define DHT22_POLL_INTERVAL_US 2000000ULL
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
display_config_t cfg = {
|
display_config_t cfg = {
|
||||||
.width = 320,
|
.width = WIDTH,
|
||||||
.height = 240,
|
.height = HEIGHT,
|
||||||
.buffer_count = 1,
|
.buffer_count = 1,
|
||||||
.mode = DISPLAY_MODE_SAFE
|
.mode = DISPLAY_MODE_SAFE
|
||||||
};
|
};
|
||||||
display_init(&cfg);
|
display_init(&cfg);
|
||||||
|
|
||||||
render_ctx_t rc;
|
render_ctx_t rc;
|
||||||
uint32_t frame = 0;
|
wchar_t temp_text[24] = L"T: --.- C";
|
||||||
|
wchar_t hum_text[24] = L"H: --.- %";
|
||||||
|
int16_t dht_temp_x10 = 0;
|
||||||
|
uint16_t dht_hum_x10 = 0;
|
||||||
|
uint64_t next_dht_poll_us = time_us_64();
|
||||||
|
|
||||||
|
dht22_t dht;
|
||||||
|
dht22_init(&dht, pio0, 0, DHT22_PIN);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint16_t *buf = display_begin_paint_blocking();
|
uint64_t now_us = time_us_64();
|
||||||
render_begin(&rc, buf, 320, 240);
|
if (now_us >= next_dht_poll_us) {
|
||||||
switch ((frame / 30u) % 4u) {
|
if (dht22_read(&dht, &dht_temp_x10, &dht_hum_x10) == DHT22_OK) {
|
||||||
case 0:
|
uint16_t t_abs_x10 = (dht_temp_x10 < 0) ? (uint16_t)(-dht_temp_x10) : (uint16_t)dht_temp_x10;
|
||||||
render_clear(&rc, RGB16(255, 0, 0));
|
wchar_t sign = (dht_temp_x10 < 0) ? L'-' : L'+';
|
||||||
break;
|
(void)swprintf(temp_text, sizeof(temp_text) / sizeof(temp_text[0]), L"T: %lc%u.%u C", sign, (unsigned)(t_abs_x10 / 10u), (unsigned)(t_abs_x10 % 10u));
|
||||||
case 1:
|
(void)swprintf(hum_text, sizeof(hum_text) / sizeof(hum_text[0]), L"H: %u.%u %%", (unsigned)(dht_hum_x10 / 10u), (unsigned)(dht_hum_x10 % 10u));
|
||||||
render_clear(&rc, RGB16(0, 255, 0));
|
}
|
||||||
break;
|
next_dht_poll_us = now_us + DHT22_POLL_INTERVAL_US;
|
||||||
case 2:
|
|
||||||
render_clear(&rc, RGB16(0, 0, 255));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
render_clear(&rc, RGB16(255, 255, 255));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t frame_text[32];
|
uint16_t *buf = display_begin_paint_blocking();
|
||||||
(void)swprintf(frame_text, sizeof(frame_text) / sizeof(frame_text[0]), L"frame: %lu", (unsigned long)frame);
|
render_begin(&rc, buf, WIDTH, HEIGHT);
|
||||||
draw_string(&rc, 100, 110, frame_text, RGB565(255, 255, 255));
|
render_clear(&rc, RGB16(0, 0, 0));
|
||||||
|
draw_string(&rc, 16, 72, temp_text, RGB16(255, 255, 255));
|
||||||
|
draw_string(&rc, 16, 96, hum_text, RGB16(255, 255, 255));
|
||||||
|
|
||||||
display_end_paint();
|
display_end_paint();
|
||||||
frame++;
|
sleep_ms(50);
|
||||||
sleep_ms(1000/50);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user