11#!/usr/bin/python
22
3- # ===========================================================================
4- # Adafruit_BBIO.Encoder Class
5- # ===========================================================================
6- # refers to graycatlabs/PyBBIO/bbio/libraries/RotaryEncoder/rotary_encoder.py
7-
8- # BeagleBone must boot with cape-universal enabled
9- # and load the cape-universala overlay in order to
10- # use all the eQEP pins
11- #
12- # Install the latest Device Tree overlays:
13- # ========================================
14- # sudo apt-get upgrade bb-cape-overlays
15- #
16- # File: /boot/uEnv.txt
17- # ====================
18- # uname_r=4.4.62-ti-r99
19- # cmdline=coherent_pool=1M quiet cape_universal=enable
20- # cape_enable=bone_capemgr.enable_partno=cape-universala
21- #
22- # File: /sys/devices/platform/bone_capemgr/slots
23- # ==============================================
24- # 0: PF---- -1
25- # 1: PF---- -1
26- # 2: PF---- -1
27- # 3: PF---- -1
28- # 4: P-O-L- 0 Override Board Name,00A0,Override Manuf,cape-universala
29- #
30- # eqep0: P9_27, P9_92
31- # ===================
32- # config-pin P9_27 qep
33- # config-pin P9_92 qep # alias for P9_42.1
34- # cat /sys/devices/platform/ocp/48300000.epwmss/48300180.eqep/position
35- #
36- # eqep1: P8.33, P8.35
37- # ===================
38- # config-pin P8.33 qep
39- # config-pin P8.35 qep
40- # cat /sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position
41- #
42- # eqep2: P8.11, P8.12
43- # ===================
44- # config-pin P8.11 qep
45- # config-pin P8.12 qep
46- # cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
47- #
48- # alternate pins for eqep2 (mutually exclusive)
49- # eqep2b: P8.41, P8.42
50- # ====================
51- # config-pin P8.41 qep
52- # config-pin P8.42 qep
53- # cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position
54-
55- from subprocess import call
3+ from subprocess import check_output , STDOUT , CalledProcessError
564import os
5+ import logging
6+
577
588class QEP :
599
@@ -100,48 +50,63 @@ class RotaryEncoder(object):
10050 EQEP1 = 1
10151 EQEP2 = 2
10252 EQEP2b = 3
103-
53+
54+ def _run_cmd (self , cmd ):
55+ '''Runs a command. If not successful (i.e. error code different than zero),
56+ print the stderr output as a warning.
57+ '''
58+
59+ try :
60+ output = check_output (cmd , stderr = STDOUT )
61+ self ._logger .info ("_run_cmd(): cmd='{}' return code={} output={}" .format (
62+ " " .join (cmd ), 0 , output ))
63+ except CalledProcessError as e :
64+ self ._logger .warning (
65+ "_run_cmd(): cmd='{}' return code={} output={}" .format (
66+ " " .join (cmd ), e .returncode , e .output ))
67+
10468 def config_pin (self , pin ):
10569 '''
10670 config_pin()
10771 Config pin for QEP
10872 '''
109- result = call (["config-pin" , pin , "qep" ])
110- print ("config_pin> pin={0} result={1}" .format (pin , result ))
111- return result
112-
73+
74+ self ._run_cmd (["config-pin" , pin , "qep" ])
75+
11376 def cat_file (self , path ):
11477 '''
11578 cat_file()
11679 Print contents of file
11780 '''
118- result = call (["cat" , path ])
119- print ("cat_file> path={0} result={1}" .format (path , result ))
120- return result
121-
81+
82+ self ._run_cmd (["cat" , path ])
83+
12284 def __init__ (self , eqep_num ):
12385 '''
12486 RotaryEncoder(eqep_num)
125- Creates an instance of the class RotaryEncoder.
126- eqep_num determines which eQEP pins are set up.
87+ Creates an instance of the class RotaryEncoder.
88+ eqep_num determines which eQEP pins are set up.
12789 eqep_num can be: EQEP0, EQEP1, EQEP2 or EQEP2b based on which pins \
12890 the rotary encoder is connected to.
12991 '''
130- print (">>>>>>>> TEST CALL BEGIN" )
13192
132- ###################################
133- print (">>>>>> eqep0: P9_27, P9_92" )
93+ self ._logger = logging .getLogger (__name__ )
94+ self ._logger .addHandler (logging .NullHandler ())
95+
96+ # Configure eqep0
97+ self ._logger .info ("Configuring eqep0, pins: P9.27, P9.92" )
98+
13499 pin = "P9_27"
135100 self .config_pin (pin )
136101
137102 pin = "P9_92"
138103 self .config_pin (pin )
139104
140105 path = "/sys/devices/platform/ocp/48300000.epwmss/48300180.eqep/position"
141- self .cat_file (path );
106+ self .cat_file (path )
142107
143- ###################################
144- print ( ">>>>>>> eqep1: P8.33, P8.35" )
108+ # Configure eqep1
109+ self . _logger . info ( "Configuring eqep1, pins : P8.33, P8.35" )
145110
146111 pin = "P8.33"
147112 self .config_pin (pin )
@@ -152,8 +117,8 @@ def __init__(self, eqep_num):
152117 path = "/sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position"
153118 self .cat_file (path );
154119
155- ###################################
156- print ( ">>>>>>> eqep2: P8.11, P8.12" )
120+ # Configure eqep2
121+ self . _logger . info ( "Configuring eqep2, pins : P8.11, P8.12" )
157122
158123 pin = "P8.11"
159124 self .config_pin (pin )
@@ -164,8 +129,8 @@ def __init__(self, eqep_num):
164129 path = "/sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position"
165130 self .cat_file (path );
166131
167- ###################################
168- print ( ">>>>>>> eqep2b : P8.41, P8.42" )
132+ # Configure eqep2b
133+ self . _logger . info ( "Configuring eqep2, pins : P8.41, P8.42" )
169134
170135 pin = "P8.41"
171136 self .config_pin (pin )
@@ -176,17 +141,17 @@ def __init__(self, eqep_num):
176141 path = "/sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position"
177142 self .cat_file (path );
178143
179- ###################################
180- print (">>>>>>>> TEST CALL END" )
144+ self ._logger .debug ("RotaryEncoder(): eqep_num: {0}" .format (eqep_num ))
145+ self ._logger .debug ("RotaryEncoder(): self._eqep_dirs[0]: {0}" .format (self ._eqep_dirs [0 ]))
146+ self ._logger .debug ("RotaryEncoder(): self._eqep_dirs[1]: {0}" .format (self ._eqep_dirs [1 ]))
147+ self ._logger .debug ("RotaryEncoder(): self._eqep_dirs[2]: {0}" .format (self ._eqep_dirs [2 ]))
148+ self ._logger .debug ("RotaryEncoder(): self._eqep_dirs[eqep_num: {0}]: {1}" .format (eqep_num , self ._eqep_dirs [eqep_num ]))
181149
182- print ("RotaryEncoder(): eqep_num: {0}" .format (eqep_num ))
183- print ("RotaryEncoder(): self._eqep_dirs[0]: {0}" .format (self ._eqep_dirs [0 ]))
184- print ("RotaryEncoder(): self._eqep_dirs[1]: {0}" .format (self ._eqep_dirs [1 ]))
185- print ("RotaryEncoder(): self._eqep_dirs[2]: {0}" .format (self ._eqep_dirs [2 ]))
186- print ("RotaryEncoder(): self._eqep_dirs[eqep_num: {0}]: {1}" .format (eqep_num , self ._eqep_dirs [eqep_num ]))
187150 assert 0 <= eqep_num <= 3 , "eqep_num must be between 0 and 3"
151+
188152 self .base_dir = self ._eqep_dirs [eqep_num ]
189- print ("RotaryEncoder(): self.base_dir: {0}" .format (self .base_dir ))
153+ self ._logger .debug ("RotaryEncoder(): self.base_dir: {0}" .format (self .base_dir ))
154+
190155 self .enable ()
191156
192157 def enable (self ):
@@ -195,93 +160,102 @@ def enable(self):
195160 Turns the eQEP hardware ON
196161 '''
197162 enable_file = "%s/enabled" % self .base_dir
198- print ("enable(): enable_file: {0}" .format (enable_file ))
199- print ("enable(): TODO: write 1 to enable_file" )
200- #return sysfs.kernelFileIO(enable_file, '1')
201-
163+ self ._logger .debug ("enable(): enable_file: {0}" .format (enable_file ))
164+ self ._logger .warning (
165+ "enable(): TODO: not implemented, write 1 to {}" .format (enable_file ))
166+ #return sysfs.kernelFileIO(enable_file, '1')
167+
202168 def disable (self ):
203169 '''
204170 disable()
205171 Turns the eQEP hardware OFF
206172 '''
207173 enable_file = "%s/enabled" % self .base_dir
208- print ("disable(): enable_file: {0}" .format (enable_file ))
209- print ("disable(): TODO: write 0 to enable_file" )
174+ self ._logger .debug ("disable(): enable_file: {0}" .format (enable_file ))
175+ self ._logger .warning (
176+ "disable(): TODO: not implemented, write 0 to {}" .format (enable_file ))
210177 #return sysfs.kernelFileIO(enable_file, '0')
211178
212179 def setAbsolute (self ):
213180 '''
214181 setAbsolute()
215182 Set mode as Absolute
216- The position starts at zero and is incremented or
183+ The position starts at zero and is incremented or
217184 decremented by the encoder's movement
218185 '''
219186 mode_file = "%s/mode" % self .base_dir
220- print ("setAbsolute(): mode_file: {0}" .format (mode_file ))
221- print ("setAbsolute(): TODO: write 0 to mode_file" )
187+ self ._logger .debug ("setAbsolute(): mode_file: {0}" .format (mode_file ))
188+ self ._logger .warning (
189+ "setAbsolute(): TODO: not implemented, write 0 to {}" .format (mode_file ))
222190 #return sysfs.kernelFileIO(mode_file, '0')
223-
191+
224192 def setRelative (self ):
225193 '''
226194 setRelative()
227195 Set mode as Relative
228196 The position is reset when the unit timer overflows.
229197 '''
230198 mode_file = "%s/mode" % self .base_dir
231- print ("setRelative(): mode_file: {0}" .format (mode_file ))
232- print ("setRelative(): TODO: write 1 to mode_file" )
199+ self ._logger .debug ("setRelative(): mode_file: {0}" .format (mode_file ))
200+ self ._logger .warning (
201+ "setRelative(): TODO: not implemented, write 1 to {}" .format (mode_file ))
233202 #return sysfs.kernelFileIO(mode_file, '1')
234-
203+
235204 def getMode (self ):
236205 '''
237206 getMode()
238207 Returns the mode the eQEP hardware is in.
239208 '''
240209 mode_file = "%s/mode" % self .base_dir
241- print ("getMode(): mode_file: {0}" .format (mode_file ))
242- print ("getMode(): TODO: read mode_file" )
210+ self . _logger . debug ("getMode(): mode_file: {0}" .format (mode_file ))
211+ self . _logger . warning ("getMode(): TODO: read mode_file" )
243212 #return sysfs.kernelFileIO(mode_file)
244213
245214 def getPosition (self ):
246215 '''
247216 getPosition()
248217 Get the current position of the encoder.
249- In absolute mode, this attribute represents the current position
250- of the encoder.
251- In relative mode, this attribute represents the position of the
218+ In absolute mode, this attribute represents the current position
219+ of the encoder.
220+ In relative mode, this attribute represents the position of the
252221 encoder at the last unit timer overflow.
253222 '''
254223 position_file = "%s/position" % self .base_dir
255- print ("getPosition(): position_file: {0}" .format (position_file ))
224+ self . _logger . debug ("getPosition(): position_file: {0}" .format (position_file ))
256225 position_handle = open (position_file , 'r' )
257- print ("getPosition(): position_handle: {0}" .format (position_handle ))
226+ self . _logger . debug ("getPosition(): position_handle: {0}" .format (position_handle ))
258227 position = position_handle .read ()
259- print ("getPosition(): position: {0}" .format (position ))
228+ self . _logger . debug ("getPosition(): position: {0}" .format (position ))
260229 #return sysfs.kernelFileIO(position_file)
230+
261231 return position
262-
263- def setFrequency (self ,freq ):
232+
233+ def setFrequency (self , freq ):
264234 '''
265235 setFrequency(freq)
266236 Set the frequency in Hz at which the driver reports new positions.
267237 '''
268238 period_file = "%s/period" % self .base_dir
269- print ("setFrequency(): period_file: {0}" .format (period_file ))
270- print ("setFrequency(): freq: {0}" .format (period_file ))
271- print ("setFrequency(): freq: {0}" .format (freq ))
272- print ("setFrequency(): 1000000000/freq: {0}" .format (1000000000 / freq ))
273- print ("setFrequency(): str(1000000000/freq)): {0}" .format (str (1000000000 / freq )))
274- print ("setFrequency(): TODO: set period_file: {0}" .format (str (1000000000 / freq )))
239+ self ._logger .debug ("setFrequency(): period_file: {0}" .format (period_file ))
240+ self ._logger .debug ("setFrequency(): freq: {0}" .format (freq ))
241+ self ._logger .debug ("setFrequency(): 1000000000/freq: {0}" .format (1000000000 / freq ))
242+ self ._logger .debug ("setFrequency(): str(1000000000/freq)): {0}" .format (str (1000000000 / freq )))
243+ self ._logger .warning (
244+ "setFrequency(): TODO: not implemented, set {} to {}" .format (
245+ period_file , str (1000000000 / freq )))
275246 #return sysfs.kernelFileIO(period_file, str(1000000000/freq))
276-
277- def setPosition (self ,val ):
278- '''
247+
248+ def setPosition (self , val ):
249+ '''
279250 setPosition(value)
280251 Give a new value to the current position
281252 '''
282253 position_file = "%s/position" % self .base_dir
254+ self ._logger .warning (
255+ "setPosition(): TODO: not implemented, write position to {}" .format (
256+ position_file ))
283257 #return sysfs.kernelFileIO(position_file, str(val))
284-
258+
285259 def zero (self ):
286260 '''
287261 zero()s
@@ -291,7 +265,7 @@ def zero(self):
291265
292266
293267#"""
294- # encoder_test.py
268+ # encoder_test.py
295269# Rekha Seethamraju
296270# An example to demonstrate the use of the eQEP library
297271# for PyBBIO.
@@ -305,9 +279,9 @@ def zero(self):
305279#def setup():
306280# encoder.setAbsolute()
307281# encoder.zero()
308- #
282+ #
309283#def loop():
310284# print("encoder position : "+encoder.getPosition())
311285# delay(1000)
312- #
286+ #
313287#run(setup, loop)
0 commit comments