Home > OS >  Send and read the button state via CAN bus using Arduino
Send and read the button state via CAN bus using Arduino

Time:01-25

I'm intending to read the change of button input using 2 separate Arduino that connected via CAN bus (MP2515). The transmitter will connect to button with internal pulldown resistor, that pin will act as external interrupt. My reference is coming from here. By not assign any value to data frame (canMsg1 and canMsg2 in the code below), is that enough for the receiver to understand the input pin state?

The origin code using digitalRead(pin) to read and later write state of the button by single Arduino.

transmitter of CAN massage

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg1;
struct can_frame canMsg2;

MCP2515 mcp2515(10);

int incPin(2);
int decPin(3);
unsigned long current_time = 0;
unsigned long previous_time = 0;

void setup() {
  Serial.begin(9600);
  SPI.begin();

  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();
  
  canMsg1.can_id = 0xAA;
  canMsg1.can_dlc = 1;
  canMsg2.can_id = 0xBB
  canMsg2.can_dlc = 1;

  pinMode(incPin, INPUT_PULLUP);
  pinMode(decnPin, INPUT_PULLUP);

  attachInterrupt(incpPin, inc, FALLING);
  attachInterrupt(decPin, dec, FALLING);              
}

void loop() {}

void inc() {
  current_time = millis();
  if (current_time - previous_time > 200) { //debouncing for 0.2s
    mcp2515.sendMessage(&canMsg1);
  }
  previous_time = current_time;
}

void dec() {
  current_time = millis();
  if (current_time - previous_time > 200) { //debouncing for 0.2s
    mcp2515.sendMessage(&canMsg2);
  }
  previous_time = current_time;
}

receiver/reader of CAN massage

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg1;
struct can_frame canMsg2;

MCP2515 mcp2515(10);

int pos = 0;
int up;
int down;

void setup() {
  Serial.begin(9600);
  SPI.begin();

  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();      
}

void loop() {
  if (mcp2515.readMessage(&canMsg1) == MCP2515::ERROR_OK) { //read CAN increament button massage
    if (canMsg1.can_id==0xAA) {
      up = canMsg1.data[0];
      if (up == LOW) {
        pos  ;
      } else {}
    }      
  }

  if (mcp2515.readMessage(&canMsg2) == MCP2515::ERROR_OK) { //read CAN decreament button massage
    if (canMsg2.can_id==0xBB) {
      down = canMsg2.data[0];
      if (down == LOW) {
        pos--;
      } else {}
    }      
  }
}

CodePudding user response:

You are right, your CAN events do not require any data. But then, why do you set can_dlc to 1? No data is 0 bytes.

You can try this:

  • Get rid of :

    struct can_frame canMsg1; // these only hog global memory for no practical use. struct can_frame canMsg2;

Change your interrupt routines to:

void inc() {
  current_time = millis();
  if (current_time - previous_time > 200) { //debouncing for 0.2s
    mcp2515.beginPacket(0xAA);
    mcp2515.endPacket();
  }
  previous_time = current_time;
}

void dec() {
  current_time = millis();
  if (current_time - previous_time > 200) { //debouncing for 0.2s
    mcp2515.beginPacket(0xBB);
    mcp2515.endPacket();
  }
  previous_time = current_time;
}

I could not figure out what canMsg7 and canMsg8 were. Nor why you'd need several message structures in global memory to receive one CAN message at a time... I really don't think that's necessary. Since your packets have no data, receiving gets streamlined as well:

int loop() {
    if (mcp2515.parsePacket() != 0) {  // != 0 => we have fully received a packet.
        switch (mcp2515.packetId()) {
           case 0xAA:
               // inc switch was pressed
               // ...
               break;

           case 0xBB:
               // dec switch was pressed
               // ...
               break;
        }
    }
}
  • Related