Skip to content

Conversation

IhorNehrutsa
Copy link
Contributor

This PR was inspired by tests/extmod_hardware: Add a test for machine.PWM freq and duty. #16147

Summary

This adds hardware tests for machine.Counter and machine.Encoder.
It requires two jumper wires between two pairs of pins, outputs, and inputs.
output1: Pin() -> input1: Pin()
output2: Pin() -> input2: Pin()
or
output1: PWM() -> input1: Pin()
output2: PWM() -> input2: Pin()
This PR is trying to use the same pins as in #16147.

machine.Pin and machine.PWM generates pulses and controls the direction of counting,
and machine.Counter/machine.Encoder inputs both.
machine.Timer generates a period for counting pulses.

machine.Counter/machine.Encoder value and irq callback tests are performed.

Trade-offs and Alternatives

A lot of PR's:

Testing

Currently supported on ports:

  • esp32 # 8766 tested on ESP32 board (except counter.irq() with trigger=Counter.IRQ_ZERO)
  • esp32 # 7582 ???
  • esp32 # 8253 ???
  • esp32 # 12346 ???
  • mimxrt # 12347 ???
  • esp8266 ???
  • rp2 ???
  • samd21 ???
  • PSoC6 ???

Copy link

codecov bot commented Feb 12, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.53%. Comparing base (bfb1bee) to head (d6486e8).
Report is 367 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #16743      +/-   ##
==========================================
- Coverage   98.58%   98.53%   -0.06%     
==========================================
  Files         167      169       +2     
  Lines       21590    21806     +216     
==========================================
+ Hits        21285    21487     +202     
- Misses        305      319      +14     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@IhorNehrutsa
Copy link
Contributor Author

Output:

>>> %run -c $EDITOR_CONTENT
MATCH:500000, MATCH_1000:1500

Test the wire connections: output1 -> input1.
output1->input1: Pin(4) 1 -> Pin(5) 1
output1->input1: Pin(4) 0 -> Pin(5) 0
Ok.

Test the wire connections: output2 -> input2.
output2->input2: Pin(16) 1 -> Pin(17) 1
output2->input2: Pin(16) 0 -> Pin(17) 0
Ok.

# =====================================================================================
1) Testing the count of pulses on 'src' Pin() if 'direction' is a constant.
'src': 'output1' Pin(4) -> 'input1' Pin(5)
# -------------------------------------------------------------------------------------
1.1) Testing the count of pulses 'output1' Pin(4) UP at the RISING edge.
Counter(0), src=Pin(5), direction=Counter.UP, edge=Counter.RISING, filter_ns=0) value: 0
Toggle Pin(4) 1 time(s).
 value: Pin(4) 0 -> 1
Counter(0), src=Pin(5), direction=Counter.UP, edge=Counter.RISING, filter_ns=0) value: 1
Toggle Pin(4) 1 time(s).
 value: Pin(4) 1 -> 0
Counter(0), src=Pin(5), direction=Counter.UP, edge=Counter.RISING, filter_ns=0) value: 1
Ok.

# -------------------------------------------------------------------------------------
1.2) Testing the count of pulses 'output1' Pin(4) DOWN at the FALLING edge.
Counter(0), src=Pin(5), direction=Counter.DOWN, edge=Counter.FALLING, filter_ns=0) value: 0
Toggle Pin(4) 1 time(s).
 value: Pin(4) 0 -> 1
Counter(0), src=Pin(5), direction=Counter.DOWN, edge=Counter.FALLING, filter_ns=0) value: 0
Toggle Pin(4) 1 time(s).
 value: Pin(4) 1 -> 0
Counter(0), src=Pin(5), direction=Counter.DOWN, edge=Counter.FALLING, filter_ns=0) value: -1
Ok.

# =====================================================================================
2) Testing the count of pulses on 'src' Pin() if 'direction' is a Pin().
'output1' Pin(4) -> 'input1' Pin(5) is 'src' of counted pulses.
'output2' Pin(16) -> 'input2' Pin(17) is 'direction' of counting.
# -------------------------------------------------------------------------------------
2.1) Testing the count of pulses 'output1' Pin(4) DOWN when 'direction='Pin(16) is 0 at RISING-FALLING edges.
'src': 'output1' Pin(4) -> 'input1' Pin(5)
'direction': Pin(16) 0 -> Pin(17) 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, filter_ns=0) value: 0
Toggle Pin(4) 1 time(s).
 value: Pin(4) 0 -> 1
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, filter_ns=0) value: -1
Toggle Pin(4) 1 time(s).
 value: Pin(4) 1 -> 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, filter_ns=0) value: -2
