Difference between revisions of "EBC Reading a Rotary Encoder via eQEP"

From eLinux.org
Jump to: navigation, search
m (Wiring the Encoder)
(Configuring the Encoder: Updated for 3-Mar-2015 image.)
Line 11: Line 11:
  
 
== Configuring the Encoder ==
 
== Configuring the Encoder ==
The following Device Tree Overlay needs to be used to enable eQEP2.
+
If you are running a current version of Debian on your Bone (3-Mar-2015 or newer), the file for configuring the eQEP are already on your Bone.
  
  /*
+
  bone$ '''# ls /lib/firmware/ | grep -i qep'''
* Copyright (C) 2013 Nathaniel R. Lewis - http://nathanielrlewis.com/
+
  PyBBIO-eqep0-00A0.dtbo
*
+
  PyBBIO-eqep1-00A0.dtbo
* This program is free software; you can redistribute it and/or modify
+
PyBBIO-eqep2-00A0.dtbo
* it under the terms of the GNU General Public License version 2 as
+
  PyBBIO-eqep2b-00A0.dtbo
* 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.
+
The different '''dtbo''' files configure for different pins.
 +
Get Derek Molloy's P8 and P9 header tables to see what pins are available.
 +
wget https://github.com/derekmolloy/boneDeviceTree/raw/master/docs/BeagleboneBlackP8HeaderTable.pdf
 +
wget https://github.com/derekmolloy/boneDeviceTree/raw/master/docs/BeagleboneBlackP9HeaderTable.pdf
  
  bone$ '''dtc -O dtb -o bone_eqep2b-00A0.dtbo -b 0 -@ bone_eqep2b.dts'''
+
Open the pdf files and search for '''eqp'''.
bone$ '''cp bone_eqep2b-00A0.dtbo /lib/firmware'''
+
'''eQEP2''' looks like a good one, but it appears in two place.  Try the first one
  bone$ '''echo bone_eqep2b > /sys/devices/bone_capemgr.*/slots'''
+
bone$ '''export SLOTS=/sys/devices/bone_capemgr.*/slots'''
 +
  bone$ '''echo PyBBIO-eqep2 > $SLOTS'''
 +
-bash: echo: write error: File exists
 +
There's a problem.  Use '''dmesg''' to see what went wrong.
 +
bone$ '''dmesg | tail'''
 +
    # [321550.694044] bone-capemgr bone_capemgr.9: slot #26: Failed verification
 +
    # [325272.156839] bone-capemgr bone_capemgr.9: part_number 'PyBBIO-eqep2', version 'N/A'
 +
    # [325272.157175] bone-capemgr bone_capemgr.9: slot #27: generic override
 +
    # [325272.157484] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 27
 +
    # [325272.157539] bone-capemgr bone_capemgr.9: slot #27: 'Override Board Name,00A0,Override Manuf,PyBBIO-eqep2'
 +
    # [325272.162296] bone-capemgr bone_capemgr.9: slot #27: Requesting part number/version based 'PyBBIO-eqep2-00A0.dtbo
 +
    # [325272.162358] bone-capemgr bone_capemgr.9: slot #27: Requesting firmware 'PyBBIO-eqep2-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
 +
    # [325272.185291] bone-capemgr bone_capemgr.9: slot #27: dtbo 'PyBBIO-eqep2-00A0.dtbo' loaded; converting to live tree
 +
    # [325272.185847] bone-capemgr bone_capemgr.9: slot #27: PyBBIO-eqep2 conflict P8.41 (#5:BB-BONELT-HDMI)
 +
    # [325272.196171] bone-capemgr bone_capemgr.9: slot #27: Failed verification
 +
There's a conflict with the HDMI pins. Try the other one
 +
  bone$ '''echo PyBBIO-eqep2b > $SLOTS'''
 +
That works!
  
 
== Reading the Encoder ==
 
== Reading the Encoder ==

Revision as of 02:22, 1 September 2015

thumb‎ Embedded Linux Class by Mark A. Yoder

Openlogo-50.png


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.

RotaryEncoder.jpg

Configuring the Encoder

If you are running a current version of Debian on your Bone (3-Mar-2015 or newer), the file for configuring the eQEP are already on your Bone.

bone$ # ls /lib/firmware/ | grep -i qep
PyBBIO-eqep0-00A0.dtbo
PyBBIO-eqep1-00A0.dtbo
PyBBIO-eqep2-00A0.dtbo
PyBBIO-eqep2b-00A0.dtbo

The different dtbo files configure for different pins. Get Derek Molloy's P8 and P9 header tables to see what pins are available.

wget https://github.com/derekmolloy/boneDeviceTree/raw/master/docs/BeagleboneBlackP8HeaderTable.pdf
wget https://github.com/derekmolloy/boneDeviceTree/raw/master/docs/BeagleboneBlackP9HeaderTable.pdf

Open the pdf files and search for eqp. eQEP2 looks like a good one, but it appears in two place. Try the first one

bone$ export SLOTS=/sys/devices/bone_capemgr.*/slots
bone$ echo PyBBIO-eqep2 > $SLOTS
-bash: echo: write error: File exists

There's a problem. Use dmesg to see what went wrong.

bone$ dmesg | tail
   # [321550.694044] bone-capemgr bone_capemgr.9: slot #26: Failed verification
   # [325272.156839] bone-capemgr bone_capemgr.9: part_number 'PyBBIO-eqep2', version 'N/A'
   # [325272.157175] bone-capemgr bone_capemgr.9: slot #27: generic override
   # [325272.157484] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 27
   # [325272.157539] bone-capemgr bone_capemgr.9: slot #27: 'Override Board Name,00A0,Override Manuf,PyBBIO-eqep2'
   # [325272.162296] bone-capemgr bone_capemgr.9: slot #27: Requesting part number/version based 'PyBBIO-eqep2-00A0.dtbo
   # [325272.162358] bone-capemgr bone_capemgr.9: slot #27: Requesting firmware 'PyBBIO-eqep2-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
   # [325272.185291] bone-capemgr bone_capemgr.9: slot #27: dtbo 'PyBBIO-eqep2-00A0.dtbo' loaded; converting to live tree
   # [325272.185847] bone-capemgr bone_capemgr.9: slot #27: PyBBIO-eqep2 conflict P8.41 (#5:BB-BONELT-HDMI)
   # [325272.196171] bone-capemgr bone_capemgr.9: slot #27: Failed verification

There's a conflict with the HDMI pins. Try the other one

bone$ echo PyBBIO-eqep2b > $SLOTS

That works!

Reading the Encoder

Put the following in a file called rotaryEncoder.js.

#!/usr/bin/env node
// 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;
         }
 }

Then run.

bone$ ./rotaryEncoder.js




thumb‎ Embedded Linux Class by Mark A. Yoder