From 4af376fa20db377fb8835b4ee322f47ea1f1dea2 Mon Sep 17 00:00:00 2001 From: bookteo <87414181+bookteo@users.noreply.github.com> Date: Sun, 26 Oct 2025 07:50:24 +0100 Subject: [PATCH] PWM Random between 25 khz and 100 khz to reduce noise working good --- fw/Core/Src/main.c | 9 ++++- fw/User/frontlight.c | 90 ++++++++++++++++++++++++++++++++++--------- fw/User/frontlight.h | 12 +++--- fw/User/ui.c | 29 +++++++++----- fw/glider_ec_rtos.ioc | 2 +- 5 files changed, 106 insertions(+), 36 deletions(-) diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c index ddf9c28..71a6500 100644 --- a/fw/Core/Src/main.c +++ b/fw/Core/Src/main.c @@ -606,7 +606,7 @@ static void MX_TIM1_Init(void) htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; - htim1.Init.Period = 479; + htim1.Init.Period = 1919; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; @@ -920,10 +920,15 @@ static void MX_GPIO_Init(void) void StartDefaultTask(void *argument) { /* USER CODE BEGIN 5 */ + // Initialisiere den Zufallsgenerator einmalig + srand(HAL_GetTick()); /* Infinite loop */ for(;;) { - osDelay(1); + // Rufe die Frequenzmodulation in jedem Zyklus auf + FL_Update_Random_Frequency(); + osDelay(50); // Kurze Verzögerung + } /* USER CODE END 5 */ } diff --git a/fw/User/frontlight.c b/fw/User/frontlight.c index 00bc1b6..13c5b43 100644 --- a/fw/User/frontlight.c +++ b/fw/User/frontlight.c @@ -1,45 +1,97 @@ // frontlight.c #include "frontlight.h" +#include "stdlib.h" +#include // Stellen Sie sicher, dass uint32_t definiert ist + // Die Timer-Handle-Struktur htim1 wird aus main.c importiert. extern TIM_HandleTypeDef htim1; +// Speichert die unskalierten Basis-Duty Cycles (0-1920) +static uint32_t fl1_base_duty_cycle = 0; +static uint32_t fl2_base_duty_cycle = 0; + /** - * @brief Startet die PWM-Kanäle für beide Frontlights (fl_pwm1 und fl_pwm2). - * Muss nach MX_TIM1_Init() im main.c aufgerufen werden. - * @retval None + * @brief Startet die PWM-Kanäle. */ void FL_Init(void) { - // Starte den PWM-Ausgang für fl_pwm1 (TIM1 Channel 3) HAL_TIM_PWM_Start(&htim1, FL_PWM1_CHANNEL); - - // Starte den PWM-Ausgang für fl_pwm2 (TIM1 Channel 4) HAL_TIM_PWM_Start(&htim1, FL_PWM2_CHANNEL); } /** - * @brief Stellt die Helligkeit für einen bestimmten Frontlight-Kanal ein. - * @param Channel: FL_PWM1_CHANNEL (TIM_CHANNEL_3) oder FL_PWM2_CHANNEL (TIM_CHANNEL_4). - * @param brightness_level: Wert zwischen 0 (Aus) und 1920 (Max). - * @retval None + * @brief Aktualisiert den PWM-Periodenwert (ARR) zufällig und skaliert den Duty Cycle. + */ +void FL_Update_Random_Frequency(void) +{ + // 1. ARR-Wert zufällig im Modulationsbereich generieren + const uint32_t range = FL_PWM_MAX_ARR_VALUE - FL_PWM_MIN_ARR_VALUE; + + // rand() % (Range + 1) generiert einen Wert im Bereich [0, Range] + uint32_t random_offset = rand() % (range + 1); + uint32_t new_arr = FL_PWM_MIN_ARR_VALUE + random_offset; + + // Setze den neuen ARR-Wert (wird am nächsten Update-Ereignis wirksam) + __HAL_TIM_SET_AUTORELOAD(&htim1, new_arr); + + // 2. Duty Cycle (CCR) proportional skalieren und setzen + + // --- Skaliere FL1 (Warm LED) --- + if (fl1_base_duty_cycle > 0) { + // CCR_neu = (Basis-Duty Cycle / Max_Resolution) * ARR_neu + // Wir verwenden uint64_t für die Multiplikation, um Überläufe zu vermeiden (1920 * 1919 kann 32-Bit übersteigen) + uint32_t scaled_pulse = (uint32_t)(((uint64_t)fl1_base_duty_cycle * new_arr) / FL_PWM_MAX_RESOLUTION); + + // Sicherheit: CCR darf ARR nicht überschreiten + if (scaled_pulse > new_arr) { + scaled_pulse = new_arr; + } + __HAL_TIM_SET_COMPARE(&htim1, FL_PWM1_CHANNEL, scaled_pulse); + } else { + __HAL_TIM_SET_COMPARE(&htim1, FL_PWM1_CHANNEL, 0); // Ausschalten + } + + // --- Skaliere FL2 (Cold LED) --- + if (fl2_base_duty_cycle > 0) { + uint32_t scaled_pulse = (uint32_t)(((uint64_t)fl2_base_duty_cycle * new_arr) / FL_PWM_MAX_RESOLUTION); + + if (scaled_pulse > new_arr) { + scaled_pulse = new_arr; + } + __HAL_TIM_SET_COMPARE(&htim1, FL_PWM2_CHANNEL, scaled_pulse); + } else { + __HAL_TIM_SET_COMPARE(&htim1, FL_PWM2_CHANNEL, 0); // Ausschalten + } +} + +/** + * @brief Stellt die Helligkeit für einen bestimmten Frontlight-Kanal ein (speichert Basiswert). + * @param Channel: TIM_CHANNEL_3 oder TIM_CHANNEL_4 + * @param brightness_level: Basiswert (unskaliert) zwischen 0 und 1920 */ void FL_SetBrightness(uint32_t Channel, uint32_t brightness_level) { - // Begrenze den Wert auf das Maximum - if (brightness_level > FL_PWM_MAX_DUTY_CYCLE) - { - brightness_level = FL_PWM_MAX_DUTY_CYCLE; + // Begrenze den Wert auf das Maximum der vollen Auflösung + if (brightness_level > FL_PWM_MAX_RESOLUTION) { + brightness_level = FL_PWM_MAX_RESOLUTION; } - // Setze den neuen Wert in das Capture/Compare Register (CCR) - __HAL_TIM_SET_COMPARE(&htim1, Channel, brightness_level); + // Speichere den unskalierten Basis-Wert + if (Channel == FL_PWM1_CHANNEL) { + fl1_base_duty_cycle = brightness_level; + } else if (Channel == FL_PWM2_CHANNEL) { + fl2_base_duty_cycle = brightness_level; + } + + // Rufe die Frequenz-Update-Funktion auf, um den Wert sofort zu skalieren und zu setzen + FL_Update_Random_Frequency(); } -// --- Hilfsfunktionen für vereinfachte Steuerung --- +// --- Hilfsfunktionen (Wrapper) --- /** - * @brief Stellt die Helligkeit des Frontlight 1 (fl_pwm1) ein. + * @brief Setzt die Helligkeit für Frontlight 1 (FL1). */ void FL1_SetBrightness(uint32_t brightness_level) { @@ -47,7 +99,7 @@ void FL1_SetBrightness(uint32_t brightness_level) } /** - * @brief Stellt die Helligkeit des Frontlight 2 (fl_pwm2) ein. + * @brief Setzt die Helligkeit für Frontlight 2 (FL2). */ void FL2_SetBrightness(uint32_t brightness_level) { diff --git a/fw/User/frontlight.h b/fw/User/frontlight.h index 42f679c..29caff0 100644 --- a/fw/User/frontlight.h +++ b/fw/User/frontlight.h @@ -9,19 +9,21 @@ extern "C" { #include "stm32h7xx_hal.h" -// Externe Deklaration der Timer-Handle-Struktur -// ACHTUNG: Die 'htim1' Struktur wird im main.c/stm32h7xx_it.c File definiert. -// Sie muss in dem File, in dem sie definiert ist, als 'extern' deklariert werden. +// Externe Deklaration der Timer-Handle-Struktur aus main.c extern TIM_HandleTypeDef htim1; -// Konstanten -#define FL_PWM_MAX_DUTY_CYCLE 1920 +// Konstanten für die Random Frequency PWM (RF-PWM) +#define FL_PWM_MAX_ARR_VALUE 1919 // Entspricht 25 kHz (Min. Frequenz) +#define FL_PWM_MIN_ARR_VALUE 479 // Entspricht 100 kHz (Max. Frequenz) +#define FL_PWM_MAX_RESOLUTION 1920 // Basis-Auflösung (Max. ARR + 1) + #define FL_PWM1_CHANNEL TIM_CHANNEL_3 #define FL_PWM2_CHANNEL TIM_CHANNEL_4 // Funktionsprototypen void FL_Init(void); void FL_SetBrightness(uint32_t Channel, uint32_t brightness_level); +void FL_Update_Random_Frequency(void); // NEU: Muss regelmäßig aufgerufen werden, um die Frequenz zu modulieren void FL1_SetBrightness(uint32_t brightness_level); void FL2_SetBrightness(uint32_t brightness_level); diff --git a/fw/User/ui.c b/fw/User/ui.c index 6d5621f..a23e6b6 100644 --- a/fw/User/ui.c +++ b/fw/User/ui.c @@ -39,14 +39,13 @@ typedef struct { // Die 7 Helligkeitsstufen mit zugehörigem OSD-Text static const brightness_setting_t BRIGHTNESS_LEVELS[] = { // 100khz - { 0, "OFF" }, - { 20, "4%" }, - { 40, "8%" }, - { 71, "15%" }, - { 134, "28%" }, - { 252, "53%" }, - { 420, "100%" } - +// { 0, "OFF" }, +// { 20, "4%" }, +// { 40, "8%" }, +// { 71, "15%" }, +// { 134, "28%" }, +// { 252, "53%" }, +// { 420, "100%" } // 30khz // { 0, "OFF" }, @@ -56,6 +55,18 @@ static const brightness_setting_t BRIGHTNESS_LEVELS[] = { // { 253, "16%" }, // { 637, "40%" }, // { 1599, "100%" } + +// 25khz + { 0, "OFF" }, + { 19, "1%" }, + { 48, "3%" }, + { 121, "6%" }, + { 304, "16%" }, + { 764, "40%" }, + { 1343, "70%" }, + { 1919, "100%" } // Maximaler Wert der Timer-Auflösung + + }; static const int NUM_BRIGHTNESS_LEVELS = sizeof(BRIGHTNESS_LEVELS) / sizeof(BRIGHTNESS_LEVELS[0]); @@ -163,7 +174,7 @@ static font_t *load_font(const char *fn) { spiffs_file f = SPIFFS_open(&spiffs_fs, fn, SPIFFS_O_RDONLY, 0); if (SPIFFS_errno(&spiffs_fs) != 0) return NULL; - + spiffs_stat s; SPIFFS_fstat(&spiffs_fs, f, &s); uint32_t size = s.size; diff --git a/fw/glider_ec_rtos.ioc b/fw/glider_ec_rtos.ioc index 998ef93..ccc822b 100644 --- a/fw/glider_ec_rtos.ioc +++ b/fw/glider_ec_rtos.ioc @@ -648,7 +648,7 @@ TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 TIM1.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,AutoReloadPreload,Period -TIM1.Period=479 +TIM1.Period=1919 USB_OTG_FS.IPParameters=VirtualMode USB_OTG_FS.VirtualMode=Device_Only VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2