Friday, September 2, 2016

nRF51822 mit Rotary Encoder (Drehgeber) und Quadrature Decoder (QDEC)

mechanischer Rotary Encoder (Drehgeber)

Ein mechanischer Rotary Encoder (Drehgeber) ist ein Eingabegerät bei dem durch die Rotation eines Knopfes Signale erzeugt werden die man z.B. zum Einstellen von Anwendungswerten verwenden kann. Den Rotary Encoder kann man meist ohne Endstellung in Uhrzeigerichtung oder gegen Uhrzeigerichtung  drehen.

Die preiswerten Versionen eines Rotary Encoder (Drehgeber) haben meist drei Anschlüsse A,B und C. Wobei die Anschlüsse A und B gegen den Anschluss C geschaltet werden.
Symbolischer Aufbau eines mechanischen Rotary Encoder (Drehgeber)

Signalzeitverläufe
 Wird der Rotary Encoder (Drehgeber) zwischen zwei Einrastpositionen in Uhrzeigerichtung gedreht, sind zunächst beide Anschlüsse A und B nicht mit C verbunden (0). Dann schließt sich zunächst der Anschluss A (1), dann B (1) und dann wird A auch wieder von C gelöst (0) und anschließend B (0). D.h. zwischen einem Wechsel zwischen zwei Einrastpositionen gibt es insgesamt vier Signalwechsel. Beim drehen entgegen der Uhrzeigerichtung sind die Signalverläufe umgedreht.
Beispieltestschaltung
Deutlicher wird dies, wenn wir eine Testschaltung mit Leuchtdioden aufbauen. Sobald sich A bzw. B mit dem Anschluss C verbindet ist der LED Schaltkreis geschlossen und die jeweilige LED (Rot oder Grün) leuchtet.
Testaufbau auf einem Entwicklerboard (Breadboard)
Signalwechsel bei einem Anschluss an den GPIO Port eines Mikrocontrollers
Will man einem Rotary Encoder (Drehgeber) mit einem Mikrokontroller auswerten, müssen die jeweiligen Signalflankenwechsel (Lo to Hi oder Hi to Lo) an einem GPIO Pin mit dem Zustand des jeweiligen anderen GPIO Pin gegenüber gestellt werden um die Drehrichtung zu ermitteln.
Beispielschaltung mit einem nRF51822
 (die LEDs und 220Ω Widerstände können auch gegen 4,7kΩ Widerstände ausgetauscht werden).


Um den Drehungen eines Rotary Encoder (Drehgeber) mit dem nRF51822 auswerten zu können könnte man entweder ständig (mit Mikrosekunden Delay) oder Timergesteuert die  beiden verwendeten GPIO Ports auswerten. Oder wir machen dies mit den GPIOTE vom letzten BLOG. Hierbei müsste dann jedoch immer noch bei einem Flankenwechsel innerhalb eines Interrupts der jeweils andere GPIO Pin abgefragt werden. Wird dann z.B. ein Interrupt bei GPIO Port A durch einen Lo to Hi Flankenwechsel ausgelöst zeigt ein GPIO Port B bei 0 eine Drehung in Uhrzeigerichtung an bei 1 eine Drehung gegen den Uhrzeigersinn.
Doch benötigt diese Art der Auswertung CPU Zeit, da die Interruptroutine nur mit Hilfe der CPU Ausgeführt wird.

Eleganter ist daher die Auswertung mit dem in dem in dem nRF51822/nRF51422 eingebauten Peripheral block, dem Quadrature Decoder (QDEC). Der kann die Signale auswerten und sich über einem Report eine definierte Anzahl von zustandsänderungen Merken ohne die CPU z.B. aus dem Low Power Schlaf zu holen.


/** @brief Function handle qdec events.
 */
static void qdec_event_handler(nrf_drv_qdec_event_t event) {
    if (event.type == NRF_QDEC_EVENT_REPORTRDY) {
        m_accdblread = event.data.report.accdbl;
        m_accread = event.data.report.acc;
        if (m_accdblread==0) {
            m_value += m_accread;
    }
        if (m_value<0) {
        m_value = 0;
    } else if (m_value>100) {
        m_value=100;
    }
        if (m_value != m_last_value) {
            uart_printf("report dbl=%u acc=%d",m_accdblread,m_accread);
                if (m_accread>0) {
            uart_printf("\x1B[1;32m"); // GREEN
                } else {
            uart_printf("\x1B[1;31m"); // RED
        }
            uart_printf(" val=%d\n\r",m_value);
        m_last_value = m_value;
        uart_printf("\x1B[0m"); // DEFAULT color
    }
    }
}

/** @brief Function initialization and configuration of QDEC driver instance.
 */
static void qdec_config(void) {
    uint32_t err_code;

        nrf_drv_qdec_config_t qdec_config = NRF_DRV_QDEC_DEFAULT_CONFIG;
    // Initialize hardware
    err_code = nrf_drv_qdec_init(&qdec_config, qdec_event_handler);
    APP_ERROR_CHECK(err_code);
   
    printf("QDEC testing started\n");
    uart_printf("nrf_drv_qdec_init\n\r");

    nrf_drv_qdec_enable(); // Event and corresponding interrupt are enabled.
    uart_printf("nrf_drv_qdec_enable \n\r");
}


Sourcecode ist über GITHUB verfügbar.
https://github.com/pcbreflux/nordic/tree/master/nRF51822/qdec_rotary_encoder

Weiter Informationen im Video:
https://youtu.be/oqvLRRR_ahs







No comments:

Post a Comment