Pages: [1]   Go Down
Author Topic: combine elements from two sketches  (Read 990 times)
0 Members and 1 Guest are viewing this topic.
London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hello, I have a working menu using push buttons and have attached the navigation function of this menu below. I want to use an encoder and have included the encoder sketch here too.
what do I have to change to get the navigation menu working off the encoder....... instead of the push buttons.

I will use the right direction of the encoder to move the menu right and left for left. The encoder has a built in push button so I will use that as the "buttonPinEnter" .

I have tried putting some of the encoder sketch into the navigation menu but it just stops any menu working. I sure anyhelp here may help others.
 
Code:
void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();

  switch (lastButtonPushed){
  case buttonPinEnter: // enter pin this is set up to use a push button BUT need it to use PUSH BUTTON ON ENCODER
    if(!(currentMenu.moveDown())){  //if the current menu has a child and enter has been pressed  then navigate menu to item below
      menu.use();
    }
    else{  //otherwise, if menu has no child and enter has been pressed---- the current menu is used
      menu.moveDown();
    }
    break;
  case buttonPinEsc: //not Set up yet but this will have a push button
    menu.toRoot();  //back to main
    break;

  case buttonPinRight:
    menu.moveRight();
    break;

  case buttonPinLeft:
    menu.moveLeft();
    break;      

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

and here is a separate working sketch of the encoder

Code:
int val;
 int encoder0PinA = 2;
 int encoder0PinB = 3;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = HIGH;

 void setup() {
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   Serial.begin (9600);
 }

 void loop() {
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == HIGH) && (n == LOW)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
   }
   encoder0PinALast = n;
 }

Any help on implimenting this change would be appreciated.
« Last Edit: January 11, 2013, 01:06:15 pm by mark7w » Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It should be easy enough to read the button on the encoder.  Get that working first by plugging it in instead of the current button.

To use the encoder to navigate the menu you need to determine which way it is rotating.  In your encoder sketch you are already working this out and changing the value of encoder0Pos appropriately, so instead of changing the value treat an increasing value as one button and a decreasing value as the other and call  menu.moveRight(); or menu.moveLeft(); to suit.

If this is what you have already tried then seeing your code would be helpful.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 509
Posts: 31483
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Read this and then post the code that you make.
http://www.thebox.myzen.co.uk/Tutorial/Merging_Code.html
Logged

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

UKHeliBob
Quote
It should be easy enough to read the button on the encoder.  Get that working first by plugging it in instead of the current button.

I have the push button on the Encoder working now smiley-grin

just the -- and ++ of the encoder to figure out. see my last part of the sketch "void navigateMenus".

this is for me the difficult part. smiley-cry
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You are working out which way the encoder is turning but you do nothing when you you know except changing the value of encoder0Pos.

How about something like this
Code:
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == HIGH) && (n == LOW))
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
        lastButtonPushed = buttonPinLeft;
    }
    else {
      lastButtonPushed = buttonPinRight;
    }
    encoder0PinALast = n;
  }

You seem to have tried to do something with the value of encoder0Pos but
Code:
if (encoder0Pos++);
is not testing whether its value has changed

When you get this working I suggest that you tidy up the variable and function names to remove confusion about whether buttons are being pressed or the encoder is being rotated.

Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
You seem to have tried to do something with the value of encoder0Pos but it is not testing whether its value has changed

Code:
if (encoder0Pos++);


Do i need to put some code here for this to work or do I leave it as

Code:

case buttonPinRight:
//???????
  menu.moveRight();
  break;

 case buttonPinLeft:
//??????
   menu.moveLeft();
   break;     

   lastButtonPushed=0; //reset the lastButtonPushed variable
  }

thanks for the help I am begining to see the wood through the trees. I will tidy up variable and function names when I have a working code
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No need for anything to go there.  You will have already determined that the encoder is moving and which way and just need to act on it.

Once it works save that version and set about tidying it up in a new sketch.  Even if it works then there is plenty that you could do as it seems quite tangled at the moment.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can see what Its trying to do but cant code what it needs to do. No matter what I do I cant get his to work. I've tried so many ways, i'm out of Ideas and feel I need to come up with a third option for the menu using a different encoder sketch. Which is not going to help me as I will be back to square one.

