Pages: [1]   Go Down
Author Topic: LCD menu control of LED’s  (Read 1775 times)
0 Members and 1 Guest are viewing this topic.
Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been trying out a few LCD examples lately and am now wanting to try an 16 x 2 LCD with a menu interface to move through four different LED patterns displaying on eight LED’s. Once again this is a learning exercise. I did have a look at and successfully implement Giuseppe Di Cillo’s “Manage menu and LCD display with Arduino” tutorial at
http://www.coagula.org/content/pages/tutorial-manage-menu-and-lcd-display-arduino
but could not work out how to modify it to actually control anything such as what I am proposing. What I envisage for example would be -
1.   Opening message “Choose from the following four  displays” > Enter
2.   You are then presented with pattern 1 > down button > pattern 2 > down button > pattern 3 > down button > pattern 4
3.   When you reach the pattern you wish to display  you press the enter button and the selected pattern will display on the eight LED’s
In essence this is exactly what Giuseppe’s code does but where his code displays “ you used Item1SubItem1” etc, I want it to run one of the four LED patterns. His code and circuit use four tact switches for enter, escape, up and down. Looking at the many questions asked after the tutorial might I be right in assuming that you can modify his menUsed function to run one of the four LED patterns by using a switch case coding or the like.
I am not asking anyone to do this for me but rather to hopefully point me in some general direction that might help get me off to a start. As always thank you for taking the time to read this Pedro.

Edit - I changed the  menuUsed function to just blink an LED on pin 13 then return to the main menu, and that works  smiley-grin So providing I can use a shift register, being controlled by three of the analog pins (seeing as the circuit as is, already  uses digital pins 2 - 11 for the LCD control and menu buttons) to control my four LED patterns, my next problem is how to incorporate four different choices within the menuUsed function to implement the four LED patterns.


« Last Edit: March 29, 2013, 04:00:59 am by Pedro147 » Logged


Quebec
Offline Offline
Jr. Member
**
Karma: 3
Posts: 78
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Pedro147, it's nice to have someone wanting to learn and not asking others to do the work for them.
The link you provided doesn't work at the moment, so I can't see the code but from what you wrote I guess there are variables somewhere that keep the displayed item number and subitem number, so from these numbers you can use if/else or a switch to trigger the different patterns you want to use.
Something like:
Code:
switch (item) {
  case 1:
    draw (LED1+LED3+LED5);
    break;
  case 2:
    draw (LED2+LED4+LED6);
    break;
  case 3:
    draw (LED1+LED2+LED3);
    break;
  case 4:
    draw (LED4+LED5+LED6);
    break;
}
Logged

Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Semicolo,

thanks for that suggestion, I will have a look and see if it can be used, Pedro.
Logged


Quebec
Offline Offline
Jr. Member
**
Karma: 3
Posts: 78
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was able to see the code, since you can switch on integer only, you'll have to use if and else

Code:
if (used.item==menuItem1) {
// do something
} else if (used.item == menuItem2) {
// do something else
} else if (used.item == menuItem3) {
}...
Logged

Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have connected a 595 shift register to analog pins 0 - 2 and am using this to control eight LED’s, with the circuit attached. I have stripped the Menubackend code of all the menu items that I do not require, just leaving four MenuItem’s to interface with my four LED patterns (hopefully  smiley-cool ) and all the code looking after the switch movements and other menu functions. Where the original code displayed “you used MenuItem…” I have substituted some shift register control code that lights eight LED’s via my “digit” byte.
What I cannot work out is how to modify the code so that I can pick one of four code patterns tied in with each of the four menu  items. I tried to incorporate some if and else if statements within the “menuChanged(MenuChangeEvent changed)” function in line 79 but that did not work..
Any suggestions would be greatly appreciated, thanks Pedro.
Code:
// http://www.coagula.org/content/pages/tutorial-manage-menu-and-lcd-display-arduino
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

const int buttonPinLeft = 8;      // pin for the Up button
const int buttonPinRight = 9;    // pin for the Down button
const int buttonPinEsc = 10;     // pin for the Esc button
const int buttonPinEnter = 11;   // pin for the Enter button
byte lastButtonPushed = 0;

byte latchPin = A2;   // connect to pin 12 on the shift register
byte dataPin  = A0;   // connect to pin 14 on the shift register    
byte clockPin = A1;   // connect to pin 11 on the shift register
byte i = 0;      
byte digit = B10011001;
byte blank = B00000000;

