Rotary Encoder Menu

algemene C code
Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Rotary Encoder Menu

Berichtdoor Hanneman » 17 Mei 2014, 08:51

Dit onderwerp is al eens eerder aangesneden in een andere context maar is nooit afgerond.
Ik heb de vraag op meerdere forums gevonden, maar nooit een bevredigend antwoord gezien.
Ik hoop dat het hier wel goed opgelost kan worden.
Er zijn een aantal apparaten waarmee je door een menu kunt browsen en beslissingen kunt maken door middel van een Rotary (Incremental) Encoder.
Het lijkt mij logisch dat dit met een Finite State Machine gebeurd.
Nu is het mij gelukt een FSM te maken die ik met losse knoppen kan besturen, maar met een Encoder is het mij nog niet gelukt en ik trek nog net niet die laatste paar haren uit mijn hoofd :?
Ik heb een code gevonden waarmee waardes beïnvloed worden door de Encoder links of rechtsom te draaien.
De button functie van een Encoder is aan te spreken zoals je standaard doet met een button.
Afzonderlijk kan ik met deze codes werken, maar ik krijg ze niet samengevoegd om het doel te bereiken.

Ik zou het geweldig vinden als het als volgt zou werken:
Main menu:
Leds uit, druk op de encoder knop -> menu RED

vanuit menu RED door te draaien, door de menus RED, GREEN, BLUE fietsen.

Met een druk op de knop terug naar Main menu

De code van de FSM:
Code: Alles selecteren
//
// Libraries
//
#include <LiquidCrystal.h> // Library voor de 16x2 LCD Display
//
// finite state machine state definitions
//
#define STATE_RED   0
#define STATE_GREEN 1
#define STATE_BLUE  2
//
// pin definitions
//
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // LCD Display Pins D2, D3, D4, D5, D11, D12
#define BLUELEDPIN   6                 // Blauwe Led aan Pin D 6
#define REDLEDPIN    9                 // Rode Led aan Pin D 9
#define GREENLEDPIN 10                 // Groene Led aan Pin D 10
//
// global variables
//
int fsm_state;                         // Switch variable
/**
 * @name setup()
 * initialize the program
 */
void setup() {
   //
   // LCD Display
   //
   lcd.begin(16, 2);                   // 16 kolommen en 2 rijen op de LCD Display
   lcd.print("Push encoder Button");   // Geeft tekst weer op de 1e rij van de LCD Display
   lcd.setCursor(0, 1);                // Zet de cursor op de 1 kolom van de 2e rij op de LCD Display
   lcd.print("for main menu");         // Geeft text weer op de 2e rij van de LCD Display
   //
   // open Seriele poort
   //
   Serial.begin(9600);                 // Baud snelheid is 9600
   //
   // outputs
   //
   pinMode(REDLEDPIN,   OUTPUT);
   pinMode(GREENLEDPIN, OUTPUT);
   pinMode(BLUELEDPIN,  OUTPUT);
   //
   // Zet de Leds standaard uit
   //
   digitalWrite(REDLEDPIN, LOW);
   digitalWrite(GREENLEDPIN, LOW);
   digitalWrite(BLUELEDPIN, LOW);

}
/**
 * @name loop()
 * main loop of program and runs endlessly
 */
void loop() {
   lcd.setCursor(0, 1);                // zet de cursor op de eerste kolom op de 2e rij
   //
   // finite state machine 1
   //
   switch (fsm_state) {
   //
   // state RED
   //
   case STATE_RED:
   
    lcd.println("RED");               // Geeft RED weer op de Display
   
    digitalWrite(REDLEDPIN,   HIGH);  // Zet de Rode led aan
     
      break;
      //
      // state GREEN
      //
   case STATE_GREEN:
   
    lcd.println("GREEN");             // Geeft GREEN weer op de Display

    digitalWrite(GREENLEDPIN, HIGH);  // Zet de Groene led aan
     
      break;
      //
      // state BLUE
      //
   case STATE_BLUE:
   
     lcd.println("BLUE");             // Geeft BLUE weer op de Display

     digitalWrite(BLUELEDPIN,  HIGH); // Zet de Blauwe led aan
     
      break;
   }
}