This is my entire sketch. I have a rotary encoder with pushbutton and one external button that is the exit menu.
Thanks for all the help everyone but even now I still dont understand it. Is there a level under noob. smiley-sad-blue

Code:
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

int encoder0PinA = 2;
int encoder0PinB =3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;

const int encoderRight = ?????; //what should go here????
const int encoderLeft = ??????;// and here ????
const int buttonPinEsc = 42;
const int encoderPushButton = 45;   // pin for the Enter button

int lastButtonPushed = 0;


LiquidCrystal lcd(7,8,9,10,11,12);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);

//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd");// first menu item
MenuItem menuItemOn = MenuItem("menuItemOn");// sub menu
MenuItem menuItemOff = MenuItem("menuItemOff");// sub menu

MenuItem menuSetClock = MenuItem("menuSetClock");// 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr");// sub menu
MenuItem menuItemMin = MenuItem("menuItemMin");//sub menu
MenuItem menuItemSec = MenuItem("menuItemSec");//sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm");//sub menu

MenuItem menuSetDate = MenuItem("menuSetDate");// 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay");// sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth");//sub menu
MenuItem menuItemYear = MenuItem("menuItemYear");//sub menu

MenuItem menuExit = MenuItem("menuExit");// 3rdh menu item

void setup()
{
  pinMode(encoderRight, INPUT);
  pinMode(encoderLeft, INPUT);
  pinMode(encoderPushButton, INPUT);
  pinMode(buttonPinEsc, INPUT);
  pinMode (encoder0PinA,INPUT);
  pinMode (encoder0PinB,INPUT);

  lcd.begin(16, 2);

  //configure menu
  lcd.setCursor(0,1);
  menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate);//set main menu items
  menuLcd.add(menuItemOn).addRight(menuItemOff);// add first sub menu then addright additional sub menues for that menu
  menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm);// add first sub menu then addright additional sub menues for that menu
  menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear);// add first sub menu then addright additional sub menues for that menu
  menu.toRoot();
}

void loop()
{
  //readButtons();  //I splitted 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)
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == HIGH) && (n == LOW))
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
      lastButtonPushed = encoderRight;//encoder0Pos--;
    }

    else {
      lastButtonPushed = encoderLeft;//encoder0Pos++;
    }

    encoder0PinALast = n;
  }
}

void menuChanged(MenuChangeEvent changed){

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

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

  if(newMenuItem.getName()==menu.getRoot())
  {
    lcd.print("Main Menu       ");
  }
  //menu lcd
  else if(newMenuItem.getName()=="menuLcd"){
    lcd.clear();
    lcd.print("Lcd");
  }
  else if(newMenuItem.getName()=="menuItemOn"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("On");
  }
  else if(newMenuItem.getName()=="menuItemOff"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Off");

  }
  //menu set clock

  else if(newMenuItem.getName()=="menuSetClock"){
    lcd.clear();
    lcd.print("Set Clock");
  }
  else if(newMenuItem.getName()=="menuItemHr"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Hr");
  }
  else if(newMenuItem.getName()=="menuItemMin"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Min");
  }
  else if(newMenuItem.getName()=="menuItemSec"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Sec");
  }
  else if(newMenuItem.getName()=="menuItemConfirm"){
    lcd.clear();
    lcd.print("Confirmed");
  }
  //menu set date

  else if(newMenuItem.getName()=="menuSetDate"){
    lcd.clear();
    lcd.print("Set Date");
  }
  else if(newMenuItem.getName()=="menuItemDay"){
    lcd.clear();
    lcd.print("Set Day");
  }
  else if(newMenuItem.getName()=="menuItemMonth"){
    lcd.clear();
    lcd.print("Set Month");
  }
  else if(newMenuItem.getName()=="menuItemYear"){
    lcd.clear();
    lcd.print("Set Year");
  }
  //menu exit
  else if(newMenuItem.getName()=="menuExit"){
    lcd.clear();
    lcd.print("Exit");
  }
}

