PWM Random between 25 khz and 100 khz to reduce noise working good

This commit is contained in:
bookteo 2025-10-26 07:50:24 +01:00
commit 4af376fa20
5 changed files with 106 additions and 36 deletions

View file

@ -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 */
}

View file

@ -1,45 +1,97 @@
// frontlight.c
#include "frontlight.h"
#include "stdlib.h"
#include <stdint.h> // 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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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