De code van de Encoder gevonden op deze site http://www.hobbytronics.co.uk/arduino-tutorial6-rotary-encoder:

Code: Alles selecteren
/*
** Rotary Encoder Example
** Use the Sparkfun Rotary Encoder to vary brightness of LED
**
** Sample the encoder at 200Hz using the millis() function
*/

int brightness = 120;    // how bright the LED is, start at half brightness
int fadeAmount = 10;    // how many points to fade the LED by
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 12;  // pin 12
const int pin_B = 11;  // pin 11
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;

void setup()  {
  // declare pin 9 to be an output:
  pinMode(9, OUTPUT);
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime;
}

void loop()  {
  // get the current elapsed time
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){
    // 5ms since last check of encoder = 200Hz 
    encoder_A = digitalRead(pin_A);    // Read encoder pins
    encoder_B = digitalRead(pin_B);   
    if((!encoder_A) && (encoder_A_prev)){
      // A has gone from high to low
      if(encoder_B) {
        // B is high so clockwise
        // increase the brightness, dont go over 255
        if(brightness + fadeAmount <= 255) brightness += fadeAmount;               
      }   
      else {
        // B is low so counter-clockwise     
        // decrease the brightness, dont go below 0
        if(brightness - fadeAmount >= 0) brightness -= fadeAmount;               
      }   

    }   
    encoder_A_prev = encoder_A;     // Store value of A for next time   
   
    // set the brightness of pin 9:
    analogWrite(9, brightness);   
   
    loopTime = currentTime;  // Updates loopTime
  }
  // Other processing can be done here
                           
}


Aansluitschema encoder:
Afbeelding
Aansluitschema LCD Display:
Afbeelding

Advertisement

Berichten: 4064
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Rotary Encoder Menu

Berichtdoor shooter » 17 Mei 2014, 19:33

encoder loop works like described, however only using half of max precision.
brightness will be fsm_state.
paul deelen
shooter@home.nl

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 17 Mei 2014, 20:33

please be more specific. That is pretty obvious.
How would you program that?

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 21 Mei 2014, 11:31

Deze code maakt een mooi menu.
Nu nog de knop functies omzetten naar de Encoder

Code: Alles selecteren
/*
    Copyright Giuseppe Di Cillo (www.coagula.org)
    Contact: dicillo@coagula.org
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
   void toRoot() {
      setCurrent( &getRoot() );
   }
*/

#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
LiquidCrystal lcd(12, 11, 5, 4, 9, 7);
const int buttonPinLeft = 2;      // pin for the Up button
const int buttonPinRight = 3;    // pin for the Down button
const int buttonPinEsc = 8;     // pin for the Esc button
const int buttonPinEnter = 13;   // pin for the Enter button

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
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int 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 display with:
// rs on pin 7
// rw on ground
// enable on pin 6
// d4, d5, d6, d7 on pins 5, 4, 3, 2

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");


void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
 
  lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  lcd.setCursor(0,0); 
  lcd.print("www.coagula.org");

}  // setup()...


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)
                 
} //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("Main Menu       ");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("Item1           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("Item1SubItem1");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("Item1SubItem2   ");
  }else if(newMenuItem.getName()=="Item2"){
      lcd.print("Item2           ");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      lcd.print("Item2SubItem1   ");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
      lcd.print("Item2SubItem2   ");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      lcd.print("Item2SubItem3   ");
  }else if(newMenuItem.getName()=="Item3"){
      lcd.print("Item3           ");
  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0); 
  lcd.print("You used        ");
  lcd.setCursor(0,1);
  lcd.print(used.item.getName());
  delay(3000);  //delay to allow message reading
  lcd.setCursor(0,0); 
  lcd.print("www.coagula.org");
  menu.toRoot();  //back to Main
}


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
}




Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 21 Mei 2014, 11:54

Deze code werkt voor de encoder, in de seriele monitor kan ik de waarde omhoog en omlaag zien gaan als ik aan de encoder draai.

Hoe kan ik deze waarden koppelen aan de menu functies?

Code: Alles selecteren
#define EncoderPinA 2
#define EncoderPinB 3

#include "pins_arduino.h"

byte portA;
byte portB;
byte bit_maskA;
byte bit_maskB;
volatile byte *registerA;
volatile byte *registerB;

