Programming Complex Sequential Tasks

I’m a hobby programmer 6 months using Arduino after ten years of working Microchip PIC in assembler.

I’m looking for input on how to approach projects more complex than a simple void loop().

I’m working on a maze solving robot performs three tasks:

the maze is black tape on white board.

The first task is to solve the maze. The robot is placed somewhere on the board and travels until the goal is reach. Every time the robot passes over a maze junction it saves its decision in a character string. The decisions include, turn right (R), turn left (L), go straight (S), turn around at a dead end (B).

The second task is to simplify the course. An algorithm takes the course character stream and removes all dead ends or other unnecessary turns.

The third task is to run the same course in the most efficient manner. The robot is placed back at its starting point. Each time it passes over a maze junction it performs the next decision based on the next optimized string character.

At the end of the last task the robot should come to a stop. I’m using a long delay statement.

Each of these tasks involves its own set of primary and secondary functions.

My current approach has been to leave the current task by calling the next. This method should result in the program never returning to the first step of void loop function. But it is going back before completing the last task.

Where do I find theory or approaches for such sequential programs?

The setup() function runs only once, and can call three successive functions that sequentially execute your tasks.

User input is likely to be required, such as a button press to “start running the maze”, a second to “solve it” and a third press to start the timed run.

There is no need or requirement to actually use the loop() function, but it must be present. loop() will be called repeatedly after setup() exits.

I'm using the following:

void FirstRun() //Starts with power on
//do the run
SolveIt();

void SolveIt()
//do the solve
Delay(5000); //Pickup up robot and move back to start
TimedRun();

void TimedRun()
//do timed run then shut down
delay(50000); //pickup robot and power off

OK

Yo, bobledoux, I don’t think your code is gonna do much. Like compile, or run …?

Do you have the actual code? If so, can you show it (inside of
** **[code]** **
tags)?

I like the concept code in Reply #2 - it provides a nice overview.

This sounds like a project that would be very appropriate for a State Machine approach. I don't see it as a series of separate functions for different phases but, rather, that there is a collection of "small" functions for different tasks and use of these is governed by the state the system is in.

There may also be a few "layers" of states - for example an "Learn" state that goes through a series of movement states, a "Prune" state that tidies things up and a "Timedrun" state that uses many of the movement states that were used during the Learn process.

...R

That is really not a good way to write an Arduino program. The low-level code that reads the sensors and follows the line gets repeated in each section.

Read Planning and Implementing an Arduino Program

My sketch has about 500 lines of code, all using basic principles. No include files.

I've been working on the code for two months with good success. I started with this project:

http://patrickmccabemakes.com/hardware/Maze_Solving_Robot_V3/

My robot monitors six IR sensors across the front every 20milliseconds. The two center sensors control path over the black line maze. Using only proportional error correction the robot drives a very smooth path down the maze.

The outer sensors detect turns and crossings. Left or right sensor pairs denote left or right turns.

All six sensors denote a "T" or crossing. To distinguish the two the robot moves further on. If the line disappears it was a T, otherwise a crossing.

When the robot crosses any junction it moves forward enough to place the wheels on the junction. Reversing the two wheels turns the robot in place, right down the middle of its new path.

My protocol is to take every possible left turn. The robot successfully completes the maze every time.

LED output verifies the robot saves its first path correctly. It also documents it generates the minimal path as a character string.

If I load the minimal path into a separate program the robot will successfully make that run to the goal.

But when I try to add the 'timed path to goal' the robot fails.

The sensor read process must be robust to avoid sensor read errors. I was able to eliminate sensor errors from my first run by performing the sensor read loop very 20 milliseconds instead of 50.

Feedback suggests that my linking of tasks is a reasonable approach. I could also try a state diagram, perhaps using a "switch...case" approach.

I think my problem is close to solution. Time for more noodling.

bobledoux:
I could also try a state diagram, perhaps using a “switch…case” approach.

These are two completely separate concepts. They can be used together but they don’t have to be.

IMHO you need to start by focusing on the state machine without concerning yourself with the implementation details.

…R

Robin2:
These are two completely separate concepts. They can be used together but they don't have to be.

IMO switch/case is the structured implementation of a state machine, everything else is blocking spaghetti code.

Robin2:
IMHO you need to start by focusing on the state machine without concerning yourself with the implementation details.

The state machines will be quite different, and should be implemented independently. For the final task, to follow the shortest path, two distinct parts must be made work: the construction of the maze map, and the machine following that map. The state machine has to follow a given path, where a number of test paths can be used to verify proper operation. The map should be dumped in readable form, so that its proper construction can be verified. Only if both parts are verified, one should try to run them together.

DrDiettrich:
IMO switch/case is the structured implementation of a state machine, everything else is blocking spaghetti code.

We may be talking at cross purposes, but to my mind SWITCH/CASE is just a convenient subset of IF/ELSE for when the full flexibility of IF/ELSE is not required. It is not difficult to make spaghetti either way.

Of course if one has figured out a clearly defined state machine it may indeed make sense to use SWITCH/CASE to implement it.

The state machines will be quite different, and should be implemented independently. For the final task, to follow the shortest path, two distinct parts must be made work: the construction of the maze map, and the machine following that map. The state machine has to follow a given path, where a number of test paths can be used to verify proper operation. The map should be dumped in readable form, so that its proper construction can be verified. Only if both parts are verified, one should try to run them together.

I'm not sure that I understand that properly so I think I agree with it. What I was trying to convey earlier is that many of the concepts (states?) used while the device is traversing the maze to make the map will also be used when the device is following the map.

...R

I don’t understand the aversion to loop().
It is not obvious to me why FirstRun(), SolveIt() and TimedRun() cannot simply be called within loop().