You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have been searching quite a lot on how to communicate back and forth between PIO and Micropython on the Pi Pico with synchronized activation between state machines and PIO blocks signaling back with interrupts etc. I came up with nothing.
This example is working as intended, but all comments have been put there quite hasty.
# Code was written for the Pi Pico, for the Pi Pico W, use an output with an external LED to get visual feedback.# This example takes a simpler approach to explain PIO and how it integrates with Micropython# on the Raspberry Pi Pico.# This is example code on how to have two pairs or state machines, who are working together, run simultaneously.# Because they can't be called at the same time, but can run independently at the same time,# we activate the machines one by one, and then use a Pin which they both are waiting for at the same time.# The onboard LED will turn ON while both programs are running. When each program is completed they will write to REPL.# Once both programs are done, user will be asked to press enter again to run the programs again.# Program can run without connecting anything to the Pi Pico, but one suggestion is adding LED's to the outputs# and use Pins that works for you.# I used this code as a base for my stepper motor project:# https://github.com/Vendelator/RP2040_PIO_Steppermotors - MIT license# The best source for explaining PIO: https://dernulleffekt.de/doku.php?id=raspberrypipico:pico_pio# To change how many times the pins toggle, change the values in sm_0.put() and sm_4.put().# To change how fast the program toggles, change frequency and add/remove delay [x]# which can be done to any isntruction in the PIO routines.# In the example i use nop() [31], which delays for 1 + 31 cycles.# At current setting with 20_000 Hz frequency, (1 + 1 + (32 * 65) + 1) instruction in delay(), # pins will toggle at approximatly 10 hZ.(10 times a second)# This means PIO block 0 will take 10 seconds to finish and PIO block 1 will take 20 seconds.importmachine# To be able to control GPIO Pinsimportrp2# To be able to use state machinestrigger_pin=machine.Pin(25, machine.Pin.OUT) # This pin will trigger our state machines using wait(1, gpio, 25).pio_block_0=False# True/False object used to see if the program is allowed to proceed.pio_block_1=False# - " -@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) # Tells our program that this is a PIO routine and to set the pin low on activation.defpin_activator():
pull(block) # Wait for FIFO to fill (put), then pull data to OSR.mov(x, osr) # Copy OSR data from to X.wait(1, gpio, 25) # Does nothing until GPIO Pin 25 is set to high, this is how we synchronize activation.label("Jump_Point") # this is a header we jump back to for counting steps.set(pins, 1) # Sets the in_base Pin high.jmp(not_x, "end") # if X is 0(zero), jump to end.irq(5) # Sets IRQ 5 high, signaling.irq(block, 4) # Waiting for IRQ flag 4 to clear before proceeding.set(pins, 0) # Sets the in_base Pin low.jmp(x_dec, "Jump_Point") # if x is NOT 0(zero), remove one (-1) from X and jump back to "Jump_Point", Else, proceed.label("end") # This is a label we can jump to if X is 0.irq(block, rel(0)) # Signals IRQ handler of the actual state machine and waits for handler to clear the flag.# Once the handler clears the flag, the program restarts and is blocked until new data is available.@rp2.asm_pio() # Does not manipulate any hardware, it's just code. empty ()defdelay():
wait(1, irq, 5) # Waiting for IRQ flag 5 from pin_activator and then clears it.set(y, 31) # Sets Y to the value 31.label("Delay") # This is a header we jump back to for adding a delay.nop() [31] # nop() does nothing for [n] instructions.nop() [31] # - " -jmp(y_dec, "Delay") # If Y not 0(zero), remove one (-1) from Y and make jump to delay, Else, proceed.irq(clear, 4) # Clears IRQ flag 4, allowing step_counter() to continue# At this point, the program restarts, and begins with waiting for IRQdefpio_0_handler(sm): # This is our Interrupt handler for PIO block 0.globalpio_block_0# To be able to change our global variable.pio_block_0=True# Change variable to True to be able to exit loop.print(sm, "sending interrupt.", "\nPio-Block 0 done!")
# sm is the statemachine calling the handler.# Here we could trigger other functions or execute code# like turning a Pin on or off.defpio_1_handler(sm): # This is our Interrupt handler for PIO block 1globalpio_block_1# To be able to change our global variablepio_block_1=True# Change variable to True to be able to exit loop.print(sm, "sending interrupt.", "\nPio-Block 1 done!")
# sm is the statemachine calling the handler.# Here we could trigger other functions or execute code# like turning a Pin on or off.# --- PIO Block 0 ---sm_0=rp2.StateMachine(0, pin_activator, freq=20000, set_base=machine.Pin(0))
# Calls rp2 and Instantiate a statemachine# (0, ... is the statemachine number. (0-7)# , pin_activator ... is the PIO routine# , freq=2000 ... sets the frequency to 2000 Hz# , in_base=machine.Pin(0) ... sets GPIO 0 as our base pin.sm_0.irq(pio_0_handler) # Tells the program that any interrupt from sm_0 should activate # the function pio_0_handler(sm):sm_1=rp2.StateMachine(1, delay, freq=20000)
# Creates object called sm_1 and binds it to state machine 1 in PIO block 0)# --- PIO Block 1 ---sm_4=rp2.StateMachine(4, pin_activator, freq=20000, set_base=machine.Pin(1))
# Calls rp2 and Instantiate a statemachine# (4, ... is the statemachine number. (0-7)# , pin_activator ... is the PIO routine# , freq=2000 ... sets the frequency to 2000 Hz# , set_base=machine.Pin(0) ... sets GPIO 0 as our base pin.sm_4.irq(pio_1_handler) # Tells the program that any interrupt from sm_4 should activate # the function pio_1_handler(sm):sm_5=rp2.StateMachine(5, delay, freq=20000)
# Creates object called sm_1 and binds it to state machine 5 in PIO block 1)# --- Starting the State machines ---sm_0.active(1), sm_1.active(1), sm_4.active(1), sm_5.active(1)
# All 4 state machines are now running# State machine 0 in PIO 0 and state machine 4 in PIO 1 are both waiting to be fed data.sm_0.put(100) # We can "put" data into state machine 0 using an integer.# This number will tell pin_activator() how many times to turn on/off.any_number=200sm_4.put(any_number) # We can also use a variable.# Both state machines are now fed, have copied this value into X# and are waiting for GPIO 25 to turn high.# --- Running the program ---whileTrue:
input("Press enter to execute both programs synchronous...")
trigger_pin.value(1)
whileTrue:
ifpio_block_0andpio_block_1: # Check if they are both Truetrigger_pin.value(0)
pio_block_0=Falsepio_block_1=Falsebreak# --- Explaining the program ---# while is an endless loop unless exited.# input will pause the while loop until user inputs something (Presses enter in REPL).# trigger_pin.value(1) sets GPIO 25 high and the onboard LED turns on, # this will activate our state machines and they will start toggeling the pins.# their pins and wait for out pre determined period of time before swithcing them of# again.# The second while loop will lock us into a loop where we check if# both handlers have changed pio_block_0 and pio_block_1 to True.
The text was updated successfully, but these errors were encountered:
I have been searching quite a lot on how to communicate back and forth between PIO and Micropython on the Pi Pico with synchronized activation between state machines and PIO blocks signaling back with interrupts etc. I came up with nothing.
I started this project: https://github.com/Vendelator/RP2040_PIO_Steppermotors
Which uses the technique i was searching for.
The best source i could find was: https://dernulleffekt.de/doku.php?id=raspberrypipico:pico_pio
My suggestion is to add an example code doing this, as i have seen a lot of people are looking for this.
I provide this example program to be added as an example in: https://github.com/raspberrypi/pico-micropython-examples
This example is working as intended, but all comments have been put there quite hasty.
The text was updated successfully, but these errors were encountered: