Ready to explore interrupts with your PSoC microcontroller and MicroPython? This guide is your gateway to understanding interrupts in a clear and enjoyable manner. We'll delve into the fundamentals of interrupts, their significance, and the various interrupt types that can enhance your projects.
We'll also take a hands-on approach by creating a game using interrupts to demonstrate their practical applications. This real-world example will showcase how interrupts can elevate the functionality of your projects.
By the end of this guide, you'll have a solid understanding of interrupts and the confidence to leverage their power in your own PSoC microcontroller projects with MicroPython. So, get ready for an insightful journey into the world of interrupts!
What is an interrupt?Interrupt is an alerting signal that hardware or software sends when a process or event demands immediate attention. Picture a microcontroller juggling various tasks until an urgent event occurs. That's when the interrupt kicks in, ensuring that critical tasks take precedence.
An interrupt springs into action when a special event occurs, such as a voltage change on a pin. It could be a button press, a sensor signal, or even a timer ticking. By wiring up a circuit to harness interrupts, you can create a hands-on example of how to use them in your own project.
When an interrupt occurs, the processor swiftly switches to run a quick routine (IRS), and seamlessly returns to its regular programming. This functionality allows you to respond to external events while your main program continues to run. Just remember, when using interrupts, keep it short and snappy, avoid delays, skip serial prints, and handle shared variables with care. With these tips, you'll be well-equipped to use interrupts effectively in your own projects.
First up, GPIO interrupts. These are like digital alerts from an external device, such as a microcontroller, to the processor. When you press a button connected to the microcontroller, it signals the processor, indicating that something critical has occurred. This prompts the processor to suspend its current operation and handle the new information promptly.
Next, we have timer interrupts. These function as triggered reminders set by a timer. They enable you to schedule tasks at specific time intervals, independent of concurrent code execution. When a timer interrupt occurs, it briefly interrupts the sequential execution of the program loop and executes a distinct set of commands.
Why Do I Need Interrupts?Interrupts are the only way to put a microcontroller to sleep and wake it up when needed, crucial for conserving power, especially in battery-powered devices. A relatable example is your smartphone, which also utilizes interrupts to wake up from sleep mode. When you press the power button or the side button to wake your phone, you're essentially triggering an interrupt that prompts the device to resume operation. This highlights the fundamental role of interrupts in managing power states and ensuring efficient power consumption in various electronic devices.
Now, let's talk about their role in making things happen at just the right time. For example, when creating a game where the first player to push a button wins. It's all about speed and precision. The conventional approach involves the while loop and continuously monitoring the pin's state at a rapid pace. This method, known as "polling", while it can be effective and simple, it is often considered unreliable. Here's where interrupt step in, it makes sure that when a button is pressed, the event is captured without missing a beat, ensuring your program responds right on time without constantly checking if the button is pressed.
Timer interruptsIf you're new to coding in MicroPython on PSoC, refer to this setup guide to ensure your environment is properly configured.
MicroPython simplifies timer usage, eliminating the need for complex coding. You just specify the waiting time for the counter before triggering an interrupt. To code your first timer interrupt with MicroPython you only need your PSoC 6 board and a USB cable and then you can follow these steps to create your code:
Import the necessary module: Begin by importing the 'machine' module.This required module is responsible for handling hardware interrupts in MicroPython.
from machine import Timer
Create a one-shot timer, tim0
, on channel 0 with a period of 1 second, which triggers a callback function to print a message.
tim0 = Timer(0, period=1000, mode=Timer.ONE_SHOT, callback=lambda t:print("One shot timer triggered")) #Default assignment: period=9999, frequency=10000
Create a periodic timer tim1
, on channel 1 with a period of 3 seconds, which triggers a callback function to print a message.
tim1 = Timer(1, period=3000, mode=Timer.PERIODIC, callback=lambda t:print("Periodic timer triggered"))
Deinitialize the tim0
and the tim1
timer.
tim0.deinit() # Deinitialise the timer
tim1.deinit() # Deinitialise the timer
For the ID you can take values between 0 and 31 as a maximum of 32 hardware timers is supported for the PSoC 6.
GPIO Interrupts with a game exampleIn this example, we’ll use interrupts to handle button presses in a reaction time game. This approach with interrupts is particularly useful for time-sensitive tasks, such as measuring reaction times in this game. Here’s a simple example of using GPIO interrupts in Python:
from machine import Pin
# Define a callback function to handle the interrupt
def button_pressed(pin):
from machine import Timerprint("Button pressed!")
# Initialize the button pin and set up the interrupt
button = Pin('P9_6', Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=button_pressed)
In this code, the button_pressed
function is called whenever the button connected to pin ‘P9_6’ is pressed.
Now, let’s move on to the reaction time game. The game is a challenge designed for two players. It involves an LED and two buttons. When the LED lights up, the players must press their buttons as quickly as possible. The player who presses their button first wins.
Using interrupts for detecting button presses ensures accurate measurement of reaction times by capturing the exact moment the buttons are pressed, avoiding potential delays associated with continuous polling.
First, let’s start with wiring the hardware components:
- Connect an LED to pin ‘P9_4’ (green).
- Connect two buttons to pins ‘P9_6’ and ‘P9_7’ (blue and yellow).
Now, let’s break down the code part by part:
1. Importing Libraries and Initializing GPIO Pins:
from machine import Pin
import time
import urandom
Initialize the pins for the LED and the buttons
led = Pin('P9_4', Pin.OUT)
button1 = Pin('P9_6', Pin.IN, Pin.PULL_UP)
button2 = Pin('P9_7', Pin.IN, Pin.PULL_UP)
In this section, the necessary libraries are imported, and the GPIO pins for the LED and buttons are initialized. The LED pin is set as an output, while the button pins are configured as inputs with pull-up resistors enabled.
2. Initializing Game State Variables and Callback Function:
# Flags to indicate if the LED is on and if the game is active
led_on = False
game_active = False
# Variable to hold the start time
start_time = 0
# Callback function for button presses
def button_press_callback(pin):
global start_time, led_on, game_active
if game_active and led_on:
reaction_time = time.ticks_diff(time.ticks_ms(), start_time)
winner = "Player 1" if pin == button1 else "Player 2"
print("{} wins with a reaction time of: {} ms".format(winner, reaction_time))
led.value(0)
led_on = False
game_active = False
Here, the global variables `led_on`, `game_active`, and `start_time` are initialized to manage the state of the game and LED. Additionally, a callback function `button_press_callback` is defined to handle button press interrupts. When a button press is detected during an active game with the LED on, the function calculates the reaction time, determines the winner, prints the result, and resets the game state.
3. Attaching Interrupts to Button Pins:
# Attach the interrupt to the callback function for both buttons
button1.irq(trigger=Pin.IRQ_RISING, handler=button_press_callback)
button2.irq(trigger=Pin.IRQ_RISING, handler=button_press_callback)
In this section, interrupt handlers are attached to both button pins. The interrupts are triggered on a rising edge (when the button is pressed), and the `button_press_callback` function is invoked to handle the interrupt.
4. Main Program Loop:
i = 0
while i < 5 :
i = i + 1
game_active = True
# Generate a random time between 5 and 10 seconds (5000 to 10000 milliseconds)
wait_time = urandom.getrandbits(20) % 5000 + 5000
time.sleep_ms(wait_time)
# Turn on the LED and start the game
led.value(1)
led_on = True
start_time = time.ticks_ms()
# Now we wait for either button press in the interrupt handler
while game_active:
time.sleep_ms(50) # Small delay to prevent busy waiting
# Wait a moment before starting the next round
time.sleep_ms(2000)
In the main program loop, the game is run for 5 rounds. After a random wait time between 5 and 10 seconds, the LED is turned on, and the game begins. The program then waits for a button press interrupt to end the current round and starts the next round after a brief delay.
You have now the essentials of using interrupts in microcontroller applications. With the knowledge gained from this guide, you’re ready to tackle more advanced projects that require precise timing and efficient event handling. Remember to refer back to this guide and other resources for technical support. Happy coding, and here’s to creating many more innovative and responsive projects!
Comments
Please log in or sign up to comment.