Debug example using Serial

Trying my best to assist new members out of my 50 years in mostly old environments I show this code as help to debug in real time. That way I managed to quickly dig into unknown and large codes.

The example use a triple loop activating an RGB LED.

Do like this:

Open Serial Monitor and set the baudrate in IDE and in the code to the same value.
In the code I used the names A, B and C and they make the loop variable i, j and k to be displayed.

Send A, B or C from Serial, at any time You want, to the controller like this: ABC Cr, or garbageABC Cr. Cr == Cariage return.

void setup() {
  // put your setup code here, to run once:
  pinMode (9, OUTPUT);//pin used for blue colour
  pinMode (10, OUTPUT);//pin used for red colour
  pinMode (11, OUTPUT);//pin used for green colour

  Serial.begin(115200);//full speed but can be any other speed
  analogWrite(9, 125);//turn on blue colour 
  Serial.print("125 ");//tell on Serial
  delay(5000);//give spectator time to verify function
  analogWrite(9, 0);//turn off blue
  analogWrite(10, 125);//turn on red
  Serial.print("125 ");//tell on Serial
  delay(5000);//give spectator time to verify function
  analogWrite(10, 0);//turn off red
  analogWrite(11, 125);//turn on green
  Serial.println("125 ");//tell on Serial
  delay(5000);//give spectator time to verify function
  analogWrite(11, 0);//turn off green
}

void loop() {

  int i, j, k;//the three colour loop variables
  int debugDisplay;//value to be displyed if a defined name is given
  bool debugFlag;//debug flag telling a valid variable name is received
  char Sa;//debugged variable name to be displayed

  for ( i = 0; i < 125; i = i + 5)//loop for blue
  {
    for ( j = 0; j < 125; j = j + 5)//loop for red
    {
      for ( k = 0; k < 125; k = k + 5)//loop for green
      {
        debugFlag = false;//initiate flag for displaying value
        if (Serial.available())//if debug order from keyboard
        {
          Sa = Serial.read();//get the name for variable to disply
          switch (Sa) {
            case 'A'://name is 'A', display its variable in switch case below
              {
                debugDisplay = i;//display correct variable value in case below
                debugFlag = true;//tell valid debug name was received
                break;
              }
            case 'B'://name is 'B', display its variable in switch case below
              {
                debugDisplay = j;//display correct variable in case below
                debugFlag = true;//tell valid debug name was received
                break;
              }
            case 'C'://name is 'C', display its variable in switch case below
              {
                debugDisplay = k; //display correct variable in case below
                debugFlag = true;//tell valid debug name was received
                break;
              }
            default:
              //              debugFlag = false;
              break;
          }//end of switch

          if (debugFlag)//print out if valid debug from Serial
          {
            Serial.print(Sa); Serial.print(" = ");//name of variable
            Serial.println(debugDisplay);// actual variable value
            debugFlag = false;//turn off display, vslue displeyd above
          }
        }
      }

      analogWrite(9, i);//PWM for blue
      analogWrite(10, j);//PWM for green
      analogWrite(11, k);//PWM for red
    }
  }
}

If you’re trying to describe good debugging practice:

Don’t do anonymous prints.

If you’re doing debug-only prints, remember if they’re string literals (see later), make sure you use the F() macro.

If you’re using string literals, don’t use them if a simple edit or typo could render them inaccurate or misleading

analogWrite(10, 123);//turn on red
  Serial.print("125 ");//tell on Serial

i.e., use the same value

const int redVal = 125;
analogWrite(redPin, redVal);//turn on red
Serial.print (F("red: "));
Serial.print(redVal);

If you’re writing a loop, think about a sensible index name, rather than adding a dumb comment

for ( i = 0; i < 125; i = i + 5)//loop for blue

aka

for (int blueVal = 0; blueVal < 125; blueVal += 5)

And, please, use pin names.

Edit: make sure you initialise variables, like locals,

bool debugFlag;

And limit scope to the bare minimum.

Maybe try to make debug commands more mnemonic.

And…rather than comment-out inconvenient bugs, try to give each case its own break.

If you factor the code as you go along, it makes things easier and more self-consistent.
Uncompiled, untested

const byte bluePin  =  9;
const byte redPin   = 10;
const byte greenPin = 11;

