Strana 1 z 1

Arduino - tlačidlá

Napísané: 29 Jún 2022, 19:38
od používateľa MrWifiHifi
Zdravím

Chcel by som sa poradiť. Je možné detekovať pri 4 tlačidlách krátke a dlhé stalčenie? Ak, tak ako by to bolo možné spraviť čo najjednoduchšie? Našiel som zatiaľ len pre jedno tlačidlo, snažil som sa to prerobiť, žiaľ neúspešne.

Re: Arduino - tlačidlá

Napísané: 29 Jún 2022, 20:41
od používateľa maskrtnik01
Najprv používate debouncing? Ak nie, môže to robiť sprostosti.

Ak áno, verím tomu, že stačí jednoducho zaznamenať čas detekcie stlačenia a pustenia. Ich rozdiel je hľadaná dĺžka stlačenia.

Vyhýbajte sa delayom, všade kde sa dá radšej millis, aj za cenu vyššej zložitosti. Potom nevidím problém s rozšírením vyššie uvedeného na viac tlačidiel.

Re: Arduino - tlačidlá

Napísané: 29 Jún 2022, 20:43
od používateľa Atlan
Ak to mss na ATmeli, ta milis nepouzivaj, ale su vytvor vlastnu premenu v preruseni....

Re: Arduino - tlačidlá

Napísané: 29 Jún 2022, 21:25
od používateľa MrWifiHifi
Je tam debounce, programujem no Arduino Uno. Používam millis(), delay sa snažím obmedziť na minimum.
Zatiaľ sa mi podarilo len detekovať stlačenie jedného zo 4 tlačidiel, no to dlhé a krátke stlačenie sa mi zatiaľ nepodarilo implementovať.

Funkciu mám postavenú tak, že kontroluje 4 tlačidlá, ak nie je žiadne stlačené, vyhodí -1. Naopak, ak je niektoré tlačidlo stlačené, tak vyhodí číslo tlačidla, teda 1 až 4.

Rozmýšlaľ som, že by som postavil dalšiu funkciu, kde na jej začiatku by sa zistoval stav tlačidiel, ak by sa niektoré stlačilo, spustila by sa slučka, ktorá by si stále na konci zapamätala aktuálnu hodnotu millis. Slučka by sa ukončila po pustení tlačidla, zapamätali by sa millis pri stlačení tlačidla odpočítali by sa od zapamätaných millis pri pustení tlačidla, následne by bola podmieka, ktorá by určovala či šlo o krátke alebo dlhé stlačenie.

Moholo by to takto nejako fungovať...?

Re: Arduino - tlačidlá

Napísané: 30 Jún 2022, 08:21
od používateľa maskrtnik01
Znovu sa chystáte zablokovať celý program len kvôli detekcii stlačenia. Toto je cesta do pekiel, čoskoro sa budete čudovať, prečo program reaguje na vstup len sem-tam.

Napíšte to ako som spomínal, zapíšte si do premennej čas pri stlačení, pri pustení odrátate od millis a máte vyhraté.


Ako robíte debouncing? Ak znovu cez nejakú slučku ktorá blokuje program, treba prerobiť.

Re: Arduino - tlačidlá

Napísané: 30 Jún 2022, 08:46
od používateľa budvar10
Lepšie ako siahodlho opisovať, je poslať kód programu.
Pre krátke stlačenie je potrebné testovať, či sa vráti tlačidlo do pôvodnej hodnoty do časového limitu. Ostatné je dlhé stlačenie. Stlačenie píšeš, že vieš ako.

Re: Arduino - tlačidlá

Napísané: 30 Jún 2022, 23:27
od používateľa balu
Arduino nepoužívám, takže budou potřeba nějaké úpravy. Tohle je vytažené z mého programu psaném v Atmel Studiu.

Kód: Vybrať všetko

/*
 * KeyProcessTimer.cpp
 */

#include "MCU_Config.h"

#include <avr/io.h>
#include <avr/interrupt.h>
#include "KeyProcessTimer.h"
#include "Common.h"

volatile KeyStateUnion Keys[_MAX_KEY_INDEX];

unsigned int _ActualKeyProcessed = 0;

typedef struct _KeyTimersStruct
{
    unsigned char Debounce;
    unsigned char LongPressTimer;
    unsigned char AutoRepeatTimer;
    unsigned char LastState:1;
} _KeyTimersStruct;

#define LongPressTimerPreset 50
#define AutoRepeatTimerPreset 25

_KeyTimersStruct _KeysTimers[_MAX_KEY_INDEX];

void KeyProcessTimerInit(void)
{
    OCR1A = ((F_CPU/(80*NUM_OF_KEYS)/8)-1);
    TCCR1A = 0;
    TCCR1B = (1<<WGM12)|PRE8;
    TIMSK |= (1<<OCIE1A);
}

