EBC Reading a Rotary Encoder via eQEP

A common way to read a rotational input is with a quadrature encoder such as these rotary encoders from SparkFun and Adafruit. BeatgleBone Black has an Enhanced Quadrature Encoder Pulse (eQEP) Module (See section 15.4 of the TRM) that makes reading encoders easy.

Wiring the Encoder
The encoders we are using have a common lead and two inputs, A and B. Wire the common to ground. We'll start using the Bone's eQEP2 since it doesn't conflict with the HDMI. Derek Molloy's P8/P9 Header chart shows eQEP2B_in is on pin P8_11 and eQEP2A_in is on P8_12.



Configuring the Encoder
The following Device Tree Overlay needs to be used to enable eQEP2.

/* * Copyright (C) 2013 Nathaniel R. Lewis - http://nathanielrlewis.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Enable eQEP2 on the Beaglebone White and Black * These pins don't conflict with the HDMI */ /dts-v1/; /plugin/; / {   compatible = "ti,beaglebone", "ti,beaglebone-black"; /* identification */ part-number = "bone_eqep2"; version    = "00A0"; fragment@0 { target = <&am33xx_pinmux>; __overlay__ { pinctrl_eqep2: pinctrl_eqep2_pins { pinctrl-single,pins = < 0x038 0x24 /* P8_16 = GPIO2_12 = EQEP2_index,  MODE4 */ 0x03C 0x24 /* P8_15 = GPIO2_13 = EQEP2_strobe, MODE4 */ 0x030 0x34 /* P8_12 = GPIO2_10 = EQEP2A_in,    MODE4 */ 0x034 0x34 /* P8_11 = GPIO2_11 = EQEP2B_in,    MODE4 */ /* From: https://groups.google.com/forum/#!searchin/beagleboard/eQep/beagleboard/Orp3tFcNgCc/mYacP_GkCQQJ */ >;           };        };    };    fragment@1 { target = <&epwmss2>; __overlay__ { status = "okay"; };   };    fragment@2 { target = <&eqep2>; __overlay__ { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_eqep2>; count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */ swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */ invert_qa = <1>;  /* Should we invert the channel A input? */           invert_qb = <1>;   /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */ invert_qi = <0>;  /* Should we invert the index input? */           invert_qs = <0>;   /* Should we invert the strobe input? */ 	       status = "okay"; };   }; };

Put it in a file called bone_eqep2b.dts and run the following.

bone$ dtc -O dtb -o bone_eqep2b-00A0.dtbo -b 0 -@ bone_eqep2b.dts bone$ cp bone_eqep2b-00A0.dtbo /lib/firmware bone$ echo bone_eqep2b > /sys/devices/bone_capemgr.*/slots

Reading the Encoder
Put the following in a file called rotaryEncoder.js.

// This uses the eQEP hardware to read a rotary encoder // echo bone_eqep2b > $SLOTS var b = require('bonescript'), fs = require('fs'); var eQEP0 = "/sys/devices/ocp.3/48300000.epwmss/48300180.eqep/", eQEP1 = "/sys/devices/ocp.3/48302000.epwmss/48302180.eqep/", eQEP2 = "/sys/devices/ocp.3/48304000.epwmss/48304180.eqep/", eQEP = eQEP2; var oldData,           // pervious data read period = 100;      // in ms // Set the eEQP period, convert to ns. fs.writeFile(eQEP+'period', period*1000000, function(err) {        if (err) throw err;         console.log('Period updated to ' + period*1000000);  }) // Enable fs.writeFile(eQEP+'enabled', 1, function(err) {     if (err) throw err;         console.log('Enabled');  }) setInterval(readEncoder, period);   // Check state every 250 ms function readEncoder(x) { fs.readFile(eQEP + 'position', {encoding: 'utf8'}, printValue); } function printValue(err, data) { if (err) throw err; if (oldData !== data) { console.log('position: '+data+' speed: '+(oldData-data)); oldData = data; } }
 * 1) !/usr/bin/env node

Then run.

bone$ ./rotaryEncoder.js