Encoder, FSM, Menus

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

Encoder, FSM, Menus

Berichtdoor Hanneman » 30 Mei 2014, 22:24

Ik heb het voor mekaar gekregen om met een Incremental Encoder door menustaten heen te scrollen en te kunnen bevestigen met de knop op de encoder.
Dit met behulp van de MenuBackend library en een handige Encoder code.

Als ik het resultaat heb dat ik wil zal ik een uitgebreid bestand posten met alle info erin. Diverse websites en codes die behulpzaam waren, instructies hoe je het zelf kunt maken etc.

Maar ik zit nu eerst met een uitdaging!

Als ik aan de encoder draai, kan ik door menus heen scrollen of ik kan waarden verhogen of verlagen.
Wat mij niet lukt is bijv. het volgende.

Stel je hebt 3 opties in 1 menu. Je kiest door aan de encoder te draaien optie 1. Binnen optie 1 kan je door aan dezelfde encoder te draaien een led feller of minder fel laten branden.

Hoe doe je dit?

Bij mij veranderd ie en de waarde en scrollt hij door het menu tegelijkertijd.

Advertisement

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

Re: Encoder, FSM, Menus

Berichtdoor shooter » 30 Mei 2014, 23:40

je hebt eigenlijk maar een drukknop, waarmee je dus een keuze bevestigd, maar je kunt niet terug,
dus andere manier bijv.
als je de knop indrukt CW draaien is verder, als je de knop indrukt en dan CCW draaien is terug.

je kunt ook gewoon de optie kiezen dan draaien en weer terug

ik zal morgen eens kijken wat je gemaakt hebt.
paul deelen
shooter@home.nl

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 31 Mei 2014, 07:38

ik kan een bevestiging doen met een druk op de knop en bijv terug door de knop 2 sec vast te houden.
Hoe ik de encoder zover krijg dat ie niet in meerdere staten tegelijk de staten beinvloed dat is moeilijker en lukt me nog niet.

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

Re: Encoder, FSM, Menus

Berichtdoor shooter » 31 Mei 2014, 18:56

http://playground.arduino.cc/Main/RotaryEncoders

ook deze is in het engels, als dat een probleem is even zeggen dan wordt het vertaald.

je moet alleen reageren als de knop naar bedient wordt, en niet als deze aan is. dus alleen bij een flank (een muis werkt ook zo, daar worden beide flanken gezien, en afhankelijk wat je doet wordt er iets anders gedaan.

http://playground.arduino.cc/Code/Menu
hier kun je zien wat er mogelijk is in een menu
paul deelen
shooter@home.nl

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 01 Jun 2014, 22:08

Met de backendmenu library kom ik er niet uit.

Ik had een nested switch structuur gemaakt, maar dat werkte ook niet zoals ik wilde.

Ik had een test gedaan met arrays en dat lijkt veelbelovend, maar het lukt ook nog niet.

De bedoeling is met 1 korte druk op de knop bevestigen en met een lange druk op de knop teruggaan.
van kiezen uit 3 modi, naar instellingen binnen die modi en terug is de bedoeling.

Code: Alles selecteren
#include <SPI.h>              // required library for use of 74HC595 chip
#include <LiquidCrystal.h>    // lcd display library
#include "IRremote.h"

LiquidCrystal lcd(10);        // initialize the library with the number of the sspin
                              //(or the latch pin of the 74HC595)
//
// Encoder
//
#define encoder0PinA 2
#define encoder0PinB 3
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int val;
 int n = LOW;
 //
 // Encoder Button
 //
#define buttonPin    4
#define debounce 20 // ms debounce period to prevent flickering when pressing or releasing the button
#define holdTime 2000 // ms hold period: how long to wait for press+hold event
int buttonVal = 0; // value read from button
int buttonLast = 0; // buffered value of the button's previous state
long btnDnTime; // time the button was pressed down
long btnUpTime; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
//
// Switch definition
//
int modes;
//
// Mode definitions and variables
//

#define stroboscopemode   0
#define custommode        1
#define prefixedmode      2

  int myModes[4] = {0, 1, 2}; // array of Modes
  int w;                  // w variable is coupled in Setup to myModes array of Modes
//
// Settings inside modes definitions
//
#define stroboscopespeed  3
#define stroboscopeRED    4
#define stroboscopeGREEN  5
#define stroboscopeBLUE   6

  int myStrobeSettings[5] = {3, 4, 5, 6}; // array of Stroboscope Settings
  int x;                                  // x variable is coupled in Setup to myStrobeSettings array of Stroboscope Settings
 
#define customRED         7
#define customGREEN       8
#define customBLUE        9

  int myCustomSettings[4] = {7, 8, 9}; // array of Custom Settings
  int y;                               // y variable is coupled in Setup to myCustomSettings array of Custom Settings
 

#define lightpurple      10
#define mediumpurple     11

  int myPrefixedSettings[3] = {10, 11}; // array of Prefixed Settings
  int z;                                // z variable is coupled in Setup to myPrefixedSettings array of Prefixed Settings

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);

    pinMode (encoder0PinA,INPUT);
    pinMode (encoder0PinB,INPUT);
   
    pinMode(buttonPin, INPUT);
    digitalWrite(buttonPin, HIGH );

lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("Mood Light");
delay(1000);
//
// Arrays
w = myModes[4];              // array of Modes(custom, stroboscope, random) coupled to variable x
x = myStrobeSettings[5];
y = myCustomSettings[4];
z = myPrefixedSettings[3];

}                       

void loop() {
// put your main code here, to run repeatedly:
           
 mainmenu();
}

void  mainmenu() {
//
// Encoder
// 
n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
      if (digitalRead(encoder0PinB) == LOW) {
       // encoder0Pos--;
        w = w - 1;
          } else {
       //encoder0Pos++;
        w = w + 1;
         }
   // Serial.print (encoder0Pos);
   // Serial.print ("/");
    }
  encoder0PinALast = n;
  modes = w; // Take advantage of the array through variable w
  // Helaas gaat ie door aan de encoder te draaien door alle staten heen en niet alleen die van de w array

//
// Encoder Button
//
// Read the state of the button
buttonVal = digitalRead(buttonPin);

// Test for button pressed and store the down time
if (buttonVal == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce))
{
btnDnTime = millis();
}

// Test for button release and store the up time
if (buttonVal == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce))
{
if (ignoreUp == false)

Hier de code om te bevestigen

else ignoreUp = false;
btnUpTime = millis();
}

// Test for button held down for longer than the hold time
if (buttonVal == LOW && (millis() - btnDnTime) > long(holdTime))
{
 
Hier de code om een menu terug te gaan

ignoreUp = true;
btnDnTime = millis();
}

buttonLast = buttonVal;


 
  switch(modes) {

    case stroboscopemode:
      lcd.setCursor(0, 0);
      lcd.print("Stroboscope Mode");
      lcd.setCursor(0, 1);
      lcd.print("PRESS |<< !!!   ");
           
      break;
       
          case stroboscopespeed:
            lcd.setCursor(0, 0);
            lcd.print("Stroboscope Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Speed");
           
            break;
           
          case stroboscopeRED:
            lcd.setCursor(0, 0);
            lcd.print("Stroboscope Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Red LED Brightness");
           
            break;
           
          case stroboscopeGREEN:
            lcd.setCursor(0, 0);
            lcd.print("Stroboscope Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Green LED Brightness");
           
            break;
           
          case stroboscopeBLUE:
            lcd.setCursor(0, 0);
            lcd.print("Stroboscope Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Blue LED Brightness");
           
            break;
           
   case custommode:
      lcd.setCursor(0, 0);
      lcd.print("Custom Mode     ");
      lcd.setCursor(0, 1);
      lcd.print("PRESS |<< OR >>|");
         
      break;
     
      case customRED:
            lcd.setCursor(0, 0);
            lcd.print("Custom Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Red LED Brightness");
     
            break;
           
          case customGREEN:
            lcd.setCursor(0, 0);
            lcd.print("Custom Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Green LED Brightness");
           
            break;
           
          case customBLUE:
            lcd.setCursor(0, 0);
            lcd.print("Custom Mode");
            lcd.setCursor(0, 1);
            lcd.print("Set Blue LED Brightness");
           
            break;
           
   case prefixedmode:
      lcd.setCursor(0, 0);
      lcd.print("Prefixed Mode   ");
      lcd.setCursor(0, 1);
      lcd.print("PRESS |<< !!!   ");
             
      break;
         
          case lightpurple:
            lcd.setCursor(0, 0);
            lcd.print("Prefixed Mode   ");
            lcd.setCursor(0, 1);
            lcd.print("Light Purple    ");
           
            break;
           
          case mediumpurple:
          printline(0, "Prefixed Mode");
          printline(1, "Medium purple");
         
          /*
            lcd.setCursor(0, 0);
            lcd.print("Prefixed Mode   ");
            lcd.setCursor(0, 1);
            lcd.print("Medium Purple   ");
            */
            break;
     
        default:

       // translateIR();
       
        break;
  }

}

