diff --git a/main/meteo_task.c b/main/meteo_task.c index 0415774..41e052b 100644 --- a/main/meteo_task.c +++ b/main/meteo_task.c @@ -5,11 +5,81 @@ #include #include #include +#include +#include #include "meteo_task.h" #include "ds18b20.h" #include "dht.h" #include "driver/gpio.h" +static volatile uint32_t timestamp_ms = 0; +static volatile uint32_t last_revolution_ts = 0; + +#define RPM_BUFFER_LEN 10 +static volatile uint16_t rpm_buffer[RPM_BUFFER_LEN] = {}; +static volatile int rpm_buffer_next = 0; +static volatile int num_valid_average = 0; + +static void gpio_isr_handler(void *arg) +{ + uint32_t ts = timestamp_ms; + uint32_t cycle_ms = ts - last_revolution_ts; + last_revolution_ts = ts; + + if (cycle_ms > 0xFFFF) { + cycle_ms = 0xFFFF; + } + rpm_buffer[rpm_buffer_next++] = (uint16_t) cycle_ms; + if (rpm_buffer_next == RPM_BUFFER_LEN) { + rpm_buffer_next = 0; + } + if (num_valid_average < RPM_BUFFER_LEN) { + num_valid_average++; + } +} + +float get_rpm() { + float res; + float current = (float)(timestamp_ms - last_revolution_ts); + + if (num_valid_average > 0) { + // we write num_valid_average only from here, so its safe to assume it stays nonzero + float average = 0; + int pos = rpm_buffer_next; + for (int i = 0; i < num_valid_average; i++) { + average += (float) rpm_buffer[pos]; + pos--; + if (pos < 0) { + pos = RPM_BUFFER_LEN - 1; + } + } + average /= (float) (num_valid_average); + + // now we have ms per revolution + + if (current > average * 10.0f) { + // if wind stopped, invalidate the averaging buffer and use the current time from the last hall event + res = current; + num_valid_average = 0; // invalidate average results + } else { + res = average; + } + } else { + res = current; + } + + float rpm = 60000.0f / res; + if (rpm < 1) { + rpm = 0; + } + return rpm; // RPM +} + +void hw_timer_callback1(void *arg) +{ + timestamp_ms++; +} + void meteo_task(void* pvParameters) { // Try to unfuck GPIOs @@ -18,21 +88,32 @@ void meteo_task(void* pvParameters) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); + // start timer used for timebase + hw_timer_init(hw_timer_callback1, NULL); + hw_timer_alarm_us(1000, true); // 1 ms timer + + gpio_config_t io_conf; + io_conf.intr_type = GPIO_INTR_POSEDGE; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = 1 << 14; + io_conf.pull_down_en = 1; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); + gpio_install_isr_service(0); + gpio_isr_handler_add(14, gpio_isr_handler, NULL); + float dht_hum, dht_temp, ds_temp; while (1) { // this works ... ds_temp = ds18b20_measure_and_read(0, DS18B20_ANY); - if (ds_temp != ds_temp) { // NAN - printf("Fail to read temp\n"); - } else { - printf("Dallas: %f °C\n", ds_temp); - } - if (dht_read_float_data(DHT_TYPE_DHT11, 12, &dht_hum, &dht_temp)) { - printf("DHT: %f °C, %f %%r.H\n", dht_temp, dht_hum); + if (!dht_read_float_data(DHT_TYPE_DHT11, 12, &dht_hum, &dht_temp)) { + dht_hum = dht_temp = NAN; } - vTaskDelay(pdMS_TO_TICKS(1000)); + printf("Dallas: %.2f °C, DHT %.2f °C, %.1f %%r.H, HALL %.1f RPM\n", ds_temp, dht_temp, dht_hum, get_rpm()); + + vTaskDelay(pdMS_TO_TICKS(500)); } vTaskDelete(NULL);