// Auto_Seat // EEPROM-backed automatic seat controller. #include #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); } }