Skip to content

Commit

Permalink
feat(hepa-uv): add current sensing for the uv lights.
Browse files Browse the repository at this point in the history
  • Loading branch information
vegano1 committed Mar 20, 2024
1 parent a6476b3 commit e871a4c
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 10 deletions.
6 changes: 4 additions & 2 deletions hepa-uv/core/tasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#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/uv_control_hardware.hpp"
#include "hepa-uv/firmware/utility_gpio.h"

#pragma GCC diagnostic push
Expand Down Expand Up @@ -56,6 +57,7 @@ void hepauv_tasks::start_tasks(
can::bus::CanBus& can_bus,
gpio_drive_hardware::GpioDrivePins& gpio_drive_pins,
hepa_control_hardware::HepaControlHardware& hepa_hardware,
uv_control_hardware::UVControlHardware& uv_hardware,
led_control_hardware::LEDControlHardware& led_hardware,
i2c::hardware::I2CBase& i2c2,
eeprom::hardware_iface::EEPromHardwareIface& eeprom_hw_iface) {
Expand All @@ -72,8 +74,8 @@ void hepauv_tasks::start_tasks(

auto& hepa_task = hepa_task_builder.start(5, "hepa_fan", gpio_drive_pins,
hepa_hardware, queues, queues);
auto& uv_task =
uv_task_builder.start(5, "uv_ballast", gpio_drive_pins, queues, queues);
auto& uv_task = uv_task_builder.start(5, "uv_ballast", gpio_drive_pins,
uv_hardware, queues, queues);
auto& led_control_task =
led_control_task_builder.start(5, "push_button_leds", led_hardware);

Expand Down
2 changes: 2 additions & 0 deletions hepa-uv/firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ 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_task/hepa_control_hardware.cpp
${CMAKE_CURRENT_SOURCE_DIR}/uv_control_task/uv_control_hardware.cpp
${COMMON_EXECUTABLE_DIR}/system/iwdg.cpp
${CAN_FW_DIR}/hal_can_bus.cpp
${CAN_FW_DIR}/utils.c
Expand All @@ -27,6 +28,7 @@ set(HEPAUV_FW_NON_LINTABLE_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/utility_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/timer_hardware.c
${CMAKE_CURRENT_SOURCE_DIR}/hepa_hardware.c
${CMAKE_CURRENT_SOURCE_DIR}/uv_hardware.c
${CMAKE_CURRENT_SOURCE_DIR}/led_hardware.c
${CMAKE_CURRENT_SOURCE_DIR}/can.c
${CMAKE_CURRENT_SOURCE_DIR}/i2c_setup.c
Expand Down
6 changes: 5 additions & 1 deletion hepa-uv/firmware/main_rev1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
#include "hepa-uv/core/messages.hpp"
#include "hepa-uv/core/tasks.hpp"
#include "hepa-uv/firmware/hepa_control_hardware.hpp"
#include "hepa-uv/firmware/uv_control_hardware.hpp"
#include "hepa-uv/firmware/led_control_hardware.hpp"
#include "hepa-uv/firmware/utility_gpio.h"
#include "i2c/firmware/i2c_comms.hpp"
#include "timer_hardware.h"
#include "uv_hardware.h"

static auto iWatchdog = iwdg::IndependentWatchDog{};

Expand Down Expand Up @@ -149,12 +151,14 @@ 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();
static auto uv_hardware = uv_control_hardware::UVControlHardware();

auto main() -> int {
HardwareInit();
RCC_Peripheral_Clock_Select();
utility_gpio_init();
initialize_pwm_hardware();
initialize_adc_hardware();
// set push button leds white
led_hardware.set_button_led_power(HEPA_BUTTON, 0, 0, 0, 50);
led_hardware.set_button_led_power(UV_BUTTON, 0, 0, 0, 50);
Expand All @@ -166,7 +170,7 @@ auto main() -> int {

canbus.start(can_bit_timings);

hepauv_tasks::start_tasks(canbus, gpio_drive_pins, hepa_hardware,
hepauv_tasks::start_tasks(canbus, gpio_drive_pins, hepa_hardware, uv_hardware,
led_hardware, i2c_comms2, eeprom_hw_iface);

iWatchdog.start(6);
Expand Down
2 changes: 1 addition & 1 deletion hepa-uv/firmware/utility_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void utility_gpio_init(void) {
reed_switch_input_gpio_init();
aux_input_gpio_init();
hepa_push_button_input_gpio_init();
uv_push_button_input_gpio_init();
hepa_on_off_output_init();
uv_push_button_input_gpio_init();
uv_on_off_output_init();
}
9 changes: 9 additions & 0 deletions hepa-uv/firmware/uv_control_task/uv_control_hardware.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "hepa-uv/firmware/uv_control_hardware.hpp"

#include "hepa-uv/firmware/uv_hardware.h"

using namespace uv_control_hardware;

uint32_t UVControlHardware::get_uv_light_voltage() {
return get_uv_light_voltage_reading();
}
106 changes: 106 additions & 0 deletions hepa-uv/firmware/uv_hardware.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include "hepa-uv/firmware/uv_hardware.h"
#include "hepa-uv/firmware/utility_gpio.h"
#include "common/firmware/errors.h"

#include "platform_specific_hal_conf.h"
#include "system_stm32g4xx.h"

ADC_HandleTypeDef hadc1;
ADC_ChannelConfTypeDef hadc1_sConfig = {0};

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hadc->Instance == ADC1) {
__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/** ADC1 GPIO Configuration
PA0 ------> ADC1_IN1
*/
GPIO_InitStruct.Pin = UV_SNS_MCU_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(UV_SNS_MCU_PORT, &GPIO_InitStruct);
}
}

static void MX_ADC_Init(ADC_TypeDef* adc, uint32_t channel) {
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef* hadc_sConfig;
ADC_HandleTypeDef* hadc;

if (adc == ADC1) {
hadc = &hadc1;
hadc_sConfig = &hadc1_sConfig;
} else {
Error_Handler();
return;
}

hadc->Instance = adc;
hadc->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc->Init.Resolution = ADC_RESOLUTION_12B;
hadc->Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc->Init.GainCompensation = 0;
hadc->Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc->Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc->Init.LowPowerAutoWait = DISABLE;
hadc->Init.ContinuousConvMode = DISABLE;
hadc->Init.NbrOfConversion = 1;
hadc->Init.DiscontinuousConvMode = DISABLE;
hadc->Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc->Init.DMAContinuousRequests = DISABLE;
hadc->Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc->Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(hadc) != HAL_OK) Error_Handler();

// Configure the ADC multi-mode
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(hadc, &multimode) != HAL_OK)
{
Error_Handler();
}

// Configure Regular Channel
hadc_sConfig->Channel = channel;
hadc_sConfig->Rank = ADC_REGULAR_RANK_1;
hadc_sConfig->SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
hadc_sConfig->SingleDiff = ADC_DIFFERENTIAL_ENDED;
hadc_sConfig->OffsetNumber = ADC_OFFSET_NONE;
hadc_sConfig->Offset = 0;
if (HAL_ADC_ConfigChannel(hadc, hadc_sConfig) != HAL_OK)
{
Error_Handler();
}
}

uint32_t get_adc_reading(ADC_HandleTypeDef* hadc, uint32_t channel) {
// Calibrate the ADC to get more accurate reading
if (HAL_ADCEx_Calibration_Start(hadc, ADC_DIFFERENTIAL_ENDED) != HAL_OK) Error_Handler();

// Configure the Channel
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5;
if (HAL_ADC_ConfigChannel(hadc, &sConfig) != HAL_OK) Error_Handler();

// Start The adc
if (HAL_ADC_Start(hadc) != HAL_OK) Error_Handler();
// Wait for convertion and stop adc
HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY);
HAL_ADC_Stop(hadc);
// return the adc conversion result
return HAL_ADC_GetValue(hadc);
}

uint32_t get_uv_light_voltage_reading(void) {
uint32_t adc_reading = get_adc_reading(&hadc1, ADC_CHANNEL_1);
// mvolts = (ADC Reading * System mV) / 12-bit adc resolution
return (uint32_t)(adc_reading*3300)/4095;;
}

void initialize_adc_hardware() {
// Initialize the adc for uv current sense
MX_ADC_Init(ADC1, ADC_CHANNEL_1);
}
18 changes: 18 additions & 0 deletions hepa-uv/firmware/uv_hardware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <stdint.h>

#include "platform_specific_hal_conf.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

extern ADC_HandleTypeDef hadc1;
extern ADC_ChannelConfTypeDef hadc1_sConfig;

void initialize_adc_hardware();

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
2 changes: 2 additions & 0 deletions include/can/core/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,13 +1709,15 @@ struct GetHepaUVStateResponse
uint32_t timeout_s;
uint8_t uv_light_on;
uint32_t remaining_time_s;
uint32_t uv_voltage_mv;

template <bit_utils::ByteIterator Output, typename Limit>
auto serialize(Output body, Limit limit) const -> uint8_t {
auto iter = bit_utils::int_to_bytes(message_index, body, limit);
iter = bit_utils::int_to_bytes(timeout_s, iter, limit);
iter = bit_utils::int_to_bytes(uv_light_on, iter, limit);
iter = bit_utils::int_to_bytes(remaining_time_s, iter, limit);
iter = bit_utils::int_to_bytes(uv_voltage_mv, iter, limit);
return iter - body;
}

Expand Down
17 changes: 16 additions & 1 deletion include/hepa-uv/core/interfaces.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,19 @@ class HepaControlInterface {

virtual auto set_hepa_fan_speed(uint32_t duty_cycle) -> void = 0;
};
} // namespace hepa_control
} // namespace hepa_control

