Help with a menu-driven program

Hi,
I am building a camera slider control based on the Arduino Pro Mini. It is going to be controlled by a 16x2 lcd and four buttons (up, down, select, and escape). The camera slider also has two limit switches (one on each end of the slider), and one motor which will be controlled by an L298 H-bridge. I am still waiting on some parts to arrive, but I think I have the electronics figured out.

I am having trouble with the menu system. Basically, I want to have a main menu that shows up when the device is turned on. From the menu, I want to be able to select and run various "programs" which will make the slider preform various movements. I have written an outline of what I would like to accomplish:

Setup()
	Display message “Homing Motor” on LCD
	run motor left until limit switch 1 is hit, then stop

Loop()
	Display Menu
		Show title “Main Menu”
		Show list
                     Mode 1
                       Run routine “mode1” when selected
                     Mode 2
                       Run routine “mode2” when selected
                     Mode 3
                       Run routine “mode3” when selected
                     Mode 4
                       Show software version number and developer information
                       return to main menu when escape button is pushed.

mode1()
	if user selects “start” on lcd,
		run motor right until limit switch 2 is pushed
		run motor left until limit switch 1 is pushed
		repeat
	if user selects “stop” on lcd,
		stop the motor
	if user pushes escape button,
		stop the motor,
		return to menu,
		run motor left until limit switch 1 is hit, then stop

mode2()
	If user selects “Start” on lcd,
		run motor right until limit 2 is hit
		stop
	if user selects “start” again,
		run motor left until limit 1 is hit
		stop
	repeat 
	if user pushes escape button,
		stop the motor,
		return to menu,
		run motor left until limit switch 1 is hit, then stop

mode3()
	ask user for number of cycles
		save number as variable “x”
	if user selects “start”
		run motor right until limit switch 2 is hit
		run motor left until limit switch 1 is hit
		repeat “x” times
	If user selects “stop”
		run motor left until limit switch 1 is hit, then stop
		reset variable “x”
		restart the routine
	if user pushes escape button,
		stop the motor,
		return to menu,
		run motor left until limit switch 1 is hit, then stop

Does anyone know how to approach a program like this? I have seen various libraries, such as MenuBackend (http://forum.arduino.cc/index.php/topic,38053.0.html) and phi-prompt (Phi_prompt | Liudr's Blog). While these seem to be inline with what I would like to accomplish, they seem complicated, and I am not sure where to start.

Any help would be greatly appreciated.

Step 1 is to write code to get the four switches to perform actions only on the signal edge. The StateChangeDetection example demonstrates this concept.
Step 2 is to implement a finite state machine where the input would be the button events, and the output would be what is written to the LCD screen.

Murray, you did a great job conceptulizing your code in english. Continue this approach by slowly refining this down to code. Create empty functions at first, then fill them in in the end.

For example:

void setup()
{
    displayMessage("Homing Motor");
    moveSlider(DIRECTION_LEFT);
}

void moveSlider(char direction)
{
    enableMotor(direction);
    while(digitalRead(END_SWITCH_LEFT) != HIGH && digitalRead(END_SWITCH_LOW) != HIGH)
         delay(5);
    stopMotor();
}

void enableMotor(char direction)
{
    // TODO: Enable motor here
}

Oh, and please post pictures of the device :slight_smile:
Sounds very nice.

Thanks for the replies. I started writing the code based on what Arrch said. I used the “Button” library to simplify my buttons, and I use the “Finite State Machine” library to implement the state machine. Here is what I came up with:

//from http://playground.arduino.cc/Code/Button
#include <Button.h>
//from http://playground.arduino.cc/code/FiniteStateMachine
#include <FiniteStateMachine.h>

const byte NUMBER_OF_SELECTABLE_STATES = 4; //how many states are we cycling through?

//Let's setup our states
State Homescreen = State(homescreen);
State Mode1 = State(mode1);
State Mode2 = State(mode2);
State Mode3 = State(mode3);
State Credits = State(credits);

//Initialize state machine
FSM stateMachine = FSM(homescreen);

//Let's setup the buttons
Button mode = Button(A0, PULLUP);
Button start = Button(9, PULLUP);
Button finish = Button(A2, PULLUP);
Button menu = Button(A1, PULLUP);

//let's setup our limit switches
const int limitleft = 12;
const int limitright = 13;

//variable for mode button presses
byte modePresses = 0;

//variables for limit switches
int limitrightState = 0;
int limitleftState = 0;

//Let's setup the leds (later these will be motors)
const int leftPin = 10;
const int rightPin = 11;

void setup() {
  pinMode(rightPin, OUTPUT);
  pinMode(leftPin, OUTPUT);
  
  pinMode(limitleft, INPUT);
  pinMode(limitright, INPUT);
  
  Serial.begin(9600);
}

void loop() {
  if (mode.uniquePress()){
    //increment mode button presses and constrain it to [0,1,2,3,4]
    modePresses = ++modePresses % NUMBER_OF_SELECTABLE_STATES;
    switch (modePresses){
      case 0: stateMachine.transitionTo(Homescreen); break;
      case 1: stateMachine.transitionTo(Mode1); break;
      case 2: stateMachine.transitionTo(Mode2); break;
      case 3: stateMachine.transitionTo(Mode3); break;
      case 4: stateMachine.transitionTo(Credits); break;
    }
  }
  stateMachine.update()
}

//utility functions
void homescreen(){
  Serial.print("SliderController");
  Serial.print("V.1.0");
  homemotor();
}

void mode1(){       
}

void mode2(){
}

void mode3(){
}

void credits(){
}

void homemotor(){
  while(digitalRead(limitleft) != HIGH){
    Serial.print("Homing Motor...");
    digitalWrite(leftPin, HIGH);
  }
}

However, something is not working right. When I verify the program, it returns the error “no matching function for call to ‘FiniteStateMachine::FiniteStateMachine(void (&)())’” What could be causing this?

Also, I am having trouble programming the three modes that the program will run (as shown in the outline in my previous post). If someone could walk me through the best way to do one of them, that would be greatly appreciated.

I will post pictures soon…

Thanks again for all the help.

State Homescreen = State(homescreen);
...
FSM stateMachine = FSM(homescreen);

I've never used the library, but I'm guessing that it expects the initial state (Homescreen) as the argument, and not the initial state's function (homescreen).

Thanks! That fixed it.