reworked Settings-handling and tuned up CLI

This commit is contained in:
2025-12-05 15:43:36 +01:00
parent c889eec818
commit 0cdc609df5
9 changed files with 413 additions and 264 deletions

View File

@@ -1,7 +1,7 @@
#include "MotorController.h"
// Default-Konfiguration
const MotorConfig defaultConfig = {
const MotorConfig_t defaultConfig = {
.minPWM = 0,
.maxPWM = 255,
.inverted = true,
@@ -9,7 +9,7 @@ const MotorConfig defaultConfig = {
.lookupTable = {0, 10, 20, 30, 40, 50, 60, 70, 80, 100} // 0..100% Kennlinie
};
MotorController::MotorController(const MotorSignals &signals)
MotorController::MotorController(const MotorSignals_t &signals)
: signals_(signals)
{
loadDefaults();
@@ -29,7 +29,7 @@ MotorController::MotorController(const MotorSignals &signals)
lastSpeedPercent = 0;
}
void MotorController::setSignals(const MotorSignals &signals)
void MotorController::setSignals(const MotorSignals_t &signals)
{
signals_ = signals;
@@ -59,12 +59,12 @@ void MotorController::loadDefaults()
}
}
MotorConfig MotorController::getConfig() const
MotorConfig_t MotorController::getConfig() const
{
return config;
}
void MotorController::setConfig(const MotorConfig &newConfig)
void MotorController::setConfig(const MotorConfig_t &newConfig)
{
config = newConfig;
@@ -105,7 +105,7 @@ void MotorController::maintain()
lastSpeedPercent = adjustedSpeed;
// 3) Lookup-Interpolation von Prozent -> LUT-Prozent
const int16_t n = MotorConfig::lookupTableSize;
const int16_t n = MotorConfig_t::lookupTableSize;
float pos = (adjustedSpeed / 100.0f) * (n - 1); // 0..(n-1) als float
int16_t lowerIndex = (int16_t)pos;
if (lowerIndex < 0)

View File

@@ -3,7 +3,7 @@
#include <Arduino.h>
struct MotorConfig
typedef struct MotorConfig
{
uint8_t minPWM;
uint8_t maxPWM;
@@ -11,7 +11,7 @@ struct MotorConfig
int16_t responseSpeed; // Prozent pro Sekunde
static const int16_t lookupTableSize = 10;
uint8_t lookupTable[lookupTableSize];
};
}MotorConfig_t;
typedef struct MotorSignals
{
@@ -28,14 +28,14 @@ typedef struct MotorSignals
// Debug
bool *debugFlag; // globales Debug-Flag
} MotorSignals;
} MotorSignals_t;
class MotorController
{
public:
explicit MotorController(const MotorSignals &signals);
explicit MotorController(const MotorSignals_t &signals);
void setSignals(const MotorSignals &signals);
void setSignals(const MotorSignals_t &signals);
// zyklisch in loop() aufrufen
void maintain();
@@ -43,13 +43,13 @@ public:
// Hard Stop
void stopMotor();
MotorConfig getConfig() const;
void setConfig(const MotorConfig &newConfig);
MotorConfig_t getConfig() const;
void setConfig(const MotorConfig_t &newConfig);
void loadDefaults();
private:
MotorSignals signals_;
MotorConfig config;
MotorSignals_t signals_;
MotorConfig_t config;
// interner Dynamik-State
int16_t smoothedPromille = 0; // 0..1000

View File

@@ -3,7 +3,7 @@
// sinnvolle Defaults grob um den real genutzen Bereich
// nicht gedrückt ~425, gedrückt ~227
static const PedalConfig defaultConfig = {
static const PedalConfig_t defaultConfig = {
.minRaw = 230, // grob gedrückt
.maxRaw = 420, // grob nicht gedrückt
.calibrated = false,
@@ -23,10 +23,8 @@ static const uint8_t MIN_FS = 1; // Filterstärke min.
static const uint8_t MAX_FS = 32; // Filterstärke max.
static const uint8_t DEFAULT_FS = 3; // Standard-Filterstärke
PedalController::PedalController(const PedalSignals &signals,
uint8_t digitalNotPressedLevel_)
PedalController::PedalController(const PedalSignals_t &signals)
: signals_(signals),
digitalNotPressedLevel(digitalNotPressedLevel_ ? 1 : 0),
config(),
filteredValue(-1),
lastPedalPercent(0),
@@ -46,12 +44,6 @@ PedalController::PedalController(const PedalSignals &signals,
step3NearReleased(false),
step4NearPressed(false)
{
// Digital-Pin als INPUT konfigurieren, falls vorhanden
if (signals_.digitalPin >= 0)
{
pinMode(signals_.digitalPin, INPUT);
}
loadDefaults();
}
@@ -461,20 +453,6 @@ int16_t PedalController::getPedal()
void PedalController::maintain()
{
int16_t raw = applySmoothing(readRaw());
// Outputs befüllen
if (signals_.rawValue)
*signals_.rawValue = raw;
// digitaler Eingang (falls vorhanden)
if (signals_.digitalState)
{
if (signals_.digitalPin >= 0)
*signals_.digitalState = digitalRead(signals_.digitalPin);
else
*signals_.digitalState = -1;
}
int16_t percent = mapRawToPercent(raw);
lastPedalPercent = percent;
@@ -490,12 +468,12 @@ void PedalController::maintain()
}
}
PedalConfig PedalController::getConfig() const
PedalConfig_t PedalController::getConfig() const
{
return config;
}
void PedalController::setConfig(const PedalConfig &newConfig)
void PedalController::setConfig(const PedalConfig_t &newConfig)
{
config = newConfig;
@@ -543,14 +521,9 @@ void PedalController::loadDefaults()
step4NearPressed = false;
}
void PedalController::setSignals(const PedalSignals &signals)
void PedalController::setSignals(const PedalSignals_t &signals)
{
signals_ = signals;
if (signals_.digitalPin >= 0)
{
pinMode(signals_.digitalPin, INPUT);
}
}
void PedalController::printStatus(int16_t raw)
@@ -571,17 +544,6 @@ void PedalController::printStatus(int16_t raw)
Serial.print(raw);
Serial.print(" Smooth=");
Serial.print(filteredValue);
Serial.print(" DO-State=");
if (signals_.digitalPin >= 0)
{
Serial.print(digitalRead(signals_.digitalPin));
}
else
{
Serial.print("N/A");
}
Serial.print(" firstRel=");
Serial.print(firstReleased);
Serial.print(" firstPress=");

View File

@@ -12,37 +12,34 @@ enum CalibrationState
ERROR
};
struct PedalConfig
typedef struct PedalConfig
{
int16_t minRaw;
int16_t maxRaw;
bool calibrated;
uint8_t filterStrength;
};
}PedalConfig_t;
typedef struct PedalSignals
{
// Pins (by value)
int16_t analogPin; // ADC-Pin
int16_t digitalPin; // -1 falls unbenutzt
// Eingänge
bool *debugFlag; // globales Debug-Flag
// Ausgänge
int16_t *pedalPercent; // 0..100%
int16_t *rawValue; // gefilterter Rawwert
bool *calibrated; // Status
int16_t *digitalState; // DO-Status oder -1
} PedalSignals;
} PedalSignals_t;
class PedalController
{
public:
PedalController(const PedalSignals &signals,
uint8_t digitalNotPressedLevel = LOW);
PedalController(const PedalSignals_t &signals);
void setSignals(const PedalSignals &signals);
void setSignals(const PedalSignals_t &signals);
CalibrationState autoCalibrate(bool reset);
CalibrationState getStatus() const;
@@ -50,15 +47,14 @@ public:
int16_t getPedal(); // alte API (blocking)
void maintain(); // neue Non-Blocking-API
PedalConfig getConfig() const;
void setConfig(const PedalConfig &cfg);
PedalConfig_t getConfig() const;
void setConfig(const PedalConfig_t &cfg);
void loadDefaults();
private:
PedalSignals signals_;
uint8_t digitalNotPressedLevel; // nur Debug / Interpretation
PedalSignals_t signals_;
PedalConfig config;
PedalConfig_t config;
int32_t filteredValue;
int16_t lastPedalPercent;

View File

@@ -1,9 +1,11 @@
#include <Arduino.h>
#include <EEPROM.h>
#include "SerialController.h"
SerialController::SerialController(const SerialSignals &signals)
SerialController::SerialController(const SerialSignals_t &signals)
: signals_(signals)
{
cmdIndex_ = 0;
}
void SerialController::maintain()
@@ -11,145 +13,309 @@ void SerialController::maintain()
while (Serial.available() > 0)
{
char c = Serial.read();
handleCommand(c);
// ESC = komplette Zeile verwerfen
if (c == 0x1B) // ESC
{
cmdIndex_ = 0;
Serial.println(); // neue Zeile für frische Eingabe
return;
}
// Backspace oder DEL
if (c == 0x08 || c == 0x7F)
{
if (cmdIndex_ > 0)
{
cmdIndex_--;
cmdBuffer_[cmdIndex_] = '\0';
// Visuelles Löschen im Terminal
Serial.print("\b \b");
}
return;
}
// Zeilenende
if (c == '\r')
{
return;
}
if (c == '\n')
{
Serial.println(); // Prompt / neue Eingabe
if (cmdIndex_ > 0)
{
cmdBuffer_[cmdIndex_] = '\0';
handleCommand(cmdBuffer_);
cmdIndex_ = 0;
}
Serial.print(F(">"));
return;
}
// Printable ASCII?
if (c >= 32 && c <= 126)
{
if (cmdIndex_ < (CMD_BUFFER_SIZE - 1))
{
cmdBuffer_[cmdIndex_++] = c;
Serial.print(c); // Zeichen lokal anzeigen
}
else
{
// Buffer voll → ignorieren oder Fehlbeep
Serial.print('\a'); // optional Terminal-Bell
}
}
}
}
void SerialController::handleCommand(char c)
void SerialController::handleCommand(char *line)
{
switch (c)
{
case 'h':
printHelp();
break;
// Leading Spaces entfernen
while (*line == ' ' || *line == '\t')
++line;
case 'd': // Debug toggeln
if (*line == '\0')
return; // leere Zeile
// Alles in UPPERCASE wandeln
for (char *p = line; *p != '\0'; ++p)
{
if (*p >= 'a' && *p <= 'z')
{
*p = *p - 'a' + 'A';
}
}
// Erstes Token (CMD) isolieren
char *p = line;
while (*p != '\0' && *p != ' ' && *p != '\t')
++p;
char *cmd = line;
char *arg1 = nullptr;
char *arg2 = nullptr;
if (*p != '\0')
{
*p++ = '\0'; // CMD terminieren
// ARG1
while (*p == ' ' || *p == '\t')
++p;
if (*p != '\0')
{
arg1 = p;
while (*p != '\0' && *p != ' ' && *p != '\t')
++p;
if (*p != '\0')
{
*p++ = '\0';
// ARG2
while (*p == ' ' || *p == '\t')
++p;
if (*p != '\0')
{
arg2 = p;
while (*p != '\0' && *p != ' ' && *p != '\t')
++p;
*p = '\0';
}
}
}
}
// === Einfache / alte Single-Char-Kommandos per strcmp ===
// Help: HELP
if (strcmp(cmd, "HELP") == 0)
{
printHelp();
return;
}
// Debug toggle:
if (strcmp(cmd, "DEBUG") == 0)
{
if (signals_.debugFlag)
{
*signals_.debugFlag = !*signals_.debugFlag;
Serial.print("Debug: ");
Serial.println(*signals_.debugFlag ? "ON" : "OFF");
Serial.print(F("Debug: "));
Serial.println(*signals_.debugFlag ? F("ON") : F("OFF"));
}
break;
return;
}
case '+': // Geschwindigkeit +5%
if (signals_.targetSpeedPercent)
// Serielles Save/Load/Defaults:
if (strcmp(cmd, "SAVE") == 0)
{
if (signals_.requestSaveEEPROM)
{
if (signals_.serialControlEnabled)
*signals_.serialControlEnabled = true;
int16_t v = *signals_.targetSpeedPercent;
v = constrain(v + 5, (int16_t)0, (int16_t)100);
*signals_.targetSpeedPercent = v;
Serial.print("Target +: ");
Serial.print(v);
Serial.println("%");
*signals_.requestSaveEEPROM = true;
Serial.println(F("Request: Save settings to EEPROM."));
}
break;
return;
}
case '-': // Geschwindigkeit -5%
if (signals_.targetSpeedPercent)
if (strcmp(cmd, "LOAD") == 0)
{
if (signals_.requestLoadEEPROM)
{
if (signals_.serialControlEnabled)
*signals_.serialControlEnabled = true;
int16_t v = *signals_.targetSpeedPercent;
v = constrain(v - 5, (int16_t)0, (int16_t)100);
*signals_.targetSpeedPercent = v;
Serial.print("Target -: ");
Serial.print(v);
Serial.println("%");
*signals_.requestLoadEEPROM = true;
Serial.println(F("Request: Load settings from EEPROM."));
}
break;
return;
}
// direkte 0100%-Vorgabe in 10%-Schritten
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (signals_.targetSpeedPercent)
if (strcmp(cmd, "DEFAULTS") == 0)
{
if (signals_.requestLoadDefaults)
{
if (signals_.serialControlEnabled)
*signals_.serialControlEnabled = true;
int16_t v = (c - '0') * 10;
v = constrain(v, (int16_t)0, (int16_t)100);
*signals_.targetSpeedPercent = v;
Serial.print("Target set: ");
Serial.print(v);
Serial.println("%");
*signals_.requestLoadDefaults = true;
Serial.println(F("Request: Load defaults."));
}
break;
return;
}
case 'x': // Serielle Steuerung stoppen & Motor freigeben
// Auto-Cal:
if (strcmp(cmd, "CAL") == 0)
{
if (signals_.requestAutoCal)
{
*signals_.requestAutoCal = true;
Serial.println(F("Request: Auto-Calibration."));
}
return;
}
// Serial Control stoppen: X
if (strcmp(cmd, "X") == 0)
{
if (signals_.serialControlEnabled)
*signals_.serialControlEnabled = false;
if (signals_.targetSpeedPercent)
*signals_.targetSpeedPercent = 0;
Serial.println("Serial control disabled, target=0%.");
break;
case 'c': // Auto-Cal anfordern
if (signals_.requestAutoCal)
{
*signals_.requestAutoCal = true;
Serial.println("Request: Auto-Calibration.");
}
break;
case 's': // Save EEPROM
if (signals_.requestSaveEEPROM)
{
*signals_.requestSaveEEPROM = true;
Serial.println("Request: Save settings to EEPROM.");
}
break;
case 'l': // Load EEPROM
if (signals_.requestLoadEEPROM)
{
*signals_.requestLoadEEPROM = true;
Serial.println("Request: Load settings from EEPROM.");
}
break;
case 'r': // Defaults laden
if (signals_.requestLoadDefaults)
{
*signals_.requestLoadDefaults = true;
Serial.println("Request: Load defaults.");
}
break;
default:
// Optional: unerkanntes Kommando anzeigen
// Serial.print("Unknown command: ");
// Serial.println(c);
break;
Serial.println(F("Serial control disabled, target=0%."));
return;
}
if (strcmp(cmd, "SPEED") == 0)
{
if (!arg1)
{
Serial.println(F("ERR: SPEED requires: SPEED <0..10>"));
return;
}
int step = atoi(arg1); // 0..10
int16_t v = (int16_t)(step * 10);
v = constrain(v, (int16_t)0, (int16_t)100);
if (signals_.targetSpeedPercent)
{
if (signals_.serialControlEnabled)
*signals_.serialControlEnabled = true;
*signals_.targetSpeedPercent = v;
snprintf_P(printBuffer_, sizeof(printBuffer_), PSTR("Target speed set: %d%%"), v);
Serial.println(printBuffer_);
}
return;
}
// === EEPROM-Kommandos ===
if (strcmp(cmd, "EW") == 0)
{
// EW <addr> <value>
if (!arg1 || !arg2)
{
Serial.println(F("ERR: EW requires: EW <addr> <value>"));
return;
}
int addr = atoi(arg1);
int value = atoi(arg2);
cmdEepromWrite(addr, value);
return;
}
if (strcmp(cmd, "ER") == 0)
{
// ER <addr>
if (!arg1)
{
Serial.println(F("ERR: ER requires: ER <addr>"));
return;
}
int addr = atoi(arg1);
cmdEepromRead(addr);
return;
}
// === Fallback ===
snprintf_P(printBuffer_, sizeof(printBuffer_), PSTR("ERR: Unknown command '%s'"), cmd);
Serial.println(printBuffer_);
}
void SerialController::cmdEepromWrite(uint16_t addr, uint8_t value)
{
if (addr < 0 || addr >= EEPROM.length())
{
snprintf_P(printBuffer_, sizeof(printBuffer_), "ERR: Address %d out of range.", addr);
Serial.println(printBuffer_);
return;
}
if (value < 0 || value > 255)
{
Serial.println(F("ERR: Value must be 0..255."));
return;
}
EEPROM.write(addr, static_cast<uint8_t>(value));
snprintf_P(printBuffer_, sizeof(printBuffer_), PSTR("EW OK: [%d] = %d"), addr, value);
Serial.println(printBuffer_);
}
void SerialController::cmdEepromRead(uint16_t addr)
{
if (addr < 0 || addr >= EEPROM.length())
{
Serial.println(F("ERR: Address out of range."));
return;
}
uint8_t v = EEPROM.read(addr);
snprintf_P(printBuffer_, sizeof(printBuffer_), PSTR("ER: [%d] = %d"), addr, v);
Serial.println(printBuffer_);
}
void SerialController::printHelp()
{
Serial.println(F("=== Serial Control Help ==="));
Serial.println(F("h - Show this help"));
Serial.println(F("d - Toggle debug output"));
Serial.println(F("c - Request auto-calibration"));
Serial.println(F("s - Request save settings to EEPROM"));
Serial.println(F("l - Request load settings from EEPROM"));
Serial.println(F("r - Request load defaults"));
Serial.println(F("x - Disable serial control, set target=0%"));
Serial.println(F("+ - Increase target speed by 5%"));
Serial.println(F("- - Decrease target speed by 5%"));
Serial.println(F("0-9- Set target speed in 10% steps (0..100%)"));
Serial.println(F("Basic commands (send + Enter):"));
Serial.println(F(" HELP - Show this help"));
Serial.println(F(" DEBUG - Toggle debug output"));
Serial.println(F(" CAL - Request auto-calibration"));
Serial.println(F(" SAVE - Request save settings to EEPROM"));
Serial.println(F(" LOAD - Request load settings from EEPROM"));
Serial.println(F(" DEFAULTS - Request load defaults"));
Serial.println(F(" X - Disable serial control, set target=0%"));
Serial.println(F(" SPEED n - Set speed to n*10% (0..10)"));
Serial.println(F(""));
Serial.println(F("EEPROM commands:"));
Serial.println(F(" EW <a> <v> - EEPROM write: address a, value v (0..255)"));
Serial.println(F(" ER <a> - EEPROM read: address a"));
}

View File

@@ -2,8 +2,6 @@
#define SERIALCONTROLLER_H
#include <Arduino.h>
#include "MotorController.h"
#include "PedalController.h"
typedef struct SerialSignals
{
@@ -18,12 +16,12 @@ typedef struct SerialSignals
bool *serialControlEnabled; // schaltet „Serielle Steuerung“ an/aus
} SerialSignals;
} SerialSignals_t;
class SerialController
{
public:
SerialController(const SerialSignals &signals);
explicit SerialController(const SerialSignals_t &signals);
// im loop() aufrufen
void maintain();
@@ -32,9 +30,18 @@ public:
void printHelp();
private:
SerialSignals signals_;
SerialSignals_t signals_;
void handleCommand(char c);
static const uint8_t CMD_BUFFER_SIZE = 32;
char cmdBuffer_[CMD_BUFFER_SIZE];
uint8_t cmdIndex_ = 0;
static const uint8_t PRINT_BUFFER_SIZE = 48;
char printBuffer_[PRINT_BUFFER_SIZE];
void handleCommand(char *line);
void cmdEepromWrite(uint16_t addr, uint8_t value);
void cmdEepromRead(uint16_t addr);
};
#endif