void menuUsed(MenuUseEvent used){ //**if you have a function call it here**
  if( used.item == menuItemOn ){
    lcd.display();
    //digitalWrite(10, HIGH);
    //delay(3000);
    //digitalWrite(10, LOW);
    lcd.clear();
    menu.toRoot();
  }
  if ( used.item == menuItemOff ){
    lcd.noDisplay();//your code here
    menu.toRoot();
  }
  //etc.
}


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

  switch (lastButtonPushed){
    digitalWrite (ledPin, HIGH);

  case encoderPushButton: // enter pin this is set up to use a push button BUT need it to use PUSH BUTTON ON ENCODER
    if (!(currentMenu.moveDown())){  //if the current menu has a child and enter has been pressed  then navigate menu to item below
      menu.use();

    }
    else{  //otherwise, if menu has no child and enter has been pressed---- the current menu is used
      menu.moveDown();
    }
    break;
   
  case encoderRight:
    menu.moveRight();
    break;
   
  case encoderLeft:
    menu.moveLeft();
    break;

  case buttonPinEsc: //not Set up yet but this will have a push button
    lcd.clear();
    menu.toRoot();  //back to main
    break;   

    lastButtonPushed=0; //reset the lastButtonPushed variable
  }
}
« Last Edit: January 10, 2013, 06:57:02 pm by mark7w » Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You have started to tidy up the code as well as using the encoder to fool the program into thinking that buttons have been pressed which has confused things somewhat.

In post 5 I suggested setting the value of LastButtonPushed to buttonPinRight or buttonPinLeft when the encoder moved.  You could then use the same code as you did to respond to the fake button presses.  What you have done is to set LastButtonPressed to encoderRight or encoderLeft.  That is a start at tidying up.  It should still work, but in setup() you need to set encoderRight and encoderLeft to the values that buttonPinRight and buttonPinLeft would return when the button(s) are pressed.

NOTE - I have not checked any other parts of your code to see if you have changed anything else.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have just added some brackets and encoder0Pos-- and encoder0Pos++ and it worked.

Code:
void loop()
{

  n = digitalRead(encoder0PinA);// value of n = n is default LOW
  if ((encoder0PinALast == HIGH) && (n == LOW)) // int encoder0PinALast default LOW
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
      
  if(lastButtonPushed = buttonPinLeft)
  encoder0Pos--;
    }

    else if
      
  (lastButtonPushed = buttonPinRight)
  encoder0Pos++;
    }

    encoder0PinALast = n;
  

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

ONE thing about this is that I have PINS assisigned to 43 and 45 for "buttonPinLeft" and "buttonPinRight". I can remove the wire connections for these and it still works but I have lost the use of TWO pins? If I remove 43 and 45 to become
 
const int encoderLeftRotation;
const int encoderRightRotation;

I get an uninitialized error.

Any Ideas on this...............anyone!

UKHeliBob as a reward for all your help Karma is duly awarded.
« Last Edit: January 11, 2013, 01:01:14 pm by mark7w » Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A const is designed to hold a value that will not change, ie it is constant, so you cannot have a const with no value, hence the error.  If you set encoderLeftRotation and encoderRightRotation to 43 and 45 respectively that has nothing to do with using pins 43 and 45 so you could use them for something else.

Can you please post your whole code as it is now ?
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hers my code. I had to split it in half as the character count exceeds forum limit. now using PINS 42 and 49 as mega board pin to slack.

Code:
/*
    This is a Test of a menu and Encoder to be used in a bigger project. I am building it in modules                                     
    so I can test each one. This module is As. A lcd displayed Menu System using a rotary encoder to navigate the menu system.           
    The "void menuUsed(MenuUseEvent used)" is where I will call functions related to the menu. At present I have just explored turning   
    the lcd light On and Off. The menu is self explanatory and functions to this will follw.                                             
*/


#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

int ledPin =  13;
int val;
int encoder0PinA = 2;// pin A signal on encoder
int encoder0PinB =3;// pin B signal on encoder
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
LiquidCrystal lcd(7,8,9,10,11,12);

