Rotačný enkodér: Rozdiel medzi revíziami
Z SensorWiki
(→Algoritmus a program) |
(→Overenie) |
||
(22 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 34: | Riadok 34: | ||
<tabs> | <tabs> | ||
<tab name="AVR C-code"><source lang="arduino" style="background: LightYellow;"> | <tab name="AVR C-code"><source lang="arduino" style="background: LightYellow;"> | ||
+ | |||
#include <avr/io.h> | #include <avr/io.h> | ||
#include <avr/interrupt.h> | #include <avr/interrupt.h> | ||
#include <util/delay.h> | #include <util/delay.h> | ||
+ | |||
#define clk_pin PB3 | #define clk_pin PB3 | ||
Riadok 42: | Riadok 44: | ||
#define swt_pin PB5 | #define swt_pin PB5 | ||
+ | volatile int poutput; | ||
volatile int counter = 0; | volatile int counter = 0; | ||
volatile bool buttonPressed = false; | volatile bool buttonPressed = false; | ||
+ | |||
enum MenuState { MENU_MAIN, MENU_VALUE }; | enum MenuState { MENU_MAIN, MENU_VALUE }; | ||
volatile MenuState menuState = MENU_MAIN; | volatile MenuState menuState = MENU_MAIN; | ||
− | void initLCD() { | + | |
+ | void initLCD() | ||
+ | { | ||
+ | |||
DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); | DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); | ||
+ | |||
+ | |||
PORTD = 0x20; | PORTD = 0x20; | ||
PORTD |= 0x04; | PORTD |= 0x04; | ||
PORTD &= ~0x04; | PORTD &= ~0x04; | ||
+ | |||
+ | |||
sendLCDCommand(0x28); | sendLCDCommand(0x28); | ||
+ | |||
+ | |||
sendLCDCommand(0x0C); | sendLCDCommand(0x0C); | ||
+ | |||
sendLCDCommand(0x01); | sendLCDCommand(0x01); | ||
− | DDRB &= ~ | + | |
+ | |||
+ | DDRB &= ~(1 << clk_pin) & ~(1 << data_pin) & ~(1 << swt_pin); | ||
PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); | PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); | ||
+ | |||
+ | |||
+ | poutput = PINB & (1 << clk_pin); | ||
} | } | ||
− | void sendLCDCommand(uint8_t command) { | + | |
+ | void sendLCDCommand(uint8_t command) | ||
+ | { | ||
PORTD = (command & 0xF0); | PORTD = (command & 0xF0); | ||
PORTD &= ~(1 << PD4); | PORTD &= ~(1 << PD4); | ||
Riadok 66: | Riadok 87: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
+ | |||
PORTD = ((command << 4) & 0xF0); | PORTD = ((command << 4) & 0xF0); | ||
PORTD &= ~(1 << PD4); | PORTD &= ~(1 << PD4); | ||
Riadok 71: | Riadok 93: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
+ | |||
_delay_us(40); | _delay_us(40); | ||
} | } | ||
− | void sendLCDData(uint8_t data) { | + | |
+ | void sendLCDData(uint8_t data) | ||
+ | { | ||
PORTD = (data & 0xF0); | PORTD = (data & 0xF0); | ||
PORTD |= (1 << PD4); | PORTD |= (1 << PD4); | ||
Riadok 80: | Riadok 105: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
+ | |||
PORTD = ((data << 4) & 0xF0); | PORTD = ((data << 4) & 0xF0); | ||
PORTD |= (1 << PD4); | PORTD |= (1 << PD4); | ||
Riadok 85: | Riadok 111: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
+ | |||
_delay_us(40); | _delay_us(40); | ||
} | } | ||
− | void updateCounterDisplay() { | + | |
− | sendLCDCommand(0x80 | 0x40); | + | void updateCounterDisplay() |
+ | { | ||
+ | sendLCDCommand(0x80 | 0x40); | ||
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('o'); | sendLCDData('o'); | ||
Riadok 99: | Riadok 128: | ||
sendLCDData('n'); | sendLCDData('n'); | ||
sendLCDData(':'); | sendLCDData(':'); | ||
− | sendLCDCommand(0x80 | 0x40 | 0x09); | + | |
+ | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
Riadok 108: | Riadok 138: | ||
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
− | sendLCDCommand(0x80 | 0x40 | 0x09); | + | |
+ | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData((counter / 100) + '0'); | sendLCDData((counter / 100) + '0'); | ||
sendLCDData(((counter / 10) % 10) + '0'); | sendLCDData(((counter / 10) % 10) + '0'); | ||
Riadok 114: | Riadok 145: | ||
} | } | ||
− | void handleMainMenu() { | + | |
− | if ((PINB & (1 << clk_pin)) != | + | void handleMainMenu() |
− | if ((PINB & (1 << data_pin)) != | + | { |
+ | if ((PINB & (1 << clk_pin)) != poutput) | ||
+ | { | ||
+ | if ((PINB & (1 << data_pin)) != poutput) | ||
+ | { | ||
counter++; | counter++; | ||
− | } else { | + | } |
+ | else | ||
+ | { | ||
counter--; | counter--; | ||
} | } | ||
Riadok 124: | Riadok 161: | ||
} | } | ||
− | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | + | poutput = PINB & (1 << clk_pin); |
+ | |||
+ | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) | ||
+ | { | ||
buttonPressed = true; | buttonPressed = true; | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('r'); | sendLCDData('r'); | ||
Riadok 135: | Riadok 175: | ||
sendLCDData('d'); | sendLCDData('d'); | ||
_delay_ms(500); | _delay_ms(500); | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
menuState = MENU_VALUE; | menuState = MENU_VALUE; | ||
updateCounterDisplay(); | updateCounterDisplay(); | ||
− | } else if ((PINB & (1 << swt_pin)) != 0) { | + | } |
+ | else if ((PINB & (1 << swt_pin)) != 0) | ||
+ | { | ||
buttonPressed = false; | buttonPressed = false; | ||
} | } | ||
} | } | ||
− | void handleValueMenu() { | + | |
− | if ((PINB & (1 << clk_pin)) != | + | void handleValueMenu() |
− | if ((PINB & (1 << data_pin)) != | + | { |
+ | if ((PINB & (1 << clk_pin)) != poutput) | ||
+ | { | ||
+ | if ((PINB & (1 << data_pin)) != poutput) | ||
+ | { | ||
counter++; | counter++; | ||
− | } else { | + | } |
+ | else | ||
+ | { | ||
counter--; | counter--; | ||
} | } | ||
− | sendLCDCommand(0x80 | 0x40); | + | sendLCDCommand(0x80 | 0x40); |
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('o'); | sendLCDData('o'); | ||
Riadok 160: | Riadok 208: | ||
sendLCDData('n'); | sendLCDData('n'); | ||
sendLCDData(':'); | sendLCDData(':'); | ||
− | sendLCDCommand(0x80 | 0x40 | 0x09); | + | |
+ | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData((counter / 100) + '0'); | sendLCDData((counter / 100) + '0'); | ||
sendLCDData(((counter / 10) % 10) + '0'); | sendLCDData(((counter / 10) % 10) + '0'); | ||
Riadok 166: | Riadok 215: | ||
} | } | ||
− | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | + | poutput = PINB & (1 << clk_pin); |
+ | |||
+ | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) | ||
+ | { | ||
menuState = MENU_MAIN; | menuState = MENU_MAIN; | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
sendLCDData('V'); | sendLCDData('V'); | ||
sendLCDData('a'); | sendLCDData('a'); | ||
Riadok 182: | Riadok 234: | ||
sendLCDData('e'); | sendLCDData('e'); | ||
sendLCDData('d'); | sendLCDData('d'); | ||
− | sendLCDCommand(0x80 | 0x40); | + | sendLCDCommand(0x80 | 0x40); |
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
Riadok 216: | Riadok 268: | ||
sendLCDData(' '); | sendLCDData(' '); | ||
updateCounterDisplay(); | updateCounterDisplay(); | ||
− | } else if ((PINB & (1 << swt_pin)) != 0) { | + | } |
+ | else if ((PINB & (1 << swt_pin)) != 0) | ||
+ | { | ||
buttonPressed = false; | buttonPressed = false; | ||
} | } | ||
} | } | ||
− | int main(void) { | + | // Hlavní smyčka programu |
+ | int main(void) | ||
+ | { | ||
initLCD(); | initLCD(); | ||
− | sei(); | + | sei(); |
− | while (1) { | + | while (1) |
− | switch (menuState) { | + | { |
+ | switch (menuState) | ||
+ | { | ||
case MENU_MAIN: | case MENU_MAIN: | ||
handleMainMenu(); | handleMainMenu(); | ||
Riadok 239: | Riadok 297: | ||
</source></tab> | </source></tab> | ||
− | <tab name=" | + | <tab name="Arduino"><source lang="c++" style="background: LightYellow;"> |
− | #include < | + | #include <LiquidCrystal.h> |
+ | |||
+ | const int clk = 3; | ||
+ | const int data = 4; | ||
+ | const int swt = 5; | ||
+ | |||
+ | int poutput; | ||
+ | int counter = 0; | ||
+ | bool buttonPressed = false; | ||
+ | |||
+ | enum MenuState { MENU_MAIN, MENU_VALUE }; | ||
+ | MenuState menuState = MENU_MAIN; | ||
+ | |||
+ | LiquidCrystal lcd(0, 1, 8, 9, 10, 11); | ||
+ | |||
+ | void setup() { | ||
+ | lcd.begin(16, 2); | ||
+ | lcd.print(" Rotary Encoder "); | ||
+ | lcd.setCursor(0, 1); | ||
+ | lcd.print(" With Arduino "); | ||
+ | delay(2000); | ||
+ | lcd.clear(); | ||
+ | |||
+ | pinMode(clk, INPUT); | ||
+ | pinMode(data, INPUT); | ||
+ | pinMode(swt, INPUT_PULLUP); | ||
+ | |||
+ | poutput = digitalRead(clk); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | switch (menuState) { | ||
+ | case MENU_MAIN: | ||
+ | handleMainMenu(); | ||
+ | break; | ||
+ | case MENU_VALUE: | ||
+ | handleValueMenu(); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void handleMainMenu() { | ||
+ | if (digitalRead(clk) != poutput) { | ||
+ | if (digitalRead(data) != poutput) { | ||
+ | counter++; | ||
+ | } else { | ||
+ | counter--; | ||
+ | } | ||
+ | updateCounterDisplay(); | ||
+ | } | ||
+ | |||
+ | poutput = digitalRead(clk); | ||
+ | |||
+ | if (digitalRead(swt) == LOW && !buttonPressed) { | ||
+ | buttonPressed = true; | ||
+ | lcd.clear(); | ||
+ | lcd.print("Pressed"); | ||
+ | delay(500); | ||
+ | lcd.clear(); | ||
+ | menuState = MENU_VALUE; | ||
+ | updateCounterDisplay(); | ||
+ | } else if (digitalRead(swt) == HIGH) { | ||
+ | buttonPressed = false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void handleValueMenu() { | ||
+ | if (digitalRead(clk) != poutput) { | ||
+ | if (digitalRead(data) != poutput) { | ||
+ | counter++; | ||
+ | } else { | ||
+ | counter--; | ||
+ | } | ||
+ | lcd.setCursor(0, 1); | ||
+ | lcd.print("Position: "); | ||
+ | lcd.print(counter); | ||
+ | |||
+ | lcd.setCursor(9, 1); | ||
+ | lcd.print(" "); // Clear the previous position | ||
+ | |||
+ | lcd.setCursor(9, 1); | ||
+ | lcd.print(counter); | ||
+ | } | ||
+ | |||
+ | poutput = digitalRead(clk); | ||
+ | |||
+ | if (digitalRead(swt) == LOW && !buttonPressed) { | ||
+ | menuState = MENU_MAIN; | ||
+ | lcd.clear(); | ||
+ | lcd.print("Value entered:"); | ||
+ | lcd.setCursor(0, 1); | ||
+ | lcd.print(counter); | ||
+ | delay(2000); | ||
+ | lcd.clear(); | ||
+ | lcd.print(" Rotary Encoder "); | ||
+ | lcd.setCursor(0, 1); | ||
+ | lcd.print(" With Arduino "); | ||
+ | delay(2000); | ||
+ | lcd.clear(); | ||
+ | updateCounterDisplay(); | ||
+ | } else if (digitalRead(swt) == HIGH) { | ||
+ | buttonPressed = false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void updateCounterDisplay() { | ||
+ | lcd.setCursor(0, 1); | ||
+ | lcd.print("Position: "); | ||
+ | lcd.print(counter); | ||
− | + | lcd.setCursor(9, 1); | |
+ | lcd.print(" "); // Clear the previous position | ||
+ | |||
+ | lcd.setCursor(9, 1); | ||
+ | lcd.print(counter); | ||
+ | } | ||
− | |||
</source></tab> | </source></tab> | ||
</tabs> | </tabs> | ||
− | + | ||
+ | |||
+ | Tento program riadi LCD displej a rotujúci enkodér pomocou AVR studia. Po inicializácii LCD displeja a nastavení pinov pre enkodér, program prechádza cez hlavnú slučku, kde sa kontinuálne vykonáva obsluha stavového automatu. Stavový automat má dva stavy: MENU_MAIN (hlavné menu) a MENU_VALUE (menu pre zmenu hodnoty). | ||
+ | |||
+ | V stave MENU_MAIN sa program sleduje rotáciu enkodéra a na základe smeru rotácie sa upravuje hodnota premennej counter. Ak je stlačené tlačidlo enkodéra, program prechádza do stavu MENU_VALUE. | ||
+ | |||
+ | V stave MENU_VALUE sa program opäť sleduje rotáciu enkodéra a upravuje hodnotu counter. Zároveň sa na LCD displej vypisuje text "Pozition:" a za ním aktuálna hodnota counter. Ak je stlačené tlačidlo enkodéra, program sa vráti do stavu MENU_MAIN. | ||
+ | |||
+ | Celkovo program zabezpečuje riadenie LCD displeja a rotujúceho enkodéra, pričom aktualizuje hodnotu na displeji podľa rotácie enkodéra a umožňuje zmenu hodnoty pomocou stlačenia tlačidla enkodéra. ''zdrojaky.zip'': | ||
Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | ||
Riadok 254: | Riadok 432: | ||
=== Overenie === | === Overenie === | ||
− | + | Program overujeme tak, že najprv restartujeme Arduino dosku, kde nám na LCD displeji vyškrtne "Rotary Encoder With Arduino". Následne sa nám na obrazovke zjavuje text "Pressed" a potom "Position: 0". V momente, keď začneme otáčať enkóderom, začne sa meniť aj hodnota na LCD displeji, ktorá bola na začiatku 0. Keď prídeme k nejakej vybranej pozícii na enkóderi, stlačíme tlačidlo a na LCD displeji sa nám zobrazí "Value Entered" a posledná zadaná hodnota. | |
− | |||
− | [[Súbor: | + | [[Súbor:Fds.jpg|400px|thumb|center|Aplikácia.]] |
'''Video:''' | '''Video:''' | ||
− | <center><youtube> | + | <center><youtube>pOf_roZGrjw</youtube></center> |
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte. | Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte. | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] |
Aktuálna revízia z 21:28, 9. jún 2023
Záverečný projekt predmetu MIPS / LS2023 - Viktor Fos
Zadanie
Rotačný enkóder - vytvorime program pre zadávanie hodnoty nejakej veličiny na LCD displeji pomocou tohoto enkodéra. Jednoduché menu, výber hodnoty a zadávanie číselnej veličiny so zmenou nahor/nadol a potvrdenie stlačením.
Literatúra:
Analýza a opis riešenia
Najprv som podľa schémy zapojenia pripojil LCD displej a rotačný enkoder na dosku Arduino Uno.
Algoritmus a program
Algoritmus programu je....
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define clk_pin PB3
#define data_pin PB4
#define swt_pin PB5
volatile int poutput;
volatile int counter = 0;
volatile bool buttonPressed = false;
enum MenuState { MENU_MAIN, MENU_VALUE };
volatile MenuState menuState = MENU_MAIN;
void initLCD()
{
DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5);
PORTD = 0x20;
PORTD |= 0x04;
PORTD &= ~0x04;
sendLCDCommand(0x28);
sendLCDCommand(0x0C);
sendLCDCommand(0x01);
DDRB &= ~(1 << clk_pin) & ~(1 << data_pin) & ~(1 << swt_pin);
PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin);
poutput = PINB & (1 << clk_pin);
}
void sendLCDCommand(uint8_t command)
{
PORTD = (command & 0xF0);
PORTD &= ~(1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
PORTD = ((command << 4) & 0xF0);
PORTD &= ~(1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
_delay_us(40);
}
void sendLCDData(uint8_t data)
{
PORTD = (data & 0xF0);
PORTD |= (1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
PORTD = ((data << 4) & 0xF0);
PORTD |= (1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
_delay_us(40);
}
void updateCounterDisplay()
{
sendLCDCommand(0x80 | 0x40);
sendLCDData('P');
sendLCDData('o');
sendLCDData('s');
sendLCDData('i');
sendLCDData('t');
sendLCDData('i');
sendLCDData('o');
sendLCDData('n');
sendLCDData(':');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData((counter / 100) + '0');
sendLCDData(((counter / 10) % 10) + '0');
sendLCDData((counter % 10) + '0');
}
void handleMainMenu()
{
if ((PINB & (1 << clk_pin)) != poutput)
{
if ((PINB & (1 << data_pin)) != poutput)
{
counter++;
}
else
{
counter--;
}
updateCounterDisplay();
}
poutput = PINB & (1 << clk_pin);
if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed)
{
buttonPressed = true;
sendLCDCommand(0x01);
sendLCDData('P');
sendLCDData('r');
sendLCDData('e');
sendLCDData('s');
sendLCDData('s');
sendLCDData('e');
sendLCDData('d');
_delay_ms(500);
sendLCDCommand(0x01);
menuState = MENU_VALUE;
updateCounterDisplay();
}
else if ((PINB & (1 << swt_pin)) != 0)
{
buttonPressed = false;
}
}
void handleValueMenu()
{
if ((PINB & (1 << clk_pin)) != poutput)
{
if ((PINB & (1 << data_pin)) != poutput)
{
counter++;
}
else
{
counter--;
}
sendLCDCommand(0x80 | 0x40);
sendLCDData('P');
sendLCDData('o');
sendLCDData('s');
sendLCDData('i');
sendLCDData('t');
sendLCDData('i');
sendLCDData('o');
sendLCDData('n');
sendLCDData(':');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData((counter / 100) + '0');
sendLCDData(((counter / 10) % 10) + '0');
sendLCDData((counter % 10) + '0');
}
poutput = PINB & (1 << clk_pin);
if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed)
{
menuState = MENU_MAIN;
sendLCDCommand(0x01);
sendLCDData('V');
sendLCDData('a');
sendLCDData('l');
sendLCDData('u');
sendLCDData('e');
sendLCDData(' ');
sendLCDData('e');
sendLCDData('n');
sendLCDData('t');
sendLCDData('e');
sendLCDData('r');
sendLCDData('e');
sendLCDData('d');
sendLCDCommand(0x80 | 0x40);
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDCommand(0x01);
sendLCDData(' ');
sendLCDData('R');
sendLCDData('o');
sendLCDData('t');
sendLCDData('a');
sendLCDData('r');
sendLCDData('y');
sendLCDData(' ');
sendLCDData('E');
sendLCDData('n');
sendLCDData('c');
sendLCDData('o');
sendLCDData('d');
sendLCDData('e');
sendLCDData('r');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
updateCounterDisplay();
}
else if ((PINB & (1 << swt_pin)) != 0)
{
buttonPressed = false;
}
}
// Hlavní smyčka programu
int main(void)
{
initLCD();
sei();
while (1)
{
switch (menuState)
{
case MENU_MAIN:
handleMainMenu();
break;
case MENU_VALUE:
handleValueMenu();
break;
}
}
}
#include <LiquidCrystal.h>
const int clk = 3;
const int data = 4;
const int swt = 5;
int poutput;
int counter = 0;
bool buttonPressed = false;
enum MenuState { MENU_MAIN, MENU_VALUE };
MenuState menuState = MENU_MAIN;
LiquidCrystal lcd(0, 1, 8, 9, 10, 11);
void setup() {
lcd.begin(16, 2);
lcd.print(" Rotary Encoder ");
lcd.setCursor(0, 1);
lcd.print(" With Arduino ");
delay(2000);
lcd.clear();
pinMode(clk, INPUT);
pinMode(data, INPUT);
pinMode(swt, INPUT_PULLUP);
poutput = digitalRead(clk);
}
void loop() {
switch (menuState) {
case MENU_MAIN:
handleMainMenu();
break;
case MENU_VALUE:
handleValueMenu();
break;
}
}
void handleMainMenu() {
if (digitalRead(clk) != poutput) {
if (digitalRead(data) != poutput) {
counter++;
} else {
counter--;
}
updateCounterDisplay();
}
poutput = digitalRead(clk);
if (digitalRead(swt) == LOW && !buttonPressed) {
buttonPressed = true;
lcd.clear();
lcd.print("Pressed");
delay(500);
lcd.clear();
menuState = MENU_VALUE;
updateCounterDisplay();
} else if (digitalRead(swt) == HIGH) {
buttonPressed = false;
}
}
void handleValueMenu() {
if (digitalRead(clk) != poutput) {
if (digitalRead(data) != poutput) {
counter++;
} else {
counter--;
}
lcd.setCursor(0, 1);
lcd.print("Position: ");
lcd.print(counter);
lcd.setCursor(9, 1);
lcd.print(" "); // Clear the previous position
lcd.setCursor(9, 1);
lcd.print(counter);
}
poutput = digitalRead(clk);
if (digitalRead(swt) == LOW && !buttonPressed) {
menuState = MENU_MAIN;
lcd.clear();
lcd.print("Value entered:");
lcd.setCursor(0, 1);
lcd.print(counter);
delay(2000);
lcd.clear();
lcd.print(" Rotary Encoder ");
lcd.setCursor(0, 1);
lcd.print(" With Arduino ");
delay(2000);
lcd.clear();
updateCounterDisplay();
} else if (digitalRead(swt) == HIGH) {
buttonPressed = false;
}
}
void updateCounterDisplay() {
lcd.setCursor(0, 1);
lcd.print("Position: ");
lcd.print(counter);
lcd.setCursor(9, 1);
lcd.print(" "); // Clear the previous position
lcd.setCursor(9, 1);
lcd.print(counter);
}
Tento program riadi LCD displej a rotujúci enkodér pomocou AVR studia. Po inicializácii LCD displeja a nastavení pinov pre enkodér, program prechádza cez hlavnú slučku, kde sa kontinuálne vykonáva obsluha stavového automatu. Stavový automat má dva stavy: MENU_MAIN (hlavné menu) a MENU_VALUE (menu pre zmenu hodnoty).
V stave MENU_MAIN sa program sleduje rotáciu enkodéra a na základe smeru rotácie sa upravuje hodnota premennej counter. Ak je stlačené tlačidlo enkodéra, program prechádza do stavu MENU_VALUE.
V stave MENU_VALUE sa program opäť sleduje rotáciu enkodéra a upravuje hodnotu counter. Zároveň sa na LCD displej vypisuje text "Pozition:" a za ním aktuálna hodnota counter. Ak je stlačené tlačidlo enkodéra, program sa vráti do stavu MENU_MAIN.
Celkovo program zabezpečuje riadenie LCD displeja a rotujúceho enkodéra, pričom aktualizuje hodnotu na displeji podľa rotácie enkodéra a umožňuje zmenu hodnoty pomocou stlačenia tlačidla enkodéra. zdrojaky.zip:
Zdrojový kód: zdrojaky.zip
Overenie
Program overujeme tak, že najprv restartujeme Arduino dosku, kde nám na LCD displeji vyškrtne "Rotary Encoder With Arduino". Následne sa nám na obrazovke zjavuje text "Pressed" a potom "Position: 0". V momente, keď začneme otáčať enkóderom, začne sa meniť aj hodnota na LCD displeji, ktorá bola na začiatku 0. Keď prídeme k nejakej vybranej pozícii na enkóderi, stlačíme tlačidlo a na LCD displeji sa nám zobrazí "Value Entered" a posledná zadaná hodnota.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.