Crash on digitalRead() with MCP2515

Hello everyone,

I've been making a CAN bus reader and gear-shift light out of a Nano clone, an MCP2515 CAN board, and some Neopixel strips - and it works! But there is a problem, specifically with the dimming circuit (reading if my car's headlights are on or off from the stereo input wire, 12-14v).

Previously, I was using a voltage divider with three resistors to a digital pin. However, after adding the MCP2515 into the mix, the Nano now crashes when turning the headlights on (previously, driven high). By crashing, I mean the Serial output stops all output (and as far as I can tell, stops looping as the neopixels don't light up when they should, either)

I decided to change the headlight circuit and use an opto-coupler instead. The 12v circuit now activates the led in the opto-coupler, and now the digital pin is pulled to ground when the headlights are on and uses the inbuilt pullup resistor. I know this works, because I ran a sketch with the code to read the digital pin only. Reads 1 on headlights off and vice versa.

...but nothing has changed. When turning the headlights on, the Nano still crashes. However, it works fine when commenting out:

  //get CAN Message
  if ((mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)) {
    getRPM();
  }

Does this mean the Nano can't read from the MCP2515 and the digital pin at the same time? Full code:


//RPM Shift Lights using an MCP2515 CAN bus board.
//Adafruit NeoPixel LED Sticks, two 8-led RGBW warm-white sticks.
//NeoPixel codes is (#,#,#,#,#) = (numberOfLed,Red,Green,Blue,White) numberOfLed = 0-15, Color is in brightness 0-255
//4N25 Opto-coupler input for dimming. 12v on diode side, ground on switch.

#include <mcp2515.h>
#include <Adafruit_NeoPixel.h>


int RPMno = 6000;   //base RPM for LED activation
int vehicleRPM = 0; //rpm value to be provided by CAN bus

struct can_frame canMsg;
MCP2515 mcp2515(7); // bracketed number is number of CS pin
int ex = 0;
int why = 0;


//NeoPixels
#define PIN 6
#define NUM_LEDS 16
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);
//full brightness
uint32_t r = strip.Color  (200, 0, 0, 0);
uint32_t g = strip.Color  (0, 180, 0, 0);
uint32_t b = strip.Color  (0, 0, 255, 0);
uint32_t w = strip.Color  (0, 0, 0, 120);
uint32_t y = strip.Color  (200, 120, 0, 0);
//dimmed
uint32_t rd = strip.Color (16, 0, 0, 0);
uint32_t gd = strip.Color (0, 14, 0, 0);
uint32_t bd = strip.Color (0, 0, 10, 0);
uint32_t wd = strip.Color (0, 0, 0, 6);
uint32_t yd = strip.Color (20, 10, 0, 0);
//off
uint32_t o = strip.Color   (0, 0, 0, 0);

int space = 100; //delay for led startup sequence

//Input for headlight circuit
#define headlights 10
bool val = 1;

//   _____ ______ _______ _    _ _____
//  / ____|  ____|__   __| |  | |  __ \ 
// | (___ | |__     | |  | |  | | |__) |
//  \___ \|  __|    | |  | |  | |  ___/
//  ____) | |____   | |  | |__| | |
// |_____/|______|  |_|   \____/|_|

void setup()
{
  //initiate neopixels
  strip.begin();
  //set strip to nothing, flushes potential random colors
  strip.clear();
  strip.fill(o);
  strip.show();

  ledStartup();

  //assign input for relay
  pinMode(headlights, INPUT_PULLUP);

  //setup the CANBus module
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_16MHZ);
  mcp2515.setListenOnlyMode();

  Serial.begin(115200);
}


//  _      ____   ____  _____
// | |    / __ \ / __ \|  __ \ 
// | |   | |  | | |  | | |__) |
// | |   | |  | | |  | |  ___/
// | |___| |__| | |__| | |
// |______\____/ \____/|_|

void loop()
{
  //get CAN Message
  if ((mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)) {
    getRPM();
  }
  
  strip.clear();
  dimmer();
}



