Finally we are at a stage, where we can
start building the menu. First we need to add a few more buttons and
a switch. To activate the “Setup Mode” I am using Arduino pin DI
12 to a switch and a 10K resistor and the other side of the switch
goes to 5 Volt supply.
The next thing to do is building a
small button shield. If you have enough space on a breadboard left,
you can also use a bread board for the menu buttons. Since I run out
of breadboards, I quickly build a 3 button shield.
We need 4 10K resistors, 3 momentary
switches, 1 small 3 point female connector and a prototyping- or
breadboard. I soldered the switches to a prototyping board, connected
on side of the switches together and to the connector, going to
Arduino's analogue pin 1. If you have various photocells connected
please use the next analogue pin available. The other side of the
buttons is connected through a 10 K resistor in serial with the
resistor of the next switch going again to the connector and to the
5V supply voltage. If you want to separate the analogue readings more
to give it a wider range due to jumping readings you can increase
the resistor value. Finally we connect a 10 K resistor from the
ground pin to the connection going to the analogue pin as a pull-down
resistor.
The next image shows how I implemented
it into the existing system:
A quick note on using only three
buttons for the menu if it would be easier to use a set of 5. Very
simple, since the main program already uses quite a lot of memory,
and the menu itself will have a huge impact on memory use itself, we
try to use as less memory as any possible.
Let's add the needed variables for the
just implemented switches.
Again, we start in our declaration
section and why we have been doing so much house keeping, we do a
little more. I categorised our variables a bit more since I was
having problems finding things again. I just through in the complete
declaration part with all the structure changes I made and on the way
down I explain the additional variables to go in. We start at the
point where it says “do not modify below here”. There we go into
the section “defining Arduino pins”. There we add:
const byte setupMode = 12; //Arduino pin for switching to setup mode
Now we go down to the end of the
declaration part and start a new section:
/////////////////////////////////////////////////////////////////////////// ///////////////////Menu and user interface///////////////////////////////// /////////////////////////////////////////////////////////////////////////// const byte btnMenu = 1; const byte btnSearch = 2; const byte btnSelect = 3; const byte btnNone = 0; int act_key_in = 0;
And here again the whole effected
declaration part from the point “do not modify below here” until
the end of the just added section.
/////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////DO NOT MODIVY BELOW HERE/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////defining Arduino Pins///////////////////////////// ////////////////////////////////////////////////////////////////////////////// ShiftLCD lcd(9, 11, 10); //initializing the LCD adaptor pins const byte latchPin = 2; //5latch pin input connected to //Arduino digital pin 2 const byte clockPin = 3; //6clock pin input connected to //Arduino digital pin 3 const byte dataPin = 4; //7data pin input connected to //Arduino digital pin 4 const byte latchPinOut = 5; //2latch pin output shift register //74HC595 connected to Arduino //digital pin 5 const byte clockPinOut = 6; //3clock pin output shift register //74HC595 connected to Arduino //digital pin 6 const byte dataPinOut = 7; //4data pin output shift register //74HC595 connected to Arduino //digital pin 7 const int lightSensor = A0; //defining the input for the photocell const byte doorMonitor = 8; //Arduino pin for a monitor LED const byte setupMode = 12; //Arduino pin for switching to setup mode ///////////////////////////////////////////////////////////////////////////// ///////Variables to hold the data for each input shift register////////////// ///////////////////////////////////////////////////////////////////////////// byte switchVar1 = 0; //data for input shift register 1 byte switchVar2 = 0; //data for input shift register 2 byte switchVar3 = 0; //data for input shift register 3 /////////////////////////////////////////////////////////////////////////////// ///////////////////////////all the other variables///////////////////////////// /////////////////////////////////////////////////////////////////////////////// ////Sensor and timer variables int delayTime[16] = {dBed1, dBed2, dBed3, dLiving, dBath1, dBath2, dBath3, dBath4, dKitchen, dCorridor, dAC1, dAC2, dAC3, dAC4, dMaster, 0}; int sensorValue = 0; //holding the indicated sensor value of the photocell byte photocellSwitch = 0; //holding the switch command after //checking sensor readings (0, 1) byte photocellSwitchOld = 0; //switch command from the previous pass byte lightLevel[17] ={0}; //array holding the switch state //checking timer and photocell (0, 1) unsigned int roomTimer[17] = {0}; //array holding the time when the PIR was last activated unsigned int currentTime = 0; //var to hold a reference time to calculate the up time //against the preprogrammed delay time unsigned int endTime = 0; //var to hold a temp result to calculate the up time //against the preprogrammed delay time unsigned int outsideOnTime = 0; //checking result if the time is within //on or off time limits //////////////////////////////////////////////////////////////////////////////////////// //////////////////////PIR and Room switch related Var's///////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// byte mainOff = 1; //variable for master relay control unsigned int offTime = 0; //var needed to calculate delay for master off byte masterSwitchStateOld = 0; //var holding the previous door switch state byte switchState[25] = {0}; //array holding the state of each switch unsigned long lightOutput[17] = {0}; //array holding a integer which converted to binary //will trigger the relay to switch in our output code byte lightStatus[17] = {0}; //array holding the switch status of each room on/off byte priorityStatus[17] = {0}; //array holding the priority status of each room on/off byte switchState1Old = 0; //var to check if the priority switch state has changed byte switchState3Old = 0; //var to check if the priority switch state has changed byte switchState5Old = 0; //var to check if the priority switch state has changed byte switchState7Old = 0; //var to check if the priority switch state has changed ////////////////////////////////////////////////////////////////////////////// ///////////////////////////Output///////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// unsigned long outputL = 0; //variable holding the output data ////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////Service Switches/////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// byte maintenancePin = 0; //defining the var for the maintenance switch byte maintenanceActive = 0; //holding the switch state ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////RTC and Holiday switch timers/////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// byte room1Lights = 0; //var to hold the on command for room light byte room2Lights = 0; //var to hold the on command for room light byte room3Lights = 0; //var to hold the on command for room light byte room4Lights = 0; //var to hold the on command for room light byte room5Lights = 0; //var to hold the on command for room light byte room6Lights = 0; //var to hold the on command for room light byte room7Lights = 0; //var to hold the on command for room light byte room8Lights = 0; //var to hold the on command for room light byte room9Lights = 0; //var to hold the on command for room light byte currentHour = 0; //var holding the time (hour 0-23) byte currentMinute = 0; //var holding the time (minute 0-59) byte currentDay = 0; //var holding the date (day 1-31) byte currentDoM = 0; //var holding the weekday (Sun - Sat, 1-7) byte currentMonth = 0; //var holding the date (month 1-12) int currentYear = 0; //var holding the year (based on Unix time) //Array holding the day names to replace the weekday index prog_char weekday_0[] PROGMEM = "Sun"; prog_char weekday_1[] PROGMEM = "Mon"; prog_char weekday_2[] PROGMEM = "Tue"; prog_char weekday_3[] PROGMEM = "Wed"; prog_char weekday_4[] PROGMEM = "Thu"; prog_char weekday_5[] PROGMEM = "Fri"; prog_char weekday_6[] PROGMEM = "Sat"; PROGMEM const char *weekday_table[] = { weekday_0, weekday_1, weekday_2, weekday_3, weekday_4, weekday_5, weekday_6 }; char buffer[20]; /////////////////////////////////////////////////////////////////////////// ///////////////////Menu and user interface///////////////////////////////// /////////////////////////////////////////////////////////////////////////// const byte btnMenu = 1; //defining the menu button – moves through the menu const byte btnSearch = 2; //defining the search button – moves through values const byte btnSelect = 3; //defining the select button – selects a menu or a value const byte btnNone = 0; //defining the non button pressed var int act_key_in = 0; //var holding the key related sensor reading
The next thing we do is storing some
message texts which show on the LCD in the program memory. There for
we add to the last addition under the new created section “Menu and
user interface”:
char buffer_M[20]; //buffer holding text strings to be displayed on LCD //Storing some menu messages in the program memory prog_char msg_0[] PROGMEM = "Not Used"; prog_char msg_1[] PROGMEM = "Saving...."; prog_char msg_2[] PROGMEM = "Setup mode"; prog_char msg_3[] PROGMEM = "Starting...."; prog_char msg_4[] PROGMEM = "RMU 1.2.5"; //Creating the table for the stored menu messages PROGMEM const char *msg_table[] = { msg_0, msg_1, msg_2, msg_3, msg_4 };
How this works is explained in the
first menu pages I wrote. From here we move down to the Setup loop
and replace the lcd print statements:
void setup() { //////////////Start Serial for Debugging///////////////////// //Serial.begin(9600); //printing initialisation message lcd.begin(16, 2); //the following lcd.print statement to replace with //lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[4])))); lcd.print("RMU 1.2.4"); delay(1000); lcd.setCursor(0, 1); //the following lcd.print statement to be replaced with //lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[3])))); lcd.print("starting......"); delay(2000); //////////////////defining pin modes////////////////////
Again, the part we just changed with all the changes made:
void setup() { //////////////Start Serial for Debugging///////////////////// //Serial.begin(9600); //printing initialisation message lcd.begin(16, 2); lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[4])))); delay(1000); lcd.setCursor(0, 1); lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[3])))); delay(2000); //////////////////defining pin modes/////////////////////
We move on to the beginning of the
main loop and add:
void loop() { //>>>>>>>>>addition starts right here>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ///////////////////checking the setup switch///////////////////////// while(digitalRead(setupMode) != 0){ //stay in here if activated lcd.clear(); //clear display lcd.print(strcpy_P(buffer_M, (char*)pgm_read_word(&(msg_table[2])))); //print Setup mode delay(500); //small delay button_loop(); //function call to monitor menu buttons } //>>>>>>>>>>>>addition ends here<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //////////////////////////////////////getting the input//////////////////////////////////////////////////
Here I am using a while loop to make
sure, we are monitoring the menu buttons if the switched to setup
mode. The buttons are monitored in the function button_loop. To build
this little function, we move again to the far end of the sketch and
add the function:
//Checking for a pressed menu button void button_loop(){ //Serial.println("in button loop"); byte button = read_act_buttons(); //function call to read the buttons if(button == btnMenu){ //if button menu was pressed lcd.setCursor(0, 1); //temp to check functionality lcd.print("Menu button"); //temp to check functionality delay(500); //delay for readability } }
Nothing really magic. We do a new
function call byte button = read_act_buttons() which converts the
analogue reading into a constant assigned to the buttons pressed. If
the button menu is pressed, for now we just print on lcd that the
menu button is pressed. Later, we will implement here another
function showing the main menu.
Above the function we just added, we
add the last function for today:
int read_act_buttons(){ act_key_in = analogRead(1); //reading the sensor //Readings centred at 170 for menu //203 for search and 252 for select //Serial.print("Reading: "); //Serial.println(act_key_in); if(act_key_in < 160) return btnNone; //most likely result first //adding a range of +/- 10 to compensate for bouncing //readings if(act_key_in > 160 && act_key_in < 180) return btnMenu; if(act_key_in > 193 && act_key_in < 213) return btnSearch; if(act_key_in > 242 && act_key_in < 262) return btnSelect; return btnNone; }
Even here nothing real magic.
With act_key_in = analogRead(1); we are
reading the value measured between supply voltage and the pressed
button. In my setup the values returned are 170 for the menu button,
203 for the search button and 252 for the select button. Since
analogue reading are never that exact and always changing within a
range, we have to take this in account when we select which button
was pressed. While watching my readings for a while, I got away with
adding +/- 10 to the average reading. That's done
in:
if(act_key_in > 160 &&
act_key_in < 180) return btnMenu;
so what ever reading is returned
between 160 and 180 is recognised as menu button. Same system works
for the next to button.
Your reading may vary depending on
resistor value and tolerance. Before you write this function, you
might just want to uncomment the Serial.begin(9600) and add temporary
in the while loop in the beginning of our main loop the following:
int value = analogRead(1);
Serial.println(value);
and check in the serial monitor what
readings are returned when you press your buttons and modify the
read_act_buttons() function accordingly.
Before we carry on and go into writing
the menu, I am preparing again a post with the full sketch with all
changes and implementations up to this point.
No comments:
Post a Comment