Getting started with an IVT-S and Arduino Uno CAN bus shield

From openinverter.org wiki
Revision as of 13:47, 15 June 2020 by Clanger9 (talk | contribs) (Add code)
Jump to navigation Jump to search

First of all, set up your Arduino Uno and CAN bus shield.

Once the data is coming in over CAN, we can write a simple program to read the current value from the IVT-S

Here's the code:

// IVT-S meter using CAN-BUS Shield // electric_dart 2020 #include <SPI.h> #include "mcp_can.h" /*SAMD core*/ #ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE #define SERIAL SerialUSB #else #define SERIAL Serial #endif // the cs pin of the version after v1.1 is default to D9 // v0.9b and v1.0 is default D10 const int SPI_CS_PIN = 10; const int CAN_INT_PIN = 2; MCP_CAN CAN(SPI_CS_PIN); // Set CS pin unsigned char flagRecv = 0; unsigned char len = 0; unsigned char buf[8]; char str[20]; void setup() { SERIAL.begin(115200); while (!SERIAL) {  ; // wait for serial port to connect. Needed for native USB port only } while (CAN_OK != CAN.begin(CAN_1000KBPS)) { // init can bus SERIAL.println("CAN BUS Shield init fail"); SERIAL.println("Init CAN BUS Shield again"); delay(100); } SERIAL.println("CAN BUS Shield init ok!"); attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), MCP2515_ISR, FALLING); // start interrupt /* set receive mask */ CAN.init_Mask(0, 0, 0x7ff); // there are 2 masks in mcp2515, you need to set both of them CAN.init_Mask(1, 0, 0x7ff); // 0x7ff is '11111111111' in binary, so we are checking 11 of the CAN message ID bits /* set receive filter */ CAN.init_Filt(0, 0, 0x521); // there are 6 filters in mcp2515 CAN.init_Filt(1, 0, 0x521); // 0x521 is the CAN mssage ID for IVT-S Current value CAN.init_Filt(2, 0, 0x521); CAN.init_Filt(3, 0, 0x521); CAN.init_Filt(4, 0, 0x521); CAN.init_Filt(5, 0, 0x521); } void MCP2515_ISR() { flagRecv = 1; } void loop() { if (flagRecv) { // check if get data flagRecv = 0; // clear flag // iterate over all pending messages // If either the bus is saturated or the MCU is busy, // both RX buffers may be in use and reading a single // message does not clear the IRQ conditon. while (CAN_MSGAVAIL == CAN.checkReceive()) { // read data, len: data length, buf: data buf CAN.readMsgBuf(&len, buf); unsigned long canId = CAN.getCanId(); if (canId == 0x521) { SERIAL.print("Data received from IVT_Msg_Result_I"); SERIAL.print("\t"); // Convert individual big endian byte values to actual reading long reading = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | (buf[5]); SERIAL.print(reading); } SERIAL.println(); } } }