void printLine(uint8_t regel, char * text) {
  lcd2.setCursor(0, regel);
  lcd2.print("                ");
  lcd2.setCursor(0, regel);
  lcd2.print(text);
}

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 02 Jun 2014, 07:33

Toch nog ff met menu backend proberen, met die push button code gaat dat misschien wel lukken.

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 03 Jun 2014, 09:43

Een simpel werkend menu lukt in ieder geval al wel na wat aanpassingen aan de code. Ik heb gebruik gemaakt van een lcd display 16x2 met een 74HC595 chip.
Een mp3 afstandsbediening, maar je kunt ook toetsen (A,W,S,D,E, ENTER) gebruiken in het seriële communicatie venster.

Dit zijn de websites waar ik mijn informatie en libraries vandaan heb:
http://playground.arduino.cc/Main/LiquidCrystal
http://arduino-info.wikispaces.com/IR-RemoteControl
http://playground.arduino.cc/Code/Menu

Met deze info moet het me haast wel gaan lukken :D

Ik ben begonnen met een afstandsbedining. Dat is wat makkelijker dan een Encoder.

en de code
Code: Alles selecteren
    /*
    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 <SPI.h>
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
#include "IRremote.h"
/*
   This is the structure of the modelled menu
   
   Settings
      Pin
      Debug
   Options
      Delay (D)
         100 ms
         200 ms
         300 ms
         400 ms
*/
LiquidCrystal lcd(10);

int receiver = 8; // pin 1 of IR receiver to Arduino digital pin 11
//IRrecv irrecv(receiver);           // create instance of 'irrecv'
IRrecv irrecv(receiver);           // create instance of 'irrecv'
decode_results results;            // create instance of 'decode_results'

#define REMOTEALERTPIN 12

//this controls the menu backend and the event generation
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
   //beneath is list of menu items needed to build the menu
   MenuItem settings = MenuItem("Settings       ");
      MenuItem pin = MenuItem("Pin             ");
      MenuItem debug = MenuItem("Debug           ");
   MenuItem options = MenuItem("Options               ");
      MenuItem setDelay = MenuItem("Delay    ",'D');
         MenuItem d100 = MenuItem("100 ms");
         MenuItem d200 = MenuItem("200 ms");
         MenuItem d300 = MenuItem("300 ms");
         MenuItem d400 = MenuItem("400 ms");
   