Ok.

# -------------------------------------------------------------------------------------
2.2) Testing the count of pulses 'output1' Pin(4) UP when 'direction='Pin(16) is 1 at RISING-FALLING edges.
'src': 'output1' Pin(4) -> 'input1' Pin(5)
'direction': Pin(16) 1 -> Pin(17) 1
Toggle Pin(4) 1 time(s).
 value: Pin(4) 0 -> 1
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, filter_ns=0) value: -1
Toggle Pin(4) 1 time(s).
 value: Pin(4) 1 -> 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, filter_ns=0) value: 0
Ok.

# =====================================================================================
3) Testing the count of pulses on 'src' Pin() UP to (2^16 + 1000) and DOWN to -(2^16 + 1000) and callbacks.
'output1' Pin(4) -> 'input1' Pin(5) is 'src' of counted pulses.
'output2' Pin(16) -> 'input2' Pin(17) is 'direction' of counting.
# -------------------------------------------------------------------------------------
3.1) Testing the count of pulses 'output1' Pin(4) UP to (2^16 + 1000).
Toggle Pin(4) 66536 time(s).
  callback Сounter value:      1000 status:  4
 value: Pin(4) 0 -> 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, match=1000, match0=0, filter_ns=0) value: 66536 dif: 2000
Ok.

# -------------------------------------------------------------------------------------
3.2) Testing the count of pulses 'output1' Pin(4) DOWN to -(2^16 + 1000).
Toggle Pin(4) 133072 time(s).
  callback Сounter value:     -1000 status:  5
 value: Pin(4) 0 -> 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING | Counter.FALLING, match=-1000, match0=0, filter_ns=0) value: -66536 dif: 0
Ok.

# =====================================================================================
4) Testing the count of pulses UP on 'src' Pin() and DOWN on '_src' Pin().
'output1' {output1} -> 'input1' {input1} is 'src' counted UP pulses.
'output2' {output2} -> 'input2' {input2} is '_src' counted DOWN pulses.
# -------------------------------------------------------------------------------------
4.1) Testing the count of pulses 'output1' Pin(4) UP on 'src' input1 Pin(4) at RISING-FALLING edges.
Counter(0), src=Pin(5), _src=Pin(17), edge=Counter.RISING | Counter.FALLING, match=1000, match0=0, filter_ns=0) value: 0
Toggle Pin(4) 1100 time(s).
  callback Сounter value:      1000 status:  5
 value: Pin(4) 0 -> 0
Counter(0), src=Pin(5), _src=Pin(17), edge=Counter.RISING | Counter.FALLING, match=1000, match0=0, filter_ns=0) value: 1100 dif: 0
Ok.

# -------------------------------------------------------------------------------------
4.2) Testing the count of pulses 'output1' Pin(4) DOWN on '_src' input2 Pin(16) at RISING-FALLING edges.
Toggle Pin(16) 2200 time(s).
  callback Сounter value:      1000 status:  5
  callback Сounter value:         0 status: 64
 value: Pin(16) 0 -> 0
Counter(0), src=Pin(5), _src=Pin(17), edge=Counter.RISING | Counter.FALLING, match=1000, match0=0, filter_ns=0) value: -1100 dif: 0
Ok.

# =====================================================================================
5) Testing the count of PWM pulses on 'src' Pin() if 'direction' is a Pin().
   Stop the PWM in Timer callbacks.
'output1' PWM(Pin(4)) -> 'input1' Pin(5) is 'src' of counted PWM pulses.
'output2' Pin(16) -> 'input2' Pin(17) is 'direction' of counting.
# -------------------------------------------------------------------------------------
5.1) Testing the count of pulses 'output1' PWM(Pin(4)) UP when 'direction='Pin(16) is 1 at FALLING edges.
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.FALLING, filter_ns=0) value: 0
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.FALLING, filter_ns=0) value: 500045 dif: 62
Ok.

