marcocamilleri1111 Just logic needs to be changed in the sketch:
- // HIGH meant closed before; set bits on HIGH
- if (digitalRead(FRONT_RIGHT_DOOR_PIN) == HIGH) newDoorMask |= 0x80;
- if (digitalRead(FRONT_LEFT_DOOR_PIN) == HIGH) newDoorMask |= 0x40;
- if (digitalRead(REAR_LEFT_DOOR_PIN) == HIGH) newDoorMask |= 0x10;
- if (digitalRead(REAR_RIGHT_DOOR_PIN) == HIGH) newDoorMask |= 0x20;
- if (digitalRead(BOOT_PIN) == HIGH) newDoorMask |= 0x08;
- // LOW (GND) means DOOR OPEN now; set bits on LOW
- if (digitalRead(FRONT_RIGHT_DOOR_PIN) == LOW) newDoorMask |= 0x80;
- if (digitalRead(FRONT_LEFT_DOOR_PIN) == LOW) newDoorMask |= 0x40;
- if (digitalRead(REAR_LEFT_DOOR_PIN) == LOW) newDoorMask |= 0x10;
- if (digitalRead(REAR_RIGHT_DOOR_PIN) == LOW) newDoorMask |= 0x20;
- if (digitalRead(BOOT_PIN) == LOW) newDoorMask |= 0x08;
Here's full sketch (provided you have resistors as per schematic):
#include <HardwareSerial.h>
// =========================================================================
// Configuration
// =========================================================================
// GPIO Pin Definitions
#define FRONT_RIGHT_DOOR_PIN 2 // UK Driver's Door
#define FRONT_LEFT_DOOR_PIN 3 // UK Passenger's Door
#define REAR_LEFT_DOOR_PIN 1
#define REAR_RIGHT_DOOR_PIN 0
#define BOOT_PIN 4
#define HEADLIGHTS_PIN 5
#define LEFT_INDICATOR_PIN 6
#define RIGHT_INDICATOR_PIN 7
// UART to headunit
const int UART_TX_PIN = 20;
const long UART_BAUD_RATE = 38400;
HardwareSerial UartPort(1);
// Timeout for stabilizing blinking indicator signals (in milliseconds)
const unsigned long INDICATOR_TIMEOUT = 1200;
// Global state variables
uint8_t currentDoorStateMask = 0;
uint8_t currentLightStateMask = 0;
unsigned long lastLeftIndicatorTime = 0;
unsigned long lastRightIndicatorTime = 0;
// Timers for periodic sends
unsigned long lastDoorSendTime = 0;
unsigned long lastLightSendTime = 0;
// Flag to ensure initial status is sent only once after boot
bool initialStatusSent = false;
// =========================================================================
// Headunit Communication Functions (Based on RAISE RAV4 Protocol)
// =========================================================================
/**
* @brief Sends the Door Status frame to the headunit.
* Implements the protocol for CMD_DOOR_STATUS (0x24).
* Frame: 2E 24 01 [Mask] [Checksum]
* @param mask The bitmask representing the state of all open doors.
*/
void sendDoorCommand(uint8_t mask) {
const uint8_t HEADER = 0x2E;
const uint8_t COMMAND = 0x24;
const uint8_t LENGTH = 0x01;
uint8_t checksum = (COMMAND + LENGTH + mask) ^ 0xFF;
uint8_t frame[5] = {HEADER, COMMAND, LENGTH, mask, checksum};
UartPort.write(frame, 5);
}
/**
* @brief Sends the Light Status frame to the headunit.
* Implements the protocol for CMD_MULTI_FUNCTION (0x7D) with sub-command 0x01.
* Frame: 2E 7D 02 01 [Mask] [Checksum]
* @param mask The bitmask representing the state of the lights.
*/
void sendLightCommand(uint8_t mask) {
const uint8_t HEADER = 0x2E;
const uint8_t COMMAND = 0x7D;
const uint8_t LENGTH = 0x02;
const uint8_t SUB_COMMAND = 0x01;
uint8_t checksum = (COMMAND + LENGTH + SUB_COMMAND + mask) ^ 0xFF;
uint8_t frame[6] = {HEADER, COMMAND, LENGTH, SUB_COMMAND, mask, checksum};
UartPort.write(frame, 6);
}
// =========================================================================
// Main Sketch
// =========================================================================
void setup() {
// USB-Serial for debugging
Serial.begin(115200);
Serial.println("RAV4 Protocol Emulator Started (Doors: LOW=OPEN, HIGH=CLOSED).");
// Headunit UART port
UartPort.begin(UART_BAUD_RATE, SERIAL_8N1, -1, UART_TX_PIN);
// -------- CHANGED: use external pull-ups, so plain INPUT ----------
pinMode(FRONT_RIGHT_DOOR_PIN, INPUT);
pinMode(FRONT_LEFT_DOOR_PIN, INPUT);
pinMode(REAR_LEFT_DOOR_PIN, INPUT);
pinMode(REAR_RIGHT_DOOR_PIN, INPUT);
pinMode(BOOT_PIN, INPUT);
// ------------------------------------------------------------------
// Configure Light pins as standard INPUT
pinMode(HEADLIGHTS_PIN, INPUT);
pinMode(LEFT_INDICATOR_PIN, INPUT);
pinMode(RIGHT_INDICATOR_PIN, INPUT);
}
void loop() {
unsigned long now = millis();
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 1) Read GPIOs and build protocol-specific state masks
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// -- Build Door Mask --
// CHANGED: LOW (GND) means DOOR OPEN -> set bit on LOW
uint8_t newDoorMask = 0;
if (digitalRead(FRONT_RIGHT_DOOR_PIN) == LOW) newDoorMask |= 0x80;
if (digitalRead(FRONT_LEFT_DOOR_PIN) == LOW) newDoorMask |= 0x40;
if (digitalRead(REAR_LEFT_DOOR_PIN) == LOW) newDoorMask |= 0x10;
if (digitalRead(REAR_RIGHT_DOOR_PIN) == LOW) newDoorMask |= 0x20;
if (digitalRead(BOOT_PIN) == LOW) newDoorMask |= 0x08;
// -- Build Light Mask -- (unchanged)
uint8_t newLightMask = 0;
if (digitalRead(HEADLIGHTS_PIN) == HIGH) newLightMask |= 0x40;
// Logic for Blinking Indicators (unchanged)
if (digitalRead(LEFT_INDICATOR_PIN) == HIGH) lastLeftIndicatorTime = now;
if (digitalRead(RIGHT_INDICATOR_PIN) == HIGH) lastRightIndicatorTime = now;
if (now - lastLeftIndicatorTime < INDICATOR_TIMEOUT) newLightMask |= 0x10;
if (now - lastRightIndicatorTime < INDICATOR_TIMEOUT) newLightMask |= 0x08;
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 2) One-time status send 3 seconds after boot
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
if (!initialStatusSent && now >= 3000) {
sendDoorCommand(newDoorMask);
sendLightCommand(newLightMask);
currentDoorStateMask = newDoorMask;
currentLightStateMask = newLightMask;
initialStatusSent = true;
Serial.println("Initial 3-second status sent.");
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 3) Scheduled sends to headunit (only on state change)
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
if (now - lastDoorSendTime >= 250) {
if (newDoorMask != currentDoorStateMask) {
currentDoorStateMask = newDoorMask;
sendDoorCommand(currentDoorStateMask);
lastDoorSendTime = now;
}
}
if (now - lastLightSendTime >= 200) {
if (newLightMask != currentLightStateMask) {
currentLightStateMask = newLightMask;
sendLightCommand(currentLightStateMask);
lastLightSendTime = now;
}
}
delay(20);
}