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.
114 lines
2.9 KiB
114 lines
2.9 KiB
#include <stdio.h>
|
|
#include "main.h"
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "app_temp.h"
|
|
#include "app_pid.h"
|
|
#include "app_heater.h"
|
|
#include "cmsis_os2.h"
|
|
#include "tim.h"
|
|
|
|
extern osMutexId_t heaterMutexHandle;
|
|
|
|
static void heater_pwm_init()
|
|
{
|
|
LL_TIM_OC_SetCompareCH1(TIM_HEATER, 0); // Off
|
|
LL_TIM_EnableCounter(TIM_HEATER);
|
|
LL_TIM_CC_EnableChannel(TIM_HEATER, LL_TIM_CHANNEL_CH1);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void app_task_heater(void *argument)
|
|
{
|
|
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));
|
|
}
|
|
}
|
|
|