I've written some code that converts RS485 to can bus, I've loaded this code onto a Uno with the usual generic Can bus transceiver shield together with a simple bit of code again using mcp_can.h and its basically working except it will only send 5 of the 6 data packets, I'm really not sure if the is an issue with the transmitter or receiver, following is the part of the transmitter code isolated from the main body to make it more readable;
/*
* This code sends 6 packet of Canbus data every second
*/
#include <Arduino.h>
#include <SPI.h>
#include <mcp_can.h>
unsigned long previousMillis = 0; // used for code cycle timing
const long interval = 1000; // code cycle time (set for 1 second)
byte CAN_MSG[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // array for transmitted can bus message
uint16_t addressID = 0; // address of can bus message to be sent
//byte sndStat = 0;
uint8_t MSG_RustyK[8] = {'G', 0x52, 0x49, 0x54, 0x45, 0x43, 0x48, 0x20}; // manufaturers name
byte sndStat = 0;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MCP_CAN CAN0(10); // Set CS to pin 10
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void setup() {
// Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
else Serial.println("Error Initializing MCP2515...");
CAN0.setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted
Serial.begin(115200); // initialise serial for IDE console to allow debugging
}
//=========================================================================================
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv main loop vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
void loop() {
//--------------------- untimed code -------this runs with every loop -----------------
//------------------------------end of untimed code -------------------------------------------
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
//----------------------------- timed code, this code runs once per second --------------------------
canbusSend(); // send can bus message to inverter
//---------------------------------- end of timed code -------------------------------------------
}
}
//================================= end of main loop ==================================================
//================================= subroutines =======================================================
void canbusSend() { // ---------- send can bus message to inverter ----------------------------------
//--------------------------------------- packet 1 ------ protection bits --------------------------
addressID = 0x359; // (flags) set as per pylon protocol
CAN_MSG[0] = 0x00;
CAN_MSG[1] = 0x00;
CAN_MSG[2] = 0x00;
CAN_MSG[3] = 0x00;
CAN_MSG[4] = 0x0A;
CAN_MSG[5] = 0x50; // sends ASCII 'P'
CAN_MSG[6] = 0x4E; // sends ASCII 'N'
CAN_MSG[7] = 0x00;
//sndStat = CAN0.sendMsgBuf(addressID, 0, 8, CAN_MSG); // send flags
//----------------packet 2------- charge / discharge voltage current temperature-------
addressID = 0x351;
CAN_MSG[0] = 0x30; // 0x30
CAN_MSG[1] = 0x02; // 0x02
CAN_MSG[2] = 0xC8; // 0xC8
CAN_MSG[3] = 0x00; // 0x00
CAN_MSG[4] = 0x58; // 0x58
CAN_MSG[5] = 0x02; // 0x02
CAN_MSG[6] = 0x00; // not used // 0x00
CAN_MSG[7] = 0x00; // not used // 0x00
sndStat = CAN0.sendMsgBuf(addressID, 0, 8, CAN_MSG); // send limits
//-------------- packet 3---------- state of charge, state of health -----------------
addressID = 0x355;
CAN_MSG[0] = 0x41; // 0x41
CAN_MSG[1] = 0x00; // 0x00
CAN_MSG[2] = 0x63; // 0x63
CAN_MSG[3] = 0x00; // 0x00
CAN_MSG[4] = 0x00;
CAN_MSG[5] = 0x00;
CAN_MSG[6] = 0x00;
CAN_MSG[7] = 0x00;
sndStat = CAN0.sendMsgBuf(addressID, 0, 8, CAN_MSG); // send state of charge
//------------------- packet 4 --------canbus send voltage current temperature-------------
addressID = 0x356;
CAN_MSG[0] = 0xB8; // packVoltageLowByte; // 0xB8
CAN_MSG[1] = 0x14; // packVoltageHighByte; // 0x14
CAN_MSG[2] = 0xF7; // packCurrentLowByte; // 0xF7
CAN_MSG[3] = 0xFF; // packCurrentHighByte; // 0xFF
CAN_MSG[4] = 0x54; // packTempLowByte; // 0x54
CAN_MSG[5] = 0x01; // packTempHighByte; // 0x01
CAN_MSG[6] = 0x00;
CAN_MSG[7] = 0x00;
sndStat = CAN0.sendMsgBuf(addressID, 0, 8, CAN_MSG); // send Volts Amps and temp
//---------------- packet 5 ----------charge request flags----------------------
addressID = 0x35C; //
CAN_MSG[0] = 0xC0; // this byte used only as per *
CAN_MSG[1] = 0x00;
CAN_MSG[2] = 0x00;
CAN_MSG[3] = 0x00;
CAN_MSG[4] = 0x00;
CAN_MSG[5] = 0x00;
CAN_MSG[6] = 0x00;
CAN_MSG[7] = 0x00;
sndStat = CAN0.sendMsgBuf(addressID, 0, 8, CAN_MSG); // send protection bits
//-------------packet 6 ---------canbus send manufactures name----------------------
addressID = 0x35E;
MSG_RustyK[0] = 1;
MSG_RustyK[1] = 2;
MSG_RustyK[2] = 3;
MSG_RustyK[3] = 4;
MSG_RustyK[4] = 5;
MSG_RustyK[5] = 6;
MSG_RustyK[6] = 7;
MSG_RustyK[7] = 8;
sndStat = CAN0.sendMsgBuf(addressID, 0, 8, MSG_RustyK); // send manufacurers name
}
Here is the code for the reciver;
/*
* This code uploads onto a Uno or similar to comunicate with the BMS RS485 / Canbus converter
*
*
*
*/
// version 1.0
#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
int data0 = 0;
// Array to store serial string
#define CAN0_INT 2 // Set INT to pin 2
MCP_CAN CAN0(10); // Set CS to pin 10
void setup()
{
Serial.begin(115200);
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
CAN0.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data.
pinMode(CAN0_INT, INPUT); // Configuring pin for /INT input
}
void loop()
{
if (!digitalRead(CAN0_INT)) // If CAN0_INT pin is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &len, rxBuf);
int data0 = rxBuf[0];
int data1 = rxBuf[1];
int data2 = rxBuf[2];
int data3 = rxBuf[3];
int data4 = rxBuf[4];
int data5 = rxBuf[5];
int data6 = rxBuf[6];
int data7 = rxBuf[7];
int data8 = rxBuf[8];
Serial.print("address ");
Serial.print(rxId,HEX);
Serial.print(" ");
Serial.print("bytes ");
Serial.print(len,HEX);
Serial.print(" ");
//----------------------------------------------
//----------------------------------------------
if (rxId == 0x359) {
Serial.print("0x359 protection bits ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
//----------------------------------------------
if (rxId == 0x351) {
Serial.print("0x351 charge perameters ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
//------------------------------------------------
if (rxId == 0x355) {
Serial.print("0x355 state of charge ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
//------------------------------------------------
if (rxId == 0x356) {
Serial.print("0x356 voltage current temp ");
Serial.print("protection ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
//------------------------------------------------
if (rxId == 0x35C) {
Serial.print("0x35C request flags ");
Serial.print("protection ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
//------------------------------------------------
if (rxId == 0x35E) {
Serial.print("0x35E manufacueres name ");
Serial.print(data0);
Serial.print(" ");
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.print(data3);
Serial.print(" ");
Serial.print(data4);
Serial.print(" ");
Serial.print(data5);
Serial.print(" ");
Serial.print(data6);
Serial.print(" ");
Serial.println(data7);
}
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/