Hi,
I’ve been trying to set up an Arduino Nano to receive inputs from a voltage source and translate that to CANBUS. I want to take inputs from the cars dashboard such as indicators, high beam, handbrake etc. and get the Arduino to sent the CAN commands to RealDash using the existing RealDash ID’s.
I have successfully made a simple sketch that can simultaneously send the commands to RealDash. I am no programmer so I’m sure there are way better way of doing this but I thought I would share this here as I couldn’t find any examples on the internet.
This works with SEEEDSTUDIO USBCananalyzer and should work with all RealDash compatible CAN devices as far as I know.
I have an Arduino Nano using the Autowp 2515 canbus library to send the can commands via a generic MCP2515. I use generic mini DC DC buck transformers to drop down the voltage from the cars instrument cluster to 5v.
You can use the analogue input for fuel level sending but I haven’t included that in this code.
#include <SPI.h>
#include <mcp2515.h>
// Pin Definitions
#define LEFT_INDICATOR_PIN 3
#define RIGHT_INDICATOR_PIN 4
#define HIGH_BEAM_PIN 5
#define PARKING_BRAKE_PIN 7
// Specific CAN Message IDs as provided
#define LEFT_INDICATOR_MSG_ID 0x160
#define RIGHT_INDICATOR_MSG_ID 0x161
#define HIGH_BEAM_MSG_ID 0x157
#define PARKING_BRAKE_MSG_ID 0x164
struct can_frame canMsg;
MCP2515 mcp2515(10); // CS pin for MCP2515
// State tracking for buttons with independent states
struct ButtonState {
bool currentState = false;
bool lastState = false;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
};
ButtonState leftIndicator;
ButtonState rightIndicator;
ButtonState highBeam;
ButtonState parkingBrake;
void setup() {
Serial.begin(115200);
// Initialize button pins as INPUT for 5V signaling
pinMode(LEFT_INDICATOR_PIN, INPUT);
pinMode(RIGHT_INDICATOR_PIN, INPUT);
pinMode(HIGH_BEAM_PIN, INPUT);
pinMode(PARKING_BRAKE_PIN, INPUT);
// Initialize CAN bus
mcp2515.reset();
// Set bitrate to 1000 Kbps (1 Mbps) with 16 MHz crystal
mcp2515.setBitrate(CAN_1000KBPS, MCP_16MHZ);
mcp2515.setNormalMode();
}
void sendCanMessage(uint16_t msgId, bool state) {
canMsg.can_id = msgId;
canMsg.can_dlc = 1;
canMsg.data[0] = state ? 0x01 : 0x00;
mcp2515.sendMessage(&canMsg);
}
void checkButton(int pin, ButtonState &buttonState, uint16_t msgId) {
int reading = digitalRead(pin);
// Check for debounce
if (reading != buttonState.lastState) {
buttonState.lastDebounceTime = millis();
}
if ((millis() - buttonState.lastDebounceTime) > buttonState.debounceDelay) {
// If the button state has changed
if (reading != buttonState.currentState) {
buttonState.currentState = reading;
// Send CAN message when state changes
sendCanMessage(msgId, reading == HIGH);
}
}
buttonState.lastState = reading;
}
void loop() {
// Check and send messages for each button independently
checkButton(LEFT_INDICATOR_PIN, leftIndicator, LEFT_INDICATOR_MSG_ID);
checkButton(RIGHT_INDICATOR_PIN, rightIndicator, RIGHT_INDICATOR_MSG_ID);
checkButton(HIGH_BEAM_PIN, highBeam, HIGH_BEAM_MSG_ID);
checkButton(PARKING_BRAKE_PIN, parkingBrake, PARKING_BRAKE_MSG_ID);
// Small delay to prevent overwhelming the CAN bus
delay(10);
}
This should be a good base for any modifications you might need to make it work for you.
Below is the XML for the inputs:
frame id=“0x160” endianess=“big” writeInterval=“100”
value targetId=“160” offset=“0” length=“1”/
frame id=“0x161” endianess=“big” writeInterval=“100”
value targetId=“161” offset=“0” length=“1”/
frame id=“0x157” endianess=“big” writeInterval=“100”
value targetId=“157” offset=“0” length=“1”/
frame id=“0x164” endianess=“big” writeInterval=“100”
value targetId=“164” offset=“0” length=“1”/
frame id=“0x170” endianess=“big” writeInterval=“100”
value targetId=“170” units=“%” offset=“0” length=“1” conversion=“V*100”/
You will have to modify the formatting to match the RealDash XML formatting.
I hope this helps someone.