namespace uv_control {

class UVControlInterface {
public:
UVControlInterface() = default;
UVControlInterface(const UVControlInterface&) = delete;
UVControlInterface(UVControlInterface&&) = delete;
auto operator=(UVControlInterface&&) -> UVControlInterface& = delete;
auto operator=(const UVControlInterface&) -> UVControlInterface& = delete;
virtual ~UVControlInterface() = default;

virtual auto get_uv_light_voltage(void) -> uint32_t = 0;
};
} // namespace uv_control
2 changes: 2 additions & 0 deletions include/hepa-uv/core/tasks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "hepa-uv/core/uv_task.hpp"
#include "hepa-uv/firmware/gpio_drive_hardware.hpp"
#include "hepa-uv/firmware/hepa_control_hardware.hpp"
#include "hepa-uv/firmware/uv_control_hardware.hpp"
#include "hepa-uv/firmware/led_control_hardware.hpp"
#include "i2c/core/hardware_iface.hpp"
#include "i2c/core/tasks/i2c_poller_task.hpp"
Expand All @@ -24,6 +25,7 @@ namespace hepauv_tasks {
void start_tasks(can::bus::CanBus& can_bus,
gpio_drive_hardware::GpioDrivePins& gpio_drive_pins,
hepa_control_hardware::HepaControlHardware& hepa_hardware,
uv_control_hardware::UVControlHardware& uv_hardware,
led_control_hardware::LEDControlHardware& led_hardware,
i2c::hardware::I2CBase& i2c2,
eeprom::hardware_iface::EEPromHardwareIface& eeprom_hw_iface);
Expand Down
23 changes: 18 additions & 5 deletions include/hepa-uv/core/uv_task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "hepa-uv/core/led_control_task.hpp"
#include "hepa-uv/core/messages.hpp"
#include "hepa-uv/firmware/gpio_drive_hardware.hpp"
#include "hepa-uv/firmware/uv_control_hardware.hpp"
#include "ot_utils/freertos/freertos_timer.hpp"

namespace uv_task {
Expand All @@ -22,10 +23,13 @@ template <led_control_task::TaskClient LEDControlClient,
can::message_writer_task::TaskClient CanClient>
class UVMessageHandler {
public:
explicit UVMessageHandler(gpio_drive_hardware::GpioDrivePins &drive_pins,
LEDControlClient &led_control_client,
CanClient &can_client)
explicit UVMessageHandler(
gpio_drive_hardware::GpioDrivePins &drive_pins,
uv_control_hardware::UVControlHardware &uv_hardware,
LEDControlClient &led_control_client,
CanClient &can_client)
: drive_pins{drive_pins},
uv_hardware{uv_hardware},
led_control_client{led_control_client},
can_client{can_client},
_timer(
Expand Down Expand Up @@ -90,7 +94,8 @@ class UVMessageHandler {
.message_index = m.message_index,
.timeout_s = uv_off_timeout_s,
.uv_light_on = uv_light_on,
.remaining_time_s = (_timer.get_remaining_time() / 1000)};
.remaining_time_s = (_timer.get_remaining_time() / 1000),
.uv_voltage_mv = uv_voltage_mv};
can_client.send_can_message(can::ids::NodeId::host, resp);
}

Expand Down Expand Up @@ -121,6 +126,7 @@ class UVMessageHandler {
}
uv_push_button = false;
uv_light_on = false;
uv_voltage_mv = 0;
return;
}

Expand All @@ -147,6 +153,9 @@ class UVMessageHandler {
if (_timer.is_running()) _timer.stop();
}

// Update the voltage usage of the uv light
uv_voltage_mv = uv_hardware.get_uv_light_voltage();

// TODO: send state change CAN message to host
}