const int encoderLeftRotation = 44;      // pin for the Up button
const int encoderRightRotation = 46;    // pin for the Down button
const int encoderPushButton = 49;   // pin for the Enter button
const int buttonPinEsc = 42;     // pin for the Esc button

int lastButtonPushed = HIGH;

int lastEncoderButtonState = LOW;   // the previous reading from the Enter input pin
int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
int lastRotationLeftState = LOW;   // the previous reading from the Left input pin
int lastRotationRightState = 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 = 15;    // the debounce time was 100


//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);

//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd");// first menu item
MenuItem menuItemOn = MenuItem("menuItemOn");// sub menu
MenuItem menuItemOff = MenuItem("menuItemOff");// sub menu

MenuItem menuSetClock = MenuItem("menuSetClock");// 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr");// sub menu
MenuItem menuItemMin = MenuItem("menuItemMin");//sub menu
MenuItem menuItemSec = MenuItem("menuItemSec");//sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm");//sub menu

MenuItem menuSetDate = MenuItem("menuSetDate");// 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay");// sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth");//sub menu
MenuItem menuItemYear = MenuItem("menuItemYear");//sub menu

MenuItem menuSetPhone = MenuItem("menuSetPhone");// 3rd menu item
MenuItem menuItemNumber = MenuItem("menuItemNumber");// sub menu

MenuItem menuSetPin = MenuItem("menuSetPin");// 4th menu item
MenuItem menuItemPin = MenuItem("menuItemPin");// sub menuu

MenuItem menuSms = MenuItem("menuSms");// 5th menu item
MenuItem menuItemSigStr = MenuItem("menuItemSigStr");// sub menu
MenuItem menuItemBalance = MenuItem("menuItemBalance");// sub menuu
MenuItem menuItemTest = MenuItem("menuItemTest");// sub menuu

MenuItem menuExit = MenuItem("menuExit");// 6th menu item


void setup()
{
  lcd.begin(16, 2);
  pinMode(encoderLeftRotation, INPUT);
  pinMode(encoderRightRotation, INPUT);
  pinMode(encoderPushButton, INPUT);
  pinMode(buttonPinEsc, INPUT);
  pinMode (encoder0PinA,INPUT);
  pinMode (encoder0PinB,INPUT);

  //configure menu
  lcd.setCursor(0,1);
  menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate).addRight(menuSetPhone).addRight(menuSetPin).addRight(menuSms).addRight(menuExit);//set main menu items
  menuLcd.add(menuItemOn).addRight(menuItemOff);// add first sub menu then addright additional sub menues for that menu
  menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm);// add first sub menu then addright additional sub menues for that menu
  menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear);// add first sub menu then addright additional sub menues for that menu
  menuSetPhone.add(menuItemNumber);
  menuSetPin.add(menuItemPin);
  menuSms.add(menuItemSigStr).addRight(menuItemBalance).addRight(menuItemTest);
  menuExit.add(menuExit);
  menu.toRoot();
}

void loop()
{
  n = digitalRead(encoder0PinA);// value of n = n is default LOW
  if ((encoder0PinALast == HIGH) && (n == LOW)) // int encoder0PinALast default LOW
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
      if(lastButtonPushed = encoderLeftRotation)
        encoder0Pos--;
    }
    else if

      (lastButtonPushed = encoderRightRotation)
      encoder0Pos++;
  }
  encoder0PinALast = n;

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

join up to next post.
Logged

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

here the rest of the code.

