Getting started with an IVT-S and Arduino Uno CAN bus shield: Difference between revisions
Jump to navigation
Jump to search
(Getting started with an IVT-S and Arduino Uno CAN bus shield) |
No edit summary |
||
Line 1: | Line 1: | ||
First of all, [[Getting started with CAN bus and an Arduino Uno|set up your Arduino Uno and CAN bus shield]]. | First of all, [[Getting started with CAN bus and an Arduino Uno|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(); | |||
} | |||
} | |||
} |
Revision as of 13:44, 15 June 2020
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(); } }
}