Files
Auto_Seat/Auto_Seat.ino
T

117 lines
4.0 KiB
Arduino

// Auto_Seat
// EEPROM-backed automatic seat controller.
#include <EEPROM.h>
#define seatRelayD8 8
#define seatRelayD9 9
#define parkingPin A0
#define ignitionPin 7
const uint16_t SEAT_HARD_LIMIT_UP_MS = 6000;
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 DRIVE_CONFIRM_MS = 80UL;
const unsigned long PARK_CONFIRM_MS = 250UL;
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 confirmedDriveMode = LOW;
boolean pendingDriveMode = LOW;
int parkingRawValue = 0;
uint16_t storedSeatPositionMs = 0;
long currentPosMs = 0;
long targetPosMs = 0;
long downSpeedRemainder = 0;
unsigned long lastTime = 0;
unsigned long pendingDriveModeStartTime = 0;
int seatAction = 0;
void setup() {
pinMode(parkingPin, INPUT);
pinMode(ignitionPin, INPUT);
pinMode(seatRelayD8, OUTPUT);
pinMode(seatRelayD9, OUTPUT);
applySeatAction(0);
loadSettings();
measurement();
confirmedDriveMode = getRawDriveMode();
pendingDriveMode = confirmedDriveMode;
targetPosMs = getTargetForConfirmedMode();
lastTime = millis();
}
void loop() {
measurement();
unsigned long now = millis();
unsigned long deltaTime = now - lastTime;
lastTime = now;
updateConfirmedDriveMode(now);
targetPosMs = getTargetForConfirmedMode();
updateMovement(deltaTime);
applySeatAction(seatAction);
}
void measurement() {
ignitionState = digitalRead(ignitionPin);
parkingRawValue = analogRead(parkingPin);
if (parkingState == LOW && parkingRawValue >= PARKING_ON_THRESHOLD) parkingState = HIGH;
else if (parkingState == HIGH && parkingRawValue <= PARKING_OFF_THRESHOLD) parkingState = LOW;
}
boolean getRawDriveMode() { return ignitionState == HIGH && parkingState == LOW; }
long getTargetForConfirmedMode() { return confirmedDriveMode == HIGH ? storedSeatPositionMs : 0; }
void updateConfirmedDriveMode(unsigned long now) {
boolean rawDriveMode = getRawDriveMode();
if (rawDriveMode != pendingDriveMode) {
pendingDriveMode = rawDriveMode;
pendingDriveModeStartTime = now;
}
unsigned long confirmMs = pendingDriveMode == HIGH ? DRIVE_CONFIRM_MS : PARK_CONFIRM_MS;
if (pendingDriveMode != confirmedDriveMode && now - pendingDriveModeStartTime >= confirmMs) {
confirmedDriveMode = pendingDriveMode;
}
}
void updateMovement(unsigned long deltaTime) {
if (currentPosMs < targetPosMs) {
seatAction = 1;
currentPosMs += deltaTime;
if (currentPosMs >= targetPosMs) { currentPosMs = targetPosMs; seatAction = 0; }
} else if (currentPosMs > targetPosMs) {
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; seatAction = 0; }
} else {
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 applySeatAction(int action) {
if (action == 1) { setRelay(seatRelayD8, 1); setRelay(seatRelayD9, 0); }
else if (action == -1) { setRelay(seatRelayD8, 0); setRelay(seatRelayD9, 1); }
else { setRelay(seatRelayD8, 0); setRelay(seatRelayD9, 0); }
}