Code:
//Debouncing also- hardware Debounce inplace
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
  reading = digitalRead(encoderPushButton);// read the state of the switch into a local variable:
  if (reading != lastEncoderButtonState) {// If the switch changed, due to noise or pressing:
    lastEnterDebounceTime = millis(); // reset the debouncing timer
  }
  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();
  }
  lastEncoderButtonState = reading;// save the reading.  Next time through the loop, it'll be the lastButtonState:


  //Esc button            
  reading = digitalRead(buttonPinEsc);// read the state of the switch into a local variable:
  if (reading != lastButtonEscState) {// If the switch changed, due to noise or pressing:
    lastEscDebounceTime = millis();// reset the debouncing timer
  }
  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();
  }
  lastButtonEscState = reading;// save the reading.  Next time through the loop, it'll be the lastButtonState:


  //Right or Down button              
  reading = digitalRead(encoderRightRotation);// read the state of the switch into a local variable
  if (reading != lastRotationRightState) {//last button state is defaulted int LOW
    lastRightDebounceTime = millis();// reset the debouncing timer
  }
  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();
  }
  lastRotationRightState = reading; // save the reading.  Next time through the loop, it'll be the lastButtonState:                


  //Left or Up button              
  reading = digitalRead(encoderLeftRotation);// read the state of the switch into a local variable:
  if (reading != lastRotationLeftState) {// If the switch changed, due to noise or pressing:
    lastLeftDebounceTime = millis();// reset the debouncing timer
  }
  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();
  }
  lastRotationLeftState = reading; // save the reading.  Next time through the loop, it'll be the lastButtonState:

  //records which button has been pressed
  if (buttonEnterState==HIGH){
    lastButtonPushed=encoderPushButton;
  }
  else if(buttonEscState==HIGH){
    lastButtonPushed=buttonPinEsc;
  }
  else if(buttonRightState==HIGH){
    lastButtonPushed=encoderRightRotation;
  }
  else if(buttonLeftState==HIGH){
    lastButtonPushed=encoderLeftRotation;
  }
  else{
    lastButtonPushed=0;
  }                  
}

void menuChanged(MenuChangeEvent changed){

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

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

  if(newMenuItem.getName()==menu.getRoot())
  {
    lcd.print("Main Menu       ");
  }
  //menu lcd
  else if(newMenuItem.getName()=="menuLcd"){
    lcd.clear();
    lcd.print("Lcd");
  }
  else if(newMenuItem.getName()=="menuItemOn"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("On");
  }
  else if(newMenuItem.getName()=="menuItemOff"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Off");
  }

  //menu set clock
  else if(newMenuItem.getName()=="menuSetClock"){
    lcd.clear();
    lcd.print("Set Clock");
  }
  else if(newMenuItem.getName()=="menuItemHr"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Hr");
  }
  else if(newMenuItem.getName()=="menuItemMin"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Min");
  }
  else if(newMenuItem.getName()=="menuItemSec"){
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Sec");
  }
  else if(newMenuItem.getName()=="menuItemConfirm"){
    lcd.clear();
    lcd.print("Confirmed");
  }

  //menu set date
  else if(newMenuItem.getName()=="menuSetDate"){
    lcd.clear();
    lcd.print("Set Date");
  }
  else if(newMenuItem.getName()=="menuItemDay"){
    lcd.clear();
    lcd.print("Set Day");
  }
  else if(newMenuItem.getName()=="menuItemMonth"){
    lcd.clear();
    lcd.print("Set Month");
  }
  else if(newMenuItem.getName()=="menuItemYear"){
    lcd.clear();
    lcd.print("Set Year");
  }

  //menu set phone number
  else if(newMenuItem.getName()=="menuSetPhone"){
    lcd.clear();
    lcd.print("Set Phone");
  }

  //menu set pin number
  else if(newMenuItem.getName()=="menuSetPin"){
    lcd.clear();
    lcd.print("Set Pin");
  }

  //menu set sms
  else if(newMenuItem.getName()=="menuSms"){
    lcd.clear();
    lcd.print("Sms ");
  }
  else if(newMenuItem.getName()=="menuItemSigStr"){
    lcd.clear();
    lcd.print("Signal Stre");
  }
  else if(newMenuItem.getName()=="menuItemBalance"){
    lcd.clear();
    lcd.print("Balance");
  }
  else if(newMenuItem.getName()=="menuItemTest"){
    lcd.clear();
    lcd.print("Test Sms");
  }

  //menu exit to time
  else if(newMenuItem.getName()=="menuExit"){
    lcd.clear();
    lcd.print("Exit");
  }
}

void menuUsed(MenuUseEvent used){ //**if you have a function call it here**
  if( used.item == menuItemOn ){
    lcd.display();
    //digitalWrite(10, HIGH);
    //delay(3000);
    //digitalWrite(10, LOW);
    lcd.clear();
    menu.toRoot();
  }
  if ( used.item == menuItemOff ){
    lcd.noDisplay();//your code here
    menu.toRoot();
  }
  //etc.
}

void navigateMenus() {

  MenuItem currentMenu=menu.getCurrent();

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

  lastButtonPushed=0; //reset the lastButtonPushed variable
}

I still would like to remove

Code:
const int encoderLeftRotation = 44;      // pin for the Up button
const int encoderRightRotation = 46;    // pin for the Down button

I have tried to remove it but my code fails if I do? even thou they're not wired up? Is the a way rount this?
« Last Edit: January 11, 2013, 08:42:15 pm by mark7w » Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 89
Posts: 3489
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mark - this is difficult for me to help with in detail because I don't have the same hardware as you and my Arduino is tied up with a project of my own.  I think that the time has come for you to step back and start again.

Load the menu navigation sketch that works with buttons and save it with a new name.
Copy the encoder declarations and pin setup into the new sketch to create the variables.

Make a new function in the sketch called readEncoder()

Code:
void readEncoder()      //read the encoder and set lastButtonPushed to values used by navigateMenu()
{
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == HIGH) && (n == LOW))
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
      lastButtonPushed = 46;
    }
    else
    {
      lastButtonPushed = 44;
    }
  }
  encoder0PinALast = n;
}

At this point the sketch should still work with buttons as it is not reading the encoder.  Fix any compile errors.
Change the readButtons() function to read only the button on the encoder and to leave lastButtonPushed alone unless it was pushed.

Now, before you call navigateMenu() in loop() call readButtons() and readEncoder()
readEncoder() will set lasButtonPushed to 44 or 46 if the encoder has moved and navigateMenu() will interpret that as a button push.  Try this much and let us know how you get on.  As I said before, once this works you can tidy up.  For instance, readEncoder() could read the button as well.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

London-UK
Offline Offline
Full Member
***
Karma: 1
Posts: 106
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have made the changes you advised and it's working perfectly.

Here is the new code split again. I have tided it up too, so I think?

Code:
/*
    This is a Test of a menu and Encoder to be used in a bigger project. I am building it in modules                                    
    so I can test each one. This module is As. A lcd displayed Menu System using a rotary encoder to navigate the menu system.          
    The "void menuUsed(MenuUseEvent used)" is where I will call functions related to the menu. At present I have just explored turning  
    the lcd light On and Off. The menu is self explanatory and functions to this will follw.                                            
*/

#include <MenuBackend.h> //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h> //this library is included in the Arduino IDE

const int encoderPushButton = 45; // pin for the Enter button
const int buttonPinEsc = 42; // pin for the Esc button

int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = HIGH;
int lastButtonPushed = 0;
int lastButtonEnterState = LOW; // the previous reading from the Enter input pin
int lastButtonEscState = LOW; // the previous reading from the Esc 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 debounceDelay = 150; // the debounce time

LiquidCrystal lcd(7,8,9,10,11,12);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);

//initialize menuitems
MenuItem menuLcd = MenuItem("menuLcd"); // first menu item
MenuItem menuItemOn = MenuItem("menuItemOn"); // sub menu
MenuItem menuItemOff = MenuItem("menuItemOff"); // sub menu
MenuItem menuSetClock = MenuItem("menuSetClock"); // 2nd menu item
MenuItem menuItemHr = MenuItem("menuItemHr"); // sub menu
MenuItem menuItemMin = MenuItem("menuItemMin"); //sub menu
MenuItem menuItemSec = MenuItem("menuItemSec"); //sub menu
MenuItem menuItemConfirm = MenuItem("menuItemConfirm"); //sub menu
MenuItem menuSetDate = MenuItem("menuSetDate"); // 2nd menu item
MenuItem menuItemDay = MenuItem("menuItemDay"); // sub menuu
MenuItem menuItemMonth = MenuItem("menuItemMonth"); //sub menu
MenuItem menuItemYear = MenuItem("menuItemYear"); //sub menu
MenuItem menuSetPhone = MenuItem("menuSetPhone"); // 3rd menu item
MenuItem menuItemNumber = MenuItem("menuItemNumber"); // sub menu
MenuItem menuSetPin = MenuItem("menuSetPin"); // 4th menu item
MenuItem menuItemPin = MenuItem("menuItemPin"); // sub menuu
MenuItem menuSms = MenuItem("menuSms"); // 5th menu item
MenuItem menuItemSigStr = MenuItem("menuItemSigStr"); // sub menu
MenuItem menuItemBalance = MenuItem("menuItemBalance"); // sub menuu
MenuItem menuItemTest = MenuItem("menuItemTest"); // sub menuu
MenuItem menuExit = MenuItem("menuExit"); // 6th menu item