//__      ______ _____ _____
// \ \    / / __ \_   _|  __ \ 
//  \ \  / / |  | || | | |  | |
//   \ \/ /| |  | || | | |  | |
//    \  / | |__| || |_| |__| |
//     \/   \____/_____|_____/
//
//            _
//  __ _  ___| |_ _ __ _ __  _ __ ___
// / _` |/ _ \ __| '__| '_ \| '_ ` _ \ 
//| (_| |  __/ |_| |  | |_) | | | | | |
// \__, |\___|\__|_|  | .__/|_| |_| |_|
// |___/              |_|

void getRPM (void) {
  if (canMsg.can_id == 0x140) {
    ex = canMsg.data[2];
    why = canMsg.data[3];
  }
  //combine the 2 digit hex for field 2 and field 3 to get decimal rpm
  vehicleRPM = (why & 0x3f) * 256 + ex;
  Serial.print("RPM: ");
  Serial.println(vehicleRPM);
}

//     _ _
//  __| (_)_ __ ___  _ __ ___   ___ _ __
// / _` | | '_ ` _ \| '_ ` _ \ / _ \ '__|
//| (_| | | | | | | | | | | | |  __/ |
// \__,_|_|_| |_| |_|_| |_| |_|\___|_|

void dimmer (void) {

  val = digitalRead(headlights);
  if (val == HIGH) leds();
  else ledsDimmed();
}


//  _          _
// | | ___  __| |___
// | |/ _ \/ _` / __|
// | |  __/ (_| \__ \
// |_|\___|\__,_|___/  font = ogre

