20 years of coding and I can't find this bug. Can you?

Hi all.

I built the Makelangelo, a robot that draws murals. The firmware is for a RUMBA board, which is arduino compatible - think a Mega 2560 and a RAMPS shield on a single PCB. The firmware is heavily based on Marlin 3D printer firmware. It supports several different kinematic systems like arms, corexy, polargraphs, etc. The polargraph is the subject today.

https://github.com/MarginallyClever/Makelangelo-firmware/releases

in release version 7.15.3 people noticed something strange - when the Makelangelo v5 is told to go home (send G28 at 57600 baud with newline) the robot (polargraph.ino, robot_findHome()) will touch both limit switches (expected) drive back to home position (fine) and then it should print "Done". Only it gets to "Do-" and reboots.

The same does not happen in 7.15.0. I took a copy of 7.15.0 and started adding features in one at a time to see if I could isolate the feature that caused the reboot. As best I can tell,

if MACHINE_HARDWARE_VERSION == 5

MENU_ACTION("Find home", LCD_find_home);

else

in lcd.ino line ~160 is the culprit. Which is 2#$*(! odd, because that code is not being called at the time the error occurs. The method LCD_find_home() calls on robot_findHome() but the call stack does not include LCD_find_home(). Commenting out the lines above and recompiling makes the bug go away.

My best guess is that there is a much older off by one error somewhere, and compiling the code in juuuust the right way causes that off by one to poke the wrong bit of ram and BOOM reboot.

Having torn out what's left of my hair looking for it, I'm at a loss. I need fresh eyes to look over my shoulder and say "put the red seven on the black eight", to spot the thing that's right in front of me that I'm missing.

Can you see it? Would you please tell me? I'm out of ideas.

Edit: a word. Edit 2: link was to software when it should have been to firmware. Oops.

This code works

#define MAGIC 5

void setup() 
{
  Serial.begin(115200);
  Serial.println(__FILE__);

#if MAGIC == 5
  Serial.println(5);
#else
  Serial.println(6);
#endif
}

void loop()
{
  
}

Could it be that MACHINE_HARDWARE_VERSION was not defined at all?

Hi,
Just came across this and was intrigued…

In robot_polargraph.h

#define NUM_MOTORS           (2)

In robot_polargraph.ino

void robot_findHome() {
...
long count[NUM_MOTORS];
  count[0] = calibrateLeft/THREAD_PER_STEP;
  count[1] = calibrateRight/THREAD_PER_STEP;
  count[2] = axies[2].pos;                      <-----------Oops !!!

Yours,
TonyWilk

int pushButton = 10;
int buttonState = 0;
int frequency =0;
int balance =6319;
/*
ArduinoFreqMetr v 1.0
*/
#include <FreqMeasure.h>

void setup() {
pinMode(pushButton, INPUT);
pinMode(2, OUTPUT); //red
pinMode(3, OUTPUT); // blue
pinMode(4, OUTPUT); // green
pinMode(7, OUTPUT); // buzer
Serial.begin(9600);
FreqMeasure.begin();
}

double sum=0;
int count=0;

void loop() {
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30) {
frequency = FreqMeasure.countToFrequency(sum / count);
Serial.println(frequency);
sum = 0;
count = 0;
}
}
//------------button-----------------
buttonState = digitalRead(pushButton);
if (buttonState == HIGH) {
balance=frequency;
};

//----------indication----------------
if (frequency==balance) {
digitalWrite(3, HIGH);
digitalWrite(7, LOW);
} else {
digitalWrite(3, LOW);
digitalWrite(7, HIGH);

};

if (frequency>balance) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
};

if (frequency<balance) {
digitalWrite(2, HIGH);
} else {
digitalWrite(2, LOW);
};

}

if (frequency>balance) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, LOW);
};

Why the superfluous semicolon after the else blocks?