#include <LiquidCrystal.h>
#include <Servo.h>
// 1. DEFINICIÓN DE ESTRUCTURA DE TRAMA CAN BUS
// Así es exactamente como se compone un mensaje CAN en la vida real
struct CAN_Message {
uint16_t id; // Identificador del nodo (11 bits)
byte dlc; // Data Length Code (Cantidad de bytes de datos: 0-8)
byte data[8]; // Buffer de datos (Hasta 8 bytes)
};
// Pines de la pantalla y actuadores
LiquidCrystal lcd(12, 13, 4, 5, 6, 7);
Servo velocimetro;
const int LED_TX = 10;
const int LED_RX = 11;
const uint16_t CAN_ID_RPM = 0x150; // ID del motor en la red CAN
void setup() {
pinMode(LED_TX, OUTPUT);
pinMode(LED_RX, OUTPUT);
velocimetro.attach(9);
velocimetro.write(0);
// Iniciar pantalla LCD
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" CAN BUS ECU ");
lcd.setCursor(0, 1);
lcd.print(" ON-LINE OK ");
delay(1500);
lcd.clear();
}
void loop() {
// =========================================================
// NODO 1: EMISOR (Acelerador / Sensor del Motor)
// =========================================================
int lecturaPot = analogRead(A0);
int rpmSimuladas = map(lecturaPot, 0, 1023, 800, 7000);
// Creamos un mensaje CAN virtual
CAN_Message tramaCAN;
tramaCAN.id = CAN_ID_RPM;
tramaCAN.dlc = 2; // Usaremos 2 bytes para transportar las RPM
tramaCAN.data[0] = highByte(rpmSimuladas); // Byte alto
tramaCAN.data[1] = lowByte(rpmSimuladas); // Byte bajo
// Encendemos el LED de transmisión (Enviando al bus virtual)
digitalWrite(LED_TX, HIGH);
delay(10);
digitalWrite(LED_TX, LOW);
// =========================================================
// NODO 2: RECEPTOR (Tablero de Instrumentos / Dashboard)
// =========================================================
// El tablero escucha el bus y reacciona si el ID es el correcto
if (tramaCAN.id == CAN_ID_RPM) {
// Indicamos que el nodo receptor detectó el ID en la red
digitalWrite(LED_RX, HIGH);
// El receptor desempaqueta los bytes de la trama CAN para recuperar el entero
int rpmRecibidas = (tramaCAN.data[0] << 8) | tramaCAN.data[1];
// Mover la aguja física del velocímetro (Servo)
int anguloServo = map(rpmRecibidas, 800, 7000, 0, 180);
velocimetro.write(anguloServo);
// Mostrar los datos de la red CAN en el LCD sin parpadeos
lcd.setCursor(0, 0);
lcd.print("CAN ID: 0x");
lcd.print(tramaCAN.id, HEX);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("RPM: ");
lcd.print(rpmRecibidas);
lcd.print(" RPM ");
delay(10);
digitalWrite(LED_RX, LOW);
}
delay(100); // Frecuencia de actualización estable
}