volatile static int numberA;

volatile int* attached_val;


void setup()
{
  Serial.begin(9600);
  pinMode(EncoderPinA, INPUT);
  pinMode(EncoderPinB, INPUT);
  digitalWrite(EncoderPinA, HIGH);
  digitalWrite(EncoderPinB, HIGH);

  portA=digitalPinToPort(EncoderPinA);
  portB=digitalPinToPort(EncoderPinB);

  bit_maskA = digitalPinToBitMask(EncoderPinA);
  bit_maskB = digitalPinToBitMask(EncoderPinB);
  registerA = portInputRegister(portA);
  registerB = portInputRegister(portB);

  attached_val = &numberA;
  attachInterrupt(0, doEncoderA, FALLING); // for some reason the new mouser encoders only work on A falling and b rising The other ones don't read fast enough

  //and always count the same way
}

void loop()
{

  Serial.print("numberA = ");
  Serial.println(numberA);

  delay(500);

}


void doEncoderA()
{

  ((((*registerA) & bit_maskA) && ((*registerB) & bit_maskB)) || ((!((*registerA) & bit_maskA)) && (!((*registerB) & bit_maskB))))? (*attached_val)++ :

  (*attached_val)--;
}


Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 24 Mei 2014, 17:47

Ik ben iets verder gekomen, maar het menu loopt vast:
http://youtu.be/1bEoH4xUh3U

Deze stukjes heb ik aangepast:
Code: Alles selecteren
   //Down button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinRight);
                  reading = encoder0Pos + 1;


Code: Alles selecteren
    //Up button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinLeft);
                  reading = encoder0Pos - 1;


Maar het is duidelijk dat het zo niet werkt.
Wat doe ik verkeerd?

Dit is de volledige code
Code: Alles selecteren
/*
    Copyright Giuseppe Di Cillo (www.coagula.org)
    Contact: dicillo@coagula.org
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
   void toRoot() {
      setCurrent( &getRoot() );
   }
*/

#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
LiquidCrystal lcd(12, 11, 5, 4, 9, 7);
//
// Encoder Pin definitions
//
int ledPin = 10;
#define encoder0PinA 2
#define encoder0PinB 3
volatile unsigned int encoder0Pos = 0;
//
// Button Pin definitions
//
const int buttonPinLeft   = 0;      // pin for the Up button
const int buttonPinRight  = 1;    // pin for the Down button
const int buttonPinEnter  = 13;   // pin for the Enter button

int lastButtonPushed = 0;

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


long lastEnterDebounceTime = 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

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");

void setup()
{
//
// Encoder Setup
//
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
// encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE); 
  Serial.begin (9600); Serial.println("START READING");
//
// Button Setup
//
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
//
// Menu Setup
//
  lcd.begin(16, 2);

  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  lcd.setCursor(0,0); 
  lcd.print("Hannes's Menu");
 
  pinMode(ledPin, OUTPUT);



void loop()

Serial.println(encoder0Pos,DEC); // Prints encoder values in Serial monitor
//
// 2 main loops run continuesly
//
  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)                 
}

//
// Encoder voids for left and right turns
//
void doEncoderA(){
  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) { 
      encoder0Pos = encoder0Pos + 1;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  {
    // check channel B to see which way encoder is turning 
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
 
}

void doEncoderB(){
  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) { 
      encoder0Pos = encoder0Pos + 1;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else {
    // check channel B to see which way encoder is turning 
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
}
//
// Print the choosen menu to Display
//
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("Main Menu       ");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("Item1           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("Item1SubItem1");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("Item1SubItem2   ");
  }else if(newMenuItem.getName()=="Item2"){
      lcd.print("Item2           ");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      lcd.print("Item2SubItem1   ");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
      lcd.print("Item2SubItem2   ");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      lcd.print("Item2SubItem3   ");
  }else if(newMenuItem.getName()=="Item3"){
      lcd.print("Item3           ");
  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0); 
  lcd.print("Choosen Menu   ");
  lcd.setCursor(0,1);
  lcd.print(used.item.getName());
}


void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter 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;                 

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

                  // 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);
                  reading = encoder0Pos - 1;

                  // 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; 

//
// Determines wich button is pressed
//

                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;
                                     
                  }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 buttonPinRight:
      menu.moveRight();
      break;     
    case buttonPinLeft:
      menu.moveLeft();
      break;     
  }
 
  lastButtonPushed=0; //reset the lastButtonPushed variable
}




Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 26 Mei 2014, 08:21