void setup()
{
  pinMode(encoderPushButton, INPUT);
  pinMode(buttonPinEsc, INPUT);

  pinMode (encoder0PinA,INPUT);
  pinMode (encoder0PinB,INPUT);
  Serial.begin (9600);

  lcd.begin(16, 2);

  //configure menu
  lcd.setCursor(0,1);
  menu.getRoot().addRight(menuLcd).addRight(menuSetClock).addRight(menuSetDate).addRight(menuSetPhone).addRight(menuSetPin).addRight(menuSms).addRight(menuExit); //set main menu items
  menuLcd.add(menuItemOn).addRight(menuItemOff); // add first sub menu then addright additional sub menues for that menu
  menuSetClock.add(menuItemHr).addRight(menuItemMin).addRight(menuItemSec).addRight(menuItemConfirm); // add first sub menu then addright additional sub menues for that menu
  menuSetDate.add(menuItemDay).addRight(menuItemMonth).addRight(menuItemYear); // add first sub menu then addright additional sub menues for that menu
  menuSetPhone.add(menuItemNumber);
  menuSetPin.add(menuItemPin);
  menuSms.add(menuItemSigStr).addRight(menuItemBalance).addRight(menuItemTest);
  menuExit.add(menuExit);
  menu.toRoot();
}

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

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


  //ENTER BUTTON DEBOUNCE

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

  if (reading != lastButtonEnterState) // If the switch changed, due to noise or pressing:
  {
    lastEnterDebounceTime = millis(); // reset the debouncing timer
  }
  if ((millis() - lastEnterDebounceTime) > debounceDelay) // whatever the reading is at, it's been there for longerthan the debounce delay, so take it as the actual current state:
  {        
    buttonEnterState=reading;
    lastEnterDebounceTime=millis();
  }
  lastButtonEnterState = reading; // save the reading.  Next time through the loop, it'll be the lastButtonState:


  //ESC BUTTON DEBOUNCE            

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

  if (reading != lastButtonEscState) // If the switch changed, due to noise or pressing:
  {
    lastEscDebounceTime = millis(); // reset the debouncing timer
  }
  if ((millis() - lastEscDebounceTime) > debounceDelay)// whatever the reading is at, it's been there for longerthan the debounce delay, so take it as the actual current state:
  {
    buttonEscState = reading;
    lastEscDebounceTime=millis();
  }
  lastButtonEscState = reading; // save the reading.  Next time through the loop, it'll be the lastButtonState:

  //Records which button has been pressed
  if (buttonEnterState==HIGH){
    lastButtonPushed=encoderPushButton;
  }
  else if(buttonEscState==HIGH){
    lastButtonPushed=buttonPinEsc;
  }
  else{
    lastButtonPushed=0;
  }                  
}

void readEncoder() //read the encoder and set lastButtonPushed to values used by navigateMenu()
{
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == HIGH) && (n == LOW))
  {
    if (digitalRead(encoder0PinB) == LOW)
    {
      lastButtonPushed = 46;
    }
    else
    {
      lastButtonPushed = 44;
    }
  }
  encoder0PinALast = n;
}



Quote
For instance, readEncoder() could read the button as well.

Do I have to move ALL my button bounce code to "Read encoder" as well? what about the separate "Esc button" does that move there too.
« Last Edit: January 15, 2013, 10:34:20 am by mark7w » Logged

Pages: [1]   Go Up
Jump to: