Adafruit: Rotary Encoder

From eLinux.org
Revision as of 00:14, 2 October 2012 by Lobdeljt (Talk | contribs)

Jump to: navigation, search
Adafruit's Rotary Encoder

Overview

Adafruit's Rotary Encoder is a device that detects rotation. As it rotates, it sends pulses on two pins. By comparing the signals, the direction of rotation can be determined. There are 24 pulses per rotation. The device also acts as a pushbutton switch.

Inputs and Outputs

The device has five pins - three on one side and two on the other. The side with three pins is for the encoder and is ordered (from left to right) ground, signal A, and signal B. The side with two pins is for the pushbutton switch. More information can be found on the product page or on the datasheet.

Bone Usage

The pins on the device can be difficult to use with a bread board, so soldering wire leads may prove useful.
Rotary encoder with soldered wire leads
The two signal pins and one of the pushbutton pins can be hooked up directly to any of the GPIO ports on the BeagleBone. The remaining pins can be hooked up to GND and +3,3v. The example below uses GPIO1_6 for signal A, GPIO1_15 for signal B, and GPIO1_16 for the pushbutton switch.
Rotary encoder hooked up to the BeagleBone

The C code below demonstrates how to use the encoder with the BeagleBone.

/*

Port Congiguration:
-Encoder A: GPIO1_6 - Header P8, pin 3 - GPIO 38
-Encoder B: GPIO1_15 - Header P8, pin 15 - GPIO 47
-Pushbutton Switch: GPIO1_16 - Header P9, pin 15 - GPIO 48

This program keeps track of an encoder. CW rotation will
increment the ticks, and CCW will decrement it. The current
number of ticks is printed when the button is pressed.

The gpio.h header consists of the GPIO methods copied directly from:
https://www.ridgerun.com/developer/wiki/index.php/Gpio-int-test.c

*/


#include <signal.h>
#include <poll.h>
#include "gpio.h"

int running = 1;

void signal_handler(int sig)
{
        running = 0;
}

int main(int argc, char* argv[])
{
        int rc;
        struct pollfd fdset[3];
        int nfds = 3;
        int len;
        char* buf[MAX_BUF];
        int i;

        int pos = 0;

        unsigned int enc_a_val;
        unsigned int enc_b_val;

        // Handle Ctrl^C
        signal(SIGINT, signal_handler);

        // Set up GPIO pins
        unsigned int gpio_a = 38;
        unsigned int gpio_b = 47;
        unsigned int gpio_sw = 48;

        int enc_a_fd;
        int enc_b_fd;
        int enc_sw_fd;

        gpio_export(gpio_a);
        gpio_export(gpio_b);
        gpio_export(gpio_sw);

        gpio_set_dir(gpio_a, 0);
        gpio_set_dir(gpio_b, 0);
        gpio_set_dir(gpio_sw, 0);

        // Interrupts
        gpio_set_edge(gpio_a, "rising");
        gpio_set_edge(gpio_sw, "rising");

        // Open the file for the encoder A signal
        enc_a_fd = gpio_fd_open(gpio_a);

       // Main loop
        while (running == 1)
        {
                memset((void*)fdset, 0, sizeof(fdset));

                fdset[0].fd = STDIN_FILENO;
                fdset[0].events = POLLIN;

                fdset[1].fd = enc_a_fd;
                fdset[1].events = POLLPRI;

                fdset[2].fd = enc_sw_fd;
                fdset[2].events = POLLPRI;

                rc = poll(fdset, nfds, -1);

                if (rc < 0)
                {
//                      printf("poll() failed.\n");
                }

                if (rc == 0)
                {
//                      printf(".");
                }

                if (fdset[0].revents & POLLIN)
                {
                        (void) read(fdset[0].fd, buf, 1);
                }

                // Encoder click
                if (fdset[1].revents & POLLPRI)
                {
                        lseek(fdset[1].fd, 0, SEEK_SET);
                        len = read(fdset[1].fd, buf, MAX_BUF);

                        enc_a_val = atoi((const char*) buf);
                        gpio_get_value(gpio_b, &enc_b_val);

                        if (enc_a_val == 1) // rising edge
                        {
                                if (enc_b_val == 0) pos--;
                                else pos++;
                        }

                }


		// Button Press
                if (fdset[2].revents & POLLPRI)
                {
                        lseek(fdset[2].fd, 0, SEEK_SET);
                        len = read(fdset[2].fd, buf, MAX_BUF);

                        printf("Ticks: %d\n", pos);
                }

        }

        gpio_fd_close(enc_a_fd);

        return 0;
}


The full code can be found in John Lobdell's Git repository.