1414 'Please upgrade your kernel to use this module.\n '
1515 'Your Linux kernel version is {}.' .format (platform .release ()))
1616
17+
18+ # eQEP module channel identifiers
19+ # eQEP 2 and 2b are the same channel, exposed on two different sets of pins,
20+ # which are mutually exclusive
1721eQEP0 = 0
1822eQEP1 = 1
1923eQEP2 = 2
2024eQEP2b = 3
2125
26+ # Definitions to initialize the eQEP modules
2227_OCP_PATH = "/sys/devices/platform/ocp"
2328_eQEP_DEFS = [
2429 {'channel' : 'eQEP0' , 'pin_A' : 'P9_92' , 'pin_B' : 'P9_27' ,
@@ -71,12 +76,31 @@ def __init__(self, channel, pin_A, pin_B, sys_path):
7176
7277
7378class RotaryEncoder (object ):
79+ '''
80+ Rotary encoder class abstraction to control a given QEP channel.
81+
82+ Constructor:
83+ eqep_num: QEP object that determines which channel to control
84+
85+ Properties:
86+ position: current position of the encoder
87+ frequency: frequency at which the encoder reports new positions
88+ enabled: (read only) true if the module is enabled, false otherwise
89+ mode: current mode of the encoder (absolute: 0, relative: 1)
90+
91+ Methods:
92+ enable: enable the QEP channel
93+ disable: disable the QEP channel
94+ setAbsolute: shortcut for setting the mode to absolute
95+ setRelative: shortcut for setting the mode to relative
96+ zero: shortcut for setting the position to 0
97+ '''
7498
7599 def _run_cmd (self , cmd ):
76100 '''Runs a command. If not successful (i.e. error code different than
77101 zero), print the stderr output as a warning.
78- '''
79102
103+ '''
80104 try :
81105 output = check_output (cmd , stderr = STDOUT )
82106 self ._logger .info (
@@ -87,11 +111,8 @@ def _run_cmd(self, cmd):
87111 "_run_cmd(): cmd='{}' return code={} output={}" .format (
88112 " " .join (cmd ), e .returncode , e .output ))
89113
90- def config_pin (self , pin ):
91- '''
92- config_pin()
93- Config pin for QEP
94- '''
114+ def _config_pin (self , pin ):
115+ '''Configures a pin in QEP mode using the `config-pin` binary'''
95116
96117 self ._run_cmd (["config-pin" , pin , "qep" ])
97118
@@ -103,8 +124,11 @@ def __init__(self, eqep_num):
103124 Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b,
104125 based on which pins the physical rotary encoder
105126 is connected to.
106-
127+
107128 '''
129+ # nanoseconds factor to convert period to frequency and back
130+ self ._NS_FACTOR = 1000000000
131+
108132 # Set up logging at the module level
109133 self ._logger = logging .getLogger (__name__ )
110134 self ._logger .addHandler (logging .NullHandler ())
@@ -117,28 +141,41 @@ def __init__(self, eqep_num):
117141 self ._eqep .sys_path ))
118142
119143 # Configure the pins for the given channel
120- self .config_pin (self ._eqep .pin_A )
121- self .config_pin (self ._eqep .pin_B )
144+ self ._config_pin (self ._eqep .pin_A )
145+ self ._config_pin (self ._eqep .pin_B )
122146
123147 self ._logger .debug (
124148 "RotaryEncoder(): sys node: {0}" .format (self ._eqep .sys_path ))
125149
126150 # Enable the channel upon initialization
127151 self .enable ()
128152
129- def _setEnable (self , value ):
153+ @property
154+ def enabled (self ):
155+ '''Returns the enabled status of the module:
156+
157+ true: module is enabled
158+ false: module is disabled
159+ '''
160+ isEnabled = bool (int (self ._eqep .node .enabled ))
161+
162+ return isEnabled
163+
164+ def _setEnable (self , enabled ):
130165 '''Turns the eQEP hardware ON or OFF
131166
132167 value (int): 1 represents enabled, 0 is disabled
168+
133169 '''
134- if value < 0 or value > 1 :
170+ enabled = int (enabled )
171+ if enabled < 0 or enabled > 1 :
135172 raise ValueError (
136173 'The "enabled" attribute can only be set to 0 or 1. '
137- 'You attempted to set it to {}.' .format (value ))
174+ 'You attempted to set it to {}.' .format (enabled ))
138175
139- self ._eqep .node .enabled = str (int ( value ) )
176+ self ._eqep .node .enabled = str (enabled )
140177 self ._logger .info ("Channel: {}, enabled: {}" .format (
141- self ._eqep .channel , self ._eqep .node .enabled ))
178+ self ._eqep .channel , self ._eqep .node .enabled ))
142179
143180 def enable (self ):
144181 '''Turns the eQEP hardware ON'''
@@ -150,56 +187,59 @@ def disable(self):
150187
151188 self ._setEnable (0 )
152189
153- def _setMode (self , value ):
190+ @property
191+ def mode (self ):
192+ '''Returns the mode the eQEP hardware is in (absolute or relative).
193+
194+ '''
195+ mode = int (self ._eqep .node .mode )
196+
197+ if mode == 0 :
198+ mode_name = "absolute"
199+ elif mode == 1 :
200+ mode_name = "relative"
201+ else :
202+ mode_name = "invalid"
203+
204+ self ._logger .debug ("getMode(): Channel {}, mode: {} ({})" .format (
205+ self ._eqep .channel , mode , mode_name ))
206+
207+ return mode
208+
209+ @mode .setter
210+ def mode (self , mode ):
154211 '''Sets the eQEP mode as absolute (0) or relative (1).
155212 See the setAbsolute() and setRelative() methods for
156213 more information.
157214
158215 '''
159- if value < 0 or value > 1 :
216+ mode = int (mode )
217+ if mode < 0 or mode > 1 :
160218 raise ValueError (
161219 'The "mode" attribute can only be set to 0 or 1. '
162- 'You attempted to set it to {}.' .format (value ))
220+ 'You attempted to set it to {}.' .format (mode ))
163221
164- self ._eqep .node .mode = str (int ( value ) )
222+ self ._eqep .node .mode = str (mode )
165223 self ._logger .debug ("Mode set to: {}" .format (
166- self ._eqep .node .mode ))
224+ self ._eqep .node .mode ))
167225
168226 def setAbsolute (self ):
169227 '''Sets the eQEP mode as Absolute:
170228 The position starts at zero and is incremented or
171229 decremented by the encoder's movement
172230
173231 '''
174- self ._setMode ( 0 )
232+ self .mode = 0
175233
176234 def setRelative (self ):
177235 '''Sets the eQEP mode as Relative:
178236 The position is reset when the unit timer overflows.
179237
180238 '''
181- self ._setMode (1 )
182-
183- def getMode (self ):
184- '''Returns the mode the eQEP hardware is in (absolute or relative).
185-
186- '''
239+ self .mode = 1
187240
188- mode = int (self ._eqep .node .mode )
189-
190- if mode == 0 :
191- mode_name = "absolute"
192- elif mode == 1 :
193- mode_name = "relative"
194- else :
195- mode_name = "invalid"
196-
197- self ._logger .debug ("getMode(): Channel {}, mode: {} ({})" .format (
198- self ._eqep .channel , mode , mode_name ))
199-
200- return mode
201-
202- def getPosition (self ):
241+ @property
242+ def position (self ):
203243 '''Returns the current position of the encoder.
204244 In absolute mode, this attribute represents the current position
205245 of the encoder.
@@ -209,31 +249,51 @@ def getPosition(self):
209249 '''
210250 position = self ._eqep .node .position
211251
212- self ._logger .debug ("getPosition() : Channel {}, position: {}" .format (
252+ self ._logger .debug ("Get position : Channel {}, position: {}" .format (
213253 self ._eqep .channel , position ))
214254
215255 return int (position )
216256
217- def setFrequency (self , freq ):
257+ @position .setter
258+ def position (self , position ):
259+ '''Sets the current position to a new value'''
260+
261+ position = int (position )
262+ self ._eqep .node .position = str (position )
263+
264+ self ._logger .debug ("Set position: Channel {}, position: {}" .format (
265+ self ._eqep .channel , position ))
266+
267+
268+ @property
269+ def frequency (self ):
218270 '''Sets the frequency in Hz at which the driver reports
219271 new positions.
220272
221273 '''
222- ns_factor = 1000000000
223- period = ns_factor / freq # Period in nanoseconds
224- self ._eqep .node .period = str (period )
274+ frequency = self ._eqep .node .period / self ._NS_FACTOR
275+
225276 self ._logger .debug (
226- "setFrequency (): Channel {}, frequency: {} Hz, "
277+ "Set frequency (): Channel {}, frequency: {} Hz, "
227278 "period: {} ns" .format (
228- self ._eqep .channel , freq , period ))
279+ self ._eqep .channel , frequency , period ))
229280
230- def setPosition (self , position ):
231- '''Sets the current position to a new value'''
281+ return frequency
232282
233- position = int (position )
234- self ._eqep .node .position = str (position )
283+ @frequency .setter
284+ def frequency (self , frequency ):
285+ '''Sets the frequency in Hz at which the driver reports
286+ new positions.
287+
288+ '''
289+ period = self ._NS_FACTOR / frequency # Period in nanoseconds
290+ self ._eqep .node .period = str (period )
291+ self ._logger .debug (
292+ "Set frequency(): Channel {}, frequency: {} Hz, "
293+ "period: {} ns" .format (
294+ self ._eqep .channel , frequency , period ))
235295
236296 def zero (self ):
237297 '''Resets the current position to 0'''
238298
239- return self .setPosition ( 0 )
299+ self .position = 0
0 commit comments