Event Driven Programming
Contents
Event Driven Programming#
%serialconnect
Found serial ports: /dev/cu.usbmodem14301, /dev/cu.Bluetooth-Incoming-Port
Connecting to --port=/dev/cu.usbmodem14301 --baud=115200
Ready.
Project Idea: Ultra Low-Cost Syring Pump#
Syringe pumps provide a convenient means of metering flows in microfluidic experiments. Conventional laboratory-grade syringe pumps are expensive, on the order of several hundreds to several thousand dollars, which stands in the way of using microfluidics as a platform for low-cost experimentation.
In the last decade there have been many reports of open-source, low-cost syringe pumps. Typically these employ NEMA 17 stepper motors, an Arduino microcontroller, and 3D printed components and off-the-shelf hardware.
Here we explore the possibiity of even lower cost devices based on 28BYJ-48 stepper motors and Raspberry Pi Pico. Would it be possible to build a viable syringe pump for less than, say, $50?
Ideas …
OMIS: The Open Millifluidic Inquiry System for small scale chemical synthesis and analysis
28BYJ-48 Stepper motor with ULN2003 driver
Linear actuator
3 way check valve to enable automatic refilling of the syringe.
Arduino Nano RP2040 Connect to enable Bluetooth/WiFi connectivity.
Interrupt Requests and Service Routines: IRQ/ISR#
Microcontrollers often incorporate hardware mechanisms to interrupt normal execution to service “interrupts”. The Raspberry Pi Pico supports a number of different interrupts, and the MicroPython interpreter provides simplified access that makes them relatively easy and safe to use.
Here we set up MicroPython to respond to interrupts on a GPIO pin. The possible triggers include
Pin.IRQ_FALLING
Pin.IRQ_RISING
Pin.IRQ_LOW_VALUE
Pin.IRQ_HIGH_VALUE
These triggers can be combined using the Python OR |
operator. For many applications, triggering on a falling or rising edge is often the method of choice. Consult the MicroPython documentation for other options.
%serialconnect
from machine import Pin
import time
btn = Pin(20, Pin.IN)
led = Pin(25, Pin.OUT)
start = time.time()
def btn_isr(_):
led.toggle()
btn.irq(btn_isr, trigger=Pin.IRQ_FALLING)
serial exception on close write failed: [Errno 6] Device not configured
Found serial ports: /dev/cu.usbmodem14401, /dev/cu.Bluetooth-Incoming-Port
Connecting to --port=/dev/cu.usbmodem14401 --baud=115200
Ready.
Here’s a second example that adds a buzzer. The buzzer toggles on when the button is pressed, and toggles off when released.
The pin assignments assume use of the Cytron Maker Pi Pico board. If so, be sure the buzzer on/off switch is in the “on” position.
%serialconnect
from machine import Pin, PWM
import time
btn20 = Pin(20, Pin.IN)
btn21 = Pin(21, Pin.IN)
led = Pin(25, Pin.OUT)
buzzer = PWM(Pin(18, Pin.OUT))
start = time.time()
def btn20_isr(_):
led.toggle()
buzzer_on = False
buzzer.freq(500)
def btn21_isr(_):
global buzzer_on
if buzzer_on:
buzzer.duty_u16(0)
buzzer_on = False
else:
buzzer.duty_u16(1000)
buzzer_on = True
btn20.irq(btn20_isr, trigger=Pin.IRQ_FALLING)
btn21.irq(btn21_isr, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
Found serial ports: /dev/cu.usbmodem14401, /dev/cu.Bluetooth-Incoming-Port
Connecting to --port=/dev/cu.usbmodem14401 --baud=115200
Ready.
Capturing data via IRQ/ISR’s#
There are many tricky issues involved with capturing data through the IRQ/ISR mechanism. This is partly due to Python’s mechanism for creating and updating objects. Interrupting Python at precisely the moment new objects are being created can lead to data or memory corruption.
One useful technique is to use IRQ/ISR within the context of an object class.
%serialconnect
from machine import Pin
import time
class Button(object):
def __init__(self, gpio):
self.btn = Pin(gpio, Pin.IN)
# set up IRQ
self.btn.irq(self.isr, trigger=Pin.IRQ_FALLING)
# flag and data
self.pressed = False
self.time_pressed = time.ticks_ms()
def isr(self, t):
self.pressed = True
self.time_pressed = time.ticks_ms()
btn = Button(20)
start = time.ticks_ms()
for k in range(10):
if btn.pressed:
print(btn.time_pressed - start)
btn.pressed = False
time.sleep(1)
Found serial ports: /dev/cu.usbmodem14401, /dev/cu.Bluetooth-Incoming-Port
Connecting to --port=/dev/cu.usbmodem14401 --baud=115200
Ready.
.7178
8803