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.
toaster-oven-bluepill/Core/Src/app_heater.c

115 lines
2.9 KiB

#include <stdio.h>
2 years ago
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "app_temp.h"
#include "app_pid.h"
2 years ago
#include "app_heater.h"
#include "cmsis_os2.h"
2 years ago
#include "tim.h"
extern osMutexId_t heaterMutexHandle;
static void heater_pwm_init()
2 years ago
{
LL_TIM_OC_SetCompareCH1(TIM_HEATER, 0); // Off
LL_TIM_EnableCounter(TIM_HEATER);
LL_TIM_CC_EnableChannel(TIM_HEATER, LL_TIM_CHANNEL_CH1);
2 years ago
}
static void heater_pwm_set_perc(float perc)
{
uint16_t perc_u = (uint16_t) perc;
if (perc_u > 100) {
perc_u = 100;
}
// (TIM3->ARR / 100)
LL_TIM_OC_SetCompareCH1(TIM_HEATER, 640 * perc_u);
// TIM3->CCR1 = 640 * perc_u;
}
static struct {
float oven_temp;
float soc_temp;
// these will be loaded from flash and stored back
float tuning_p;
float tuning_i;
float tuning_d;
// PID state
struct PID pid;
} state = {
.tuning_p = 10.0f,
.tuning_i = 0.052f,
.tuning_d = 100.0f,
.pid = {
.SampleTimeTicks = pdMS_TO_TICKS(1000),
.outMax = 100.0f,
.outMin = 0.0f,
.ctlMode = PID_MANUAL,
.controllerDirection = PID_DIRECT,
},
};
static inline void heaterEnterCritical() {
osMutexAcquire(heaterMutexHandle, portMAX_DELAY);
}
static inline void heaterExitCritical() {
osMutexRelease(heaterMutexHandle);
}
void app_heater_set_tuning(float p, float i, float d) {
heaterEnterCritical();
PID_SetTunings(&state.pid, p, i, d);
heaterExitCritical();
}
void app_heater_enable(bool enable) {
PRINTF("Set heater enabled = %d\r\n", (int) enable);
heaterEnterCritical();
PID_SetCtlMode(&state.pid, enable ? PID_AUTOMATIC : PID_MANUAL);
heaterExitCritical();
}
void app_heater_set_target(float target) {
PRINTF("Set heater target = %d\r\n", (int) target);
heaterEnterCritical();
PID_SetSetpoint(&state.pid, target);
heaterExitCritical();
}
2 years ago
void app_task_heater(void *argument)
2 years ago
{
heater_pwm_init();
heaterEnterCritical();
// TODO load from flash
PID_SetTunings(&state.pid, state.tuning_p, state.tuning_i, state.tuning_d);
PID_Initialize(&state.pid);
heaterExitCritical();
uint32_t wake_time = xTaskGetTickCount();
while (1) {
app_temp_sample();
state.oven_temp = app_temp_read_oven();
state.soc_temp = app_temp_read_soc();
heaterEnterCritical();
PID_Compute(&state.pid, state.oven_temp);
if (state.pid.ctlMode == PID_AUTOMATIC) {
PRINTF("temp %d, output %d\r\n", (int) state.oven_temp, (int) state.pid.Output);
heater_pwm_set_perc(state.pid.Output);
} else {
// turn it off
heater_pwm_set_perc(0);
}
heaterExitCritical();
// TODO notify UI thread of the new temperature and heating percent
vTaskDelayUntil(&wake_time, pdMS_TO_TICKS(100));
}
2 years ago
}