|
| 1 | +.. currentmodule:: machine |
| 2 | +.. _mimxrt_machine.Encoder: |
| 3 | + |
| 4 | +class Encoder -- Quadrature Encoder for i.MXRT MCUs |
| 5 | +==================================================== |
| 6 | + |
| 7 | +This class provides the Quadrature Encoder Service. |
| 8 | + |
| 9 | +Example usage:: |
| 10 | + |
| 11 | + # Samples for Teensy |
| 12 | + # |
| 13 | + |
| 14 | + from machine import Pin, Encoder |
| 15 | + |
| 16 | + qe = Encoder(0, Pin(0), Pin(1)) # create Quadrature Encoder object |
| 17 | + qe.value() # get current counter values |
| 18 | + qe.value(0) # Set value and cycles to 0 |
| 19 | + qe.init(cpc=128) # Specify 128 counts/cycle |
| 20 | + qe.init(index=Pin(3)) # Specify Pin 3 as Index pulse input |
| 21 | + qe.deinit() # turn off the Quadrature Encoder |
| 22 | + qe.init(match=64) # Set a match event at count 64 |
| 23 | + qe.irq(qe.IRQ_MATCH, value=100, handler=handler) |
| 24 | + # Call the function handler at a match event |
| 25 | + |
| 26 | + qe # show the Encoder object properties |
| 27 | + |
| 28 | +Constructors |
| 29 | +------------ |
| 30 | + |
| 31 | +.. class:: Encoder(id, phase_a, phase_b, *, home, match_pin, filter_ns, cpc, signed, index) |
| 32 | + |
| 33 | + Construct and return a new quadrature encoder object using the following parameters: |
| 34 | + |
| 35 | + - id: The number of the Encoder. The range is board-specific, starting with 0. |
| 36 | + For i.MX RT1015 and i.MX RT1021 based boards, this is 0..1, for i.MX RT1052, |
| 37 | + i.MX RT106x and i.MX RT11xx based boards it is 0..3. |
| 38 | + - *phase_a*. *phase_a* tells to which pin the phase a of the |
| 39 | + encoder is connected. This is usually a :ref:`machine.Pin <machine.Pin>` |
| 40 | + object, but a port may allow other values, like integers or strings, |
| 41 | + which designate a Pin in the machine.PIN class. |
| 42 | + - *phase_b*. *phase_b* tells to which pin the phase b of the |
| 43 | + encoder is connected. This is usually a :ref:`machine.Pin <machine.Pin>` |
| 44 | + object, but a port may allow other values, like integers or strings, |
| 45 | + which designate a Pin in the machine.PIN class. |
| 46 | + |
| 47 | + Keyword arguments: |
| 48 | + |
| 49 | + - *phase_a*\=value and *phase_b*\=value may be assigned by keyword arguments as well. |
| 50 | + - *home*\=value. A Pin specifier telling to which pin the home pulse is connected. |
| 51 | + At a rising slope of the home pulse the position counter is set to the init |
| 52 | + value, but the cycles counter is not changed. A *value* of *None* disables the home input. |
| 53 | + - *match_pin*\=value. A Pin specifier telling to which pin the match output is connected. |
| 54 | + This output will have a high level as long as the position counter matches the |
| 55 | + match value. The signal is generated by the encoder logic and requires no |
| 56 | + further software support. The pulse width is defined by the input signal frequency |
| 57 | + and can be very short, like 20ns, or stay, if the counter stops at the match position. |
| 58 | + A *value* of *None* disables the match output. |
| 59 | + - *filter_ns*\=value. Specifies a ns-value for the minimal time a signal has to be stable |
| 60 | + at the input to be recognized. The code does the best effort to configure the filter. |
| 61 | + The largest value is 20400 for the i.MXRT102x and 17000 for the i.MXRT105x/i.MXRT106x |
| 62 | + (1000000000 * 2550 * 4 / CPU_CLK). A value of 0 sets the filter off. |
| 63 | + - *cpc*\=value. Specify the number of counts per cycle. Since the |
| 64 | + Encoder counts all four phases of the input signal, the cpc value has to be four |
| 65 | + time the ppr value given in the encoder data sheet. The position counter will count up |
| 66 | + from the 0 up to cpc - 1, and then reset to the init value of 0 and increase |
| 67 | + the cycles counter by one. The default is: no cpc set. In that case the |
| 68 | + position counter overflows at 2**32 - 1. When counting down, the cycles counter changes |
| 69 | + at the transition from 0 to cpc - 1. |
| 70 | + - *signed*\=False|True tells, whether the value return by Encoder.value() is signed or |
| 71 | + unsigned. The default is ``True``. |
| 72 | + - *index*\=value. A Pin specifier telling to which pin the index pulse is connected. |
| 73 | + At a rising slope of the index pulse the position counter is set to the init value |
| 74 | + and the cycles counter is increased by one. A *value* of *None* disables the index input. |
| 75 | + |
| 76 | +The arguments phase_a, phase_b and filter_ns are generic across ports, all other arguments are port-specific. |
| 77 | + |
| 78 | +Methods |
| 79 | +------- |
| 80 | + |
| 81 | +.. method:: Encoder.init(*, phase_a, phase_b, home, reverse, match_pin, filter_ns, cpc, match, signed, index) |
| 82 | + |
| 83 | + Modify settings for the Encoder object. See the above constructor for details |
| 84 | + about the parameters. |
| 85 | + |
| 86 | +.. method:: Encoder.deinit() |
| 87 | + |
| 88 | + Stops the Encoder, disables interrupts and releases the resources used by the encoder. On |
| 89 | + Soft Reset, all instances of Encoder and Counter are deinitialized. |
| 90 | + |
| 91 | +.. method:: value=Encoder.value([value]) |
| 92 | + |
| 93 | + Get or set the current position counter of the Encoder as signed or unsigned 32 bit integer, |
| 94 | + depending on the signed=xxx keyword option of init(). |
| 95 | + |
| 96 | + With no arguments the actual position counter value is returned. |
| 97 | + |
| 98 | + With a single *value* argument the position counter is set to that value and the |
| 99 | + cycles counter is cleared. The methods returns the previous value. |
| 100 | + |
| 101 | +.. method:: cycles=Encoder.cycles([value]) |
| 102 | + |
| 103 | + Get or set the current cycles counter of the Encoder as signed 16 bit integer. |
| 104 | + |
| 105 | + With no arguments the actual cycles counter value is returned. |
| 106 | + |
| 107 | + With a single *value* argument the cycles counter is set to that value. The |
| 108 | + position counter is not changed. The methods returns the previous value. |
| 109 | + |
| 110 | + If the value returned by Encoder.value() is unsigned, |
| 111 | + the total position can be calculated as cycles() * cpc + value(). |
| 112 | + If the total position range is still too small, you can create your own cycles |
| 113 | + counter using the irq() callback method. |
| 114 | + |
| 115 | +.. method:: Encoder.irq(trigger=event, value=nnn, handler=handler, hard=False) |
| 116 | + |
| 117 | + Specifies, that the *handler* is called when the respective *event* happens. |
| 118 | + |
| 119 | + *event* may be: |
| 120 | + - Encoder.IRQ_MATCH Triggered when the position counter matches the match value. |
| 121 | + - Encoder.IRQ_ROLL_OVER Triggered when the position counter rolls over from the highest |
| 122 | + to the lowest value. |
| 123 | + - Encoder.IRQ_ROLL_UNDER Triggered when the position counter rolls under from the lowest |
| 124 | + to the highest value. |
| 125 | + |
| 126 | + The callback is called, when the Encoder is at *value*. For fas signals, the actual counter |
| 127 | + value may be different from the trigger value. |
| 128 | + The callback function *handler* receives a single argument, which is the Encoder object. All |
| 12
10000
9 | + events share the same callback. The event which triggers the callback can be identified |
| 130 | + with the Encoder.status() method. The argument *hard* specifies, whether the callback is called |
| 131 | + as a hard interrupt or as regular scheduled function. Hard interrupts have always a short latency, |
| 132 | + but are limited in that they must not allocate memory. Regular scheduled functions are not limited |
| 133 | + in what can be used, but depending on the load of the device execution may be delayed. |
| 134 | + Under low load, the difference in latency is minor. |
| 135 | + |
| 136 | + The default arguments values are trigger=0, handler=None, hard=False. The callback will be |
| 137 | + disabled, when called with handler=None. |
| 138 | + |
| 139 | + The position match event is triggered as long as the position and match value are identical. |
| 140 | + Therefore the position match callback is run in a one-shot fashion, and has to be enabled |
| 141 | + again when the position has changed. |
| 142 | + |
| 143 | +.. method:: Encoder.status() |
| 144 | + |
| 145 | + Returns the event status flags of the recent handled Encoder interrupt as a bitmap. |
| 146 | + The assignment of events to the bits are: |
| 147 | + |
| 148 | + - 0: Transition at the HOME signal. (*) |
| 149 | + - 1: Transition at the INDEX signal. (*) |
| 150 | + - 2: Watchdog event. (*) |
| 151 | + - 3 or Encoder.IRQ_MATCH: Position match event. |
| 152 | + - 4: Phase_A and Phase_B changed at the same time. (*) |
| 153 | + - 5 or Encoder.IRQ_ROLL_OVER: Roll-Over event of the counter. |
| 154 | + - 6 or Encoder.IRQ_ROLL_UNDER: Roll-Under event of the counter. |
| 155 | + - 7: Direction of the last count. 1 for counting up, 0 for counting down. |
| 156 | + |
| 157 | + (*) These flags are defined, but not (yet) enabled. |
| 158 | + |
| 159 | +.. method:: Encoder.id() |
| 160 | + |
| 161 | + Return the id of the Encoder. That may be helpful for interrupt callback functions. |
| 162 | + |
| 163 | +The Encoder was tested to work up to 25MHz on a Teensy. It may work at |
| 164 | +higher frequencies as well, but that was the limit of the test set-up. |
| 165 | + |
| 166 | + |
| 167 | +.. _mimxrt_machine.Counter: |
| 168 | + |
| 169 | +class Counter-- Signal counter for i.MXRT MCUs |
| 170 | +============================================== |
| 171 | + |
| 172 | +This class provides a Counter service using the Quadrature Encoder module |
| 173 | + |
| 174 | +Example usage:: |
| 175 | + |
| 176 | + # Samples for Teensy |
| 177 | + # |
| 178 | + |
| 179 | + from machine import Pin, Counter |
| 180 | + |
| 181 | + counter = Counter(0, Pin(0)) # create Counter object |
| 182 | + counter.value() # get current counter value |
| 183 | + counter.value(0) # Set the counter to 0 |
| 184 | + counter.init(cpc=128) # Specify 128 counts/cycle |
| 185 | + counter.deinit() # turn off the Counter |
| 186 | + counter.init(match=1000) # Create a match event at count 1000 |
| 187 | + counter.irq(Counter.IRQ_MATCH, handler) # Call the function handler at a counter match |
| 188 | + |
| 189 | + counter # show the Counter object properties |
| 190 | + |
| 191 | +Constructors |
| 192 | +------------ |
| 193 | + |
| 194 | +.. class:: Counter(id, src, *, direction, match_pin, filter_ns, cpc, match, signed, index) |
| 195 | + |
| 196 | + Construct and return a new Counter object using the following parameters: |
| 197 | + |
| 198 | + - id: The number of the Counter. The range is board-specific, starting with 0. |
| 199 | + For i.MX RT1015 and i.MX RT1021 based boards, this is 0..1, for i.MX RT1052, |
| 200 | + i.MX RT106x and i.MX RT11xx based boards it is 0..3. |
| 201 | + - *src*. *src* tells to which pin the counter |
| 202 | + is connected. This is usually a :ref:`machine.Pin <machine.Pin>` |
| 203 | + object, but a port may allow other values, like integers or strings, |
| 204 | + which designate a Pin in the machine.PIN class. |
| 205 | + |
| 206 | + Keyword arguments: |
| 207 | + |
| 208 | + - *src*\=value may be assigned by a keyword argument as well. |
| 209 | + - *direction*\=value. Specifying the direction of counting. Suitable values are: |
| 210 | + |
| 211 | + - Counter.UP: Count up, with a roll-over to 0 at 2**48-1. |
| 212 | + - Counter.DOWN: Count down, with a roll-under to 2**48-1 at 0. |
| 213 | + - a :ref:`machine.Pin <machine.Pin>` object. The level at that pin controls |
| 214 | + the counting direction. Low: Count up, High: Count down. |
| 215 | + |
| 216 | + - *match_pin*\=value. A Pin specifier telling to which pin the match output is connected. |
| 217 | + This output will have a high level as long as the lower 32 bit of the counter value |
| 218 | + matches the match value. The signal is generated by the encoder logic and |
| 219 | + requires no further software support. A *value* of *None* disables the match output. |
| 220 | + - *filter_ns*\=value. Specifies a ns-value for the minimal time a signal has to be stable |
| 221 | + at the input to be recognized. The code does the best effort to configure the filter. |
| 222 | + The largest value is 20400 for the i.MXRT102x and 17000 for the i.MXRT105x/i.MXRT106x |
| 223 | + (1000000000 * 2550 * 4 / CPU_CLK). A value of 0 sets the filter off. |
| 224 | + - *cpc*\=value. Specify the number of counts per cycle.The counter will count up |
| 225 | + from the 0 up to cpc - 1, and then reset to 0 and increase |
| 226 | + the cycles counter by one. The default is: no cpc set. In that case the |
| 227 | + counter overflows at 2**32 - 1. If the counting direction is DOWN, then the cycles |
| 228 | + counter is decreased when counting from 0 to cpc-1. |
| 229 | + - *signed*\=False|True tells, whether the value returned by Counter.value() is signed or |
| 230 | + unsigned. The default is ``True``. |
| 231 | + - *index*\=value. A Pin specifier telling to which pin the index pulse is connected. |
| 232 | + At a rising slope of the index pulse the counter is set to 0 |
| 233 | + and the cycles counter is increased by one. A *value* of *None* disables the index input. |
| 234 | + |
| 235 | +The arguments input, direction and filter are generic across ports, all other arguments are port-specific. |
| 236 | + |
| 237 | + |
| 238 | +Methods |
| 239 | +------- |
| 240 | + |
| 241 | +.. method:: Counter.init( *, src, direction, match_pin, filter_ns, cpc, match, signed, index) |
| 242 | + |
| 243 | + Modify settings for the Counter object. See the above constructor for details |
| 244 | + about the parameters. |
| 245 | + |
| 246 | +.. method:: Counter.deinit() |
| 247 | + |
| 248 | + Stops the Counter, disables interrupts and releases the resources used by the encoder. On |
| 249 | + Soft Reset, all instances of Encoder and Counter are deinitialized. |
| 250 | + |
| 251 | +.. method:: value=Counter.value([value]) |
| 252 | + |
| 253 | + Get or set the current event value of the Counter. The value is returned as a signed or |
| 254 | + unsigned 32 bit integer, as defined with the signed=True/False option of init() |
| 255 | + |
| 256 | + With a single *value* argument the counter is set to the lower 32 bits of that value, |
| 257 | + and the cycles counter to the bits 32-47 of the supplied number. The methods returns the |
| 258 | + previous value. |
| 259 | + |
| 260 | +.. method:: cycles=Counter.cycles([value]) |
| 261 | + |
| 262 | + Get or set the current cycles counter of the counter as signed 16 bit integer. |
| 263 | + The value represents the overflow or underflow events of the 32bit basic counter. |
| 264 | + A total count can be calculated as cycles() * 0x100000000 + value(). |
| 265 | + If the total count range is still too small, you can create your own overflow |
| 266 | + counter using the irq() callback method. |
| 267 | + |
| 268 | + With no arguments the actual cycles counter value is returned. |
| 269 | + |
| 270 | + With a single *value* argument the cycles counter is set to that value. The |
| 271 | + base counter is not changed. The methods returns the previous value. |
| 272 | + |
| 273 | +.. method:: Counter.irq(trigger=event, value=nnn, handler=handler, hard=False) |
| 274 | + |
| 275 | + Specifies, that the *handler* is called when the respective *event* happens. |
| 276 | + |
| 277 | + *event* may be: |
| 278 | + - Counter.IRQ_COMPARE Triggered when the positions counter matches the match value. |
| 279 | + - Counter.IRQ_ROLL_OVER Triggered when the position counter rolls over from the highest |
| 280 | + to the lowest value. |
| 281 | + - Counter.IRQ_ROLL_UNDER Triggered when the position counter rolls under from the lowest |
| 282 | + to the highest value. |
| 283 | + |
| 284 | + The callback is called, when the Counter is at *value*. For fast signals, the actual counter |
| 285 | + value may be different from the trigger value. |
| 286 | + The callback function *handler* receives a single argument, which is the Counter object. All |
| 287 | + events share the same callback. The event which triggers the callback can be identified |
| 288 | + with the Counter.status() method. The argument *hard* specifies, whether the callback is called |
| 289 | + as a hard interrupt or as regular scheduled function. Hard interrupts have always a short latency, |
| 290 | + but are limited in that they must not allocate memory. Regular scheduled functions are not limited |
| 291 | + in what can be used, but depending on the load of the device execution may be delayed. |
| 292 | + Under low load, the difference in latency is minor. |
| 293 | + |
| 294 | + The default arguments values are trigger=0, handler=None, hard=False. The callback will be |
| 295 | + disabled, when called with handler=None. |
| 296 | + |
| 297 | + The counter match event is triggered as long as the lower 32 bit of the counter and match |
| 298 | + value match. Therefore the counter match callback is run in a one-shot fashion, and has to be enabled |
| 299 | + again when the counter value has changed. |
| 300 | + |
| 301 | +.. method:: Counter.status() |
| 302 | + |
| 303 | + Returns the event status flags of the recent handled Counter interrupt as a bitmap. |
| 304 | + The assignment of events to the bits are: |
| 305 | + |
| 306 | + - 0: Transition at the HOME signal. (*) |
| 307 | + - 1: Transition at the INDEX signal. (*) |
| 308 | + - 2: Watchdog event. (*) |
| 309 | + - 3 or Counter.IRQ_MATCH: Position match event. |
| 310 | + - 4: Phase_A and Phase_B changed at the same time. (*) |
| 311 | + - 5 or Counter.IRQ_ROLL_OVER: Roll-Over event of the counter. |
| 312 | + - 6 or Counter.IRQ_ROLL_UNDER: Roll-Under event of the counter. |
| 313 | + - 7: Direction of the last count. 1 for counting up, 0 for counting down. |
| 314 | + |
| 315 | + (*) These flags are defined, but not (yet) enabled. |
| 316 | + |
| 317 | +.. method:: Counter.id() |
| 318 | + |
| 319 | + Return the id of the Counter. That may be helpful for interrupt callback functions. |
| 320 | + |
| 321 | + |
| 322 | +The counter was tested up to 50MHz. It may work at higher frequencies |
| 323 | +as well, but that was the limit of the test set-up. |
| 324 | + |
| 325 | +Pin Assignment |
| 326 | +-------------- |
| 327 | + |
| 328 | +Pins are specified in the same way as for the Pin class. The pins available for an |
| 329 | +assignment to the Encoder or Counter are: |
| 330 | + |
| 331 | +**IMXRT1010_EVK**: |
| 332 | + |
| 333 | + Not supported. |
| 334 | + |
| 335 | +**IMXRT1015_EVK**: |
| 336 | + |
| 337 | + J30, pins 1 and 3, with the pin names "ENC1" and "ENC2". |
| 338 | + |
| 339 | +**IMXRT1020_EVK**: |
| 340 | + |
| 341 | + Pins D0 and D1. |
| 342 | + |
| 343 | +**IMXRT1050_EVK**, **IMXRT1050_EVKB**, **IMXRT1060_EVK**, **IMXRT1064_EBK**: |
| 344 | + |
| 345 | + Pins D2, D4, D5, D8, D9, D10, D11, D12, D13, D14, D15, A4, A5. |
| 346 | + Depending on the board configuration, not all pins may be wired. |
| 347 | + Pins D2, D4 and D5 cannot be used for the match output. |
| 348 | + |
| 349 | +**IMXRT1170_EVK**: |
| 350 | + |
| 351 | + Pins D0, D1, D2. |
| 352 | + |
| 353 | + D2 is connected to the 1G PHY chip as well. So levels may be distorted. |
| 354 | + |
| 355 | +**Teensy 4.0**: |
| 356 | + |
| 357 | + Pins 0, 1, 2, 3, 4, 5, 7, 8, 26, 27, 30, 31, 32, 33. Pin 0 and 5 share the |
| 358 | + same signal and cannot be used independently. |
| 359 | + Pins 26, 27, 30 and 31 cannot be used for the match output. |
| 360 | + |
| 361 | +**Teensy 4.1**: |
| 362 | + |
| 363 | + Pins 0, 1, 2, 3, 4, 5, 7, 8, 26, 27, 30, 31, 32, 33, 37, 42, 43, 44, 45, 46 and 47. |
| 364 | + Pins 26, 27, 30 and 31 cannot be used for the match output. |
| 365 | + Some pins are assigned to the same signal and cannot be used independently. These are: |
| 366 | + |
| 367 | + - Pin 0, 5 and 37, |
| 368 | + - Pin 2 and 43, |
| 369 | + - Pin 3 and 42, and |
| 370 | + - Pin 4 and 47. |
| 371 | + |
| 372 | +**Seeed ARCH MIX** |
| 373 | + |
| 374 | + Pins J3_14, J3_15, J4_19, J4_20, J5_15, J5_16, J5_17, J5_22, J5_23, J5_24, J5_25 and J5_26. |
| 375 | + Pins J3_14 and J3_15 cannot be used for the match output. |
| 376 | + |
| 377 | +**Olimex RT1010Py** |
| 378 | + |
| 379 | + Not supported. |
0 commit comments