Add EEPROM-backed seat position setting
This commit is contained in:
+36
-85
@@ -1,5 +1,6 @@
|
||||
// Auto_Seat
|
||||
// Timed automatic seat controller with relay protection.
|
||||
// EEPROM-backed automatic seat controller.
|
||||
#include <EEPROM.h>
|
||||
|
||||
#define seatRelayD8 8
|
||||
#define seatRelayD9 9
|
||||
@@ -11,31 +12,24 @@ const int PARKING_ON_THRESHOLD = 950;
|
||||
const int PARKING_OFF_THRESHOLD = 940;
|
||||
const int DOWN_SPEED_NUM = 11;
|
||||
const int DOWN_SPEED_DEN = 10;
|
||||
const unsigned long IGNITION_STABILIZE_MS = 1000UL;
|
||||
const unsigned long DRIVE_CONFIRM_MS = 80UL;
|
||||
const unsigned long PARK_CONFIRM_MS = 250UL;
|
||||
const unsigned long RELAY_DEADTIME_MS = 120UL;
|
||||
const unsigned long DOWN_EDGE_MARGIN_MS = 300UL;
|
||||
const int EEPROM_MAGIC_ADDR = 0;
|
||||
const byte EEPROM_MAGIC_VALUE = 0x64;
|
||||
const int EEPROM_SEAT_POSITION_ADDR = 2;
|
||||
|
||||
boolean ignitionState = LOW;
|
||||
boolean parkingState = LOW;
|
||||
boolean prevIgnitionState = LOW;
|
||||
boolean confirmedDriveMode = LOW;
|
||||
boolean pendingDriveMode = LOW;
|
||||
bool isStabilizing = false;
|
||||
bool downEdgeMarginActive = false;
|
||||
int parkingRawValue = 0;
|
||||
uint16_t storedSeatPositionMs = 0;
|
||||
long currentPosMs = 0;
|
||||
long targetPosMs = 0;
|
||||
long downSpeedRemainder = 0;
|
||||
unsigned long lastTime = 0;
|
||||
unsigned long stabilizeStartTime = 0;
|
||||
unsigned long pendingDriveModeStartTime = 0;
|
||||
unsigned long relayDeadtimeStartTime = 0;
|
||||
unsigned long downEdgeMarginTime = DOWN_EDGE_MARGIN_MS;
|
||||
int currentSeatAction = 0;
|
||||
int requestedSeatAction = 0;
|
||||
int lastStoppedSeatAction = 0;
|
||||
int seatAction = 0;
|
||||
|
||||
void setup() {
|
||||
pinMode(parkingPin, INPUT);
|
||||
@@ -43,7 +37,7 @@ void setup() {
|
||||
pinMode(seatRelayD8, OUTPUT);
|
||||
pinMode(seatRelayD9, OUTPUT);
|
||||
applySeatAction(0);
|
||||
seat(0);
|
||||
loadSettings();
|
||||
measurement();
|
||||
confirmedDriveMode = getRawDriveMode();
|
||||
pendingDriveMode = confirmedDriveMode;
|
||||
@@ -53,27 +47,13 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
measurement();
|
||||
unsigned long currentTime = millis();
|
||||
unsigned long deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
if (prevIgnitionState == LOW && ignitionState == HIGH) {
|
||||
isStabilizing = true;
|
||||
stabilizeStartTime = currentTime;
|
||||
}
|
||||
prevIgnitionState = ignitionState;
|
||||
|
||||
if (isStabilizing && currentTime - stabilizeStartTime < IGNITION_STABILIZE_MS) {
|
||||
seat(0);
|
||||
updateRelayOutput(currentTime);
|
||||
return;
|
||||
}
|
||||
isStabilizing = false;
|
||||
|
||||
updateConfirmedDriveMode(currentTime);
|
||||
unsigned long now = millis();
|
||||
unsigned long deltaTime = now - lastTime;
|
||||
lastTime = now;
|
||||
updateConfirmedDriveMode(now);
|
||||
targetPosMs = getTargetForConfirmedMode();
|
||||
updateMovement(deltaTime);
|
||||
updateRelayOutput(currentTime);
|
||||
applySeatAction(seatAction);
|
||||
}
|
||||
|
||||
void measurement() {
|
||||
@@ -84,80 +64,51 @@ void measurement() {
|
||||
}
|
||||
|
||||
boolean getRawDriveMode() { return ignitionState == HIGH && parkingState == LOW; }
|
||||
long getTargetForConfirmedMode() { return confirmedDriveMode == HIGH ? SEAT_HARD_LIMIT_UP_MS : 0; }
|
||||
long getTargetForConfirmedMode() { return confirmedDriveMode == HIGH ? storedSeatPositionMs : 0; }
|
||||
|
||||
void updateConfirmedDriveMode(unsigned long currentTime) {
|
||||
void updateConfirmedDriveMode(unsigned long now) {
|
||||
boolean rawDriveMode = getRawDriveMode();
|
||||
if (rawDriveMode != pendingDriveMode) {
|
||||
pendingDriveMode = rawDriveMode;
|
||||
pendingDriveModeStartTime = currentTime;
|
||||
pendingDriveModeStartTime = now;
|
||||
}
|
||||
unsigned long confirmMs = pendingDriveMode == HIGH ? DRIVE_CONFIRM_MS : PARK_CONFIRM_MS;
|
||||
if (pendingDriveMode != confirmedDriveMode && currentTime - pendingDriveModeStartTime >= confirmMs) {
|
||||
if (pendingDriveMode != confirmedDriveMode && now - pendingDriveModeStartTime >= confirmMs) {
|
||||
confirmedDriveMode = pendingDriveMode;
|
||||
}
|
||||
}
|
||||
|
||||
void updateMovement(unsigned long deltaTime) {
|
||||
if (downEdgeMarginActive) {
|
||||
seat(-1);
|
||||
downEdgeMarginTime += deltaTime;
|
||||
if (downEdgeMarginTime >= DOWN_EDGE_MARGIN_MS) {
|
||||
downEdgeMarginActive = false;
|
||||
downEdgeMarginTime = DOWN_EDGE_MARGIN_MS;
|
||||
seat(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPosMs < targetPosMs) {
|
||||
seat(1);
|
||||
seatAction = 1;
|
||||
currentPosMs += deltaTime;
|
||||
if (currentPosMs >= targetPosMs) {
|
||||
currentPosMs = targetPosMs;
|
||||
seat(0);
|
||||
}
|
||||
if (currentPosMs >= targetPosMs) { currentPosMs = targetPosMs; seatAction = 0; }
|
||||
} else if (currentPosMs > targetPosMs) {
|
||||
seat(-1);
|
||||
seatAction = -1;
|
||||
long scaled = deltaTime * DOWN_SPEED_NUM + downSpeedRemainder;
|
||||
currentPosMs -= scaled / DOWN_SPEED_DEN;
|
||||
downSpeedRemainder = scaled % DOWN_SPEED_DEN;
|
||||
if (currentPosMs <= targetPosMs) {
|
||||
currentPosMs = targetPosMs;
|
||||
downSpeedRemainder = 0;
|
||||
if (targetPosMs == 0) {
|
||||
downEdgeMarginActive = true;
|
||||
downEdgeMarginTime = 0;
|
||||
} else {
|
||||
seat(0);
|
||||
}
|
||||
}
|
||||
if (currentPosMs <= targetPosMs) { currentPosMs = targetPosMs; downSpeedRemainder = 0; seatAction = 0; }
|
||||
} else {
|
||||
seat(0);
|
||||
seatAction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void loadSettings() {
|
||||
if (EEPROM.read(EEPROM_MAGIC_ADDR) != EEPROM_MAGIC_VALUE) {
|
||||
EEPROM.update(EEPROM_MAGIC_ADDR, EEPROM_MAGIC_VALUE);
|
||||
writeUint16(EEPROM_SEAT_POSITION_ADDR, SEAT_HARD_LIMIT_UP_MS);
|
||||
}
|
||||
storedSeatPositionMs = readUint16(EEPROM_SEAT_POSITION_ADDR);
|
||||
if (storedSeatPositionMs > SEAT_HARD_LIMIT_UP_MS) {
|
||||
storedSeatPositionMs = SEAT_HARD_LIMIT_UP_MS;
|
||||
writeUint16(EEPROM_SEAT_POSITION_ADDR, storedSeatPositionMs);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t readUint16(int addr) { return (uint16_t)EEPROM.read(addr) | ((uint16_t)EEPROM.read(addr + 1) << 8); }
|
||||
void writeUint16(int addr, uint16_t value) { EEPROM.update(addr, value & 0xFF); EEPROM.update(addr + 1, (value >> 8) & 0xFF); }
|
||||
void setRelay(int relayPin, boolean state) { digitalWrite(relayPin, state ? LOW : HIGH); }
|
||||
void seat(int action) { requestedSeatAction = action; }
|
||||
|
||||
void updateRelayOutput(unsigned long currentTime) {
|
||||
if (requestedSeatAction == currentSeatAction) {
|
||||
applySeatAction(currentSeatAction);
|
||||
return;
|
||||
}
|
||||
if (currentSeatAction != 0) {
|
||||
lastStoppedSeatAction = currentSeatAction;
|
||||
currentSeatAction = 0;
|
||||
relayDeadtimeStartTime = currentTime;
|
||||
applySeatAction(0);
|
||||
return;
|
||||
}
|
||||
bool sameDirectionResume = requestedSeatAction != 0 && requestedSeatAction == lastStoppedSeatAction;
|
||||
bool deadtimeDone = currentTime - relayDeadtimeStartTime >= RELAY_DEADTIME_MS;
|
||||
if (sameDirectionResume || deadtimeDone) currentSeatAction = requestedSeatAction;
|
||||
applySeatAction(currentSeatAction);
|
||||
}
|
||||
|
||||
void applySeatAction(int action) {
|
||||
if (action == 1) { setRelay(seatRelayD8, 1); setRelay(seatRelayD9, 0); }
|
||||
else if (action == -1) { setRelay(seatRelayD8, 0); setRelay(seatRelayD9, 1); }
|
||||
|
||||
Reference in New Issue
Block a user