Ik heb dit stukje code hieronder aangepast en nu werkt het wat beter Ik bedacht me dat als er een 0 staat is voor de knoppen, moet er ook een 0 staat voor de encoder komen.
Code: Alles selecteren
//
// Determines wich button is pressed
//

                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                    lastButtonPushe[code][/code]d=buttonPinEnter;
                                     
                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

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

                  }else{
                    if (reading = (encoder0Pos = 0)) {   // I added this and it works better now
                    lastButtonPushed=0;
                    }
                  } 


Omdat hij alleen een stap naar links of rechts ging als ik flink aan de encoder draaide, realiseerde ik me ineens dat de encoder sprongen maakt van 4 omhoog of omlaag. Toen ik dit aanpaste (hieronder) werkte dat ook veel stabieler, maar niet perfect, soms draai ik 1 stap aan de encoder en veranderd er niets. Dan zal hij wel 3 omhoog / omlaag zijn gegaan in plaats van 4. Hoe kan ik dat ondervangen?
Code: Alles selecteren
   //Down button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinRight);
                  reading = encoder0Pos + 1 / 4;

en
Code: Alles selecteren
    //Up button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinLeft);
                  reading = encoder0Pos - 1 / 4;


Er is nog een uitdaging... Ik kan scrollen tussen Item1SubItem1 en Item1SubItem2, maar verder terug of vooruit gaat het niet.

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 26 Mei 2014, 23:25

Ik heb de code flink aangepast om het mezelf makkelijk te maken en voor wat ik wil werkt dit.
Het werkt alleen nog niet zo soepel als ik zou willen.
Ik moet soms veel draaien om een menu verder te gaan en soms pakt ie ineens en dan schiet ie een aantal menus door.
Wat kan ik hieraan doen?

Code: Alles selecteren
/*
    Copyright Giuseppe Di Cillo (www.coagula.org)
    Contact: dicillo@coagula.org
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
   void toRoot() {
      setCurrent( &getRoot() );
   }
*/

#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
LiquidCrystal lcd(12, 11, 5, 4, 9, 7);
//
// Encoder Pin definitions
//
// int ledPin = 10;
#define encoder0PinA 2
#define encoder0PinB 3
int encoder0Pos = 30000;
//
// Button Pin definitions
//
const int buttonPinLeft   = 6;      // pin for the Up button
const int buttonPinRight  = 8;    // pin for the Down button
const int buttonPinEnter  = 13;   // pin for the Enter button

int lastButtonPushed = 0;

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


long lastEnterDebounceTime = 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

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1 = MenuItem("menu1");
    MenuItem menu2 = MenuItem("menu2");
    MenuItem menu3 = MenuItem("menu3");
    MenuItem menu4 = MenuItem("menu4");
    MenuItem menu5 = MenuItem("menu5");
    MenuItem menu6 = MenuItem("menu6");
    MenuItem menu7 = MenuItem("menu7");
    MenuItem menu8 = MenuItem("menu8");


void setup()
{
//
// Encoder Setup
//
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
// encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE); 
  Serial.begin (9600); Serial.println("START READING");
//
// Button Setup
//
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
//
// Menu Setup
//
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("Hannes's Menu");
  delay(2000);

  //configure menu
  menu.getRoot().add(menu1);
  menu1.add(menu2);
  menu2.add(menu3);
  menu3.add(menu4);
  menu4.add(menu5);
  menu5.add(menu6);
  menu6.add(menu7);
  menu7.add(menu8);
menu.toRoot();

//  pinMode(ledPin, OUTPUT);


}  // setup()...


void loop()

Serial.println(encoder0Pos,DEC); // Prints encoder values in Serial monitor
//
// 2 main loops run continuesly
//
  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)                 
}

