|
|
|
@ -5,11 +5,81 @@ |
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <FreeRTOS.h> |
|
|
|
|
#include <task.h> |
|
|
|
|
#include <math.h> |
|
|
|
|
#include <driver/hw_timer.h> |
|
|
|
|
#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); |
|
|
|
|