You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
esp-geiger/main/actuators.c

194 lines
5.0 KiB

//
// Created by MightyPork on 2022/08/20.
//
#include <driver/ledc.h>
#include <esp_log.h>
#include <driver/adc.h>
#include <esp_adc_cal.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#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();
}