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.
195 lines
5.0 KiB
195 lines
5.0 KiB
2 years ago
|
//
|
||
|
// 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();
|
||
|
}
|