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