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();
}