I have found this question on different forums, but never did I find a straight and correct answer.
I hope it can be solved on this forum.
There are several device that use a Encoder to browse through a menu.
To me it seems logical that they use a Finite state machine in their code.
I have made a Finite Stae Machine that can be controlled through push buttons, but I cannot get it to work using a Rotary Encoder.
I have found a code for the encoder and I have a fsm code, but I do not know how to combine them to get it working.
The button on the encoder can be programmed like you would with a regular push button.
It would be great if it would work like this:
Main menu:
Leds off, push the encoder button -> menu RED
from menu RED while turning encoder, flip through menus; RED, GREEN, BLUE.
With a push on the Encoder Button, back to main menu
The code of the FSM:
//
// 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;
}
}
The Encoder code found on this website: http://www.hobbytronics.co.uk/arduino-tutorial6-rotary-encoder:
/*
** 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:
Aansluitschema LCD Display: