Rotačný enkodér: Rozdiel medzi revíziami
Zo stránky SensorWiki
Riadok 35: | Riadok 35: | ||
<tab name="AVR C-code"><source lang="c++" style="background: LightYellow;"> | <tab name="AVR C-code"><source lang="c++" style="background: LightYellow;"> | ||
#include <avr/io.h> | #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); | |||
// Čtení počátečního stavu enkodéru | |||
poutput = PINB & (1 << clk_pin); | |||
} | |||
// Odeslání příkazu na LCD | |||
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); | |||
} | |||
// Odeslání dat na LCD | |||
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'); | |||
} | |||
// Obsluha menu MENU_MAIN | |||
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; | |||
} | |||
} | |||
// Obsluha menu MENU_VALUE | |||
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); // Vymazání displeje | |||
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) | int main(void) | ||
{ | { | ||
initLCD(); | |||
sei(); | |||
while (1) | |||
{ | |||
switch (menuState) | |||
{ | |||
case MENU_MAIN: | |||
handleMainMenu(); | |||
break; | |||
case MENU_VALUE: | |||
handleValueMenu(); | |||
break; | |||
} | |||
} | |||
} | |||
return(0); | return(0); | ||
Riadok 61: | Riadok 311: | ||
Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | ||
=== Overenie === | === Overenie === |
Verzia z 15:47, 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);
// Čtení počátečního stavu enkodéru
poutput = PINB & (1 << clk_pin);
}
// Odeslání příkazu na LCD
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);
}
// Odeslání dat na LCD
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');
}
// Obsluha menu MENU_MAIN
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;
}
}
// Obsluha menu MENU_VALUE
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); // Vymazání displeje
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;
}
}
}
return(0);
}
#include <avr/io.h>
void adc_init(void); // A/D converter initialization
unsigned int adc_read(char a_pin);
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.