From 9d08b7df59a27b21c6fa165f2a88be7739e4ec21 Mon Sep 17 00:00:00 2001 From: dooku Date: Sun, 6 Jun 2021 08:19:20 +0200 Subject: [PATCH] Added soft PWM --- fw/Core/Inc/led.h | 52 +++++++++++++ fw/Core/Inc/main.h | 2 +- fw/Core/Src/led.c | 121 +++++++++++++++++++++++++++++++ fw/Core/Src/main.c | 39 ++++++---- fw/Core/Src/stm32l0xx_it.c | 3 +- fw/iaq_wired_sensor Debug.launch | 1 + 6 files changed, 202 insertions(+), 16 deletions(-) create mode 100644 fw/Core/Inc/led.h create mode 100644 fw/Core/Src/led.c diff --git a/fw/Core/Inc/led.h b/fw/Core/Inc/led.h new file mode 100644 index 0000000..7031759 --- /dev/null +++ b/fw/Core/Inc/led.h @@ -0,0 +1,52 @@ +/* + * led.h + * + * Created on: Jun 6, 2021 + * Author: user + */ + +#ifndef INC_LED_H_ +#define INC_LED_H_ + +#include "stdint.h" +#include "stm32l0xx_hal.h" + +/* + * Context struct + */ + +typedef struct { + GPIO_TypeDef *red_led_port; + int red_led_pin; + GPIO_TypeDef *green_led_port; + int green_led_pin; + GPIO_TypeDef *blue_led_port; + int blue_led_pin; + +} led_context_t; + +/* + * Externally defined variables + */ + +extern int led_pwm_max; +extern int led_pwm_counter; +extern int led_red_intensity; +extern int led_green_intensity; +extern int led_blue_intensity; + +/* + * Function prototypes + */ + +void led_test(); +void led_set_color(float red, float green, float blue); +// led_off(): turn off all LEDs +void led_off(); +// led_pwm_handler(): handles switching LEDs on/off according to desired intensity; +// should be regularly called in timer routine, preferably in SysTick_Handler() +void led_pwm_handler(); +void led_init(led_context_t *context, int pwm_freq, int pwm_handler_freq); +void led_test(int r, int g, int b); + +#endif /* INC_LED_H_ */ diff --git a/fw/Core/Inc/main.h b/fw/Core/Inc/main.h index 85dd1dc..f4efcd0 100644 --- a/fw/Core/Inc/main.h +++ b/fw/Core/Inc/main.h @@ -32,7 +32,7 @@ extern "C" { /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "led.h" /* USER CODE END Includes */ /* Exported types ------------------------------------------------------------*/ diff --git a/fw/Core/Src/led.c b/fw/Core/Src/led.c new file mode 100644 index 0000000..96a35d0 --- /dev/null +++ b/fw/Core/Src/led.c @@ -0,0 +1,121 @@ +/* + * led.c + * + * Created on: Jun 6, 2021 + * Author: user + */ + +#include "led.h" + +/* + * Global variables + */ + +int led_pwm_max; +int led_pwm_counter; +int led_red_intensity; +int led_green_intensity; +int led_blue_intensity; +int led_red_state; +int led_green_state; +int led_blue_state; +led_context_t *led_context; + +/* + * Functions + */ + +/* + * led_set_color(): + * Set LED color + * Arguments: + * float red: red color intensity, possible values 0.0 ... 1.0 + * float green: green color intensity, possible values 0.0 ... 1.0 + * float blue: blue color intensity, possible values 0.0 ... 1.0 + */ +void led_set_color(float red, float green, float blue) +{ + led_red_intensity = red * led_pwm_max; + led_green_intensity = green * led_pwm_max; + led_blue_intensity = blue * led_pwm_max; +} + +/* + * led_off(): + * Set LED intensity to 0 for each color + */ +void led_off() +{ + led_red_intensity = 0; + led_green_intensity = 0; + led_blue_intensity = 0; +} + +/* + * led_pwm_handler(): + * handles switching LEDs on/off according to desired intensity; + * should be regularly called in timer routine, preferably in SysTick_Handler() + */ +void led_pwm_handler() +{ + int new_red_state, new_green_state, new_blue_state; + + new_red_state = led_pwm_counter >= led_red_intensity ? 1 : 0; + new_green_state = led_pwm_counter >= led_green_intensity ? 1 : 0; + new_blue_state = led_pwm_counter >= led_blue_intensity ? 1 : 0; + // SysTick() is called at 1 kHz frequency, we don't want to call HAL_GPIO_WritePin() every time + if (led_red_state != new_red_state) { + HAL_GPIO_WritePin(led_context->red_led_port, led_context->red_led_pin, new_red_state); + led_red_state = new_red_state; + } + if (led_green_state != new_green_state) { + HAL_GPIO_WritePin(led_context->green_led_port, led_context->green_led_pin, new_green_state); + led_green_state = new_green_state; + } + if (led_blue_state != new_blue_state) { + HAL_GPIO_WritePin(led_context->blue_led_port, led_context->blue_led_pin, new_blue_state); + led_blue_state = new_blue_state; + } + if (++led_pwm_counter > led_pwm_max) { + led_pwm_counter = 0; + } +} + +/* + * led_init(): + * Saves context and calculates max pwm value. Note that is PWM frequency is low (< 25 Hz), + * flickering might be visible. If pwm_handler_freq is low (less than several kHz), + * resolution of PWM will be limited + * Arguments: + * led_context_t *context: + * Pointer to LED context struct, which contains port and pin for each LED + * int pwm_freq: + * Desired frequency of PWM in Hz (e.g. 25 Hz) + * int pwm_handler_freq: + * Frequency of led_pwm_handler() calls. Eequal to timer frequency if timer callback is used, + * e.g. if led_pwm_handler() is called within SysTick_Handler(), then frequency is + * HAL_TICK_FREQ_1KHZ + */ +void led_init(led_context_t *context, int pwm_freq, int pwm_handler_freq) +{ + // save context + led_context = context; + // Initial values + led_red_intensity = 0; + led_red_state = 1; // state is inverted (LEDs are sinking current into MCU) + led_green_intensity = 0; + led_green_state = 1; + led_blue_intensity = 0; + led_blue_state = 1; + // calculate PWM counter overflow value (max value) + // e.g. for 1 kHz handler freq and 25 Hz PWM freq, we only have + // resolution of 40 steps for pwm + led_pwm_max = pwm_handler_freq / pwm_freq; +} + +void led_test(int r, int g, int b) +{ + HAL_GPIO_WritePin(led_context->red_led_port, led_context->red_led_pin, r); + HAL_GPIO_WritePin(led_context->green_led_port, led_context->green_led_pin, g); + HAL_GPIO_WritePin(led_context->blue_led_port, led_context->blue_led_pin, b); +} diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c index 8112496..656fd92 100644 --- a/fw/Core/Src/main.c +++ b/fw/Core/Src/main.c @@ -93,27 +93,38 @@ int main(void) MX_I2C1_Init(); MX_LPUART1_UART_Init(); /* USER CODE BEGIN 2 */ + /* Create LED context */ + led_context_t led_context; + led_context.red_led_port = LED_R_GPIO_Port; + led_context.red_led_pin = LED_R_Pin; + led_context.green_led_port = LED_G_GPIO_Port; + led_context.green_led_pin = LED_G_Pin; + led_context.blue_led_port = LED_B_GPIO_Port; + led_context.blue_led_pin = LED_B_Pin; + led_init(&led_context, 25, 1000); /* Turn off all LEDs */ - HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, 1); - HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, 1); - HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 1); + led_off(); + led_set_color(0.1, 0.0, 0.0); +// led_test(0,0,0); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ + int counter = 0; + float R = 0.0, G = 0.0, B = 0.0; while (1) { - HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin); - HAL_Delay(500); - HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin); - HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); - HAL_Delay(500); - HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); - HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); - HAL_Delay(500); - HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); - - + led_pwm_handler(); + if (counter % 1000 == 0) { + R += 0.05; + G += 0.01; + B += 0.02; + if (R > 1.0) R = 0; + if (G > 1.0) G = 0; + if (B > 1.0) B = 0; + led_set_color(R, G, B); + } + counter++; /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/fw/Core/Src/stm32l0xx_it.c b/fw/Core/Src/stm32l0xx_it.c index bf098ed..33758c5 100644 --- a/fw/Core/Src/stm32l0xx_it.c +++ b/fw/Core/Src/stm32l0xx_it.c @@ -23,6 +23,7 @@ #include "stm32l0xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "led.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -130,7 +131,7 @@ void SysTick_Handler(void) /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ - +// led_pwm_handler(); /* USER CODE END SysTick_IRQn 1 */ } diff --git a/fw/iaq_wired_sensor Debug.launch b/fw/iaq_wired_sensor Debug.launch index e86809a..c6a4875 100644 --- a/fw/iaq_wired_sensor Debug.launch +++ b/fw/iaq_wired_sensor Debug.launch @@ -68,5 +68,6 @@ +