Rotačný enkodér: Rozdiel medzi revíziami
Zo stránky SensorWiki
| Riadok 37: | Riadok 37: | ||
| #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 43: | Riadok 42: | ||
| #define swt_pin PB5 | #define swt_pin PB5 | ||
| 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 &= ~((1 << clk_pin) | (1 << data_pin) | (1 << swt_pin)); | |||
|      DDRB &= ~(1 << clk_pin)  | |||
|      PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); |      PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); | ||
| } | } | ||
| void sendLCDCommand(uint8_t command) { | |||
| void sendLCDCommand(uint8_t command) | |||
| { | |||
|      PORTD = (command & 0xF0); |      PORTD = (command & 0xF0); | ||
|      PORTD &= ~(1 << PD4); |      PORTD &= ~(1 << PD4); | ||
| Riadok 87: | Riadok 66: | ||
|      _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 93: | Riadok 71: | ||
|      _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 105: | Riadok 80: | ||
|      _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 111: | Riadok 85: | ||
|      _delay_us(1); |      _delay_us(1); | ||
|      PORTD &= ~(1 << PD5); |      PORTD &= ~(1 << PD5); | ||
|      _delay_us(40); |      _delay_us(40); | ||
| } | } | ||
| void updateCounterDisplay() { | |||
| void updateCounterDisplay() |      sendLCDCommand(0x80 | 0x40); | ||
| { | |||
|      sendLCDCommand(0x80 | 0x40);  | |||
|      sendLCDData('P'); |      sendLCDData('P'); | ||
|      sendLCDData('o'); |      sendLCDData('o'); | ||
| Riadok 128: | Riadok 99: | ||
|      sendLCDData('n'); |      sendLCDData('n'); | ||
|      sendLCDData(':'); |      sendLCDData(':'); | ||
|      sendLCDCommand(0x80 | 0x40 | 0x09); | |||
|      sendLCDCommand(0x80 | 0x40 | 0x09);  | |||
|      sendLCDData(' '); |      sendLCDData(' '); | ||
|      sendLCDData(' '); |      sendLCDData(' '); | ||
| Riadok 138: | Riadok 108: | ||
|      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 145: | Riadok 114: | ||
| } | } | ||
| void handleMainMenu() { | |||
| void handleMainMenu() |      if ((PINB & (1 << clk_pin)) != 0) { | ||
| { |          if ((PINB & (1 << data_pin)) != 0) { | ||
|      if ((PINB & (1 << clk_pin)) !=  | |||
|          if ((PINB & (1 << data_pin)) !=  | |||
|              counter++; |              counter++; | ||
|          } |          } else { | ||
|              counter--; |              counter--; | ||
|          } |          } | ||
| Riadok 161: | Riadok 124: | ||
|      } |      } | ||
|      if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | |||
|      if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) | |||
|          buttonPressed = true; |          buttonPressed = true; | ||
|          sendLCDCommand(0x01);  |          sendLCDCommand(0x01); | ||
|          sendLCDData('P'); |          sendLCDData('P'); | ||
|          sendLCDData('r'); |          sendLCDData('r'); | ||
| Riadok 175: | Riadok 135: | ||
|          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) { | ||
|          buttonPressed = false; |          buttonPressed = false; | ||
|      } |      } | ||
| } | } | ||
| void handleValueMenu() { | |||
| void handleValueMenu() |      if ((PINB & (1 << clk_pin)) != 0) { | ||
| { |          if ((PINB & (1 << data_pin)) != 0) { | ||
|      if ((PINB & (1 << clk_pin)) !=  | |||
|          if ((PINB & (1 << data_pin)) !=  | |||
|              counter++; |              counter++; | ||
|          } |          } else { | ||
|              counter--; |              counter--; | ||
|          } |          } | ||
|          sendLCDCommand(0x80 | 0x40);  |          sendLCDCommand(0x80 | 0x40); | ||
|          sendLCDData('P'); |          sendLCDData('P'); | ||
|          sendLCDData('o'); |          sendLCDData('o'); | ||
| Riadok 208: | Riadok 160: | ||
|          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 215: | Riadok 166: | ||
|      } |      } | ||
|      if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | |||
|      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 234: | Riadok 182: | ||
|          sendLCDData('e'); |          sendLCDData('e'); | ||
|          sendLCDData('d'); |          sendLCDData('d'); | ||
|          sendLCDCommand(0x80 | 0x40);  |          sendLCDCommand(0x80 | 0x40); | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
| Riadok 243: | Riadok 191: | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
|          sendLCDCommand(0x01);  |          sendLCDCommand(0x01); | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
|          sendLCDData('R'); |          sendLCDData('R'); | ||
| Riadok 268: | Riadok 216: | ||
|          sendLCDData(' '); |          sendLCDData(' '); | ||
|          updateCounterDisplay(); |          updateCounterDisplay(); | ||
|      } |      } else if ((PINB & (1 << swt_pin)) != 0) { | ||
|          buttonPressed = false; |          buttonPressed = false; | ||
|      } |      } | ||
| } | } | ||
| int main(void) { | |||
| int main(void) | |||
| { | |||
|      initLCD(); |      initLCD(); | ||
|      sei();  |      sei(); | ||
|      while (1) |      while (1) { | ||
|          switch (menuState) { | |||
|          switch (menuState) | |||
|              case MENU_MAIN: |              case MENU_MAIN: | ||
|                  handleMainMenu(); |                  handleMainMenu(); | ||
| Riadok 295: | Riadok 237: | ||
| } | } | ||
| </source></tab> | </source></tab> | ||
Verzia z 15:52, 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 <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.