Expand All @@ -156,8 +165,10 @@ class UVMessageHandler {
bool uv_push_button = false;
bool uv_light_on = false;
uint32_t uv_off_timeout_s = DELAY_S;
uint32_t uv_voltage_mv = 0;

gpio_drive_hardware::GpioDrivePins &drive_pins;
uv_control_hardware::UVControlHardware &uv_hardware;
LEDControlClient &led_control_client;
CanClient &can_client;
ot_utils::freertos_timer::FreeRTOSTimer _timer;
Expand Down Expand Up @@ -185,10 +196,12 @@ class UVTask {
template <led_control_task::TaskClient LEDControlClient,
can::message_writer_task::TaskClient CanClient>
[[noreturn]] void operator()(gpio_drive_hardware::GpioDrivePins *drive_pins,
uv_control_hardware::UVControlHardware *uv_hardware,
LEDControlClient *led_control_client,
CanClient *can_client) {
auto handler =
UVMessageHandler{*drive_pins, *led_control_client, *can_client};
UVMessageHandler{*drive_pins, *uv_hardware,
*led_control_client, *can_client};
TaskMessage message{};
for (;;) {
if (queue.try_read(&message, queue.max_delay)) {
Expand Down
23 changes: 23 additions & 0 deletions include/hepa-uv/firmware/uv_control_hardware.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "hepa-uv/core/interfaces.hpp"

namespace uv_control_hardware {

class UVControlHardware : public uv_control::UVControlInterface {
public:
UVControlHardware() = default;
UVControlHardware(const UVControlHardware&) = delete;
UVControlHardware(UVControlHardware&&) = delete;
auto operator=(UVControlHardware&&) -> UVControlHardware& = delete;
auto operator=(const UVControlHardware&) -> UVControlHardware& = delete;
~UVControlHardware() final = default;

// TODO: (ba, 2024-03-18): Now that we have a uv control interface,
// lets migrate gpio.set/reset to it, so we can de-couple hardware
// specific functionality from logic so we can fix simulation.

uint32_t get_uv_light_voltage() final;
};

} // namespace uv_control_hardware
13 changes: 13 additions & 0 deletions include/hepa-uv/firmware/uv_hardware.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

uint32_t get_uv_light_voltage_reading(void);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

0 comments on commit e871a4c

Please sign in to comment.