Difference between revisions of "EBC Reading a Rotary Encoder via eQEP"
m (→Wiring the Encoder) |
m (→Wiring the Encoder) |
||
(13 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:EmbeddedBeagleClass]] | [[Category:EmbeddedBeagleClass]] | ||
− | [[Category: | + | [[Category:ECE497 |exer35]] |
{{YoderHeadDeb}} | {{YoderHeadDeb}} | ||
− | A common way to read a rotational input is with a quadrature encoder such as these rotary encoders from [https://www.sparkfun.com/products/9117 SparkFun] and [http://www.adafruit.com/products/377 Adafruit]. | + | A common way to read a rotational input is with a quadrature encoder such as these rotary encoders from [https://www.sparkfun.com/products/9117 SparkFun] and [http://www.adafruit.com/products/377 Adafruit]. BeagleBone Black has an Enhanced Quadrature Encoder Pulse (eQEP) Module (See section 15.4 of the TRM) that makes reading encoders easy. |
+ | |||
+ | This is updated to use the Linux counter subsystem which was introduced with the 5.2 version of the kernel. | ||
+ | |||
+ | See https://adafruit-beaglebone-io-python.readthedocs.io/en/latest/Encoder.html for a code example based on Adafruit_BBIO. | ||
== Wiring the Encoder == | == 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. [[EBC_Getting_Exercise_Support_Materials | Derek Molloy's P8/P9 Header chart]] shows eQEP2B_in is on pin P8_11 and eQEP2A_in is on P8_12. | 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. [[EBC_Getting_Exercise_Support_Materials | Derek Molloy's P8/P9 Header chart]] shows eQEP2B_in is on pin P8_11 and eQEP2A_in is on P8_12. | ||
− | [[File:RotaryEncoder.jpg]] | + | [[File:RotaryEncoder.jpg]] [[File:RotaryEncoder2.jpg]] |
+ | |||
+ | // Black OR Pocket | ||
+ | // eQEP0: P9.27 and P9.42 OR P1_33 and P2_34 | ||
+ | // eQEP1: P9.33 and P9.35 | ||
+ | // eQEP2: P8.11 and P8.12 OR P2_24 and P2_33 | ||
+ | |||
+ | // AI | ||
+ | // eQEP1: P8.33 and P8.35 | ||
+ | // eQEP2: P8.11 and P8.12 or P9.19 and P9.41 | ||
+ | // eQEP3: P8.24 and P8.25 or P9.27 and P9.42 | ||
+ | |||
+ | Let's use eQEP2. First set the pin muxes: | ||
+ | bone$ '''config-pin P8_11 qep''' | ||
+ | bone$ '''config-pin P8_12 qep''' | ||
+ | |||
+ | Then change to the counter directory: (Note, that count2 is because we are using eEQP2.) | ||
+ | bone$ '''cd /sys/bus/counter/devices/counter2/count0''' | ||
+ | bone$ '''ls''' | ||
+ | ceiling enable function_available signal0_action signal1_action | ||
+ | count function name signal0_action_available signal1_action_available | ||
+ | |||
+ | Set the max range and turn on: | ||
+ | bone$ '''sudo chmod o+w *''' (Only do once. It may not be needed at all.) | ||
+ | bone$ '''echo 1000000 > ceiling''' | ||
+ | bone$ '''echo 1 > enable''' | ||
+ | |||
+ | Then read count. Try reading then turning the encoder. | ||
+ | bone$ '''cat count''' | ||
+ | 2 | ||
+ | bone$ '''cat count''' | ||
+ | 999998 | ||
+ | |||
+ | == Ignore the rest of this for now== | ||
+ | |||
+ | == On the Blue == | ||
+ | |||
+ | bone$ '''cd /opt/source/rcpy''' | ||
+ | bone$ '''sudo python3 setup.py install''' | ||
+ | |||
+ | You should then be able to run the python example. | ||
− | == Configuring the Encoder == | + | == Configuring the Encoder (skip) == |
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. | 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. | ||
Line 43: | Line 87: | ||
There's a conflict with the HDMI pins. Try the other one | There's a conflict with the HDMI pins. Try the other one | ||
bone$ '''echo PyBBIO-eqep2b > $SLOTS''' | bone$ '''echo PyBBIO-eqep2b > $SLOTS''' | ||
− | That works! | + | That works! Wire encoder to '''P8_11''' and '''P8_12''' and then: |
+ | bone '''cd /sys/devices/ocp.3/48304000.epwmss/48304180.eqep/''' | ||
+ | bone$ '''ls''' | ||
+ | driver enabled modalias mode period position power subsystem uevent | ||
+ | bone$ '''cat position''' | ||
+ | 0 | ||
+ | Turn the encoder and '''cat''' again. | ||
+ | bone$ '''cat position''' | ||
+ | 12 | ||
+ | Try turning the other way. | ||
== Reading the Encoder == | == Reading the Encoder == | ||
− | + | In '''exercises/sensors/eQEP''' you'll find file called '''rotaryEncoder.js'''. | |
#!/usr/bin/env node | #!/usr/bin/env node | ||
// This uses the eQEP hardware to read a rotary encoder | // This uses the eQEP hardware to read a rotary encoder | ||
− | // echo | + | // export SLOTS=/sys/devices/bone_capemgr.*/slots |
+ | // echo PyBBIO-eqep2b > > $SLOTS | ||
+ | // Wire encoder to P8_11 and P8_12 when using eQEP2. | ||
+ | |||
var b = require('bonescript'), | var b = require('bonescript'), | ||
fs = require('fs'); | fs = require('fs'); | ||
Line 81: | Line 137: | ||
} | } | ||
− | + | Run it with: | |
− | bone$ ./rotaryEncoder.js | + | bone$ '''./rotaryEncoder.js''' |
{{YoderFoot}} | {{YoderFoot}} |
Revision as of 11:20, 30 June 2022
Embedded Linux Class by Mark A. Yoder
A common way to read a rotational input is with a quadrature encoder such as these rotary encoders from SparkFun and Adafruit. BeagleBone Black has an Enhanced Quadrature Encoder Pulse (eQEP) Module (See section 15.4 of the TRM) that makes reading encoders easy.
This is updated to use the Linux counter subsystem which was introduced with the 5.2 version of the kernel.
See https://adafruit-beaglebone-io-python.readthedocs.io/en/latest/Encoder.html for a code example based on Adafruit_BBIO.
Contents
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.
// Black OR Pocket // eQEP0: P9.27 and P9.42 OR P1_33 and P2_34 // eQEP1: P9.33 and P9.35 // eQEP2: P8.11 and P8.12 OR P2_24 and P2_33 // AI // eQEP1: P8.33 and P8.35 // eQEP2: P8.11 and P8.12 or P9.19 and P9.41 // eQEP3: P8.24 and P8.25 or P9.27 and P9.42
Let's use eQEP2. First set the pin muxes:
bone$ config-pin P8_11 qep bone$ config-pin P8_12 qep
Then change to the counter directory: (Note, that count2 is because we are using eEQP2.)
bone$ cd /sys/bus/counter/devices/counter2/count0 bone$ ls ceiling enable function_available signal0_action signal1_action count function name signal0_action_available signal1_action_available
Set the max range and turn on:
bone$ sudo chmod o+w * (Only do once. It may not be needed at all.) bone$ echo 1000000 > ceiling bone$ echo 1 > enable
Then read count. Try reading then turning the encoder.
bone$ cat count 2 bone$ cat count 999998
Ignore the rest of this for now
On the Blue
bone$ cd /opt/source/rcpy bone$ sudo python3 setup.py install
You should then be able to run the python example.
Configuring the Encoder (skip)
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! Wire encoder to P8_11 and P8_12 and then:
bone cd /sys/devices/ocp.3/48304000.epwmss/48304180.eqep/ bone$ ls driver enabled modalias mode period position power subsystem uevent bone$ cat position 0
Turn the encoder and cat again.
bone$ cat position 12
Try turning the other way.
Reading the Encoder
In exercises/sensors/eQEP you'll find file called rotaryEncoder.js.
#!/usr/bin/env node // This uses the eQEP hardware to read a rotary encoder // export SLOTS=/sys/devices/bone_capemgr.*/slots // echo PyBBIO-eqep2b > > $SLOTS // Wire encoder to P8_11 and P8_12 when using eQEP2. 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; } }
Run it with:
bone$ ./rotaryEncoder.js
Embedded Linux Class by Mark A. Yoder