void reportPin (byte pin, byte val)
{
  switch (pin) {
    case bluePin:  Serial.print (F("Blue: ");  break;
    case greenPin: Serial.print (F("Green: "); break;
    case redPin:   Serial.print (F("Red: ");   break;
  }
  Serial.print(val);
}

void colourWrite (byte pin, byte val)
{
  reportPin (pin, val);
  analogWrite(pin, val);
}

void setup() 
{
  Serial.begin(115200);
  // all the colour pins are used with analogWrite,
  // so are automatically OUTPUTs
  
  colourWrite (bluePin, 125);
  delay(5000);
  colourWrite (bluePin, 0);

  colourWrite (redPin, 125);
  delay(5000);
  colourWrite (redPin, 0);

  colourWrite (greenPin, 125);
  delay(5000);
  colourWrite (greenPin, 0);
}

void loop() 
{
  for (int blueVal = 0; blueVal < 125; blueVal += 5) {
    for (int redVal = 0; redVal < 125; redVal += 5) {
      for (int greenVal = 0; greenVal < 125; greenVal += 5) {
        if (Serial.available()) {
          char Sa = Serial.read();
          switch (Sa) {
            case 'B':
              reportPin (bluePin, blueVal);
            break;
            case 'R':
              reportPin (redPin, redVal);
            break;
            case 'G':
              reportPin (greenPin, greenVal);
            break;
            default:
              // maybe report a bum command?
            break;
          }
        }

        analogWrite(bluePin,  blueVal);
        analogWrite(greenPin, greenVal);
        analogWrite(redVal,   redVal);
      }
    } 
  }
}

TheMemberFormerlyKnownAsAWOL:
If you’re trying to describe good debugging practice:

Good debuuging or not? One way to do it working well.

Don’t do anonymous prints.
Just made this out of an inspiring video, and it works. Explain what You try to tell. I don’t get the point.

If you’re doing debug-only prints, remember if they’re string literals (see later), make sure you use the F() macro.
Yes, debug printing of internal variables. Strings are, as we know, not good to use due to poor garbage collection.

If you’re using string literals, don’t use them if a simple edit or typo could render them inaccurate or misleading

analogWrite(10, 123);//turn on red

Serial.print("125 ");//tell on Serial



i.e., use the same value


const int redVal = 125;
analogWrite(redPin, redVal);//turn on red
Serial.print (F("red: "));
Serial.print(redVal);



**Just used for verifying the function of the hardware as I tried a few different LEDs**


If you're writing a loop, think about a sensible index name, rather than adding a dumb comment


for ( i = 0; i < 125; i = i + 5)//loop for blue



aka 


for (int blueVal = 0; blueVal < 125; blueVal += 5)




**You're fully right, use better names. I posted the first version...**

And, please, use pin names.

**Yes, adressing new members that had been more pedagogic but the intention was showing the debug logic, not the surrounding code itself. If readers use good names or not, not important. Debug whatever variables You like.**

Edit: make sure you initialise variables, like locals, 


bool debugFlag;




**debugFlag is indeed initiated where it needs to be. In this code the inner for loop.**

And limit scope to the bare minimum.
**Giving the debug idea some content I used the last code I was running.**

Maybe try to make debug commands more mnemonic.
**Do You look at:**
**```**
**              //              debugFlag = false;**
**```**
**?** 
__**Yes, a cleaning up mistake.**__
<strong><strong>__**Shure this topic could be refined a lot. Not having the ambition to be a master I launched this as an example for the debug curious members.**__</strong></strong>
<strong>__**And...rather than comment-out inconvenient bugs, try to give each case its own break.**__</strong>
<strong>__**If you factor the code as you go along, it makes things easier and more self-consistent.**__</strong>
<strong>__**Uncompiled, untested**__</strong>
<strong>__**```**__</strong>
<strong><strong>**const byte bluePin  =  9;

const byte redPin  = 10;
const byte greenPin = 11;

void reportPin (byte pin, byte val)
{
  switch (pin) {
    case bluePin:  Serial.print (F("Blue: ");  break;
    case greenPin: Serial.print (F("Green: "); break;
    case redPin:  Serial.print (F("Red: ");  break;
  }
  Serial.print(val);
}

void colourWrite (byte pin, byte val)
{
  reportPin (pin, val);
  analogWrite(pin, val);
}

void setup()
{
  Serial.begin(115200);
  // all the colour pins are used with analogWrite,
  // so are automatically OUTPUTs
 
  colourWrite (bluePin, 125);
  delay(5000);
  colourWrite (bluePin, 0);

colourWrite (redPin, 125);
  delay(5000);
  colourWrite (redPin, 0);

colourWrite (greenPin, 125);
  delay(5000);
  colourWrite (greenPin, 0);
}

void loop()
{
  for (int blueVal = 0; blueVal < 125; blueVal += 5) {
    for (int redVal = 0; redVal < 125; redVal += 5) {
      for (int greenVal = 0; greenVal < 125; greenVal += 5) {
        if (Serial.available()) {
          char Sa = Serial.read();
          switch (Sa) {
            case ‘B’:
              reportPin (bluePin, blueVal);
            break;
            case ‘R’:
              reportPin (redPin, redVal);
            break;
            case ‘G’:
              reportPin (greenPin, greenVal);
            break;
            default:
              // maybe report a bum command?
            break;
          }
        }

analogWrite(bluePin,  blueVal);
        analogWrite(greenPin, greenVal);
        analogWrite(redVal,  redVal);
      }
    }
  }
}**

```
[/quote]
You are quite right, almost. Correcting the “crappy example code” is waisted time, not the point I aimed at.
A long time a ago I wrote a real time debugger tool for a Z80 real time operating system and got a flash back remembering it and now trying to apply it to an Arduino code.
Putting that debugging code any ware debugging is needed to be monitored, it can be a good tool. But, of course, launched as a lesson, it could have been more refined, more general, more modularised etc.

Your comment?
Corrected for the missing break in "case "C"".

I wrote a small macro that makes it comfortable to print

  1. a fixed text
  2. name of the variable
    and
  3. content of the variable short as

dbg("my fixed text",variablename)

best regards Stefan