38
src/Settings.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "Settings.h"
#include <EEPROM.h>
uint8_t calculateChecksum(const Settings_t &s)
{
uint8_t sum = 0;
const uint8_t *data = reinterpret_cast<const uint8_t *>(&s);
for (size_t i = 0; i < sizeof(Settings_t) - 1; i++)
{
sum ^= data[i];
}
return sum;
}
bool loadSettings(Settings_t &settings)
{
EEPROM.get(0, settings);
if (calculateChecksum(settings) != settings.checksum)
{
Serial.println(F("Invalid settings checksum, loading defaults."));
return false;
}
else
{
Serial.println(F("Settings loaded from EEPROM."));
return true;
}
}
void saveSettings(const Settings_t &settings)
{
Settings_t tmp = settings;
tmp.checksum = calculateChecksum(settings);
EEPROM.put(0, tmp);
Serial.println(F("Settings saved to EEPROM."));
}

22
src/Settings.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <Arduino.h>
#include "MotorController.h"
#include "PedalController.h"
typedef struct Settings
{
MotorConfig_t motorConfig;
PedalConfig_t pedalConfig;
uint8_t checksum;
}Settings_t;
bool loadSettings(Settings_t &settings);
void saveSettings(const Settings_t &settings);
uint8_t calculateChecksum(const Settings_t &s);
// optional:
inline size_t settingsSize()
{
return sizeof(Settings_t);
}

