From a7749c08efa8464dd6a298a52a1a7f2dd7840724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 7 Mar 2023 01:13:41 +0100 Subject: [PATCH] mostly working PID now --- BluepillTrouba.ioc | 10 ++- Core/Src/app.c | 114 ------------------------ Core/Src/app_analog.h | 19 ---- Core/Src/app_buzzer.c | 25 ++++-- Core/Src/app_gui.c | 12 +++ Core/Src/app_gui.h | 10 +++ Core/Src/app_heater.c | 111 ++++++++++++++++++++--- Core/Src/app_heater.h | 16 +++- Core/Src/app_knob.c | 5 ++ Core/Src/app_knob.h | 1 + Core/Src/app_main.c | 122 ++++++++++++++++++++++++++ Core/Src/app_pid.c | 61 +++++++------ Core/Src/app_pid.h | 16 ++-- Core/Src/{app_analog.c => app_temp.c} | 46 +++++++--- Core/Src/app_temp.h | 27 ++++++ Core/Src/freertos.c | 115 ++++++++++++++++++++---- Core/Src/tim.c | 2 +- Makefile | 7 +- 18 files changed, 499 insertions(+), 220 deletions(-) delete mode 100644 Core/Src/app.c delete mode 100644 Core/Src/app_analog.h create mode 100644 Core/Src/app_gui.c create mode 100644 Core/Src/app_gui.h create mode 100644 Core/Src/app_main.c rename Core/Src/{app_analog.c => app_temp.c} (85%) create mode 100644 Core/Src/app_temp.h diff --git a/BluepillTrouba.ioc b/BluepillTrouba.ioc index a6b189b..fdd6a39 100644 --- a/BluepillTrouba.ioc +++ b/BluepillTrouba.ioc @@ -27,8 +27,12 @@ Dma.ADC1.0.Priority=DMA_PRIORITY_MEDIUM Dma.ADC1.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority Dma.Request0=ADC1 Dma.RequestsNb=1 -FREERTOS.IPParameters=Tasks01,configUSE_MALLOC_FAILED_HOOK,configCHECK_FOR_STACK_OVERFLOW,configUSE_NEWLIB_REENTRANT -FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL +FREERTOS.FootprintOK=true +FREERTOS.IPParameters=Tasks01,configUSE_MALLOC_FAILED_HOOK,configCHECK_FOR_STACK_OVERFLOW,configUSE_NEWLIB_REENTRANT,FootprintOK,Mutexes01,Queues01,Timers01 +FREERTOS.Mutexes01=heaterMutex,Static,heaterMutexControlBlock +FREERTOS.Queues01=guiEventQue,16,8,1,Static,guiEventQueBuffer,guiEventQueControlBlock +FREERTOS.Tasks01=mainTsk,24,128,app_task_main,As weak,NULL,Static,defaultTaskBuffer,defaultTaskControlBlock;heaterTsk,24,128,app_task_heater,As external,NULL,Static,heaterTskBuffer,heaterTskControlBlock;guiTsk,40,128,app_task_gui,As external,NULL,Static,guiTskBuffer,guiTskControlBlock +FREERTOS.Timers01=beepTimer,app_beep_end,osTimerOnce,As external,NULL,Static,beepTimerControlBlock FREERTOS.configCHECK_FOR_STACK_OVERFLOW=2 FREERTOS.configUSE_MALLOC_FAILED_HOOK=1 FREERTOS.configUSE_NEWLIB_REENTRANT=1 @@ -236,7 +240,7 @@ TIM3.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 TIM3.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Pulse-PWM Generation1 CH1,Period TIM3.Period=64000 TIM3.Prescaler=2000 -TIM3.Pulse-PWM\ Generation1\ CH1=32000 +TIM3.Pulse-PWM\ Generation1\ CH1=0 TIM4.IC2Filter=15 TIM4.IPParameters=IC2Filter,Prescaler TIM4.Prescaler=0 diff --git a/Core/Src/app.c b/Core/Src/app.c deleted file mode 100644 index 512df9c..0000000 --- a/Core/Src/app.c +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Main task - */ - -#include -#include "FreeRTOS.h" -#include "task.h" - -#include "main.h" -#include "app.h" - -#include "ufb/framebuffer.h" -#include "iwdg.h" -#include "oled.h" -#include "ufb/fb_text.h" -#include "app_analog.h" -#include "app_knob.h" -#include "app_buzzer.h" -#include "app_heater.h" - -static struct App { - float oven_temp; - int16_t set_temp; - int16_t wheel_normed; - uint16_t wheel; - bool heating; -} s_app = {}; - -static void hw_init() -{ - app_analog_init(); - app_buzzer_init(); - app_heater_init(); - app_knob_init(); - - /* Prepare the framebuffer and OLED interface */ - oled_init(); - fb_clear(); -} - -void app_main_task(void *argument) -{ - hw_init(); - - /* Infinite loop */ - for (;;) { - HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); - - s_app.oven_temp = app_analog_get_temp(); - - for (int i = 0; i < 50; i++) { - uint16_t old_wheel = s_app.wheel; - s_app.wheel = app_knob_get_raw(); - - int16_t wheel_change = (int16_t)(s_app.wheel - old_wheel); - - if (wheel_change != 0) { - s_app.wheel_normed += wheel_change; - if (s_app.wheel_normed < 0) { - s_app.wheel_normed = 0; - } - if (s_app.wheel_normed > 500) { - s_app.wheel_normed = 500; - } - - int16_t old_temp = s_app.set_temp; - - s_app.set_temp = (s_app.wheel_normed / 2) * 5; - - if (old_temp != s_app.set_temp) { - app_buzzer_beep(); - } - } - - //s_app.push = 0 == HAL_GPIO_ReadPin(KNOB_PUSH_GPIO_Port, KNOB_PUSH_Pin); - - if (wheel_change != 0 || i == 0) { - fb_clear(); - - char tmp[100]; - - sprintf(tmp, "Mereni: %d°C", (int) s_app.oven_temp); - fb_text(10, 10, tmp, 0, 1); - - sprintf(tmp, " Cil: %d°C", s_app.set_temp); - fb_text(10, 25, tmp, 0, 1); - - if (s_app.heating) { - fb_frame(0, 0, FBW, FBH, 2, 1); - } - - fb_blit(); - } - - vTaskDelay(10); - } - - // regulation - - float set_f = (float) s_app.set_temp; - - if (!s_app.heating && s_app.oven_temp < set_f - 5.0f) { /* hysteresis */ - s_app.heating = true; - } - if (s_app.heating && s_app.oven_temp >= set_f) { - s_app.heating = false; - } - - app_heater_set(s_app.heating); - - // feed dogs - HAL_IWDG_Refresh(&hiwdg); - } -} diff --git a/Core/Src/app_analog.h b/Core/Src/app_analog.h deleted file mode 100644 index 45bba82..0000000 --- a/Core/Src/app_analog.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * TODO file description - */ - -#ifndef BLUEPILLTROUBA_APP_ANALOG_H -#define BLUEPILLTROUBA_APP_ANALOG_H - -void app_analog_init(); - -/** - * Get current oven temp. - * - * A slow float calculation is done here - call only when needed, at a roughly constant rate (e.g. 1s) to make smoothing work properly. - * - * @return the value in celsius - */ -float app_analog_get_temp(); - -#endif //BLUEPILLTROUBA_APP_ANALOG_H diff --git a/Core/Src/app_buzzer.c b/Core/Src/app_buzzer.c index 342093c..c06f5a0 100644 --- a/Core/Src/app_buzzer.c +++ b/Core/Src/app_buzzer.c @@ -6,20 +6,35 @@ #include "app_buzzer.h" #include "tim.h" #include "FreeRTOS.h" -#include "task.h" +#include "cmsis_os2.h" +#include "timers.h" + +extern osTimerId_t beepTimerHandle; + +//void app_beep_end(void *argument); + +//static TimerHandle_t s_timer; void app_buzzer_init() { /* Enable buzzer PWM */ + TIM2->CCR1 = 0; HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); + +// s_timer = xTimerCreate("beep", 50, 0, NULL, app_beep_end); } void app_buzzer_beep() { - - // TODO make this non-blocking TIM2->ARR = 25714; TIM2->CCR1 = TIM2->ARR/2; - vTaskDelay(50); + + osTimerStop(beepTimerHandle); + + osTimerStart(beepTimerHandle, pdMS_TO_TICKS(10)); + +// xTimerStart(s_timer, pdMS_TO_TICKS(1000)); +} + +void app_beep_end(TimerHandle_t timerHandle) { TIM2->CCR1 = 0; - vTaskDelay(50); } diff --git a/Core/Src/app_gui.c b/Core/Src/app_gui.c new file mode 100644 index 0000000..76684a3 --- /dev/null +++ b/Core/Src/app_gui.c @@ -0,0 +1,12 @@ +/** + * TODO file description + */ + +#include "app_gui.h" +#include "cmsis_os2.h" + +void app_task_gui(void *argument) { + while (1) { + osDelay(1000); + } +} diff --git a/Core/Src/app_gui.h b/Core/Src/app_gui.h new file mode 100644 index 0000000..722aa54 --- /dev/null +++ b/Core/Src/app_gui.h @@ -0,0 +1,10 @@ +/** + * TODO file description + */ + +#ifndef BLUEPILLTROUBA_APP_GUI_H +#define BLUEPILLTROUBA_APP_GUI_H + +void app_task_gui(void *argument); + +#endif //BLUEPILLTROUBA_APP_GUI_H diff --git a/Core/Src/app_heater.c b/Core/Src/app_heater.c index 490b645..3f77abf 100644 --- a/Core/Src/app_heater.c +++ b/Core/Src/app_heater.c @@ -1,23 +1,114 @@ -/** - * TODO file description - */ - +#include #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" -void app_heater_init() +extern osMutexId_t heaterMutexHandle; + +static void heater_pwm_init() { HAL_TIM_Base_Start(&htim3); + htim3.Instance->CCR1 = 0; // OFF HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); } +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) + + 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_heater_set(bool active) +void app_task_heater(void *argument) { - if (active) { - TIM3->CCR1 = TIM3->ARR / 2; // testing - 50% - } else { - TIM3->CCR1 = 0; + 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(500)); } } diff --git a/Core/Src/app_heater.h b/Core/Src/app_heater.h index 46f310c..9b80fc6 100644 --- a/Core/Src/app_heater.h +++ b/Core/Src/app_heater.h @@ -1,5 +1,5 @@ /** - * TODO file description + * Heater PWM control & regulation + temp sensing loop */ #ifndef BLUEPILLTROUBA_APP_HEATER_H @@ -7,8 +7,18 @@ #include -void app_heater_init(); +void app_task_heater(void *argument); -void app_heater_set(bool active); +/// Set heater regulator tuning. +/// Mutex is locked internally. +void app_heater_set_tuning(float p, float i, float d); + +/// Set heater on/off. +/// Mutex is locked internally. +void app_heater_enable(bool enable); + +/// Set heater setpoint +/// Mutex is locked internally. +void app_heater_set_target(float target); #endif //BLUEPILLTROUBA_APP_HEATER_H diff --git a/Core/Src/app_knob.c b/Core/Src/app_knob.c index 9b52cdd..49f0b05 100644 --- a/Core/Src/app_knob.c +++ b/Core/Src/app_knob.c @@ -21,3 +21,8 @@ void app_knob_init() uint16_t app_knob_get_raw() { return htim4.Instance->CNT; } + + +bool app_knob_pushed() { + return 0 == HAL_GPIO_ReadPin(KNOB_PUSH_GPIO_Port, KNOB_PUSH_Pin); +} diff --git a/Core/Src/app_knob.h b/Core/Src/app_knob.h index 596d261..e7c0eb6 100644 --- a/Core/Src/app_knob.h +++ b/Core/Src/app_knob.h @@ -8,5 +8,6 @@ void app_knob_init(); uint16_t app_knob_get_raw(); +bool app_knob_pushed(); #endif //BLUEPILLTROUBA_APP_KNOB_H diff --git a/Core/Src/app_main.c b/Core/Src/app_main.c new file mode 100644 index 0000000..3fd5cde --- /dev/null +++ b/Core/Src/app_main.c @@ -0,0 +1,122 @@ +/** + * Main task + */ + +#include +#include "FreeRTOS.h" +#include "task.h" + +#include "main.h" +#include "app.h" + +#include "ufb/framebuffer.h" +#include "iwdg.h" +#include "oled.h" +#include "ufb/fb_text.h" +#include "app_temp.h" +#include "app_knob.h" +#include "app_buzzer.h" +#include "app_heater.h" +#include "cmsis_os2.h" + +static struct App { + float oven_temp; + int16_t set_temp; + int16_t wheel_normed; + uint16_t wheel; + bool run; +} s_app = {}; + +static void redraw_display() { + fb_clear(); + + char tmp[100]; + + sprintf(tmp, "Mereni: %d°C", (int) s_app.oven_temp); + fb_text(10, 5, tmp, 0, 1); + + sprintf(tmp, " Cil: %d°C", s_app.set_temp); + fb_text(10, 20, tmp, 0, 1); + + sprintf(tmp, " Stav: %s", s_app.run ? "ZAP" : "VYP"); + fb_text(10, 35, tmp, 0, 1); + + if (s_app.run) { + fb_frame(0, 0, FBW, FBH, 2, 1); + } + + fb_blit(); +} + +void app_task_main(void *argument) +{ + app_analog_init(); + app_buzzer_init(); + app_knob_init(); + + /* Prepare the framebuffer and OLED interface */ + oled_init(); + fb_clear(); + + /* Infinite loop */ + bool old_pushed = app_knob_pushed(); + + bool any_change = true; + uint32_t last_redraw = osKernelGetTickCount(); + + for (;;) { + // sampling is done in the heater loop + + s_app.oven_temp = app_temp_read_oven(); + + uint16_t old_wheel = s_app.wheel; + s_app.wheel = app_knob_get_raw(); + + // TODO do this with interrupt and/or debouncing + bool pushed = app_knob_pushed(); + if (pushed && !old_pushed) { + s_app.run ^= 1; + app_heater_enable(s_app.run); + app_buzzer_beep(); + any_change = true; + } + old_pushed = pushed; + + + int16_t wheel_change = (int16_t)(s_app.wheel - old_wheel); + if (wheel_change != 0) { + s_app.wheel_normed += wheel_change; + if (s_app.wheel_normed < 0) { + s_app.wheel_normed = 0; + } + if (s_app.wheel_normed > 500) { + s_app.wheel_normed = 500; + } + + int16_t old_temp = s_app.set_temp; + + s_app.set_temp = (s_app.wheel_normed / 2) * 5; + + if (old_temp != s_app.set_temp) { + app_buzzer_beep(); + app_heater_set_target((float) s_app.set_temp); + any_change = true; + } + } + + uint32_t now = osKernelGetTickCount(); + if (any_change || (now - last_redraw > pdMS_TO_TICKS(500))) { + last_redraw = now; + redraw_display(); + any_change = false; + + // Blink + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + + // feed dogs + HAL_IWDG_Refresh(&hiwdg); + } +} diff --git a/Core/Src/app_pid.c b/Core/Src/app_pid.c index 72946ec..fe1ae0f 100644 --- a/Core/Src/app_pid.c +++ b/Core/Src/app_pid.c @@ -3,6 +3,7 @@ #include #include #include +#include static void clampOutput(struct PID *self) { @@ -16,21 +17,29 @@ static void clampIterm(struct PID *self) else if (self->ITerm < self->outMin) { self->ITerm = self->outMin; } } -void PID_Compute(struct PID *self, float Input) +void PID_Compute(struct PID *self, float input) { - if (!self->ctlMode) { return; } - self->Input = Input; + if (self->ctlMode != PID_AUTOMATIC) { return; } + self->Input = input; uint32_t now = xTaskGetTickCount(); - int32_t timeChange = (now - self->lastTime) * (uint32_t) 1000 / (uint32_t) configTICK_RATE_HZ; - if (timeChange >= self->SampleTime) { + int32_t timeChange = (now - self->lastTime); + if (timeChange >= self->SampleTimeTicks) { + printf("compute\r\n"); /*Compute all the working error variables*/ - float error = self->Setpoint - Input; + float error = self->Setpoint - input; self->ITerm += (self->ki * error); clampIterm(self); - float dInput = (Input - self->lastInput); + float dInput = (input - self->lastInput); + + + printf("calc x100 %d + %d - %d\r\n", + (int) (100 * (self->kp * error)), + (int) (100 * (self->ITerm)), + (int) (100 * (self->kd * dInput)) + ); /*Compute PID Output*/ self->Output = self->kp * error + self->ITerm - self->kd * dInput; @@ -38,21 +47,21 @@ void PID_Compute(struct PID *self, float Input) clampOutput(self); /*Remember some variables for next time*/ - self->lastInput = Input; + self->lastInput = input; self->lastTime = now; } } -void PID_SetSetpoint(struct PID *self, float Setpoint) +void PID_SetSetpoint(struct PID *self, float setpoint) { - self->Setpoint = Setpoint; + self->Setpoint = setpoint; } void PID_SetTunings(struct PID *self, float Kp, float Ki, float Kd) { if (Kp < 0 || Ki < 0 || Kd < 0) { return; } - float SampleTimeInSec = ((float) self->SampleTime) / 1000; + float SampleTimeInSec = ((float) self->SampleTimeTicks) / configTICK_RATE_HZ; self->kp = Kp; self->ki = Ki * SampleTimeInSec; self->kd = Kd / SampleTimeInSec; @@ -64,34 +73,34 @@ void PID_SetTunings(struct PID *self, float Kp, float Ki, float Kd) } } -void PID_SetSampleTime(struct PID *self, uint32_t NewSampleTime) +void PID_SetSampleTime(struct PID *self, uint32_t new_sample_time) { - if (NewSampleTime > 0) { - float ratio = (float) NewSampleTime - / (float) self->SampleTime; + if (new_sample_time > 0) { + float ratio = (float) new_sample_time + / (float) self->SampleTimeTicks; self->ki *= ratio; self->kd /= ratio; - self->SampleTime = (uint32_t) NewSampleTime; + self->SampleTimeTicks = (uint32_t) new_sample_time; } } -void PID_SetOutputLimits(struct PID *self, float Min, float Max) +void PID_SetOutputLimits(struct PID *self, float min, float max) { - if (Min > Max) { return; } - self->outMin = Min; - self->outMax = Max; + if (min > max) { return; } + self->outMin = min; + self->outMax = max; clampOutput(self); clampIterm(self); } -void PID_SetCtlMode(struct PID *self, enum PIDCtlMode Mode) +void PID_SetCtlMode(struct PID *self, enum PIDCtlMode mode) { - bool newAuto = (Mode == PID_AUTOMATIC); - if (newAuto == !self->ctlMode) { /*we just went from manual to auto*/ + if (mode == PID_AUTOMATIC && self->ctlMode == PID_MANUAL) { + /*we just went from manual to auto*/ PID_Initialize(self); } - self->ctlMode = newAuto; + self->ctlMode = mode; } void PID_Initialize(struct PID *self) @@ -102,7 +111,7 @@ void PID_Initialize(struct PID *self) clampIterm(self); } -void PID_SetControllerDirection(struct PID *self, enum PIDDirection Direction) +void PID_SetControllerDirection(struct PID *self, enum PIDDirection direction) { - self->controllerDirection = Direction; + self->controllerDirection = direction; } diff --git a/Core/Src/app_pid.h b/Core/Src/app_pid.h index 9cf2330..a84bfb6 100644 --- a/Core/Src/app_pid.h +++ b/Core/Src/app_pid.h @@ -25,28 +25,28 @@ struct PID { float Input, Output, Setpoint; float ITerm, lastInput; float kp, ki, kd; - uint32_t SampleTime; // millis + uint32_t SampleTimeTicks; float outMin, outMax; enum PIDCtlMode ctlMode; // false enum PIDDirection controllerDirection; }; -#define PID_DEFAULT() { .SampleTime = 1000, .ctlMode=PID_MANUAL, .controllerDirection=PID_DIRECT } +#define PID_DEFAULT() { .SampleTimeMs = 1000, .ctlMode=PID_MANUAL, .controllerDirection=PID_DIRECT } -void PID_Compute(struct PID *self, float Input); +void PID_Compute(struct PID *self, float input); void PID_SetTunings(struct PID *self, float Kp, float Ki, float Kd); -void PID_SetSampleTime(struct PID *self, uint32_t NewSampleTime); +void PID_SetSampleTime(struct PID *self, uint32_t new_sample_time); -void PID_SetOutputLimits(struct PID *self, float Min, float Max); +void PID_SetOutputLimits(struct PID *self, float min, float max); -void PID_SetCtlMode(struct PID *self, enum PIDCtlMode Mode); +void PID_SetCtlMode(struct PID *self, enum PIDCtlMode mode); void PID_Initialize(struct PID *self); -void PID_SetSetpoint(struct PID *self, float Setpoint); +void PID_SetSetpoint(struct PID *self, float setpoint); -void PID_SetControllerDirection(struct PID *self, enum PIDDirection Direction); +void PID_SetControllerDirection(struct PID *self, enum PIDDirection direction); #endif //ARDUINOPID_H diff --git a/Core/Src/app_analog.c b/Core/Src/app_temp.c similarity index 85% rename from Core/Src/app_analog.c rename to Core/Src/app_temp.c index f8a9551..a19213c 100644 --- a/Core/Src/app_analog.c +++ b/Core/Src/app_temp.c @@ -6,7 +6,7 @@ #include #include #include -#include "app_analog.h" +#include "app_temp.h" #include "adc.h" /* DMA dest */ @@ -159,19 +159,27 @@ static float val_to_c(float val) return TSENSE_T_MAX; } -float app_analog_get_temp() +void app_temp_sample() { uint32_t sums[4] = {}; + int count = 0; for (int i = 0; i < AVERAGEBUF_DEPTH * 4; i += 4) { - sums[0] += s_analog.adc_averagebuf[i]; - sums[1] += s_analog.adc_averagebuf[i + 1]; - sums[2] += s_analog.adc_averagebuf[i + 2]; - sums[3] += s_analog.adc_averagebuf[i + 3]; + if (s_analog.adc_averagebuf[i + 3] != 0) { + sums[0] += s_analog.adc_averagebuf[i]; + sums[1] += s_analog.adc_averagebuf[i + 1]; + sums[2] += s_analog.adc_averagebuf[i + 2]; + sums[3] += s_analog.adc_averagebuf[i + 3]; + count++; + } + } + if (count == 0) { + return; } - s_analog.adc_averages[0] = (float) sums[0] / AVERAGEBUF_DEPTH; - s_analog.adc_averages[1] = (float) sums[1] / AVERAGEBUF_DEPTH; - s_analog.adc_averages[2] = (float) sums[2] / AVERAGEBUF_DEPTH; - s_analog.adc_averages[3] = (float) sums[3] / AVERAGEBUF_DEPTH; + + s_analog.adc_averages[0] = (float) sums[0] / count; + s_analog.adc_averages[1] = (float) sums[1] / count; + s_analog.adc_averages[2] = (float) sums[2] / count; + s_analog.adc_averages[3] = (float) sums[3] / count; /* r_pt100, r_ref, internal_temp, v_ref_int */ float refint = s_analog.adc_averages[3]; @@ -193,15 +201,29 @@ float app_analog_get_temp() s_analog.oventemp_history_ptr = (s_analog.oventemp_history_ptr + 1) % OVENTEMP_HISTORY_DEPTH; float sum = 0; + int depth = 0; for (int i = 0; i < OVENTEMP_HISTORY_DEPTH; i++) { - sum += s_analog.oventemp_history[i]; + if (s_analog.oventemp_history[i] > 0.0f) { + sum += s_analog.oventemp_history[i]; + depth++; + } + } + if (depth > 0) { + sum /= depth; } - sum /= OVENTEMP_HISTORY_DEPTH; s_analog.oven_temp = sum; +} +float app_temp_read_oven() +{ return s_analog.oven_temp; } +float app_temp_read_soc() +{ + return s_analog.soc_temp; +} + void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { // notify diff --git a/Core/Src/app_temp.h b/Core/Src/app_temp.h new file mode 100644 index 0000000..af0d4c8 --- /dev/null +++ b/Core/Src/app_temp.h @@ -0,0 +1,27 @@ +/** + * TODO file description + */ + +#ifndef BLUEPILLTROUBA_APP_TEMP_H +#define BLUEPILLTROUBA_APP_TEMP_H + +void app_analog_init(); + +/** + * Update temperature measurement. + * + * A slow float calculation is done here - call only when needed, at a roughly constant rate (e.g. 1s) to make smoothing work properly. + * + * The oven temp is further averaged internally. + */ +void app_temp_sample(); + +/// Read current oven temperature (celsius) +/// The value is valid after calling app_temp_sample() +float app_temp_read_oven(); + +/// Read current SOC temperature (celsius) +/// The value is valid after calling app_temp_sample() +float app_temp_read_soc(); + +#endif //BLUEPILLTROUBA_APP_TEMP_H diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c index fead74c..1b2c942 100644 --- a/Core/Src/freertos.c +++ b/Core/Src/freertos.c @@ -31,6 +31,10 @@ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ +typedef StaticTask_t osStaticThreadDef_t; +typedef StaticQueue_t osStaticMessageQDef_t; +typedef StaticTimer_t osStaticTimerDef_t; +typedef StaticSemaphore_t osStaticMutexDef_t; /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ @@ -49,20 +53,79 @@ /* USER CODE BEGIN Variables */ /* USER CODE END Variables */ -/* Definitions for defaultTask */ -osThreadId_t defaultTaskHandle; -const osThreadAttr_t defaultTask_attributes = { - .name = "defaultTask", - .stack_size = 128 * 4, +/* Definitions for mainTsk */ +osThreadId_t mainTskHandle; +uint32_t defaultTaskBuffer[ 128 ]; +osStaticThreadDef_t defaultTaskControlBlock; +const osThreadAttr_t mainTsk_attributes = { + .name = "mainTsk", + .cb_mem = &defaultTaskControlBlock, + .cb_size = sizeof(defaultTaskControlBlock), + .stack_mem = &defaultTaskBuffer[0], + .stack_size = sizeof(defaultTaskBuffer), .priority = (osPriority_t) osPriorityNormal, }; +/* Definitions for heaterTsk */ +osThreadId_t heaterTskHandle; +uint32_t heaterTskBuffer[ 128 ]; +osStaticThreadDef_t heaterTskControlBlock; +const osThreadAttr_t heaterTsk_attributes = { + .name = "heaterTsk", + .cb_mem = &heaterTskControlBlock, + .cb_size = sizeof(heaterTskControlBlock), + .stack_mem = &heaterTskBuffer[0], + .stack_size = sizeof(heaterTskBuffer), + .priority = (osPriority_t) osPriorityNormal, +}; +/* Definitions for guiTsk */ +osThreadId_t guiTskHandle; +uint32_t guiTskBuffer[ 128 ]; +osStaticThreadDef_t guiTskControlBlock; +const osThreadAttr_t guiTsk_attributes = { + .name = "guiTsk", + .cb_mem = &guiTskControlBlock, + .cb_size = sizeof(guiTskControlBlock), + .stack_mem = &guiTskBuffer[0], + .stack_size = sizeof(guiTskBuffer), + .priority = (osPriority_t) osPriorityHigh, +}; +/* Definitions for guiEventQue */ +osMessageQueueId_t guiEventQueHandle; +uint8_t guiEventQueBuffer[ 16 * 8 ]; +osStaticMessageQDef_t guiEventQueControlBlock; +const osMessageQueueAttr_t guiEventQue_attributes = { + .name = "guiEventQue", + .cb_mem = &guiEventQueControlBlock, + .cb_size = sizeof(guiEventQueControlBlock), + .mq_mem = &guiEventQueBuffer, + .mq_size = sizeof(guiEventQueBuffer) +}; +/* Definitions for beepTimer */ +osTimerId_t beepTimerHandle; +osStaticTimerDef_t beepTimerControlBlock; +const osTimerAttr_t beepTimer_attributes = { + .name = "beepTimer", + .cb_mem = &beepTimerControlBlock, + .cb_size = sizeof(beepTimerControlBlock), +}; +/* Definitions for heaterMutex */ +osMutexId_t heaterMutexHandle; +osStaticMutexDef_t heaterMutexControlBlock; +const osMutexAttr_t heaterMutex_attributes = { + .name = "heaterMutex", + .cb_mem = &heaterMutexControlBlock, + .cb_size = sizeof(heaterMutexControlBlock), +}; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ -void StartDefaultTask(void *argument); +void app_task_main(void *argument); +extern void app_task_heater(void *argument); +extern void app_task_gui(void *argument); +extern void app_beep_end(void *argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ @@ -104,6 +167,9 @@ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ + /* Create the mutex(es) */ + /* creation of heaterMutex */ + heaterMutexHandle = osMutexNew(&heaterMutex_attributes); /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ @@ -113,17 +179,31 @@ void MX_FREERTOS_Init(void) { /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ + /* Create the timer(s) */ + /* creation of beepTimer */ + beepTimerHandle = osTimerNew(app_beep_end, osTimerOnce, NULL, &beepTimer_attributes); + /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ + /* Create the queue(s) */ + /* creation of guiEventQue */ + guiEventQueHandle = osMessageQueueNew (16, 8, &guiEventQue_attributes); + /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ - /* creation of defaultTask */ - defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); + /* creation of mainTsk */ + mainTskHandle = osThreadNew(app_task_main, NULL, &mainTsk_attributes); + + /* creation of heaterTsk */ + heaterTskHandle = osThreadNew(app_task_heater, NULL, &heaterTsk_attributes); + + /* creation of guiTsk */ + guiTskHandle = osThreadNew(app_task_gui, NULL, &guiTsk_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ @@ -135,19 +215,22 @@ void MX_FREERTOS_Init(void) { } -/* USER CODE BEGIN Header_StartDefaultTask */ +/* USER CODE BEGIN Header_app_task_main */ /** - * @brief Function implementing the defaultTask thread. + * @brief Function implementing the mainTsk thread. * @param argument: Not used * @retval None */ -/* USER CODE END Header_StartDefaultTask */ -void StartDefaultTask(void *argument) +/* USER CODE END Header_app_task_main */ +__weak void app_task_main(void *argument) { - /* USER CODE BEGIN StartDefaultTask */ - app_main_task(argument); - vTaskDelete(NULL); - /* USER CODE END StartDefaultTask */ + /* USER CODE BEGIN app_task_main */ + /* Infinite loop */ + for(;;) + { + osDelay(1); + } + /* USER CODE END app_task_main */ } /* Private application code --------------------------------------------------*/ diff --git a/Core/Src/tim.c b/Core/Src/tim.c index a89d69f..2db92f7 100644 --- a/Core/Src/tim.c +++ b/Core/Src/tim.c @@ -123,7 +123,7 @@ void MX_TIM3_Init(void) Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 32000; + sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) diff --git a/Makefile b/Makefile index 0a2e579..3c3f638 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Mon Mar 06 21:48:34 CET 2023] +# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Tue Mar 07 00:54:18 CET 2023] ########################################################################################################################## # ------------------------------------------------ @@ -45,9 +45,10 @@ Core/Src/spi.c \ Core/Src/tim.c \ Core/Src/usart.c \ Core/Src/oled.c \ -Core/Src/app.c \ +Core/Src/app_main.c \ Core/Src/app_pid.c \ -Core/Src/app_analog.c \ +Core/Src/app_gui.c \ +Core/Src/app_temp.c \ Core/Src/app_knob.c \ Core/Src/app_buzzer.c \ Core/Src/app_heater.c \