//
// Encoder voids for left and right turns
//
void doEncoderA(){
  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) { 
      encoder0Pos = encoder0Pos + 1 / 0.5;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1 / 0.5;         // CCW
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  {
    // check channel B to see which way encoder is turning 
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1 / 0.5;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1 / 0.5;          // CCW
    }
  }
 
}

void doEncoderB(){
  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) { 
      encoder0Pos = encoder0Pos + 1 / 0.5;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1 / 0.5;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else {
    // check channel B to see which way encoder is turning 
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1 / 0.5;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1 / 0.5;          // CCW
    }
  }
}
//
// Print the choosen menu to Display
//
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("Main Menu       ");
  }else if(newMenuItem.getName()=="menu1"){
      lcd.print("1           ");
  }else if(newMenuItem.getName()=="menu2"){
      lcd.print("2");
  }else if(newMenuItem.getName()=="menu3"){
      lcd.print("3   ");
  }else if(newMenuItem.getName()=="menu4"){
      lcd.print("4           ");
  }else if(newMenuItem.getName()=="menu5"){
      lcd.print("5   ");
  }else if(newMenuItem.getName()=="menu6"){
      lcd.print("6   ");
  }else if(newMenuItem.getName()=="menu7"){
      lcd.print("7   ");
  }else if(newMenuItem.getName()=="menu8"){
      lcd.print("8           ");
  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0); 
  lcd.print("Choosen Menu   ");
  lcd.setCursor(0,1);
  lcd.print(used.item.getName());
}
void(* resetFunc) (void) = 0; //declare reset function @ address 0

void  readButtons(){  //read buttons status
  int readingEnter;
  int readingDown;
  int readingUp;
  int buttonEnterState=LOW;             // the current reading from the Enter 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:
                  readingEnter = 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 (readingEnter != 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=buttonPinEnter;
                   menu.getRoot();
                   lastEnterDebounceTime=millis();
                  }
     
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
         
                  lastButtonEnterState = readingEnter;                 

                 
   //up button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinRight);
                  readingUp = encoder0Pos;
                                               
                  // 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 (readingUp != 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:
                    if (encoder0Pos >= 30002 ) {
                    buttonRightState=buttonPinRight;
                    menu.moveUp();
                    buttonRightState = readingUp;
                   }
                  }
                 
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                 lastButtonRightState = readingUp;     
             
                 
    //down button               
                  // read the state of the switch into a local variable:
                  //reading = digitalRead(buttonPinLeft);
                  readingDown = encoder0Pos;
                                                   
                  // 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 (readingDown != 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:
                    if (encoder0Pos <= 29998 ) {
                    buttonLeftState=buttonPinLeft;
                    menu.moveDown();
                    buttonLeftState = readingDown;
                   
                    }
                  }
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonLeftState = readingDown;


//
// Determines wich button is pressed


                  //records which button has been pressed
                  if (buttonEnterState==HIGH){
                   menu.getRoot();
                  lastButtonPushed=buttonPinEnter;
                                   
                  }else if(buttonRightState==HIGH){
                    menu.moveUp();
                  lastButtonPushed=buttonPinRight;
                  }else{
                    encoder0Pos = 30000;
                 

                  }
                  if(buttonLeftState==HIGH){
                    menu.moveDown();
                  lastButtonPushed=buttonPinLeft;
                  }else{
                    encoder0Pos = 30000;
                  }
         
                  while (encoder0Pos == 30000) {
                  menu.use();
                  }
}
/*
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
  //resetFunc();  //call reset
     //menu.moveLeft();  //back to main
   menu.getRoot();
   
  }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
      //  menu.getCurrent();
    menu.getRoot();
      }
     break;
    case buttonPinRight:
      menu.moveRight();
      break;     
    case buttonPinLeft:
      menu.moveLeft();
      break;
 }
lastButtonPushed=0; //reset the lastButtonPushed variable
}
*/




Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 27 Mei 2014, 13:53

Nog niet heel precies, maar wel veel beter!

Code: Alles selecteren
long debounceDelay = 10;    // the debounce time


in plaats van 500

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Rotary Encoder Menu

Berichtdoor Hanneman » 27 Mei 2014, 17:10

De volledige functionerende code tot zover:

