PWM works
This commit is contained in:
BIN
EE-Editor-Project.eeproj
Normal file
BIN
EE-Editor-Project.eeproj
Normal file
Binary file not shown.
@@ -1,12 +1,13 @@
|
||||
#include "MotorController.h"
|
||||
|
||||
static constexpr uint16_t PWM_TOP = 0xFFFF;
|
||||
// PWM-Top für Timer1 (Fast PWM, ICR1)
|
||||
static constexpr uint16_t PWM_TOP = 4095; // 12-bit Auflösung, ~488 Hz bei Prescaler 8
|
||||
|
||||
// Default-Konfiguration
|
||||
const MotorConfig_t defaultConfig = {
|
||||
.minPWM = 0,
|
||||
.maxPWM = PWM_TOP,
|
||||
.inverted = false,
|
||||
.inverted = true,
|
||||
.responseSpeedAccel = 50, // ca. 50% pro Sekunde Beschleunigung
|
||||
.responseSpeedDecel = 200, // schnelleres Abbremsen
|
||||
// Stark progressiv: viel Feingefühl unten, steiler Verlauf oben
|
||||
@@ -35,6 +36,10 @@ void MotorController::loadDefaults()
|
||||
{
|
||||
config = defaultConfig;
|
||||
|
||||
if (config.minPWM > PWM_TOP)
|
||||
config.minPWM = PWM_TOP;
|
||||
if (config.maxPWM > PWM_TOP)
|
||||
config.maxPWM = PWM_TOP;
|
||||
// Response-Werte absichern
|
||||
if (config.responseSpeedAccel <= 0)
|
||||
config.responseSpeedAccel = 50;
|
||||
@@ -59,6 +64,10 @@ void MotorController::setConfig(const MotorConfig_t &newConfig)
|
||||
{
|
||||
config = newConfig;
|
||||
|
||||
if (config.minPWM > PWM_TOP)
|
||||
config.minPWM = PWM_TOP;
|
||||
if (config.maxPWM > PWM_TOP)
|
||||
config.maxPWM = PWM_TOP;
|
||||
// min/max sanity
|
||||
if (config.maxPWM < config.minPWM)
|
||||
{
|
||||
@@ -173,15 +182,14 @@ int16_t MotorController::applyDynamicResponse(int16_t targetPercent)
|
||||
}
|
||||
|
||||
targetPercent = constrain(targetPercent, 0, 100);
|
||||
int16_t targetPromille = targetPercent * 10;
|
||||
|
||||
int16_t delta = targetPromille - smoothedPromille;
|
||||
int32_t targetPromille = (int32_t)targetPercent * 10;
|
||||
int32_t delta = targetPromille - smoothedPromille;
|
||||
|
||||
// responseSpeed = Prozent pro Sekunde → Promille pro Sekunde
|
||||
int16_t maxChangePerSec = (delta >= 0 ? config.responseSpeedAccel : config.responseSpeedDecel) * 10;
|
||||
int32_t maxChangePerSec = (delta >= 0 ? config.responseSpeedAccel : config.responseSpeedDecel) * 10L;
|
||||
|
||||
// maximaler Delta in diesem Zeitintervall
|
||||
int16_t maxDelta = (int16_t)((maxChangePerSec * (int32_t)elapsedTime) / 1000L);
|
||||
// maximaler Delta in diesem Zeitintervall (mit Rundung)
|
||||
int32_t maxDelta = (maxChangePerSec * (int32_t)elapsedTime + 999) / 1000L;
|
||||
if (maxDelta < 1)
|
||||
maxDelta = 1; // minimale Änderung erlauben
|
||||
|
||||
@@ -190,7 +198,7 @@ int16_t MotorController::applyDynamicResponse(int16_t targetPercent)
|
||||
else if (delta < -maxDelta)
|
||||
delta = -maxDelta;
|
||||
|
||||
smoothedPromille += delta;
|
||||
smoothedPromille += (int16_t)delta;
|
||||
lastUpdateTime = currentTime;
|
||||
|
||||
return (smoothedPromille + 5) / 10; // runden
|
||||
@@ -198,38 +206,30 @@ int16_t MotorController::applyDynamicResponse(int16_t targetPercent)
|
||||
|
||||
uint16_t MotorController::computePwm(uint16_t pwmLogical)
|
||||
{
|
||||
// explizit 0 erlauben, auch wenn minPWM > 0 gesetzt ist
|
||||
if (pwmLogical == 0)
|
||||
// bei nicht invertierter Logik darf 0 auch unter minPWM fallen
|
||||
if (!config.inverted && pwmLogical == 0)
|
||||
return 0;
|
||||
|
||||
uint16_t pwmOut = pwmLogical;
|
||||
if (pwmOut < config.minPWM)
|
||||
pwmOut = config.minPWM;
|
||||
if (pwmOut > config.maxPWM)
|
||||
pwmOut = config.maxPWM;
|
||||
uint32_t base = pwmLogical;
|
||||
if (base < config.minPWM)
|
||||
base = config.minPWM;
|
||||
if (base > config.maxPWM)
|
||||
base = config.maxPWM;
|
||||
|
||||
uint32_t pwmOut = base;
|
||||
if (config.inverted)
|
||||
{
|
||||
// Logischer Wert im Bereich [min,max] wird gespiegelt
|
||||
uint32_t span = (uint32_t)config.maxPWM - (uint32_t)config.minPWM;
|
||||
uint32_t offset = (uint32_t)pwmLogical - (uint32_t)config.minPWM;
|
||||
uint32_t invOffset = span - offset;
|
||||
uint32_t inv = (uint32_t)config.minPWM + invOffset;
|
||||
if (inv > PWM_TOP)
|
||||
inv = PWM_TOP;
|
||||
pwmOut = (uint16_t)inv;
|
||||
uint32_t offset = base - (uint32_t)config.minPWM;
|
||||
uint32_t inv = (uint32_t)config.minPWM + (span - offset);
|
||||
pwmOut = inv;
|
||||
}
|
||||
|
||||
if (pwmOut < config.minPWM)
|
||||
pwmOut = config.minPWM;
|
||||
if (pwmOut > config.maxPWM)
|
||||
pwmOut = config.maxPWM;
|
||||
|
||||
// Clamp auf 16-bit Top (ICR1)
|
||||
if (pwmOut > PWM_TOP)
|
||||
pwmOut = PWM_TOP;
|
||||
|
||||
return pwmOut;
|
||||
return (uint16_t)pwmOut;
|
||||
}
|
||||
|
||||
void MotorController::printStatus()
|
||||
@@ -255,6 +255,8 @@ void MotorController::printStatus()
|
||||
Serial.print(config.maxPWM);
|
||||
Serial.print(" span=");
|
||||
Serial.print((uint32_t)config.maxPWM - (uint32_t)config.minPWM);
|
||||
Serial.print(" top=");
|
||||
Serial.print(PWM_TOP);
|
||||
Serial.print(" respA=");
|
||||
Serial.print(config.responseSpeedAccel);
|
||||
Serial.print(" respD=");
|
||||
|
||||
12
src/main.cpp
12
src/main.cpp
@@ -206,8 +206,8 @@ void loop()
|
||||
motor.maintain();
|
||||
// PWM auf Timer1 ausgeben (OC1A / D9), MotorController liefert bereits invertiert/geklemmt
|
||||
uint16_t pwmOut = gCurrentPwm;
|
||||
if (pwmOut > 0xFFFF)
|
||||
pwmOut = 0xFFFF;
|
||||
if (pwmOut > 0x0FFF)
|
||||
pwmOut = 0x0FFF;
|
||||
OCR1A = pwmOut;
|
||||
|
||||
#ifdef DISPLAY_ENABLE
|
||||
@@ -273,7 +273,7 @@ void updateDisplay()
|
||||
|
||||
void configurePWMFrequency()
|
||||
{
|
||||
// Timer1 16-bit Fast PWM on OC1A (Pin D9)
|
||||
// Timer1 Fast PWM on OC1A (Pin D9)
|
||||
// Mode 14: Fast PWM, TOP = ICR1
|
||||
pinMode(motorPwmPin, OUTPUT);
|
||||
|
||||
@@ -287,10 +287,10 @@ void configurePWMFrequency()
|
||||
TCCR1A |= (1 << WGM11);
|
||||
TCCR1B |= (1 << WGM12) | (1 << WGM13);
|
||||
|
||||
// 16-bit Auflösung, voller Bereich
|
||||
ICR1 = 0xFFFF;
|
||||
// 12-bit Auflösung, niedrigere PWM-Frequenz (~488 Hz bei Prescaler 8)
|
||||
ICR1 = 0x0FFF;
|
||||
OCR1A = 0;
|
||||
|
||||
// Prescaler 8 für ~2 kHz (16 MHz / 8 / 65536)
|
||||
// Prescaler 8
|
||||
TCCR1B |= (1 << CS11);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user