PymateIO-Delaying: Difference between revisions
| (8 intermediate revisions by the same user not shown) | |||
| Line 11: | Line 11: | ||
The solution for this is: | The solution for this is: | ||
* use the ''' | * use the '''EventTimer''' class | ||
* set the delay on the ''' | * set the delay on the '''EventTimer''' when the source event occurs. | ||
* check the ''' | * check the '''EventTimer.done''' at every mainloop cycle. | ||
* Once '''done''', it is time to executed the delayed code. | * Once '''done''', it is time to executed the delayed code. | ||
Remark: the '''done''' will | Remark: the '''done''' will assert True '''only once''' for every '''set()'''! | ||
== Practical example == | |||
As practical example, we will read DS18B20 OneWire sensor connected on the Pymate Expansion port. | |||
The problem with the DS18B20 is required pause of 750ms between the temperature request and values reading. | |||
=== Wiring DS18B20 === | |||
[[File:PymateIO-DS18B20-Wiring.jpg]] | |||
=== Blocking script === | |||
Here follow a basic MicroPython script showing how to deal with the DS18B20 sensor. | |||
This script makes a reading every 5 seconds (execution limited to 10 iteration). | |||
{{rbox-orange|Unfortunately, this use blocking instructions like sleep_ms() and sleep().}} | |||
<syntaxhighlight lang="python" line> | |||
from machine import Pin | |||
import onewire, ds18x20 | |||
import time | |||
dat = Pin( "I2C4_SMB", Pin.IN ) | |||
bus = onewire.OneWire(dat) | |||
ds = ds18x20.DS18X20( bus ) | |||
roms = ds.scan() | |||
print( "Found devices", roms ) | |||
for i in range(10): | |||
print( "%i: Read temperature" %i ) | |||
ds.convert_temp() | |||
time.sleep_ms(750) # Required by OneWire protocol | |||
for rom in roms: | |||
print( 'ROM', rom, 'Temperature', ds.read_temp(rom) ) | |||
time.sleep( 5 ) | |||
print( "That's all Folks" ) | |||
</syntaxhighlight> | |||
Which produce the following: | |||
<nowiki>Found devices [bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb')] | |||
0: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5625 | |||
1: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
2: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
3: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
4: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5625 | |||
5: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
6: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
7: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
8: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
9: Read temperature | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
That's all Folks | |||
</nowiki> | |||
=== Pymate Non-Blocking script === | |||
This implementation do use the {{fname|EventTimer}} class to create non-blocking delay. | |||
Once the {{fname|EventTimer.set()}} called, the property {{fname|done}} will the True only when the time is elapsed. | |||
Notes that {{fname|done}} will be True only once for each {{fname|EventTimer.set()}}. | |||
<syntaxhighlight lang="python" line> | |||
from machine import Pin | |||
from pymate import EventTimer | |||
import onewire, ds18x20 | |||
import time | |||
dat = Pin( "I2C4_SMB", Pin.IN ) | |||
bus = onewire.OneWire(dat) | |||
ds = ds18x20.DS18X20( bus ) | |||
roms = ds.scan() | |||
first_rom = roms[0] # Only remember first rom | |||
print( "Found device", first_rom ) | |||
i = 0 | |||
convert_event = EventTimer(0.1) # Immediately starts | |||
read_event = EventTimer() # Do not start this one | |||
while True: | |||
if convert_event.done: | |||
ds.convert_temp() | |||
read_event.set(0.750) # Prepare the reading in 750 ms | |||
convert_event.set( 5 ) # Prepare for next conversion request | |||
if read_event.done: | |||
print( 'ROM', first_rom, 'Temperature', ds.read_temp(first_rom) ) | |||
print( 'i', i ) | |||
# Remain of code to execute | |||
i += 1 | |||
</syntaxhighlight> | |||
The mainloop can run full speed as demonstrates the {{fname|i}} variable that get incremented at each mainloop pass. | |||
The incrementation of {{fname|i}} shows the effectiveness of non-blocking delay for {{fname|convert_temp()}} and {{fname|read_temp()}} . | |||
<nowiki>Found devices bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.625 | |||
i 0 | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.375 | |||
i 6583 | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.4375 | |||
i 58218 | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 | |||
i 109931 | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.4375 | |||
i 161604 | |||
ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.375 | |||
i 213262 | |||
</nowiki> | |||
{{PYMATE-TRAILER}} | {{PYMATE-TRAILER}} | ||
Latest revision as of 00:34, 30 June 2026
Abstract
The "Cycle Timing" tutorial state the following:
NEVER USE BLOCKING INSTRUCTION in the mainloop
Blocking instruction locks the script execution in a waiting state... whereas critical operation may requires quick reaction from the script.
The sleep(), sleep_ms() are BLOCKING INSTRUCTIONS.
They should never be used in your script, neither in the mainloop
The solution for this is:
- use the EventTimer class
- set the delay on the EventTimer when the source event occurs.
- check the EventTimer.done at every mainloop cycle.
- Once done, it is time to executed the delayed code.
Remark: the done will assert True only once for every set()!
Practical example
As practical example, we will read DS18B20 OneWire sensor connected on the Pymate Expansion port.
The problem with the DS18B20 is required pause of 750ms between the temperature request and values reading.
Wiring DS18B20
Blocking script
Here follow a basic MicroPython script showing how to deal with the DS18B20 sensor.
This script makes a reading every 5 seconds (execution limited to 10 iteration).
from machine import Pin
import onewire, ds18x20
import time
dat = Pin( "I2C4_SMB", Pin.IN )
bus = onewire.OneWire(dat)
ds = ds18x20.DS18X20( bus )
roms = ds.scan()
print( "Found devices", roms )
for i in range(10):
print( "%i: Read temperature" %i )
ds.convert_temp()
time.sleep_ms(750) # Required by OneWire protocol
for rom in roms:
print( 'ROM', rom, 'Temperature', ds.read_temp(rom) )
time.sleep( 5 )
print( "That's all Folks" )Which produce the following:
Found devices [bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb')] 0: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5625 1: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 2: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 3: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 4: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5625 5: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 6: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 7: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 8: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 9: Read temperature ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 That's all Folks
Pymate Non-Blocking script
This implementation do use the EventTimer class to create non-blocking delay.
Once the EventTimer.set() called, the property done will the True only when the time is elapsed.
Notes that done will be True only once for each EventTimer.set().
from machine import Pin
from pymate import EventTimer
import onewire, ds18x20
import time
dat = Pin( "I2C4_SMB", Pin.IN )
bus = onewire.OneWire(dat)
ds = ds18x20.DS18X20( bus )
roms = ds.scan()
first_rom = roms[0] # Only remember first rom
print( "Found device", first_rom )
i = 0
convert_event = EventTimer(0.1) # Immediately starts
read_event = EventTimer() # Do not start this one
while True:
if convert_event.done:
ds.convert_temp()
read_event.set(0.750) # Prepare the reading in 750 ms
convert_event.set( 5 ) # Prepare for next conversion request
if read_event.done:
print( 'ROM', first_rom, 'Temperature', ds.read_temp(first_rom) )
print( 'i', i )
# Remain of code to execute
i += 1The mainloop can run full speed as demonstrates the i variable that get incremented at each mainloop pass.
The incrementation of i shows the effectiveness of non-blocking delay for convert_temp() and read_temp() .
Found devices bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.625 i 0 ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.375 i 6583 ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.4375 i 58218 ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.5 i 109931 ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.4375 i 161604 ROM bytearray(b'(\xf2\t\x94\x97\x03\x03\xfb') Temperature 20.375 i 213262
PymateIO all right reserved © 2026 - Written by MCHobby for PymateIO
