LEDky & Tlačítka

NSWI170, 2026, Labs 03

Jáchym Bártík

Feedback

  • Domácí úkoly - akceptované řešení, body

Pravidlo #3 - DRY

  • Don't Repeat Yourself
  • Vše je napsáno jen jednou
    • Rychlejší vývoj, snadnější změny
    • Lepší kontrola chyb, optimalizace
    • Větší přehlednost
  • Nástroje - funkce, konstanty, cykly, objekty, ...
  • Čemu se vyhnout:
    • Sjednocování příliš různorodého kódu
    • Horší rozšiřitelnost, plno if-else podmínek
    • Zbytečně moc abstrakcí

KISS

  • Keep It Simple, Stupid
  • Jednodušší systémy jsou lepší, než složitější
    • Rychlejší vývoj, snadnější změny
    • Lepší kontrola chyb, optimalizace
    • Větší přehlednost
  • Může však být v rozporu s velmi DRY kódem
    • Abstrakce, "obecná" řešení, ...
  • Úspěsná kombinace obou principů není easy

Cvičení #1

  • Vytvořte funkci, která zobrazí číslo na LEDkách
    • Modulo 16
    • Převedení do binární soustavy
    • Zobrazení bitů pomocí čtyř LED
  • Hint: binární operátory
    • & (and), | (or), ~ (negation)
    • <<, >> (left shift, right shift)

7 & 2  // 0111 & 0010 -> 0010 = 2
7 | 8  // 0111 | 1000 -> 1111 = 15

2 << 1 // 0010 -> 0100 = 4
3 << 2 // 0011 -> 1100 = 12
    

Cvičení #2

  • Vytvořte čítač, který se periodicky inkrementuje
    • Hodnotu vypisujte pomocí funkce ze cvičení #1
    • Modulo není nutně potřeba - stejně jde jen o poslední čtyři bity

Tlačítka

  • Nastavení pinu pro čtení
    • Je to tak sice defaultně, ale stejně bychom to měli dělat kvůli čitelnosti
    
    void setup() {
        pinMode(BUTTON1_PIN, INPUT);
    }
                
  • Čtení je podobné jako zapisování
    • Pokud funkce vrátí ON, tlačítko je zapnuté
    
    void loop() {
        bool isPressed = digitalRead(BUTTON1_PIN) == ON;
    }
                

Cvičení #3

  • Zařiďte, aby LEDka svítila právě tehdy, když je stisknuté tlačítko
  • Bonus: Druhé tlačítko přepíná, která LEDka to bude

#include <funshield.h>

void setup() {
    pinMode(LED1_PIN, OUTPUT);
    pinMode(BUTTON1_PIN, INPUT);
}

void loop() {
    digitalWrite(LED1_PIN, digitalRead(BUTTON1_PIN));
}
    

Cvičení #4

  • Vytvořte čítač, který se periodicky inkrementuje pokud je stisknuto tlačítko
    • Vyjděte z úlohy #2
    • Čas se měří jen pokud je stisknuto tlačítko
      • Pozor, reálný čas samozřejmě běží pořád

Cvičení #5

  • Vytvořte čítač, který se inkrementuje stisknutím tlačítka
    • Hodnota se časem (sama) nijak nemění
    • Při stisknutí tlačítka se zvýší o 1
    • Je nutné rozlišit, ve kterém průběhu loop bylo tlačítko stisknuto, tj. kdy digitalRead poprvé vrátila ON
  • Bonus: Debounce
    • Tlačítko může oscilovat, neboli několikrát rychle za sebou změnit stav
    • Řešení - po každém stisknutí jej na chvíli zablokujte
    • Vyzkoušejte různé délky blokačního intervalu

Cvičení #6

  • Přidejte další tlačítka
    • Jedno dekrementuje čítač
      • Tady už bude nutné použít modulo
      • x = (x + 15) % 16
    • Druhé jej zvýší o 5
    • Všechna tři tlačítka pracují se stejným čítačem
  • Všimněte si, že všechna tlačítka dělají v podstatě to samé
    • Zaměřte se na odstranění duplicitní logiky
    • Dále si můžete všimnout, že už je tu neprakticky moc proměnných ...

Lepší řešení

  • Cílem je oddělit logiku tlačítek od logiky počítání času a dalších částí programu
    • K tomu se hodí funkce
    • Ty ale vyžadují předávání příliš mnoha proměnných
    • Navíc neoddělují data, pouze funkcionality
  • Struktury:
    
    struct Button {
        int pin;
        bool isPressed;
    };
    
    void processButton(Button &button) {
        if (digitalRead(button.pin) == ON && !button.isPressed) {
            button.isPressed = true;
            ... // Handle click event
        }
    }
    
    Button buttons[3];
    processButton(buttons[0]);
                

Lepší řešení

  • Struktury mohou obsahovat i funkce
    • Kombinují data s funkcionalitami, které se jich týkají
  • Pro každý prvek lze specifikovat viditelnost
    • public vs. private
    • Defaultně je vše public
  • Třídy - úplně stejné jako struktury, akorát že defaultně je vše private
    
    class Button { // Basically structure
    public:
        int pin;
        bool isPressed;
    };
                    
    
    struct Button { // Basically class
    private:
        int pin;
        bool isPressed;
    };
                    
  • Používejte výhradně třídy
    • Struktury jsou specifikem C/C++
    • Jinde se nepoužívají
    • Private je lepší default

Domácí úkol #3

  • Vytvořte tlačítka, která inkrementují čítač jak spojitě, tak diskrétně
    • Tlačítko inkrementuje čítač ihned po stisknutí
    • Zároveň, pokud jej držíte dostatečně dlouho, začne samo periodicky inkrementovat čítač