ego console - attempt at self documenting sketches

Several times I have gone to update or modify an old arduino project and realise I have no idea where I last had the sketch code or which version I ended up deploying.

I feel like the best solution for me is to put the source code in with the sketch and made available via serial so here is ego console.

Ego console presents a menu that gives up three texts via serial: sketch info, sketch code, and ego code and instructions.

/* Ego Console demonstration using blink sketch */
/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
  if (Serial.available()) egoConsole();
}

void egoConsole() {
  switch (Serial.read()) {
    case 'N':
    case 'n':
      Serial.println(F("Sketch Info:"));
      Serial.println(F(R"ego(
Blink

Turns an LED on for one second, then off for one second, repeatedly.

Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products

modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/Blink
      )ego"));
      break;
    case 'L':
    case 'l':
      Serial.println(F("Sketch Code Listing:"));
      Serial.println(F(R"ego(
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}
      )ego"));
      break;
    case 'E':
    case 'e':
      Serial.println(F(R"ego(
Ego Code and Instructions:
*** 1. paste the egoConsole function below to the end of your sketch
*** 2. replace all "ego_" with "ego"
*** 3. paste information about your sketch at [sketch info]
*** 4. paste your sketch code (excluding the egoConsole function)
        at [sketch code]
*** 5. paste this listing at [ego listing]
*** 6. add the following line inside the end of your sketch loop
  if (Serial.available()) egoConsole();
*** 7. add the following line to your sketch setup if it's required by your arduino
  Serial.begin(9600);

void egoConsole() {
  switch (Serial.read()) {
    case 'N':
    case 'n':
      Serial.println(F("Sketch Info:"));
      Serial.println(F(R"ego_(
[sketch info]
      )ego_"));
      break;
    case 'L':
    case 'l':
      Serial.println(F("Sketch Code:"));
      Serial.println(F(R"ego_(
[sketch code]
      )ego_"));
      break;
    case 'E':
    case 'e':
      Serial.println(F(R"ego_(
[ego listing]
      )ego_"));
      break;
    default:
      Serial.println(F(R"(
Sketch Ego:
N - show sketch info
L - list sketch code
E - show ego code and instructions
      )"));
      break;
  }
  // flush serial input through next newline
  bool flush = true;
  while (Serial.available() && flush){
    flush = (Serial.read() != '\n');
  }
}
      )ego"));
      break;
    default:
      Serial.println(F(R"(
Sketch Ego:
N - show sketch info
L - list source code
E - show ego code and instructions
      )"));
      break;
  }
  // flush serial input through next newline
  bool flush = true;
  while (Serial.available() && flush){
    flush = (Serial.read() != '\n');
  }
}

Thoughts? Problems? Improvements?

Edit: It will probably clarify to show the output from "show ego code and instructions".

Ego Code and Instructions:
*** 1. paste the egoConsole function below to the end of your sketch
*** 2. replace all "ego_" with "ego"
*** 3. paste information about your sketch at [sketch info]
*** 4. paste your sketch code (excluding the egoConsole function)
        at [sketch code]
*** 5. paste this listing at [ego listing]
*** 6. add the following line inside the end of your sketch loop
  if (Serial.available()) egoConsole();
*** 7. add the following line to your sketch setup if it's required by your arduino
  Serial.begin(9600);

void egoConsole() {
  switch (Serial.read()) {
    case 'N':
    case 'n':
      Serial.println(F("Sketch Info:"));
      Serial.println(F(R"ego_(
[sketch info]
      )ego_"));
      break;
    case 'L':
    case 'l':
      Serial.println(F("Sketch Code:"));
      Serial.println(F(R"ego_(
[sketch code]
      )ego_"));
      break;
    case 'E':
    case 'e':
      Serial.println(F(R"ego_(
[ego listing]
      )ego_"));
      break;
    default:
      Serial.println(F(R"(
Sketch Ego:
N - show sketch info
L - list sketch code
E - show ego code and instructions
      )"));
      break;
  }
  // flush serial input through next newline
  bool flush = true;
  while (Serial.available() && flush){
    flush = (Serial.read() != '\n');
  }
}

The problem is this has significant overhead and might conflict with other uses of Serial in a sketch. Whether either of those things are a problem depends on the sketch. It's not going to be a issue for the Blink sketch, but you also don't need it for the Blink sketch.

However, I am very much a proponent of good documentation and I support efforts toward this goal. Personally, I'm mostly happy enough with just adding documentation to some files alonside the source code. I have added some summary documentation to a program I made that has a control interface via serial. Other than that, I have made some programs print the version number, which is helpful to detrermine which version of the documentation is applicable.

I use the Geany editor for all my programming

I have written a simple Python program to compile and upload Arduino code using the command-line IDE. I have a menu option in Geany to call the Python program. The Python program can also be used without Geany.

The Python code includes an option to create an archive copy (on the PC) of the Arduino code, including the code in any libraries and to include the full path name to that archive within the Arduino program so it is printed out when the Arduino program starts.

...R

I get the feeling that you have experienced similar frustration to have put that solution together.

@pert I agree mine is a rather fat solution, pushing full text of the source plus some into progmem. I haven't ruled out reducing it to a version number and a URL if space is short.

My bigger concern is that with the manual copypasting involved and my haphazard style the reported source code could easily become mismatched from the running code. I hunted for some kind of preprocessor trick to stringify the source to no avail.

Seems like I have a reason to do something useful with python. Thanks for the tip/link.

Being one out of 2 guys maintaining a quite large software package documenting was essential. Every module of source code had a header telling date, designer and type of change.

For my simple Arduino projs I also name the sketch with a telling name that ends with the date and version of the day.
This name is printed out in Setup, usually to an LCD in use, or to Serial monitor. Then a 10 seconds delay follows to give time to read the version of the code.'