//this function builds the menu and connects the correct items together
void menuSetup()
{
 

        //add the file menu to the menu root
   menu.getRoot().add(settings);
      //setup the settings menu item
      settings.addRight(pin);
         //we want looping both up and down
         pin.addBefore(debug);
         pin.addAfter(debug);
         debug.addAfter(pin);
         //we want a left movement to pint to settings from anywhere
         debug.addLeft(settings);
         pin.addLeft(settings);
   settings.addBefore(options);
   settings.addAfter(options);
      options.addRight(setDelay);
         setDelay.addLeft(options);
         setDelay.addRight(d100);
            d100.addBefore(d100); //loop to d400
            d100.addAfter(d200);
            d200.addAfter(d300);
            d300.addAfter(d400);
            d400.addAfter(d100); //loop back to d100
            //we want left to always be bak to delay
            d100.addLeft(setDelay);
            d200.addLeft(setDelay);
            d300.addLeft(setDelay);
            d400.addLeft(setDelay);
   options.addAfter(settings);  //settings was originally options but then it would get stuck at options
}

/*
   This is an important function
   Here all use events are handled
   
   This is where you define a behaviour for a menu item
*/
void menuUseEvent(MenuUseEvent used)
{
     lcd.setCursor(0,0);
     lcd.print("Menu use        ");
     lcd.setCursor(0,1);
     lcd.print(used.item.getName());
   if (used.item == setDelay) //comparison agains a known item
   {
      Serial.println("menuUseEvent found Dealy (D)");
   }
}

/*
   This is an important function
   Here we get a notification whenever the user changes the menu
   That is, when the menu is navigated
*/
void menuChangeEvent(MenuChangeEvent changed)
{
   lcd.setCursor(0,0);
   lcd.print("Menu change     ");
   lcd.setCursor(0,1);
   lcd.print(changed.from.getName());
   lcd.print(" ");
   lcd.setCursor(0,1);
   lcd.print(changed.to.getName());
}

void setup()
{
        irrecv.enableIRIn(); // Start the receiver
   Serial.begin(9600);
   
   menuSetup();
   Serial.println("Starting navigation:\r\nUp: w   Down: seft: a   Right: d   Use: e");

 lcd.begin(16, 2);
 
 lcd.setCursor(0,0);
 lcd.print("Menu System test");
 lcd.setCursor(0,1);
 lcd.print("Press DownButton");
}

void loop()
{
 
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
//    Serial.println(results.value, HEX);  UN Comment to see raw values
    translateIR();
    irrecv.resume(); // receive the next value
   
  }
   if (Serial.available()) {
      byte read = Serial.read();
      switch (read) {
         case 'w': menu.moveUp(); break;
         case 's': menu.moveDown(); break;
         case 'd': menu.moveRight(); break;
         case 'a': menu.moveLeft(); break;
         case 'e': menu.use(); break;
      }
   }
}
void translateIR() // takes action based on IR code received
// describing Car MP3 IR codes
{
   
lcd.setCursor(0,1); //set the start position for lcd printing to the second row
switch(results.value)

  {

  case 0xFF18E7:
  Serial.print("2. menu up");
  // lcd.print("Green LED More  ");
  menu.moveUp();
  digitalWrite(REMOTEALERTPIN, LOW);
    break;

  case 0xFF7A85: 
  Serial.print("3");
  // lcd.print("Blue LED More   ");
  //  blueamount = blueamount +10;
  digitalWrite(REMOTEALERTPIN, LOW);
    break;

  case 0xFF10EF: 
  Serial.print("4. menu left");
  // lcd.print("Red LED less    "); 
  menu.moveLeft();
  digitalWrite(REMOTEALERTPIN, LOW);
    break;

  case 0xFF38C7: 
  Serial.print("5. menu use");
  // lcd.print("Green LED less  ");
  menu.use();
  digitalWrite(REMOTEALERTPIN, LOW);
    break;

  case 0xFF5AA5: 
  Serial.print("6. menu right");
  // lcd.print("Blue LED less   "); 
  // blueamount = blueamount -10;
  menu.moveRight();
  digitalWrite(REMOTEALERTPIN, LOW);
    break;

  case 0xFF4AB5: 
    Serial.print("8. menu down");
    menu.moveDown();
    digitalWrite(REMOTEALERTPIN, LOW);
    break;


  default:
  Serial.print("    Try again   "); // prints try again message when buttonpush didnt come through right
  digitalWrite(REMOTEALERTPIN, HIGH); //sets a red led on when button didnt take
  break;
  }
  delay(500);
  }
 

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Encoder, FSM, Menus