ISR(TIMER1_COMPA_vect)
{
    _KeysTimers[_ActualKeyProcessed].Debounce <<= 1;

    bool _ActualKeyInput;

    _ActualKeyInput = false;

    switch(_ActualKeyProcessed)
    {
        case 0: if (!KEY_CONNECT_INPUT) _ActualKeyInput = true;
                break;
        case 1: if (!KEY_DISCONNECT_INPUT) _ActualKeyInput = true;
                break;
        case 2: if (!KEY_UP_INPUT) _ActualKeyInput = true;
                break;
        case 3: if (!KEY_DOWN_INPUT) _ActualKeyInput = true;
                break;
        default:
                break;
    }
    if (_ActualKeyInput)
    {
        _KeysTimers[_ActualKeyProcessed].Debounce++;
    }

    if (_KeysTimers[_ActualKeyProcessed].Debounce == 0xFF)
    {
        Keys[_ActualKeyProcessed].StateBits.ActualState = 1;
        if (_KeysTimers[_ActualKeyProcessed].LastState == 0)
        {
            Keys[_ActualKeyProcessed].StateBits.RisingEdge = 1;
        }
        else
        {
            Keys[_ActualKeyProcessed].StateBits.RisingEdge = 0;
        }
        if (_KeysTimers[_ActualKeyProcessed].LongPressTimer == LongPressTimerPreset)
        {
            if (!_KeysTimers[_ActualKeyProcessed].AutoRepeatTimer)
            {
                _KeysTimers[_ActualKeyProcessed].AutoRepeatTimer = AutoRepeatTimerPreset;
                Keys[_ActualKeyProcessed].StateBits.LongPress = 1;
                Keys[_ActualKeyProcessed].StateBits.AutoRepeat= 1;
            }
            else
            {
                _KeysTimers[_ActualKeyProcessed].AutoRepeatTimer--;
                Keys[_ActualKeyProcessed].StateBits.AutoRepeat = 0;
            }
        }
        else
        {
            _KeysTimers[_ActualKeyProcessed].LongPressTimer++;
        }
    }
    else
    {
        Keys[_ActualKeyProcessed].CompleteByte = 0;
        if (_KeysTimers[_ActualKeyProcessed].LastState == 1)
        {
            Keys[_ActualKeyProcessed].StateBits.FallingEdge = 1;
        }
        else
        {
            Keys[_ActualKeyProcessed].StateBits.FallingEdge = 0;
        }
        _KeysTimers[_ActualKeyProcessed].AutoRepeatTimer = 0;
        _KeysTimers[_ActualKeyProcessed].LongPressTimer = 0;
    }
    _KeysTimers[_ActualKeyProcessed].LastState = Keys[_ActualKeyProcessed].StateBits.ActualState;
    Keys[_ActualKeyProcessed].StateBits.KeyUpdated = 1;

    _ActualKeyProcessed++;
    if (_ActualKeyProcessed>_MAX_KEY_INDEX) _ActualKeyProcessed = 0;
}

V souboru "MCU_Config.h" je definovaný F_CPU, v souboru "Common.h" jsou definované názvy tlačítek na vstupech procesoru.

Kód: Vybrať všetko

/*
 * KeyProcessTimer.h
 */


#ifndef KeyProcessTimer_H_
#define KeyProcessTimer_H_

// KeyProcessTimer configuration

#define NUM_OF_KEYS (4)

#define _MAX_KEY_INDEX (NUM_OF_KEYS - 1)

typedef struct KeyStateStruct
{
    unsigned char ActualState:1;
    unsigned char RisingEdge:1;
    unsigned char FallingEdge:1;
    unsigned char LongPress:1;
    unsigned char AutoRepeat:1;
    unsigned char KeyUpdated:1;
} KeyStateStruct;

typedef union KeyStateUnion
{
    unsigned char CompleteByte;
    KeyStateStruct StateBits;
} KeyStateUnion;

extern volatile KeyStateUnion Keys[_MAX_KEY_INDEX];

void KeyProcessTimerInit(void);

#endif /* KeyProcessTimer_H_ */
Program je psaný tak, že změnou #define NUM_OF_KEYS (4) a počtu (a názvů) case ve switch(_ActualKeyProcessed) upravíš program pro libovolný počet tlačítek - teda co stačí paměť a rychlost procesoru.

Položka KeyUpdated u každého tlačítka znamená, že jsou v proměnné nové stavy. Po reakci programu na jednotlivé "události" je třeba tento příznak vynulovat.


Téma presunutá do správnej sekcie,presunul:5.7.2022 mirosne.