# -------------------------------------------------------------------------------------
5.2) Testing the count of pulses 'output1' Pin(4) DOWN when 'direction='Pin(16) is 0 at FALLING edges.
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.FALLING, filter_ns=0) value: 499526
Timer(1, mode=ONE_SHOT, period=5000)
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.FALLING, filter_ns=0) value: -500044 dif: -61
Ok.

# =====================================================================================
6) Testing the count of PWM pulses on 'src' Pin() if 'direction' is a Pin().
   Stop PWM in Counter callback.
'output1' PWM(Pin(4)) -> 'input1' Pin(5) is 'src' of counted PWM pulses.
'output2' Pin(16) -> 'input2' Pin(17) is 'direction' of counting.
# -------------------------------------------------------------------------------------
6.1) Testing the count of pulses 'output1' PWM(Pin(4)) UP when 'direction='Pin(16) is 1 at RISING edges.
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500000, filter_ns=25) value: 0
  callback pwm.deinit()
  callback Сounter value:    500117 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500000, filter_ns=25) value: 500117 dif: 117
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500300, filter_ns=25) value: 500117
  callback pwm.deinit()
  callback Сounter value:    500396 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500300, filter_ns=25) value: 500396 dif: 96
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500500, filter_ns=25) value: 500396
  callback pwm.deinit()
  callback Сounter value:    500617 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500500, filter_ns=25) value: 500617 dif: 117
Ok.

# -------------------------------------------------------------------------------------
6.2) Testing the count of pulses 'output1' PWM(Pin(4)) DOWN when 'direction='Pin(16) is 0 at RISING edges.
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500300, filter_ns=25) value: 500617
  callback pwm.deinit()
  callback Сounter value:    500228 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500300, filter_ns=25) value: 500228 dif: -72
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500000, filter_ns=25) value: 500228
  callback pwm.deinit()
  callback Сounter value:    499916 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=500000, filter_ns=25) value: 499916 dif: -84
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=0, filter_ns=25) value: 499916
  callback pwm.deinit()
  callback Сounter value:       -70 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=0, filter_ns=25) value: -70 dif: -70
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500000, filter_ns=25) value: -70
  callback pwm.deinit()
  callback Сounter value:   -500063 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500000, filter_ns=25) value: -500063 dif: -63
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500300, filter_ns=25) value: -500063
  callback pwm.deinit()
  callback Сounter value:   -500397 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500300, filter_ns=25) value: -500397 dif: -97
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500500, filter_ns=25) value: -500397
  callback pwm.deinit()
  callback Сounter value:   -500619 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500500, filter_ns=25) value: -500619 dif: -119
Ok.

# -------------------------------------------------------------------------------------
6.3) Testing the count of pulses 'output1' PWM(Pin(4)) UP when 'direction='Pin(16) is 1 at RISING edges.
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500300, filter_ns=25) value: -500619
  callback pwm.deinit()
  callback Сounter value:   -500229 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500300, filter_ns=25) value: -500229 dif: 71
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500000, filter_ns=25) value: -500229
  callback pwm.deinit()
  callback Сounter value:   -499923 status:  4
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match=-500000, filter_ns=25) value: -499923 dif: 77
Ok.

Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match0=0, filter_ns=25) value: -499923
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match0=0, filter_ns=25) value: 48 dif: 64
Ok.

END.
finally:
Counter(1), src=Pin(5), direction=Pin(17), edge=Counter.RISING, filter_ns=25) value: 438
Counter(0), src=Pin(5), direction=Pin(17), edge=Counter.RISING, match0=0, filter_ns=25) value: 438
>>> 

This adds hardware tests for machine.Counter.
It requires two jumper wires between two pairs of pins,
outputs, and inputs.
output1: Pin() -> input1: Pin()
output2: Pin() -> input2: Pin()
or
output1: PWM() -> input1: Pin()
output2: PWM() -> input2: Pin()

machine.Pin and machine.PWM generates pulses and controls
the direction of counting, and machine.Counter inputs both.
machine.Timer generates a period for counting pulses.

machine.Counter value and irq callback tests are performed.

Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
@dpgeorge dpgeorge added the tests Relates to tests/ directory in source label May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tests Relates to tests/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants