Operácie

Rotačný enkodér: Rozdiel medzi revíziami

Z SensorWiki

(Algoritmus a program)
(Algoritmus a program)
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 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 &= ~((1 << clk_pin) | (1 << data_pin) | (1 << swt_pin));
 
 
     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);
   
 
    // Čtení počátečního stavu enkodéru
 
    poutput = PINB & (1 << clk_pin);
 
 
}
 
}
  
// Odeslání příkazu na LCD
+
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);
 
}
 
}
  
// Odeslání dat na LCD
+
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:
 
}
 
}
  
// Obsluha menu MENU_MAIN
+
void handleMainMenu() {
void handleMainMenu()
+
     if ((PINB & (1 << clk_pin)) != 0) {
{
+
         if ((PINB & (1 << data_pin)) != 0) {
     if ((PINB & (1 << clk_pin)) != poutput)
 
    {
 
         if ((PINB & (1 << data_pin)) != poutput)
 
        {
 
 
             counter++;
 
             counter++;
         }
+
         } else {
        else
 
        {
 
 
             counter--;
 
             counter--;
 
         }
 
         }
Riadok 161: Riadok 124:
 
     }
 
     }
 
      
 
      
    poutput = PINB & (1 << clk_pin);
+
     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) {
    else if ((PINB & (1 << swt_pin)) != 0)
 
    {
 
 
         buttonPressed = false;
 
         buttonPressed = false;
 
     }
 
     }
 
}
 
}
  
// Obsluha menu MENU_VALUE
+
void handleValueMenu() {
void handleValueMenu()
+
     if ((PINB & (1 << clk_pin)) != 0) {
{
+
         if ((PINB & (1 << data_pin)) != 0) {
     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 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:
 
     }
 
     }
 
      
 
      
    poutput = PINB & (1 << clk_pin);
+
     if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) {
   
 
     if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed)
 
    {
 
 
         menuState = MENU_MAIN;
 
         menuState = MENU_MAIN;
         sendLCDCommand(0x01); // Vymazání displeje
+
         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) {
    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:
 
}
 
}
  
  return(0);
 
}
 
  
 
</source></tab>
 
</source></tab>

Verzia zo dňa a času 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.

Vývojová doska ACROB.

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.

Schéma zapojenia



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.

Aplikácia.

Video:

Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.