Getting started with an IVT-S and Arduino Uno CAN bus shield: Difference between revisions

From openinverter.org wiki
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

  1. include <SPI.h>
  2. include "mcp_can.h"

/*SAMD core*/

  1. ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
   #define SERIAL SerialUSB
  1. else
   #define SERIAL Serial
  1. 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();
       }
   }

}