// // Created by MightyPork on 2022/08/20. // #include #include #include #include #include #include #include "freertos/queue.h" #include "actuators.h" #include "tasks.h" #include "settings.h" static const char *TAG="act"; // TODO move these to settings and make them accessible via modbus uint32_t pwm_freq = 3000; uint32_t pwm_duty = 600; uint32_t pwm_thres = 850; uint32_t pwm_on = 1; uint32_t last_adc_mv = 0; uint32_t tick_count = 0; uint32_t tick_count_start = 0; uint32_t last_cpm = 0; uint32_t count_total = 0; float last_usv_h = 0.0f; float total_usv = 0.0f; static xQueueHandle gpio_evt_queue = NULL; static void IRAM_ATTR gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t) arg; xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); } static void TickHandlingTask(void* arg) { uint32_t io_num; for(;;) { if(xQueueReceive(gpio_evt_queue, &io_num, pdMS_TO_TICKS(20))) { printf("TICK! "); act_statusled_set(0); tick_count++; count_total++; } else { act_statusled_set(1); } if (tick_count_start == 0) { tick_count_start = xTaskGetTickCount(); } else { if (xTaskGetTickCount() - tick_count_start >= pdMS_TO_TICKS(60000)) { last_cpm = tick_count; tick_count = 0; tick_count_start = xTaskGetTickCount(); // https://sites.google.com/site/diygeigercounter/technical/gm-tubes-supported last_usv_h = (float)last_cpm / 153.8f; total_usv += (last_usv_h / 60.0f); printf("\r\n\r\nCPM = %d ~~ %f uSv/h\r\n\r\n", last_cpm, last_usv_h); } } } } void power_task() { while (1) { const uint32_t val = act_read_adc(); act_pwm_set(val <= pwm_thres); last_adc_mv = val; // basically, just yield vTaskDelay(pdMS_TO_TICKS(1)); } } void act_pwm_update_conf() { ledc_timer_config_t ledc_timer = { .duty_resolution = LEDC_TIMER_10_BIT, .freq_hz = pwm_freq, .speed_mode = LEDC_HIGH_SPEED_MODE, .timer_num = LEDC_TIMER_1, .clk_cfg = LEDC_AUTO_CLK, }; ledc_timer_config(&ledc_timer); } static void pwm_init() { act_pwm_update_conf(); // PWM output ledc_channel_config_t chan = { .channel = LEDC_CHANNEL_1, .duty = 512, .gpio_num = CONFIG_PIN_PWM, .speed_mode = LEDC_HIGH_SPEED_MODE, .hpoint = 0, .timer_sel = LEDC_TIMER_1, .flags.output_invert = false, }; ledc_channel_config(&chan); ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); } void act_pwm_set(bool on) { if (on) { pwm_on = 1; ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, pwm_duty); ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1); } else { pwm_on = 0; ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); } } static void led_init() { gpio_config_t ioconf = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = (1 << CONFIG_PIN_STATUSLED), }; gpio_config(&ioconf); } #define DEFAULT_VREF 1100 #define CHANNEL ADC1_CHANNEL_6 /* 34 */ #define WIDTH ADC_WIDTH_BIT_12 #define ATTEN ADC_ATTEN_DB_0 #define ADCX ADC_UNIT_1 static esp_adc_cal_characteristics_t adc_chars; static void adc_init() { adc1_config_width(WIDTH); adc1_config_channel_atten(CHANNEL, ATTEN); esp_adc_cal_characterize(ADCX, ATTEN, WIDTH, DEFAULT_VREF, &adc_chars); // route vref to GPIO25 so it can be measured esp_err_t status = adc_vref_to_gpio(ADC_UNIT_2, GPIO_NUM_25); if (status == ESP_OK) { printf("v_ref routed to GPIO\n"); } else { printf("failed to route v_ref\n"); } } uint32_t act_read_adc() { uint32_t raw = adc1_get_raw(CHANNEL); return esp_adc_cal_raw_to_voltage(raw, &adc_chars); } void act_statusled_set(bool on) { gpio_set_level(CONFIG_PIN_STATUSLED, (int) on); } static void int_init() { gpio_pad_select_gpio(CONFIG_PIN_INT); gpio_set_direction(CONFIG_PIN_INT, GPIO_MODE_INPUT); gpio_pulldown_en(CONFIG_PIN_INT); gpio_pullup_dis(CONFIG_PIN_INT); gpio_set_intr_type(CONFIG_PIN_INT, GPIO_INTR_POSEDGE); gpio_evt_queue = xQueueCreate(20, sizeof(int)); xTaskCreate(TickHandlingTask, "ticks", 3000, NULL, PRIO_NORMAL, NULL); gpio_isr_handler_add(CONFIG_PIN_INT, gpio_isr_handler, (void *)CONFIG_PIN_INT); } void act_init() { pwm_freq = gSettings.pwm_freq; pwm_duty = gSettings.pwm_duty; pwm_thres = gSettings.pwm_thres; led_init(); pwm_init(); adc_init(); act_statusled_set(1); // = off xTaskCreate(power_task, "pwr", 3000, NULL, PRIO_HIGH, NULL); int_init(); }