void leds(void) {

  if (vehicleRPM > 0 && vehicleRPM < RPMno)
  {
    strip.fill(o); //----------------
    //strip.setPixelColor(o, 0);
    strip.show();
  }

  if (vehicleRPM > RPMno && vehicleRPM < (RPMno + 125))
  {
    strip.fill(g, 14);  //gg--------------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 125) && vehicleRPM < (RPMno + 250))
  {
    strip.fill(g, 12);  //gggg------------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 250) && vehicleRPM < (RPMno + 375))
  {
    strip.fill(g, 10);  //gggggg----------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 375) && vehicleRPM < (RPMno + 500))
  {
    strip.fill(g, 8);  //gggggggg--------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 500) && vehicleRPM < (RPMno + 625))
  {
    strip.fill(y, 6);  //yyyyyyyyyy------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 625) && vehicleRPM < (RPMno + 750))
  {
    strip.fill(y, 4);        //yyyyyyyyyyyy----
    strip.show();
  }

  if (vehicleRPM > (RPMno + 750) && vehicleRPM < (RPMno + 875))
  {
    strip.fill(r, 2);        //rrrrrrrrrrrrrr--
    strip.show();
  }

  if (vehicleRPM > (RPMno + 875) && vehicleRPM < (RPMno + 1000))
  {
    strip.fill(r, 0);       //rrrrrrrrrrrrrr
    strip.show();
  }

  if (vehicleRPM > (RPMno + 1000) && vehicleRPM < (RPMno + 1500))
  {
    strip.fill(w);        //wwwwwwwwwwwwwwww
    strip.show();
  }

  if (vehicleRPM > (RPMno + 1500) && vehicleRPM < (RPMno + 2000) )
  {
    strip.fill(o);
    strip.show();
  }

  if (vehicleRPM > 10000)
  {
    strip.fill(o);
    strip.show();
  }
}

//  _          _        ___ _                              _
// | | ___  __| |___   /   (_)_ __ ___  _ __ ___   ___  __| |
// | |/ _ \/ _` / __| / /\ / | '_ ` _ \| '_ ` _ \ / _ \/ _` |
// | |  __/ (_| \__ \/ /_//| | | | | | | | | | | |  __/ (_| |
// |_|\___|\__,_|___/___,' |_|_| |_| |_|_| |_| |_|\___|\__,_|

void ledsDimmed(void)  {

  if (vehicleRPM > 0 && vehicleRPM < RPMno)
  {
    strip.fill(o); //----------------
    //strip.setPixelColor(o, 0);
    strip.show();
  }

  if (vehicleRPM > RPMno && vehicleRPM < (RPMno + 125))
  {
    strip.fill(gd, 14);  //gg--------------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 125) && vehicleRPM < (RPMno + 250))
  {
    strip.fill(gd, 12);  //gggg------------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 250) && vehicleRPM < (RPMno + 375))
  {
    strip.fill(gd, 10);  //gggggg----------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 375) && vehicleRPM < (RPMno + 500))
  {
    strip.fill(gd, 8);  //gggggggg--------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 500) && vehicleRPM < (RPMno + 625))
  {
    strip.fill(yd, 6);  //yyyyyyyyyy------
    strip.show();
  }

  if (vehicleRPM > (RPMno + 625) && vehicleRPM < (RPMno + 750))
  {
    strip.fill(yd, 4);        //yyyyyyyyyyyy----
    strip.show();
  }

  if (vehicleRPM > (RPMno + 750) && vehicleRPM < (RPMno + 875))
  {
    strip.fill(rd, 2);        //rrrrrrrrrrrrrr--
    strip.show();
  }

  if (vehicleRPM > (RPMno + 875) && vehicleRPM < (RPMno + 1000))
  {
    strip.fill(rd, 0);       //rrrrrrrrrrrrrr
    strip.show();
  }

  if (vehicleRPM > (RPMno + 1000) && vehicleRPM < (RPMno + 1500))
  {
    strip.fill(wd);        //wwwwwwwwwwwwwwww
    strip.show();
  }

  if (vehicleRPM > (RPMno + 1500) && vehicleRPM < (RPMno + 2000) )
  {
    strip.fill(o);
    strip.show();
  }

  if (vehicleRPM > 10000)
  {
    strip.fill(o);
    strip.show();
  }
}

//  _          _      __ _             _
// | | ___  __| |___ / _\ |_ __ _ _ __| |_ _   _ _ __
// | |/ _ \/ _` / __|\ \| __/ _` | '__| __| | | | '_ \ 
// | |  __/ (_| \__ \_\ \ || (_| | |  | |_| |_| | |_) |
// |_|\___|\__,_|___/\__/\__\__,_|_|   \__|\__,_| .__/
//                                             |_|
void ledStartup(void)
{
  strip.fill(o);
  strip.show();
  delay(space);

  strip.fill(gd, 14);
  strip.show();
  delay(space);

  strip.fill(gd, 12);
  strip.show();
  delay(space);

  strip.fill(gd, 10);
  strip.show();
  delay(space);

  strip.fill(yd, 8);
  strip.show();
  delay(space);

  strip.fill(yd, 6);
  strip.show();
  delay(space);

  strip.fill(yd, 4);
  strip.show();
  delay(space);

  strip.fill(rd, 2);
  strip.show();
  delay(space);

  strip.fill(rd);
  strip.show();
  delay(space);
  //---------------------------
  strip.fill(wd);
  strip.show();
  delay(space * 2);
  //----------------------------
  strip.clear();
  strip.fill(rd);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(rd, 2);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd, 4);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd, 6);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(yd, 8);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(gd, 10);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(gd, 12);
  strip.show();
  delay(space);

  strip.clear();
  strip.fill(gd, 14);
  strip.show();
  delay(space);

  strip.fill(o);
  strip.show();
}

You are not reading these things at the same time?
Sure they are on the same line but the compiler reduces these things to one instruction after the other, so nothing is done "at the same time" as anything else.

You may want to read this before you proceed:-
how to get the best out of this forum
It will tell you how to ask a question.
Specifically we will need a schematic and a description of your project.

Does this "work"

//get CAN Message
  if ((mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)) {
   // getRPM();
  }

If so the issue may be in the function getRPM():

void getRPM (void) {
  if (canMsg.can_id == 0x140) {
//    ex = canMsg.data[2];
 //   why = canMsg.data[3];
  }
  //combine the 2 digit hex for field 2 and field 3 to get decimal rpm
  //vehicleRPM = (why & 0x3f) * 256 + ex;
  //Serial.print("RPM: ");
  //Serial.println(vehicleRPM);
}

then it becomes a matter of troubleshooting getRPM()

try changing this to a different pin.

Worked, thank you so much. Cant believe I didn't think to test other pins.

Swapped to digital pin 2 and no longer crashes. As digital pin 10 is the SS pin for the Nano, it must have been interfering with the communication with the MCP2515.

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