MCP2515 only receiving data from one Nano at a time

Good day!

With the use of multiple MCP2515 boards I am trying to make a CAN network for my model railroad. The purpose of this network is relaying all information to a single ESP8266 module for making it possible to make it available online.

I'm currently at a block, and cannot figure out what is wrong:

I have 2 nano's with each a rotary encoder with the NewEncoder library. The clock pins is connected to D2 and the data pin to D3. These both work, as confirmed by reading the encoder values from the serial monitor.

Together with this each nano is connected to a canbus module (see link to board in first paragraph). These modules are connected accordingly:
INT D2, SCK D13, SI D11, SO D12, CS D10

A third canbus module is connected to a Nodemcu esp8266 as follows:
INT D4, SCK D5, SI D7, SO D6, CS D3

The can bus modules High and Low are connected with the end resistors in place where required.
Code on both nano's:

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

struct can_frame canMsg;
MCP2515 mcp2515(10);

// Rotary Encoder
#define CLK 2
#define DT 3
#define SW 4

const int minVal = -30;
const int maxVal = 30;
const int startVal = 0;
int16_t currentValue;
int16_t prevEncoderValue;
unsigned long lastButtonPress = 0;

NewEncoder myEncoderObject(CLK, DT, minVal, maxVal, startVal, FULL_PULSE);

void setup() {
  NewEncoder::EncoderState myEncState;

  Serial.begin(115200);
  
  SPI.begin();
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();
  
  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } 
  else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;
    
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;

      canMsg.can_id = 0x021; // CAN id (other nano has different can id (0x036)
      canMsg.can_dlc = 8; // CAN data length as 8
      canMsg.data[0] = currentValue;
      canMsg.data[1] = 0x00; 
      canMsg.data[2] = 0x00; 
      canMsg.data[3] = 0x00;  
      canMsg.data[4] = 0x00;
      canMsg.data[5] = 0x00;
      canMsg.data[6] = 0x00;
      canMsg.data[7] = 0x00;
      mcp2515.sendMessage(&canMsg);
      
    // if currentValue stayed the same because the number is at upper/lower limit
    // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;
        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

Receiver code on the Nodemcu:

#include <SPI.h> // Library for using SPI Communication 
#include <mcp2515.h> // Library for using CAN Communication
 
struct can_frame canMsg; 
MCP2515 mcp2515(0); // SPI CS Pin 10 

void setup() {
  SPI.begin(); // Begins SPI communication
  Serial.begin(115200); // Begins Serial Communication at 9600 baud rate 
  mcp2515.reset();                          
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ); // Sets CAN at speed 500KBPS and Clock 8MHz 
  mcp2515.setNormalMode(); // Sets CAN at normal mode
}
 
void loop(){
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    if (canMsg.can_id == 0x021) {
      Serial.print("Raw CANmsg 0x021: "); Serial.println(canMsg.data[0]);
    }
    if (canMsg.can_id == 0x036) {
      Serial.print("Raw CANmsg 0x036: "); Serial.println(canMsg.data[0]);
    }
  }
 } 

Now as soon as I power everything on, one of the two Nano's works fine, sending its data over the CAN network to the Nodemcu. Except, the other does nothing. Now as soon as I disconnect the power of both Nano's, and connect the one that was not working first, this one starts working correctly and the other one stops working.

I've tried switching CAN modules and Nano's, but they all give the same result.
I hope someone can help me out. Sorry for the long story but thanks in advance.

Kind regards,
Sam

Hi, @samfleur

That is how Canbus works, if one unit is transmitting, other stay quiet.

You need to poll each Nano from the 8266, not just let them all try and transmit.

Only have a Nano transmit if it receives a command from the 8266 to do so.

Tom.. :smiley: :+1: :coffee: :australia:
PS. I was developing a similar system with my brother for T-Track, but Covid got in the way.

2 Likes

As an alternative to polling, try limiting the rate at which each Nano sends a message, for example, send a message every 20 milliseconds.

Currently both are attempting to send as fast as possible which saturates the bus and the one sending messages with the lowest Id always wins due to the way address arbitration works.

Not the cause of your problems but you can't use one pin for two different functions.

Hi, @samfleur

Can we please have a circuit diagram?
An image of a hand drawn schematic will be fine, include ALL power supplies, component names and pin labels.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Good day,

Thank you all very much for your replies and ideas.
As requested, a circuit diagram. Very sorry for the messy scaling, but first time using the software.
Everything is fed by a 5V power supply, displayed as the step down coils on the top.

Kind regards,
Sam


canrotaryencoder.pdf (1.7 MB)

Connecting CLK and the MCP2515 INT makes no sense. They are fighting for control of the signal going into the Arduino. The encoder will always win as it is a low resistance mechanical switch.

The transformer symbol implies an AC supply, but hopefully it's a regular DC supply?

Yes, this is of course a regular DC power supply.
About the double used pin;
I tried the NewEncoder library with the rotary encoder with various pins, but it only works with CLK on pin 2 and DT on pin 3. As these are the two interrupt pins from the Arduino Nano, I don't really know how to solve this.

Your code doesn't use the INT pin therefore you can disconnect it.

Good day,

So as I was trying to figuring out to how to make it so the 8266 polls instead of the nodes just transmitting, I was reading the readme.md on Github. I noticed that the way of polling is the same as I'm currently using.

How would one program the nano & 8266 to make the nano's get polled by the 8266?

Kind regards,
Sam

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.