Rotačný enkodér: Rozdiel medzi revíziami
Zo stránky SensorWiki
Riadok 240: | Riadok 240: | ||
</source></tab> | </source></tab> | ||
<tab name="arduino"><source lang="arduino" style="background: LightYellow;"> | <tab name="arduino"><source lang="arduino" 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> |
Verzia z 15:56, 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 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);
}
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)) != 0) {
if ((PINB & (1 << data_pin)) != 0) {
counter++;
} else {
counter--;
}
updateCounterDisplay();
}
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)) != 0) {
if ((PINB & (1 << data_pin)) != 0) {
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');
}
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;
}
}
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);
}
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:
Zdrojový kód: zdrojaky.zip
Overenie
Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku záverečnej obrazovky pred resetom. Vypísaný je tu priemerný čas a najlepší čas.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.