byte lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
byte lastButtonEscState = LOW;   // the previous reading from the Esc input pin
byte lastButtonLeftState = LOW;   // the previous reading from the Left input pin
byte lastButtonRightState = LOW;   // the previous reading from the Right input pin

long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
long lastEscDebounceTime = 0;  // the last time the output pin was toggled
long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
long lastRightDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 500;    // the debounce time


LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem menu1Item1 = MenuItem("Item1");
MenuItem menu1Item2 = MenuItem("Item2");
MenuItem menu1Item3 = MenuItem("Item3");
MenuItem menu1Item4 = MenuItem("Item4");

void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);

  pinMode(dataPin, OUTPUT);       // Configure dataPin  as OUTPUT
  pinMode(latchPin, OUTPUT);      // Configure latchPin as OUTPUT
  pinMode(clockPin, OUTPUT);      // Configure clockPin as OUTPUT
  lcd.begin(16, 2);

  //configure menu

  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3).addRight(menu1Item4);
  menu.toRoot();
  lcd.setCursor(0,0);  
  lcd.print("Pedro's Digital");

}  // setup()...


Part 2 of code follows
p.s. Hi semicolo, I just saw that you had posted as I was updating this thread.




* 4MENU_~1.png (23.8 KB, 1495x1060 - viewed 82 times.)
« Last Edit: March 30, 2013, 08:28:02 am by Pedro147 » Logged


Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Part 2 of code

Code:
void loop()
{

  readButtons();  //I split button reading and navigation in two procedures because
  navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)

} //loop()...

void menuChanged(MenuChangeEvent changed){

  MenuItem newMenuItem=changed.to; //get the destination menu

  lcd.setCursor(0,1); //set the start position for lcd printing to the second row

  if(newMenuItem.getName()==menu.getRoot()){
    lcd.print("  LED Patterns       ");

  }
  else if(newMenuItem.getName()=="Item1"){
    lcd.print("   Pattern 1        ");

  }
  else if(newMenuItem.getName()=="Item2"){
    lcd.print("   Pattern 2        ");

  }
  else if(newMenuItem.getName()=="Item3"){
    lcd.print("   Pattern 3        ");

  }
  else if(newMenuItem.getName()=="Item4"){
    lcd.print("   Pattern 4        ");

  }
}

void menuUsed(MenuUseEvent used)
{
  for(i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);                            // Pull latch LOW to start sending data
    shiftOut(dataPin, clockPin, LSBFIRST,digit);         // Send the data
    digitalWrite(latchPin, HIGH);                           // Pull latch HIGH to stop sending data
    delay(200);
    digitalWrite(latchPin, LOW);                            // Pull latch LOW to start sending data
    shiftOut(dataPin, clockPin, LSBFIRST,blank);         // Send the data
    digitalWrite(latchPin, HIGH);                           // Pull latch HIGH to stop sending data

  }
  lcd.setCursor(0,0); 
  lcd.print("PatternDisplayed");
  lcd.setCursor(0,1);
  lcd.print("  Back to Menu");
  delay(2000);  //delay to allow message reading
  lcd.setCursor(0,0); 
  lcd.print("Pedro's Digital  ");
  menu.toRoot();
}

void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter input pin
  int buttonEscState=LOW;             // the current reading from the input pin
  int buttonLeftState=LOW;             // the current reading from the input pin
  int buttonRightState=LOW;             // the current reading from the input pin

  //Enter button
  // read the state of the switch into a local variable:
  reading = digitalRead(buttonPinEnter);

  // check to see if you just pressed the enter button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise: 

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonEnterState) {
    // reset the debouncing timer
    lastEnterDebounceTime = millis();
  }

  if ((millis() - lastEnterDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonEnterState=reading;
    lastEnterDebounceTime=millis();
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonEnterState = reading;


  //Esc button               
  // read the state of the switch into a local variable:
  reading = digitalRead(buttonPinEsc);

  // check to see if you just pressed the Down button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise: 

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonEscState) {
    // reset the debouncing timer
    lastEscDebounceTime = millis();
  }

  if ((millis() - lastEscDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonEscState = reading;
    lastEscDebounceTime=millis();
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonEscState = reading;


  //Down button               
  // read the state of the switch into a local variable:
  reading = digitalRead(buttonPinRight);

  // check to see if you just pressed the Down button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise: 

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonRightState) {
    // reset the debouncing timer
    lastRightDebounceTime = millis();
  }

  if ((millis() - lastRightDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonRightState = reading;
    lastRightDebounceTime =millis();
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonRightState = reading;                 


  //Up button               
  // read the state of the switch into a local variable:
  reading = digitalRead(buttonPinLeft);

  // check to see if you just pressed the Down button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise: 

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonLeftState) {
    // reset the debouncing timer
    lastLeftDebounceTime = millis();
  }

  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonLeftState = reading;
    lastLeftDebounceTime=millis();
    ;
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonLeftState = reading; 

  //records which button has been pressed
  if (buttonEnterState==HIGH){
    lastButtonPushed=buttonPinEnter;

  }
  else if(buttonEscState==HIGH){
    lastButtonPushed=buttonPinEsc;

  }
  else if(buttonRightState==HIGH){
    lastButtonPushed=buttonPinRight;

  }
  else if(buttonLeftState==HIGH){
    lastButtonPushed=buttonPinLeft;

  }
  else{
    lastButtonPushed=0;
  }                 
}

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();

  switch (lastButtonPushed){
  case buttonPinEnter:
    if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
      menu.use();
    }
    else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
      menu.moveDown();
    }
    break;
  case buttonPinEsc:
    menu.toRoot();  //back to main
    break;
  case buttonPinRight:
    menu.moveRight();
    break;     
  case buttonPinLeft:
    menu.moveLeft();
    break;     
  }

  lastButtonPushed=0; //reset the lastButtonPushed variable
}
Logged


Quebec
Offline Offline
Jr. Member
**
Karma: 3
Posts: 78
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Pedro, you're almost there, you should define your led patterns and then affect them to your digit variable just before sending the data to the shift register:

Code:
#define pattern1 B11000000
#define pattern2 B00110000
#define pattern3 B00001100
#define pattern4 B00000011
...
void menuUsed(MenuUseEvent used)
{
  if (used.item == "Item1")
    digit=pattern1;
  else if (used.item == "Item2")
    digit=pattern2;
  else if (used.item == "Item3")
    digit=pattern3;
  else
    digit=pattern4;
  for(i = 0; i < 8; i++)
  {
    digitalWrite(latchPin, LOW);                            // Pull latch LOW to start sending data
    shiftOut(dataPin, clockPin, LSBFIRST,digit);         // Send the data
    digitalWrite(latchPin, HIGH);                           // Pull latch HIGH to stop sending data
    delay(200);
    digitalWrite(latchPin, LOW);                            // Pull latch LOW to start sending data
    shiftOut(dataPin, clockPin, LSBFIRST,blank);         // Send the data
    digitalWrite(latchPin, HIGH);                           // Pull latch HIGH to stop sending data

  }
  lcd.setCursor(0,0); 
  lcd.print("PatternDisplayed");
  lcd.setCursor(0,1);
  lcd.print("  Back to Menu");
  delay(2000);  //delay to allow message reading
  lcd.setCursor(0,0); 
  lcd.print("Pedro's Digital  ");
  menu.toRoot();
}


Logged

Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you so much semicolo,
that did the trick, it works perfectly. I must be slowly learning a few things which is heartening  smiley-grin When you initially suggested  using if / else if atatements in post #3, I had a look through the code to try and find out where I might incorporate them, but was not sure where they needed to go.

Just as a matter of interest, I changed the digit byte from byte digit = B10011001 to byte digit = 0,which still works but is this, how can I say, “more correct’ Also in the “menuUsed” function I felt that the for loop was redundant seeing as the shiftout code was not using it. It was only left there from some other coding that I had been trying within the SR operations. After I removed the for loop the LED’s only stayed on very briefly  so I increased the delay between the two shift register operations to compensate. Why did the LED’s stay on for longer with the for loop in place? Was it that even though the for loop was not actually doing anything useful, other than taking up processer time and therefore making the LED’S stay on while the for loop was executed.

Now I want to try and work out how to change the four static patterns to four dynamic pieces of code like knightrider style and some other patterns that I have come across. Thanks again for helping me get this far and I will post any progress that I make Pedro.



Logged


Canberra Australia
Offline Offline
God Member
*****
Karma: 11
Posts: 518
Hardcore Arduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

With some invaluable help from semicolo, I have now completed my 16*2 LCD menu control of four LED patterns. I might just expand the menu to six items and then look for my next learning experience  smiley-cool

http://www.youtube.com/watch?v=20u6zRJz6Is&feature=youtu.be

Logged


Quebec
Offline Offline
Jr. Member
**
Karma: 3
Posts: 78
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Happy to be of help, yes the for was just turning the leds off then on again in a loop giving you a longer delay.
Logged

Pages: [1]   Go Up
Jump to: