Flow Chart from Sketch

Is it possible to automatically generate a flow-chart from a sketch? Any 3rd-party software? It should be possible to analyze the loop statements and bracketing, then convert to a flow chart with blocks.

I recently created a program that uses several deeply nested if/else statements. I only write using structured logic but I'm having a helluva' time keeping my brackets organized during the nesting. As such, I would like to convert the code to a flow-chart, then compare the auto-generated chart against my design flow-chart. This would help to quickly identify incorrect bracketing.

Paul

If you do CTRL-T in the IDE, it goes a long ways towrds helping figure that out.

CTRL-T really helps find indentation errors.
I found an online flowchart generator that uses a pseudo code. Here is a flow I did trying to understand the program flow of a function I was working with. Not quite from the sketch, but this took me about 20-minutes to make using my sketch as a guide.

Loop;
Read HandsetPin;
if(OffHook) {
  Set HandsetFlag=TRUE;
}
if(OnHook){
  Set HandsetFlag=FALSE;
}
if(Handset=OffHook?){
  Read dialPin;
}
if(Finished Rotating?){
  if(Need to Print?){
    Print the digit;
    Accumulate the dialed number;
    Clear some flags;
  }

  if(Did the dialPin change?){
    Update the LastStateChange Time;
  }
  if(Debounce Timeout?){
    if(Did the dialPin change?){
      Save Debounced State;
      if(Is the Debounced State HIGH?){
        Bump count;
        Set 'needtoPrint'flag;
      }
    }
  }
  lastState=reading;
}
if(Is Dialing Finished?){
  Print CRLF;
}

If you're struggling with nesting, that would be a sign to me that you have functions that are unmanageably long. Try refactoring some of the inmost nested code out into a new function. Pick a good name for it too and it makes your code more self documenting.

You can also mark the checkbox "Enable Code Folding" in the preferences, which will give you little plus/minus buttons on the left of your code, at paired braces.

1 Like

When you place your cursor on an opening { the matching closing } has a box round it. Also works the other way round.

RFEngineer:
I recently created a program that uses several deeply nested if/else statements.

Try to avoid that if possible. One script I maintain at my work has a beast of if-elses and for loops at the end to determine if the overall result of all the work the script did counts as a pass or fail. It's nested 13 levels in at the deepest part, and is not-very-affectionately called the "Baker's Dozen" by the previous people that have worked on it. I prefer to call if the "13 Levels of Hell". The last time I had to fix something in there it took about 50 times longer to find what I needed to change than to make the change itself, then several rounds of testing just to make sure I didn't break some other case that was supposed to follow a different path through the branches.

Instead of just throwing all your raw code together, the best way to simplify complex conditions is to pull some subconditions out into functions. That way you can hide some of the complexity behind the function name instead of having to scroll over it every time you're in that section.

It's really hard to follow program logic if your nesting is more than 3 or 4 levels deep. Don't try to make it work. Write your code with an eye on the limits of human attention and short-term memory.

Jiggy-Ninja:
It's really hard to follow program logic if your nesting is more than 3 or 4 levels deep. Don't try to make it work. Write your code with an eye on the limits of human attention and short-term memory.

In this Forum, I have seen a veteran to declare his following 'Serial.print()' code as the simplest one for printing the binary32 formatted value of a float number:

float x = 1.23;
Serial.print(*(long*)&x, HEX);  //shows: 3F9D70A4

I wander if the stated Serial.print() command does comply with the quoted doctrine of programming!

GolamMostafa:
In this Forum, I have seen a veteran to declare his following 'Serial.print()' code as the simplest one for printing the binary32 formatted value of a float number:

float x = 1.23;

Serial.print((long)&x, HEX);  //shows: 3F9D70A4

That code prints hex, not binary.
Perhaps that's what is confusing you.

Grumpy_Mike:
When you place your cursor on an opening { the matching closing } has a box round it. Also works the other way round.

It was even better when double clicking after an opening { the whole code block up to the corresponding } was highlighted.

Unfortunately the IDE editor was "improved" and the feature was removed when the code folding option was introduced.

GolamMostafa:
In this Forum, I have seen a veteran to declare his following 'Serial.print()' code as the simplest one for printing the binary32 formatted value of a float number:

float x = 1.23;