Code: Alles selecteren
    /*
        Original Menu code; Giuseppe Di Cillo (www.coagula.org)
        For Menu Code; Contact: dicillo@coagula.org
       
        Adjusted for use with Incremental Encoder.
        This is an adaptation from a menu working with buttons.
       
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.

        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

    /*
    IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
       void toRoot() {
          setCurrent( &getRoot() );
       }
    */

    #include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
    #include <LiquidCrystal.h>  //this library is included in the Arduino IDE
   
    // LCD Display array
    LiquidCrystal lcd(12, 11, 5, 4, 9, 7);
   
    //
    // Encoder Pin definitions
    //
    #define encoder0PinA 2
    #define encoder0PinB 3
    //
    // Encoder variables
    //
    int encoder0Pos = 30000;   // variable for when u are not using the Encoder
    int reading;               // For the status of the button
    //
    // Button Pin definitions
    //
    int buttonPinLeft;         // pin for the Up button,  now used for Encoder
    int buttonPinRight;        // pin for the Down button,  now used for Encoder
    const int buttonPinEnter  = 8;   // pin for the Enter button
    //
    // Variables for Encoder   
    //
    int lastButtonPushed = 0;         // saves the state after a turn left or right on encoder
    int lastButtonLeftState  = LOW;   // the previous reading from the Left input pin
    int lastButtonRightState = LOW;   // the previous reading from the Right input pin
    int buttonState;                  // the current reading from the input pin
    int lastButtonState = LOW;        // the previous reading from the input pin
    long lastDebounceTime = 0;        // the last time the output pin was toggled
    long debounceDelayButton = 50;    // the debounce time; increase if the output flickers
    long lastLeftDebounceTime  = 0;   // the last time the output pin was toggled
    long lastRightDebounceTime = 0;   // the last time the output pin was toggled
    long debounceDelay = 1;           // the debounce time, important for Encoder
    //
    // LED flashes when button is pushed
    //
    int ledPin = 13;

    //Menu variables
    MenuBackend menu = MenuBackend(menuUsed,menuChanged);
    //initialize menuitems
        MenuItem menu1 = MenuItem("menu1");
        MenuItem menu2 = MenuItem("menu2");
        MenuItem menu3 = MenuItem("menu3");
        MenuItem menu4 = MenuItem("menu4");
        MenuItem menu5 = MenuItem("menu5");
        MenuItem menu6 = MenuItem("menu6");
        MenuItem menu7 = MenuItem("menu7");
        MenuItem menu8 = MenuItem("menu8");


    void setup()
    {
    pinMode(ledPin, OUTPUT);   // For the LED     
    //
    // Encoder Setup
    //
    pinMode(encoder0PinA, INPUT);
    pinMode(encoder0PinB, INPUT);
    // encoder pin on interrupt 0 (pin 2)
    attachInterrupt(0, doEncoderA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
    attachInterrupt(1, doEncoderB, CHANGE);
    //
    // Prints this to serial monitor
    Serial.begin (9600); Serial.println("START READING");
    //
    // Button Setup
    //
    pinMode(buttonPinEnter, INPUT);
    digitalWrite(buttonPinEnter, HIGH); // Activates Pull-Up for Encoder button
    //
    // LCD Menu Setup
    //
    lcd.begin(16, 2);
    lcd.setCursor(0,0);
    lcd.print("Hannes's Menu");
    delay(2000);

      //configure menu
    menu.getRoot().add(menu1);
      menu1.add(menu2);
      menu2.add(menu3);
      menu3.add(menu4);
      menu4.add(menu5);
      menu5.add(menu6);
      menu6.add(menu7);
      menu7.add(menu8);
    menu.toRoot();

    } 
   
    void loop()
    {
    Serial.println(encoder0Pos,DEC); // Prints encoder values in Serial monitor
    //
    // main loop runs continuesly
    //
    readButtons(); 
    }

    //
    // Encoder voids for left and right turns
    //
    void doEncoderA(){
      // look for a low-to-high on channel A
      if (digitalRead(encoder0PinA) == HIGH) {
        // check channel B to see which way encoder is turning
        if (digitalRead(encoder0PinB) == LOW) {
          encoder0Pos = encoder0Pos + 5;         // CW
        }
        else {
          encoder0Pos = encoder0Pos - 5;         // CCW
        }
      }
      else   // must be a high-to-low edge on channel A                                       
      {
        // check channel B to see which way encoder is turning
        if (digitalRead(encoder0PinB) == HIGH) {   
          encoder0Pos = encoder0Pos + 5;          // CW
        }
        else {
          encoder0Pos = encoder0Pos - 5;          // CCW
        }
      }
     
    }

    void doEncoderB(){
      // look for a low-to-high on channel B
      if (digitalRead(encoder0PinB) == HIGH) {   
       // check channel A to see which way encoder is turning
        if (digitalRead(encoder0PinA) == HIGH) {
          encoder0Pos = encoder0Pos + 5;         // CW increments encoder0Pos value with 5
        }
        else {
          encoder0Pos = encoder0Pos - 5;         // CCW
        }
      }
      // Look for a high-to-low on channel B
      else {
        // check channel B to see which way encoder is turning
        if (digitalRead(encoder0PinA) == LOW) {   
          encoder0Pos = encoder0Pos + 5;          // CW
        }
        else {
          encoder0Pos = encoder0Pos - 5;          // CCW
        }
      }
    }
    //
    // Print the choosen menu to Display
    //
    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("Main Menu       ");
      }else if(newMenuItem.getName()=="menu1"){
          lcd.print("1           ");
      }else if(newMenuItem.getName()=="menu2"){
          lcd.print("2");
      }else if(newMenuItem.getName()=="menu3"){
          lcd.print("3   ");
      }else if(newMenuItem.getName()=="menu4"){
          lcd.print("4           ");
      }else if(newMenuItem.getName()=="menu5"){
          lcd.print("5   ");
      }else if(newMenuItem.getName()=="menu6"){
          lcd.print("6   ");
      }else if(newMenuItem.getName()=="menu7"){
          lcd.print("7   ");
      }else if(newMenuItem.getName()=="menu8"){
          lcd.print("8           ");
      }
    }
    //
    // When the button is pushed it, blinks the LED, sets the Current menu and shows it on the Display
    //
    void menuUsed(MenuUseEvent used){
      lcd.setCursor(0,0);
      lcd.print("Current Menu   ");
      lcd.setCursor(0,1);
      lcd.print(used.item.getName());
    }

    void  readButtons(){             //read buttons status
      int readingDown;               // For encoder
      int readingUp;                 // For encoder
      int buttonLeftState=LOW;       // the current reading from the input pin
      int buttonRightState=LOW;      // the current reading from the input pin
    //
    // Encoder Button
    //
    // read the state of the switch into a local variable:
    reading = digitalRead(buttonPinEnter);

    // check to see if you just pressed the 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 != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
    }
 
    if ((millis() - lastDebounceTime) > debounceDelayButton) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
    }     

    digitalWrite(ledPin, !buttonState); // Pull up resistor is active, when buttonState is NOT high it saves the Current menu
 
      if (buttonState==LOW){
        menu.use();
    }         
         
    lastButtonState = reading;
    //
    // Up button
    //
    readingUp = encoder0Pos; // read the state of the switch into a local variable:
    // 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 (readingUp != 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:
       if (encoder0Pos > 30004 ) {
           buttonRightState=buttonPinRight;
             menu.moveUp();
               buttonRightState = readingUp;
                 }
    }
    // save the reading.  Next time through the loop,
    // it'll be the lastButtonState:
    lastButtonRightState = readingUp;     
    //
    // Down button               
    //
    // read the state of the switch into a local variable:
    readingDown = encoder0Pos;
    // 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 (readingDown != 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:
    if (encoder0Pos < 29997 ) {
      buttonLeftState=buttonPinLeft;
        menu.moveDown();
          buttonLeftState = readingDown;
            }
    }
   
    // save the reading.  Next time through the loop,
    // it'll be the lastButtonState:
    lastButtonLeftState = readingDown;
    //
    // Determines wich button is pressed
    //
    if(buttonRightState==HIGH){
      lastButtonPushed=buttonPinRight;
        }else{
          encoder0Pos = 30000;
          }
            if(buttonLeftState==HIGH){
              lastButtonPushed=buttonPinLeft;
                }else{
                  encoder0Pos = 30000;
                    }
     }

Volgende

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 10 gasten