You are on page 1of 7

#define ST_DISPLAY_MAINMENU 0

#define ST_WAIT 1
#define ST_SETSPEED 2
#define ST_SETTIMING 3

#include <LiquidCrystal.h>;
#include <Keypad.h>;

int motorPin = 3;

const byte ROWS = 4; //four rows


const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};

byte rowPins[ROWS] = {10, 9, 8, 7}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {13, 12, 11}; //connect to the column pinouts of the keypad

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// the state of our application; start with main menu display


byte currentState = ST_DISPLAY_MAINMENU;

// speed and timing variables


// both are global so we can display them in the main menu
int theSpeed = 0;
int theTiming = 0;

void setup() {
pinMode(motorPin, OUTPUT);
// set up the LCD's number of columns and rows:
lcd.begin(20, 4);
}

void loop()
{
// single key from keypad
char key;
// text from keypad
char *text;

// set the speed


if (theSpeed >= 0 && theSpeed <= 255)
{
// set the speed
analogWrite(motorPin, theSpeed);
// we've done it, don't do it again
theSpeed = -1;
}

switch (currentState)
{
case ST_DISPLAY_MAINMENU:
// display main menu
displayMenu();
// switch to wait state
currentState = ST_WAIT;
break;
case ST_WAIT:
// get key
key = getKeyWithEcho();
// if speed setting selected
if (key == '1')
{
// display speed 'menu'
displaySpeedMenu();
// change to state where user can enter speed
currentState = ST_SETSPEED;
}
// if timing setting selected
if (key == '2')
{
// display 'timing' menu
displayTimingMenu();
// change to state where user can enter timing
currentState = ST_SETTIMING;
}
// Note: state does not change if entry is not '1' or '2'
break;
case ST_SETSPEED:
// get the text entered on the keypad
text = getKeypadText();
// if text complete
if (text != NULL)
{
// if user did enter a speed
if (text[0] != '\0')
{
theSpeed = atoi(text);
}
currentState = ST_DISPLAY_MAINMENU;
}
break;
case ST_SETTIMING:
// get the text entered on the keypad
text = getKeypadText();
// if text complete
if (text != NULL)
{
// if user did enter a speed
if (text[0] != '\0')
{
theTiming = atoi(text);
}
currentState = ST_DISPLAY_MAINMENU;
}
break;
} // end_of_switch
}

/*
display a title on the first line of the display; it always clears the LCD
*/
void displayTitle()
{
// clear the lcd
lcd.clear();

// print the project title on the first line


lcd.setCursor(0, 0);
lcd.print("Speed controller");
}

/*
display main menu
*/
void displayMenu()
{
// current line where to write on LCD; every time that we write, currentLine will be incremented
byte currentLine = 0;
// text buffer for 20 characters and string terminator
char textbuffer[21];

// display the title on the first line and update currentLine


displayTitle();
currentLine = 1;

// print the current settings on the second line


lcd.setCursor(0, currentLine++);
sprintf(textbuffer, "S = %d, T = %d", theSpeed, theTiming);
lcd.print(textbuffer);

// print the first menu option on the third line


lcd.setCursor(0, currentLine++);
lcd.print("1 Set speed");

// print the second menu option on the fourth line


lcd.setCursor(0, currentLine++);
lcd.print("2 Set time");
}

/*
display a 'menu' where the user can enter a speed
*/
void displaySpeedMenu()
{
// display the title on the 1st line
displayTitle();
// display additional info on 3rd line
lcd.setCursor(0, 2);
lcd.print("#Finish, *Cancel");
// prompt user to set speed (2nd line)
lcd.setCursor(0, 1);
lcd.print("Set speed: ");
}

/*
display a 'menu' where the user can enter a timing
*/
void displayTimingMenu()
{

/*
get a keystroke from the keypad
echo the key that was pressed to the LCD
the echo will be on the current position of the LCD
returns
the key that was pressed or NO_KEY
*/
char getKeyWithEcho()
{
// read a key
char key = keypad.getKey();
// if no key pressed
if (key != NO_KEY)
{
// for debugging, output to serial monitor
Serial.print("Key: "); Serial.println(key);
// display on current position of LCD
lcd.print(key);
}
return key;
}

/*
get a text from the keypad (max 20 characters)
'#' finishes the entry of data
'*' cancels the entry of data
returns
NULL if not complete
empty text if canceled
entered tet (might be empty)
*/
char *getKeypadText()
{
// a buffer for 20 keypresses and one
static char keypadbuffer[21];
// index in above buffer
static char index = 0;

// read a key
char key = getKeyWithEcho();
// if nothing pressed
if (key == NO_KEY)
{
// indicate no complete data
return NULL;
}
// if 'cancel' key
if (key == '*')
{
// reset index
index = 0;
// create empty text
keypadbuffer[index] = '\0';
// return text
return keypadbuffer;
}
// if 'enter' key
if (key == '#')
{
// add a string terminator
keypadbuffer[index] = '\0';
// reset index for next time
index = 0;
// return the text
return keypadbuffer;
}
// check for buffer overflow
if (index >= sizeof(keypadbuffer))
{
// add a string terminator
keypadbuffer[sizeof(keypadbuffer) - 1] = '\0';
// reset index for next time
index = 0;
// return the text
return keypadbuffer;
}

// add the character to the buffer


keypadbuffer[index++] = key;

// indicate that text is not complete


return NULL;
}

You might also like