Serial.print((long)&x, HEX);  //shows: 3F9D70A4




I wander if the stated Serial.print() command does comply with the quoted doctrine of programming!

That has absolutely nothing to do with anything here. This topic is not about the complexity or obscurity of an individual expression, but the larger scale arrangement of control structures (switch, if-else, and for/while loops). It's pretty straightforward to evaluate a single statement even if it is very complex (as long as you haven't created something with undefined behavior), but if you nest control structures too deeply then you can easily get dizzy trying to trace out all the various paths through the labyrinth of branches and loops. Your short-term memory just gets massively overloaded.

What is about this one:

while(Serial.available() && Serial.read());

instead of the following--

byte n = Serial.available();
for (int i=0; i<n; i++)
{
   char c = Serial.read();   //read and discard
}
   char c = Serial.read();   //read and discard

If you're going to discard, make the code obvious, and lose the stupid comment.(void)Serial.read();

GolamMostafa:
What is about this one:

while(Serial.available() && Serial.read());

instead of the following--

byte n = Serial.available();

for (int i=0; i<n; i++)
{
  char c = Serial.read();  //read and discard
}

You're still missing the point. The difference between those two statements is so minor that worry about the difference is more trouble than it's worth, and it still has nothing to do with the problem I was addressing. This is a discussion about, as the OP said, "several deeply nested if/else statements".

I'll show you an example. A real example from work. In short, this code is passed a data structure that contains a group of potential operations that we could perform on the device we are connected to. Each operation contains a list of alternate options we can use for the job (like different configuration numbers). Each alternative contains a list of prerequisite values to check on the connected device to determine if that alternative is the correct one. So this one function is checking a group of groups of groups and returns true if at least one of the operations has exactly one alternative that matches all of the prerequisite values, and false otherwise. If that last sentence made your head spin, congratulations, you're a normal human being. Just recently I had to modify this function to add a 4th layer to the bottom of the grouping (So that each prerequisite value could have a list of possible values instead of only one), and I ripped this whole nonsense out, replacing it with 4 separate functions that each dealt with only one layer of the structure, and it's about 8,000 times nicer to look at.

I've stripped out all the contents (since it's company property), but I've left the skeleton of control structures in place so that you can get an idea of the madness. It's 50 lines in its barebones form here, but with all the other code in it it was almost 3 times longer. Just imagine yourself debugging this, trying to trace a path through this labyrinth, and keeping track of which values affected by which previous values of all the iterations would send you down which paths. I can tell you that it made me cross-eyed.

bool ValidatePrerequisites( )
{
  for(unsigned long i = 0; ; i++)
  {
    for(unsigned long j=0; ; j++)
    {
      for(unsigned long d=0; ; d++)
      {
          if( )
          {
            continue;
          }
          if( )
          {
          }
          if( )
          {
            if ( ) {
              for(short e = 0; ; e++){
                if( ){
                }
              }
              if( ){
                break;
              }
            }
            else if( )
            {
              break;
            }
          }
      }
      if( )
      {
      }
      if( )
      {
      }
    }
    if( )
    {
      if( )
      {
      }
      else {
      }
      return false;
    }
  }
  return true;
}

This is bad. This is too be avoided, because it's very hard for human short-term memory to deal with this entire structure all at once. This monstrosity is 7 levels at its deepest and 130 lines long. When I refactored it into separate functions, they max out at 2 levels deep and are between 15 - 40 lines long. 4 small functions are much easier to deal with than one big mass of spaghetti.

When a Teacher explains things with examples, the disciple finds answers to his unasked queries which he could not place explicitly due to language limitation(+).

GolamMostafa:
When a Teacher explains things with examples, the disciple finds answers to his unasked queries which he could not place explicitly due to language limitation(+).

...Grasshopper.

Grasshopper – Spirit Animal, Symbolism and Meaning. Grasshopper is an insect which has long hind legs and he usually uses them for jumping. ... In ancient Greece it was considered the symbol of status and power. In China the Grasshopper usually symbolizes abundance, good health, good luck an longevity.

While grasshoppers can do significant damage to a farmer's crops, without these insects the ecosystem would be a much different place. They play a critical role in the environment, making it a safer and more efficient place for plants and other animals to thrive.

Grasshopper - Obscure 1970s cultural reference