Hello
I have the following short test/demo script to measure the pulse width of an incoming pulse (for an RC servo in this case, i.e. between 1ms and 2ms approx).
When trying the script in v.3.7.0 everything works as expected and the correct pulse length is printed to stdout.
When trying the script with the newest firmware v3.8.0 the printed pulse width is always 0. I checked, and the callback is actually never executed.
Do I need to implement this differently with v3.8.0? Did I miss something in the documentation?
# tmr_ic_test.py
#
# Minimal test/demo script to measure pulse width of RC servo signal
# using timer input capture and interrupts.
#
################################################################################
import sensor, image, time, pyb, micropython
sensor.reset();
sensor.set_pixformat(sensor.RGB565);
sensor.set_framesize(sensor.QVGA);
sensor.skip_frames(time = 2000);
clock = time.clock();
# Pin P0 / Timer 12 / Channel 2
#
ic_pin = pyb.Pin(pyb.Pin.board.P0, pyb.Pin.IN);
tim = pyb.Timer(12, prescaler=12-1, period=0xFFFF);
tim_ch = tim.channel(2, pyb.Timer.IC, pin=ic_pin, polarity=pyb.Timer.BOTH);
################################################################################
ic_start = 0;
ic_width = 0;
################################################################################
# Interrupt Routine (callback)
def tim_ic_isr(tim):
# static variables don't exist, use globals
global ic_start;
global ic_width;
if ic_pin.value(): # rising edge
ic_start = tim_ch.capture();
else: # falling edge
ic_width = (tim_ch.capture() - ic_start) & 0xFFFF;
################################################################################
micropython.alloc_emergency_exception_buf(100);
tim_ch.callback(tim_ic_isr);
while(True):
clock.tick();
img = sensor.snapshot();
print("{:.1f} FPS {:.2f} us".format(clock.fps(), ic_width/20));
################################################################################
Thanks
Regards
Felix
Please report an issue on github, and make sure to fill the issue template.
Ok. I’ve opened an issue:
opened 11:16PM - 16 Dec 20 UTC
closed 09:54PM - 07 Jan 21 UTC
bug
### Description of Issue
Measuring the pulse length of a digital pulse signal a… t a pin does not seem to work with firmware 3.8.0, with code that works correctly with version 3.7.0:
- A servo signal (pulse of approx 1ms..2ms, period 20ms) is applied to P0.
- P0 is expected to be connected to Timer12, Channel 2.
- Timer12, Channel 2 is set up for input capture and to trigger a callback on every edge of the signal.
- The callback then processes the capture values to obtain the pulse length.
- Access to the result is achieved through the use of global variables.
Note that this was only tested with Timer12 (P0/Channel 2 as in the script, and P1/Channel1 as well)
### How to reproduce the Issue
1. Connect a pulse signal to pin P0 (e.g. output of servo tester, RC receiver, or a function generator. Anything around 1-2ms with a repetition period of a few ms should work (not really critical)
2. Run the example script below
```
# tmr_ic_test.py
#
# Minimal test/demo script to measure pulse width of RC servo signal
# using timer input capture and interrupts.
#
################################################################################
import sensor, image, time, pyb, micropython
sensor.reset();
sensor.set_pixformat(sensor.RGB565);
sensor.set_framesize(sensor.QVGA);
sensor.skip_frames(time = 2000);
clock = time.clock();
# Pin P0 / Timer 12 / Channel 2
#
ic_pin = pyb.Pin(pyb.Pin.board.P0, pyb.Pin.IN);
tim = pyb.Timer(12, prescaler=12-1, period=0xFFFF);
tim_ch = tim.channel(2, pyb.Timer.IC, pin=ic_pin, polarity=pyb.Timer.BOTH);
################################################################################
ic_start = 0;
ic_width = 0;
################################################################################
# Interrupt Routine (callback)
def tim_ic_isr(tim):
# static variables don't exist, use globals
global ic_start;
global ic_width;
if ic_pin.value(): # rising edge
ic_start = tim_ch.capture();
else: # falling edge
ic_width = (tim_ch.capture() - ic_start) & 0xFFFF;
################################################################################
micropython.alloc_emergency_exception_buf(100);
tim_ch.callback(tim_ic_isr);
while(True):
clock.tick();
img = sensor.snapshot();
print("{:.1f} FPS {:.2f} us".format(clock.fps(), ic_width/20));
################################################################################
```
### Expected Behavior
The script should continue printing the measured FPS and the measured pulse length of the signal on P0:
```
19.8 FPS 1225.55 us
19.8 FPS 1225.55 us
19.8 FPS 1225.50 us
19.8 FPS 1225.50 us
19.8 FPS 1225.50 us
```
### Actual Behavior
The script always prints only 0.00 as the value of "ic_width":
```
19.8 FPS 0.00 us
19.8 FPS 0.00 us
19.8 FPS 0.00 us
19.8 FPS 0.00 us
19.8 FPS 0.00 us
```
No exceptions are reported.
### Setup:
- IDE version: 2.6.8
- Firmware version: 3.8.0 (works with 3.7.0)
- Board: OPENMV-H7
- OS: Windows
Thanks, I’ll take a look. In the meantime, can you try setting the callback arg instead ?
....
....
micropython.alloc_emergency_exception_buf(100);
tim_ch = tim.channel(2, pyb.Timer.IC, pin=ic_pin, polarity=pyb.Timer.BOTH, callback=tim_ic_isr);
....
Had only now time to test this, but yes, this is working as intended!
Thanks!
Felix