View File

@@ -1,6 +1,6 @@
#include <Arduino.h>
#include <EEPROM.h>
#include "Settings.h"
#include "MotorController.h"
#include "PedalController.h"
#include "SerialController.h"
@@ -35,9 +35,7 @@ bool gMotorEnabled = true;
// Globale Signale für Pedal
int16_t gPedalPercent = 0;
int16_t gPedalRaw = 0;
bool gPedalCalibrated = false;
int16_t gPedalDigitalState = 0;
// Serial-Steuerflags
bool gReqAutoCal = false;
@@ -46,16 +44,8 @@ bool gReqLoadEEPROM = false;
bool gReqDefaults = false;
bool gSerialControl = false;
// Combined settings structure
typedef struct Settings_t
{
MotorConfig motorConfig;
PedalConfig pedalConfig;
uint8_t checksum;
} Settings_s;
// Signals-Instanzen
MotorSignals motorSignals{
MotorSignals_t motorSignals{
.pwmPin = motorPwmPin,
.targetSpeedPercent = &gTargetSpeedPercent,
.enabled = &gMotorEnabled,
@@ -63,16 +53,14 @@ MotorSignals motorSignals{
.currentPWM = &gCurrentPwm,
.debugFlag = &debug};
PedalSignals pedalSignals{
PedalSignals_t pedalSignals{
.analogPin = pedalPinAnalog,
.digitalPin = pedalPinDigital,
.debugFlag = &debug,
.pedalPercent = &gPedalPercent,
.rawValue = &gPedalRaw,
.calibrated = &gPedalCalibrated,
.digitalState = &gPedalDigitalState};
};
SerialSignals serialSignals{
SerialSignals_t serialSignals{
.targetSpeedPercent = &gTargetSpeedPercent,
.debugFlag = &debug,
.requestAutoCal = &gReqAutoCal,
@@ -84,13 +72,10 @@ SerialSignals serialSignals{
// Global objects
MotorController motor(motorSignals);
PedalController pedal(pedalSignals, LOW);
PedalController pedal(pedalSignals);
SerialController serialCtrl(serialSignals);
// Function prototypes
void loadSettings();
void saveSettings();
uint8_t calculateChecksum(const Settings_t &s);
void handleEncoder();
void handleEncoderButton();
void configurePWMFrequency();
@@ -119,7 +104,17 @@ void setup()
attachInterrupt(digitalPinToInterrupt(encoderButtonPin), handleEncoderButton, FALLING);
Serial.begin(9600);
loadSettings();
Settings_t settings;
if (loadSettings(settings) == false)
{
motor.loadDefaults();
settings.motorConfig = motor.getConfig();
pedal.loadDefaults();
settings.pedalConfig = pedal.getConfig();
saveSettings(settings);
Serial.println(F("EEPROM Checksum mismatch, applied defaults"));
}
#ifdef DISPLAY_ENABLE
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
@@ -153,14 +148,26 @@ void loop()
{
gReqLoadEEPROM = false;
Serial.println(F("Loading settings from EEPROM."));
loadSettings();
Settings_t settings;
if (loadSettings(settings) != false)
{
motor.setConfig(settings.motorConfig);
pedal.setConfig(settings.pedalConfig);
}
else
{
Serial.println(F("EEPROM Checksum mismatch, cannot Load"));
}
}
if (gReqSaveEEPROM)
{
gReqSaveEEPROM = false;
Serial.println(F("Saving settings to EEPROM."));
saveSettings();
Settings_t settings{
.motorConfig = motor.getConfig(),
.pedalConfig = pedal.getConfig()};
saveSettings(settings);
}
if (gReqAutoCal)
@@ -197,7 +204,6 @@ void loop()
#ifdef DISPLAY_ENABLE
updateDisplay();
#endif
}
// ----------------- HILFSFUNKTIONEN -----------------
@@ -207,54 +213,6 @@ void stopMotorAtNeedleUp()
motor.stopMotor();
}
void loadSettings()
{
Settings_t tmp;
EEPROM.get(0, tmp);
if (calculateChecksum(tmp) != tmp.checksum)
{
Serial.println(F("Invalid settings checksum, loading defaults."));
motor.loadDefaults();
pedal.loadDefaults();
tmp.motorConfig = motor.getConfig();
tmp.pedalConfig = pedal.getConfig();
tmp.checksum = calculateChecksum(tmp);
EEPROM.put(0, tmp);
Serial.println(F("Defaults written to EEPROM."));
}
else
{
motor.setConfig(tmp.motorConfig);
pedal.setConfig(tmp.pedalConfig);
Serial.println(F("Settings loaded from EEPROM."));
}
}
void saveSettings()
{
Settings_t tmp;
tmp.motorConfig = motor.getConfig();
tmp.pedalConfig = pedal.getConfig();
tmp.checksum = calculateChecksum(tmp);
EEPROM.put(0, tmp);
Serial.println(F("Settings saved to EEPROM."));
}
uint8_t calculateChecksum(const Settings_t &s)
{
uint8_t sum = 0;
const uint8_t *data = reinterpret_cast<const uint8_t *>(&s);
for (size_t i = 0; i < sizeof(Settings_t) - 1; i++)
{
sum ^= data[i];
}
return sum;
}
void handleEncoder()
{
static uint8_t lastState = 0;
@@ -308,4 +266,4 @@ void configurePWMFrequency()
{
// Configure Timer1 for higher PWM frequency (~4 kHz)
TCCR1B = (1 << CS11); // Set prescaler to 8
}
}