From fd85844c48743501ad20f705ab9fa861eea3ca68 Mon Sep 17 00:00:00 2001 From: vegano1 Date: Mon, 22 Jan 2024 13:12:47 -0500 Subject: [PATCH] faet(hepa-uv): Add hardware control to drive hepa fan. --- hepa-uv/core/tasks.cpp | 6 +- hepa-uv/firmware/CMakeLists.txt | 2 + hepa-uv/firmware/hardware.c | 114 ++++++++++++++++++ hepa-uv/firmware/hepa_control_hardware.cpp | 9 ++ .../led_control_task/led_control_hardware.cpp | 2 +- hepa-uv/firmware/led_hardware.c | 2 +- hepa-uv/firmware/main_rev1.cpp | 8 +- include/hepa-uv/core/hepa_task.hpp | 14 ++- include/hepa-uv/core/interfaces.hpp | 35 ++++++ include/hepa-uv/core/led_control_task.hpp | 16 +-- include/hepa-uv/core/tasks.hpp | 4 +- include/hepa-uv/firmware/hardware.h | 16 +++ .../firmware/hepa_control_hardware.hpp | 22 ++++ .../hepa-uv/firmware/led_control_hardware.hpp | 4 +- include/hepa-uv/firmware/led_hardware.h | 2 +- 15 files changed, 229 insertions(+), 27 deletions(-) create mode 100644 hepa-uv/firmware/hardware.c create mode 100644 hepa-uv/firmware/hepa_control_hardware.cpp create mode 100644 include/hepa-uv/core/interfaces.hpp create mode 100644 include/hepa-uv/firmware/hardware.h create mode 100644 include/hepa-uv/firmware/hepa_control_hardware.hpp diff --git a/hepa-uv/core/tasks.cpp b/hepa-uv/core/tasks.cpp index b4195b269..77ab9925b 100644 --- a/hepa-uv/core/tasks.cpp +++ b/hepa-uv/core/tasks.cpp @@ -4,6 +4,7 @@ #include "common/core/freertos_timer.hpp" #include "hepa-uv/core/can_task.hpp" #include "hepa-uv/firmware/gpio_drive_hardware.hpp" +#include "hepa-uv/firmware/hepa_control_hardware.hpp" #include "hepa-uv/firmware/utility_gpio.h" #pragma GCC diagnostic push @@ -29,13 +30,14 @@ static auto led_control_task_builder = void hepauv_tasks::start_tasks( can::bus::CanBus& can_bus, gpio_drive_hardware::GpioDrivePins& gpio_drive_pins, - led_control_hardware::LEDControlHardware& led_hardware) { + led_control_hardware::LEDControlHardware& led_hardware, + hepa_control_hardware::HepaControlHardware& hepa_hardware) { auto& can_writer = can_task::start_writer(can_bus); can_task::start_reader(can_bus); // TODO: including led_hardware for testing, this should be a AssesorClient auto& hepa_task = - hepa_task_builder.start(5, "hepa_fan", gpio_drive_pins, led_hardware); + hepa_task_builder.start(5, "hepa_fan", gpio_drive_pins, led_hardware, hepa_hardware); auto& uv_task = uv_task_builder.start(5, "uv_ballast", gpio_drive_pins, led_hardware); auto& led_control_task = diff --git a/hepa-uv/firmware/CMakeLists.txt b/hepa-uv/firmware/CMakeLists.txt index 1e2f1f16f..a0932c198 100644 --- a/hepa-uv/firmware/CMakeLists.txt +++ b/hepa-uv/firmware/CMakeLists.txt @@ -13,6 +13,7 @@ set(REVISIONS hepa-rev1) set(HEPA_UV_FW_LINTABLE_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/freertos_idle_timer_task.cpp ${CMAKE_CURRENT_SOURCE_DIR}/led_control_task/led_control_hardware.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hepa_control_hardware.cpp ${COMMON_EXECUTABLE_DIR}/system/iwdg.cpp ${CAN_FW_DIR}/hal_can_bus.cpp ${CAN_FW_DIR}/utils.c @@ -25,6 +26,7 @@ set(HEPAUV_FW_NON_LINTABLE_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/clocking.c ${CMAKE_CURRENT_SOURCE_DIR}/utility_gpio.c ${CMAKE_CURRENT_SOURCE_DIR}/led_hardware.c + ${CMAKE_CURRENT_SOURCE_DIR}/hardware.c ${CMAKE_CURRENT_SOURCE_DIR}/can.c ${CMAKE_CURRENT_SOURCE_DIR}/i2c_setup.c ${COMMON_EXECUTABLE_DIR}/errors/errors.c diff --git a/hepa-uv/firmware/hardware.c b/hepa-uv/firmware/hardware.c new file mode 100644 index 000000000..afe84d074 --- /dev/null +++ b/hepa-uv/firmware/hardware.c @@ -0,0 +1,114 @@ +#include "hepa-uv/firmware/hardware.h" +#include "hepa-uv/firmware/utility_gpio.h" +#include "common/firmware/errors.h" + +#include "platform_specific_hal_conf.h" +#include "system_stm32g4xx.h" + +TIM_HandleTypeDef htim3; + +TIM_OC_InitTypeDef htim3_sConfigOC = {0}; + + +// void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_pwm) { +// if(htim_pwm->Instance == TIM3) { +// __HAL_RCC_TIM3_CLK_ENABLE(); +// } +// } + +// void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { +// GPIO_InitTypeDef GPIO_InitStruct = {0}; +// if (htim->Instance == TIM3) { +// __HAL_RCC_GPIOA_CLK_ENABLE(); +// /**TIM3 GPIO Configuration +// PA6 ------> TIM3_CH1 +// */ +// GPIO_InitStruct.Pin = HEPA_PWM_PIN; +// GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; +// GPIO_InitStruct.Pull = GPIO_NOPULL; +// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; +// GPIO_InitStruct.Alternate = GPIO_AF2_TIM3; +// HAL_GPIO_Init(HEPA_PWM_PORT, &GPIO_InitStruct); +// } +// } + +/** + * @brief TIM3 Initialization Function for HEPA_PWM + * @param None + * @retval None + */ +static void MX_TIM3_Init(void) { + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + htim3.State = HAL_TIM_STATE_RESET; + htim3.Instance = TIM3; + htim3.Init.Prescaler = 64 - 1; + htim3.Init.CounterMode = TIM_COUNTERMODE_UP; + htim3.Init.Period = 40 - 1; + htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim3.Init.RepetitionCounter = 0; + htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { + Error_Handler(); + } + if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != + HAL_OK) { + Error_Handler(); + } + htim3_sConfigOC.OCMode = TIM_OCMODE_PWM1; + // 0% duty cycle + htim3_sConfigOC.Pulse = 0; + htim3_sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + htim3_sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + htim3_sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + htim3_sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + htim3_sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim3, &htim3_sConfigOC, TIM_CHANNEL_1) != + HAL_OK) { + Error_Handler(); + } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.BreakFilter = 0; + sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; + sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; + sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; + sBreakDeadTimeConfig.Break2Filter = 0; + sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim3, &sBreakDeadTimeConfig) != + HAL_OK) { + Error_Handler(); + } + // HAL_TIM_MspPostInit(&htim3); +} + +void hepa_fan_hw_update_pwm(uint32_t duty_cycle) { + // update hepa fan speed + htim3.Instance->CCR1 = duty_cycle; +} + +void initialize_hardware() { + MX_TIM3_Init(); + + // Set the hepa fan speed to 0 + hepa_fan_hw_update_pwm(0); + + // Activate the channels + HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); +} diff --git a/hepa-uv/firmware/hepa_control_hardware.cpp b/hepa-uv/firmware/hepa_control_hardware.cpp new file mode 100644 index 000000000..27a77b4d1 --- /dev/null +++ b/hepa-uv/firmware/hepa_control_hardware.cpp @@ -0,0 +1,9 @@ +#include "hepa-uv/firmware/hepa_control_hardware.hpp" +#include "hepa-uv/firmware/hardware.h" + +using namespace hepa_control_hardware; + + +void HepaControlHardware::set_hepa_fan_speed(uint32_t duty_cycle) { + hepa_fan_hw_update_pwm(duty_cycle); +} \ No newline at end of file diff --git a/hepa-uv/firmware/led_control_task/led_control_hardware.cpp b/hepa-uv/firmware/led_control_task/led_control_hardware.cpp index e14822e75..76a89e80f 100644 --- a/hepa-uv/firmware/led_control_task/led_control_hardware.cpp +++ b/hepa-uv/firmware/led_control_task/led_control_hardware.cpp @@ -7,7 +7,7 @@ using namespace led_control_hardware; // NOLINTNEXTLINE(readability-convert-member-functions-to-static) auto LEDControlHardware::initialize() -> void { - button_led_hw_initialize_leds(); + button_hw_initialize_leds(); } void LEDControlHardware::set_button_led_power(uint8_t button, uint32_t r, diff --git a/hepa-uv/firmware/led_hardware.c b/hepa-uv/firmware/led_hardware.c index 6c6f431de..67a2ffb71 100644 --- a/hepa-uv/firmware/led_hardware.c +++ b/hepa-uv/firmware/led_hardware.c @@ -448,7 +448,7 @@ void set_button_led_pwm(PUSH_BUTTON_TYPE button, uint32_t red, uint32_t green, u button_led_hw_update_pwm(white, WHITE_LED, button); } -void button_led_hw_initialize_leds() { +void button_hw_initialize_leds() { MX_TIM1_Init(); MX_TIM8_Init(); MX_TIM16_Init(); diff --git a/hepa-uv/firmware/main_rev1.cpp b/hepa-uv/firmware/main_rev1.cpp index f800b4996..cd9545ae9 100644 --- a/hepa-uv/firmware/main_rev1.cpp +++ b/hepa-uv/firmware/main_rev1.cpp @@ -24,6 +24,8 @@ #include "hepa-uv/core/tasks.hpp" #include "hepa-uv/firmware/led_control_hardware.hpp" #include "hepa-uv/firmware/led_hardware.h" +#include "hepa-uv/firmware/hardware.h" +#include "hepa-uv/firmware/hepa_control_hardware.hpp" #include "hepa-uv/firmware/utility_gpio.h" static auto iWatchdog = iwdg::IndependentWatchDog{}; @@ -118,18 +120,20 @@ extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { } static auto led_hardware = led_control_hardware::LEDControlHardware(); +static auto hepa_hardware = hepa_control_hardware::HepaControlHardware(); auto main() -> int { HardwareInit(); RCC_Peripheral_Clock_Select(); utility_gpio_init(); - button_led_hw_initialize_leds(); + button_hw_initialize_leds(); + initialize_hardware(); app_update_clear_flags(); canbus.start(can_bit_timings); - hepauv_tasks::start_tasks(canbus, gpio_drive_pins, led_hardware); + hepauv_tasks::start_tasks(canbus, gpio_drive_pins, led_hardware, hepa_hardware); iWatchdog.start(6); diff --git a/include/hepa-uv/core/hepa_task.hpp b/include/hepa-uv/core/hepa_task.hpp index 6aace03a5..e25dafe50 100644 --- a/include/hepa-uv/core/hepa_task.hpp +++ b/include/hepa-uv/core/hepa_task.hpp @@ -9,6 +9,7 @@ #include "hepa-uv/core/messages.hpp" #include "hepa-uv/firmware/gpio_drive_hardware.hpp" #include "hepa-uv/firmware/led_control_hardware.hpp" +#include "hepa-uv/firmware/hepa_control_hardware.hpp" namespace hepa_task { @@ -18,8 +19,9 @@ class HepaMessageHandler { public: explicit HepaMessageHandler( gpio_drive_hardware::GpioDrivePins &drive_pins, - led_control_hardware::LEDControlHardware &led_hardware) - : drive_pins{drive_pins}, led_hardware{led_hardware} { + led_control_hardware::LEDControlHardware &led_hardware, + hepa_control_hardware::HepaControlHardware &hepa_hardware) + : drive_pins{drive_pins}, led_hardware{led_hardware}, hepa_hardware{hepa_hardware} { // get current state hepa_push_button = gpio::is_set(drive_pins.hepa_push_button); // turn off the HEPA fan @@ -45,9 +47,11 @@ class HepaMessageHandler { hepa_push_button = !hepa_push_button; // handle state changes here if (hepa_push_button) { + hepa_hardware.set_hepa_fan_speed(50); gpio::set(drive_pins.hepa_on_off); led_hardware.set_button_led_power(HEPA_BUTTON, 0, 50, 0, 0); } else { + hepa_hardware.set_hepa_fan_speed(0); gpio::reset(drive_pins.hepa_on_off); led_hardware.set_button_led_power(HEPA_BUTTON, 0, 0, 0, 50); } @@ -62,6 +66,7 @@ class HepaMessageHandler { gpio_drive_hardware::GpioDrivePins &drive_pins; led_control_hardware::LEDControlHardware &led_hardware; + hepa_control_hardware::HepaControlHardware &hepa_hardware; }; /** @@ -85,8 +90,9 @@ class HepaTask { */ [[noreturn]] void operator()( gpio_drive_hardware::GpioDrivePins *drive_pins, - led_control_hardware::LEDControlHardware *led_hardware) { - auto handler = HepaMessageHandler{*drive_pins, *led_hardware}; + led_control_hardware::LEDControlHardware *led_hardware, + hepa_control_hardware::HepaControlHardware *hepa_hardware) { + auto handler = HepaMessageHandler{*drive_pins, *led_hardware, *hepa_hardware}; TaskMessage message{}; for (;;) { if (queue.try_read(&message, queue.max_delay)) { diff --git a/include/hepa-uv/core/interfaces.hpp b/include/hepa-uv/core/interfaces.hpp new file mode 100644 index 000000000..ddaace920 --- /dev/null +++ b/include/hepa-uv/core/interfaces.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "hepa-uv/core/constants.h" + +namespace led_control { + +class LEDControlInterface { + public: + LEDControlInterface() = default; + LEDControlInterface(const LEDControlInterface&) = delete; + LEDControlInterface(LEDControlInterface&&) = delete; + auto operator=(LEDControlInterface&&) -> LEDControlInterface& = delete; + auto operator=(const LEDControlInterface&) -> LEDControlInterface& = delete; + virtual ~LEDControlInterface() = default; + + virtual auto set_button_led_power(uint8_t button, uint32_t r, uint32_t g, + uint32_t b, uint32_t w) -> void = 0; +}; + +} // led_control namespace + +namespace hepa_control { + +class HepaControlInterface { + public: + HepaControlInterface() = default; + HepaControlInterface(const HepaControlInterface&) = delete; + HepaControlInterface(HepaControlInterface&&) = delete; + auto operator=(HepaControlInterface&&) -> HepaControlInterface& = delete; + auto operator=(const HepaControlInterface&) -> HepaControlInterface& = delete; + virtual ~HepaControlInterface() = default; + + virtual void set_hepa_fan_speed(uint32_t duty_cycle); +}; +} // hepa_control namespace \ No newline at end of file diff --git a/include/hepa-uv/core/led_control_task.hpp b/include/hepa-uv/core/led_control_task.hpp index b7ee1fb86..2b9514ea0 100644 --- a/include/hepa-uv/core/led_control_task.hpp +++ b/include/hepa-uv/core/led_control_task.hpp @@ -5,23 +5,13 @@ #include "common/core/message_queue.hpp" #include "hepa-uv/core/constants.h" #include "hepa-uv/core/messages.hpp" +#include "hepa-uv/core/interfaces.hpp" namespace led_control_task { -using TaskMessage = led_control_task_messages::TaskMessage; +using namespace led_control; -class LEDControlInterface { - public: - LEDControlInterface() = default; - LEDControlInterface(const LEDControlInterface&) = delete; - LEDControlInterface(LEDControlInterface&&) = delete; - auto operator=(LEDControlInterface&&) -> LEDControlInterface& = delete; - auto operator=(const LEDControlInterface&) -> LEDControlInterface& = delete; - virtual ~LEDControlInterface() = default; - - virtual auto set_button_led_power(uint8_t button, uint32_t r, uint32_t g, - uint32_t b, uint32_t w) -> void = 0; -}; +using TaskMessage = led_control_task_messages::TaskMessage; class LEDControlMessageHandler { public: diff --git a/include/hepa-uv/core/tasks.hpp b/include/hepa-uv/core/tasks.hpp index 8cec19726..ab969b1bb 100644 --- a/include/hepa-uv/core/tasks.hpp +++ b/include/hepa-uv/core/tasks.hpp @@ -6,6 +6,7 @@ #include "hepa-uv/core/uv_task.hpp" #include "hepa-uv/firmware/gpio_drive_hardware.hpp" #include "hepa-uv/firmware/led_control_hardware.hpp" +#include "hepa-uv/firmware/hepa_control_hardware.hpp" namespace hepauv_tasks { @@ -14,7 +15,8 @@ namespace hepauv_tasks { */ void start_tasks(can::bus::CanBus& can_bus, gpio_drive_hardware::GpioDrivePins& gpio_drive_pins, - led_control_hardware::LEDControlHardware& led_hardware); + led_control_hardware::LEDControlHardware& led_hardware, + hepa_control_hardware::HepaControlHardware& hepa_hardware); /** * Access to all the message queues in the system. diff --git a/include/hepa-uv/firmware/hardware.h b/include/hepa-uv/firmware/hardware.h new file mode 100644 index 000000000..2ec4e6214 --- /dev/null +++ b/include/hepa-uv/firmware/hardware.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "hepa-uv/core/constants.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void hepa_fan_hw_update_pwm(uint32_t duty_cycle); +void initialize_hardware(); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/include/hepa-uv/firmware/hepa_control_hardware.hpp b/include/hepa-uv/firmware/hepa_control_hardware.hpp new file mode 100644 index 000000000..809060d04 --- /dev/null +++ b/include/hepa-uv/firmware/hepa_control_hardware.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "hepa-uv/core/interfaces.hpp" + +namespace hepa_control_hardware { + +using namespace hepa_control; + +class HepaControlHardware : public HepaControlInterface { + public: + HepaControlHardware() = default; + HepaControlHardware(const HepaControlHardware&) = delete; + HepaControlHardware(HepaControlHardware&&) = delete; + auto operator=(HepaControlHardware&&) -> HepaControlHardware& = delete; + auto operator=(const HepaControlHardware&) -> HepaControlHardware& = delete; + ~HepaControlHardware() final = default; + + auto initialize() -> void; + void set_hepa_fan_speed(uint32_t duty_cycle); +}; + +} // namespace led_control_hardware \ No newline at end of file diff --git a/include/hepa-uv/firmware/led_control_hardware.hpp b/include/hepa-uv/firmware/led_control_hardware.hpp index 095068492..13ced808a 100644 --- a/include/hepa-uv/firmware/led_control_hardware.hpp +++ b/include/hepa-uv/firmware/led_control_hardware.hpp @@ -1,10 +1,10 @@ #pragma once -#include "hepa-uv/core/led_control_task.hpp" +#include "hepa-uv/core/interfaces.hpp" namespace led_control_hardware { -class LEDControlHardware : public led_control_task::LEDControlInterface { +class LEDControlHardware : public led_control::LEDControlInterface { public: LEDControlHardware() = default; LEDControlHardware(const LEDControlHardware&) = delete; diff --git a/include/hepa-uv/firmware/led_hardware.h b/include/hepa-uv/firmware/led_hardware.h index db86e35ec..75ab0d022 100644 --- a/include/hepa-uv/firmware/led_hardware.h +++ b/include/hepa-uv/firmware/led_hardware.h @@ -17,7 +17,7 @@ extern "C" { void set_button_led_pwm(PUSH_BUTTON_TYPE button, uint32_t red, uint32_t green, uint32_t blue, uint32_t white); void button_led_hw_update_pwm(uint32_t duty_cycle, LED_TYPE led, PUSH_BUTTON_TYPE button); -void button_led_hw_initialize_leds(); +void button_hw_initialize_leds(); #ifdef __cplusplus } // extern "C"