Uno randomly stops while decoding DCC signal
Closed this issue · 4 comments
rm5248 commented
I am using an Uno to decode the DCC signal using a custom shield, but my code will randomly stop working. This is pretty easy for me to tell, since I blink LEDs on the board as long as DCC packets are incoming. The DCC signal is routed through an isolator and then to D2 on the Uno. Even if there are no packets coming across(DCC is not plugged in) it still seems to randomly stop after a few seconds.
Is there something to look at in order to debug this?
kiwi64ajs commented
Hi Robert,
On 8/10/2023, at 8:57 AM, Robert Middleton ***@***.***> wrote:
I am using an Uno to decode the DCC signal using a custom shield, but my code will randomly stop working. This is pretty easy for me to tell, since I blink LEDs on the board as long as DCC packets are incoming. The DCC signal is routed through an isolator and then to D2 on the Uno. Even if there are no packets coming across(DCC is not plugged in) it still seems to randomly stop after a few seconds.
Is there something to look at in order to debug this?
Yup, your code… ;)
This code is generally pretty solid, so you must be doing something to provoke/annoy it...
Could you send me your sketch and I can take a look? If it locks up within a few seconds, it shouldn’t take much to debug.
HTH
Alex
rm5248 commented
Sketch below. I'm only concerned about decoding DCC packets, I don't care about ACKing anything.
#include <NmraDcc.h>
#define DCC_PIN 2
int lastDccPacketTime = 0;
int blinkLedDate = 0;
int blinkVal = 0;
int shieldBlinkVal = 0;
int nextLedUpdate = 500;
NmraDcc Dcc;
void notifyDccAccTurnoutOutput (uint16_t Addr, uint8_t Direction, uint8_t OutputPower){
Serial.print("Accessory: ");
Serial.print(Addr);
Serial.print(" dir: ");
Serial.println(Direction);
}
void setup() {
Serial.begin(9600);
uint8_t maxWaitLoops = 255;
while(!Serial && maxWaitLoops--)
delay(20);
pinMode (LED_BUILTIN, OUTPUT);
// Pins 5 and 6 on the LCC shield are used for LEDs
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
// Many Arduino Cores now support the digitalPinToInterrupt() function that makes it easier to figure out the
// Interrupt Number for the Arduino Pin number, which reduces confusion.
#ifdef digitalPinToInterrupt
Dcc.pin(DCC_PIN, 1);
#else
Dcc.pin(0, DCC_PIN, 1);
#endif
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
Serial.println("Init Done");
}
void notifyDccMsg( DCC_MSG * Msg)
{
lastDccPacketTime = millis();
// Serial.print('.');
}
void loop() {
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
Dcc.process();
unsigned long now = millis();
// Blink our builtin LED periodically
if (blinkLedDate < now) {
blinkLedDate += 1000 ;
digitalWrite (LED_BUILTIN, blinkVal);
blinkVal = !blinkVal;
}
int rxDccPacket = (now - lastDccPacketTime) < 250;
// As long as we continue to get DCC packets, blink the LEDs on the shield
if(now == nextLedUpdate && rxDccPacket){
digitalWrite(5, shieldBlinkVal);
digitalWrite(6, !shieldBlinkVal);
shieldBlinkVal = !shieldBlinkVal;
nextLedUpdate += 100;
}else if(now == nextLedUpdate && !rxDccPacket){
digitalWrite(5, 0);
digitalWrite(6, 0);
nextLedUpdate += 100;
}
}
kiwi64ajs commented
Hi Robert,
I refactored a few things in your code and it should work as expected now… ;)
The variables you were using to store the result of millis() needed to be unsigned long not int as an int will wrap around before it should.
Also when comparing the various variables containing millis() you should use a “>=“ and not just a “==“ as you can’t assume to be executing the loop every ms
#include <NmraDcc.h>
#define DCC_PIN 2
#define BLINK_LED LED_BUILTIN
#define DCC_RX_LED_A 5
// #define BLINK_LED 7
// #define DCC_RX_LED_A LED_BUILTIN
#define DCC_RX_LED_B 6
bool blinkLedVal = false;
unsigned long blinkLedMillis = 0;
bool rxDccBlinkVal = false;
int rxDccCount = 0;
unsigned long rxDccLedMillis = 0;
NmraDcc Dcc;
void notifyDccAccTurnoutOutput (uint16_t Addr, uint8_t Direction, uint8_t OutputPower){
Serial.print("Accessory: ");
Serial.print(Addr);
Serial.print(" dir: ");
Serial.println(Direction);
}
void setup() {
Serial.begin(115200);
uint8_t maxWaitLoops = 255;
while(!Serial && maxWaitLoops--)
delay(20);
pinMode (LED_BUILTIN, OUTPUT);
// Pins 5 and 6 on the LCC shield are used for LEDs
pinMode(DCC_RX_LED_A, OUTPUT);
pinMode(DCC_RX_LED_B, OUTPUT);
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(DCC_PIN, 1);
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
Serial.println("Init Done");
}
void notifyDccMsg( DCC_MSG * Msg)
{
rxDccCount++;
// Serial.print("Rx:");
// Serial.println(rxDccCount);
}
void loop() {
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
Dcc.process();
unsigned long now = millis();
// Serial.print("Now: ");
// Serial.println(now);
// Blink our builtin LED periodically
if (now >= blinkLedMillis)
{
blinkLedMillis += 1000 ;
digitalWrite (LED_BUILTIN, blinkLedVal);
blinkLedVal = !blinkLedVal;
// Serial.print('b');
// Serial.print('-');
// Serial.print(blinkLedMillis);
// Serial.print('-');
// Serial.println(blinkLedVal, DEC);
}
// As long as we continue to get DCC packets, blink the LEDs on the shield
if(now >= rxDccLedMillis)
{
rxDccLedMillis += 100;
// Serial.print("Dcc Rx:");
// Serial.println(rxDccCount);
if(rxDccCount)
{
rxDccCount = 0;
digitalWrite(DCC_RX_LED_A, rxDccBlinkVal);
digitalWrite(DCC_RX_LED_B, !rxDccBlinkVal);
rxDccBlinkVal = !rxDccBlinkVal;
}
else
{
digitalWrite(DCC_RX_LED_A, 0);
digitalWrite(DCC_RX_LED_B, 0);
}
}
}
… On 8/10/2023, at 11:49 AM, Robert Middleton ***@***.***> wrote:
Sketch below. I'm only concerned about decoding DCC packets, I don't care about ACKing anything.
#include <NmraDcc.h>
#define DCC_PIN 2
int lastDccPacketTime = 0;
int blinkLedDate = 0;
int blinkVal = 0;
int shieldBlinkVal = 0;
int nextLedUpdate = 500;
NmraDcc Dcc;
void notifyDccAccTurnoutOutput (uint16_t Addr, uint8_t Direction, uint8_t OutputPower){
Serial.print("Accessory: ");
Serial.print(Addr);
Serial.print(" dir: ");
Serial.println(Direction);
}
void setup() {
Serial.begin(9600);
uint8_t maxWaitLoops = 255;
while(!Serial && maxWaitLoops--)
delay(20);
pinMode (LED_BUILTIN, OUTPUT);
// Pins 5 and 6 on the LCC shield are used for LEDs
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
// Many Arduino Cores now support the digitalPinToInterrupt() function that makes it easier to figure out the
// Interrupt Number for the Arduino Pin number, which reduces confusion.
#ifdef digitalPinToInterrupt
Dcc.pin(DCC_PIN, 1);
#else
Dcc.pin(0, DCC_PIN, 1);
#endif
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
Serial.println("Init Done");
}
void notifyDccMsg( DCC_MSG * Msg)
{
lastDccPacketTime = millis();
// Serial.print('.');
}
void loop() {
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
Dcc.process();
unsigned long now = millis();
// Blink our builtin LED periodically
if (blinkLedDate < now) {
blinkLedDate += 1000 ;
digitalWrite (LED_BUILTIN, blinkVal);
blinkVal = !blinkVal;
}
int rxDccPacket = (now - lastDccPacketTime) < 250;
// As long as we continue to get DCC packets, blink the LEDs on the shield
if(now == nextLedUpdate && rxDccPacket){
digitalWrite(5, shieldBlinkVal);
digitalWrite(6, !shieldBlinkVal);
shieldBlinkVal = !shieldBlinkVal;
nextLedUpdate += 100;
}else if(now == nextLedUpdate && !rxDccPacket){
digitalWrite(5, 0);
digitalWrite(6, 0);
nextLedUpdate += 100;
}
}
—
Reply to this email directly, view it on GitHub <#75 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AB5Y53JOT5UHDZHGKW3GL33X6HL6LAVCNFSM6AAAAAA5XEKBH2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJRHA2DOMJQGM>.
You are receiving this because you commented.
rm5248 commented
Oh, that's exactly right. I completely missed the timing problem on there, even though I had fixed it on a few other sketches before. Thanks!