Berichtdoor nicoverduin » 03 Jun 2014, 13:59

Gaat de repeat inmiddels goed met IRremote? Ik heb ruim 1 1/2 jaar terug ermee gewerkt, en toen gaf die repeat (knop ingedrukt houden) nogal wat problemen. Heb toen eea zitten aanpassen (:) What's new)
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 04 Jun 2014, 10:50

Yes, het menu doet eindelijk wat het moet doen! :D :D :D

Op 1 klein dingetje na :x

Als ik op de Rechts knop druk gaat hij van stroboscoop modus naar Blue Led on/ off (blueon). Terwijl ik toch duidelijk opgegeven heb dat ik naar Flash Speed (strobespeed) wil :roll:

Whats wrong here?

Code: Alles selecteren
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
   //beneath is list of menu items needed to build the menu
   MenuItem custommode =            MenuItem("Custom Mode     ");
           MenuItem redbright =            MenuItem("Red Brightness  ");
           MenuItem greenbright =           MenuItem("Green Brightness");
      MenuItem bluebright =           MenuItem("Blue Brightness ");
   MenuItem strobomode =            MenuItem("Stroboscope Mode");
                MenuItem strobespeed =           MenuItem("Flash Speed     ");
                MenuItem redon =                  MenuItem("Red LED On/Off  ");
           MenuItem greenon =                MenuItem("Green LED On/Off");
      MenuItem blueon =                 MenuItem("Blue LED  On/Off");
        MenuItem _randommode =           MenuItem("Random Mode     ");
                MenuItem randomspeed =           MenuItem("Change Speed    ");

void menuSetup()
{
   //add the file menu to the menu root
   menu.getRoot().add(custommode);
      //setup the custommode menu item
                  custommode.addRight(redbright);
              //we want looping both up and down
         redbright.addBefore(bluebright);
                        redbright.addAfter(greenbright);
                        greenbright.addBefore(redbright);
         greenbright.addAfter(bluebright);
                        bluebright.addBefore(greenbright);
                        bluebright.addAfter(redbright);
                        //we want a left movement to pin to custommode from anywhere
         greenbright.addLeft(custommode);
         redbright.addLeft(custommode);
                        bluebright.addLeft(custommode);
      custommode.addBefore(_randommode);  // I HAD to use an underscore _ before randommode or I would get an
                custommode.addAfter(strobomode);     // Error message
                    strobomode.addRight(strobespeed);
                        strobespeed.addAfter(redon);
                        strobespeed.addBefore(blueon);
                        redon.addBefore(strobespeed);
                        redon.addAfter(greenon);
                        greenon.addBefore(redon);
                        greenon.addAfter(blueon);                      
                        blueon.addBefore(greenon);
                        blueon.addAfter(strobespeed);                   
                        strobespeed.addLeft(strobomode);
                        redon.addLeft(strobomode);
                        greenon.addLeft(strobomode);
                        blueon.addLeft(strobomode);
                strobomode.addBefore(custommode);
                strobomode.addAfter(_randommode);
                _randommode.addRight(randomspeed);
                      randomspeed.addLeft(_randommode);
                      randomspeed.addBefore(randomspeed);
                      randomspeed.addAfter(randomspeed);
                _randommode.addBefore(strobomode);
                _randommode.addAfter(custommode);
}

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

Re: Encoder, FSM, Menus

Berichtdoor Hanneman » 10 Jun 2014, 12:26

Het is al duidelijk.

De white.addLeft(presetmode) moet onderaanstaan en niet bovenaan.
Alle .addBefores kunnen er trouwens uitgelaten worden.

Dan doet ie het wel zoals het moet ;)

Met dank Alexander Brevig, de ontwerper van de MenuBackend Library.

Nederlandstalig instructie volgt nog....

Volgende

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 29 gasten