A trouble shooting aid

Debugging aid, you may find useful.

Tutorial

Every now and then I use the following technique to help in trouble shooting a sketch.

You might find this useful too or maybe have some suggestions that expand on its capability.

First things first, we must remember that adding debug code to a sketch will change timing and might make things not work.

Basic Idea

We have what I call a PSW (Process Status Word) which is printed to the serial monitor (or LCD) whenever the PSW changes.

  • No changes, no printing.

A 16-bit representation of our PSW is displayed along with a two-line header to identify the bits.

We could use a 32-bit PSW if extra bits are needed.

The following sketch shows the toggling of pins 13 and 12 along with the current state of a switch on pin 8.

This could be used to monitor the state of a State Machine, Flags, analog limit events etc.

We must remember that the PSW is only printed when loop() starts so events that happen several times before a return to loop() will be missed.

Example, here we see pins 13 and 12 are HIGH and our switch is released (HIGH).

111111
5432109876543210
0011000100000000




//                                          P S W
//********************************************^************************************************
//Debugging with PSW (Process Status Word)
//Used to help diagnose coding problems.
//Whenever the PSW changes, the PSW bit fields are printed.
//We can use these bits to see the state of strategic variables which might help in our debugging.
//To set a bit use bitSet(XX, YY); and to reset a bit use bitClear(XX, YY),
//where XX is the variable and YY is the bit number to be modified.
//  example:
//                111111
//                5432109876543210
//  Assume PSW =  B000000011111111
//  set bit 11    bitSet(PSW, 11);
//         PSW =  B000100011111111
//  clear bit 4   bitClear(PSW, 4);
//         PSW =  B000100011101111
//****************************************

#define           DEBUG   //comment this line to remove all debug code <-------<<<<<<

#ifdef            DEBUG

#define SET(...)            bitSet(PSW, __VA_ARGS__)
#define RESET(...)          bitClear(PSW, __VA_ARGS__)

#define PSWupdate(...)      modifyPSW(__VA_ARGS__)
#define PSWshow             printPSW()

const byte numberOfBits   = sizeof(int) * 8;

unsigned int PSW          = 0;
unsigned int oldPSW       = 0;
unsigned int PSWcounter   = 0;

//****************************************
inline void printPSW()
{
  if (oldPSW != PSW)
  {
    //update to the new value
    oldPSW = PSW;

    //print the binary value of our PSW
    Serial.println(F("111111"));
    Serial.print(F("5432109876543210 PSW# = "));
    Serial.println(++PSWcounter);

    //add leading 0s
    for (byte i = 0; i < numberOfBits; i++)
    {
      char BIT = (PSW & (1 << (numberOfBits - 1 - i))) > 0 ? '1' : '0';
      Serial.print(BIT);
    }

    Serial.println("\n");
  }
}

//****************************************
void modifyPSW(byte BIT, byte state)
{
  if (state == HIGH)
  {
    bitSet(PSW, BIT);

    return;
  }

  bitClear(PSW, BIT);

} //END of   updatePSW()

#else

#define SET(...)
#define RESET(...)
#define PSWupdate(...)
#define PSWshow

#endif


//                              G P I O   &   V a r i a b l e s
//********************************************^************************************************
//
const byte heartbeatLED            = 13;          //+5V---[220R]---[LED]---PIN
const byte testLED                 = 12;          //+5V---[220R]---[LED]---PIN

const byte mySwitch                = 8;           //+5V---[50k]---PIN---[Switch]---GND

//*****************
//Timing stuff
unsigned long heartbeatLEDTime;
unsigned long testLedTime;


//                                      s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(115200);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(testLED, OUTPUT);

  pinMode(mySwitch, INPUT_PULLUP);

} //END of   setup()


//                                       l o o p ( )
//********************************************^************************************************
void loop()
{
  //****************************************
  //during debug mode, print changes in PSW (Process Status Word)
  PSWshow;

  //****************************************         toggle heartbeatLED
  if (millis() - heartbeatLEDTime >= 1000ul)
  {
    //restart this TIMER
    heartbeatLEDTime = millis();

    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

    //******************
    //update PSW
    PSWupdate(heartbeatLED, digitalRead(heartbeatLED));
  }

  //****************************************         toggle testLED
  if (millis() - testLedTime >= 500ul)
  {
    //restart this TIMER
    testLedTime = millis();

    digitalWrite(testLED, !digitalRead(testLED));

    //******************
    //update PSW
    PSWupdate(testLED, digitalRead(testLED));
  }

  //****************************************         read mySwitch
  //update PSW
  PSWupdate(mySwitch, digitalRead(mySwitch));

  delay(50); //just for testing

} //END of   loop()

Hi,
I usually have my heartbeat code as a function that I call at the top of the loop.

Tom.. :smiley: :+1: :+1: :+1: :coffee: :australia: