Handling Inputs with the Raspberry Pi Pico
In this installment of How to Program a Raspberry Pi Pico with Rust, I’m configuring a controller to receive inputs and describing some control logic for evaluating those inputs. You can check out my GitHub Repo for my project called PicoPonics if you want to see some examples of a system in the field now, handling inputs.
What is Input Handling?
Handling an input from a field device means receiving and interpreting a signal from a sensor or device that can provide that type of signal.
A push button can be considered a field device but is more commonly referred to as an input device. In the graphic above we see a temperature sensor and a pressure sensor, but we’ll focus on the button for now, as it’s almost always a discrete / digital input.
Receiving the signal
This part is often more difficult than programming the logic for dealing with the signal. But in the ideal world, there isn’t much more to it than:
1. wiring the device to the proper input
2. configuring the input to recognize the incoming signal
Interpreting the Signal
Signals produced by various instrumentation aren’t always exactly ‘common sense’. But even in cases where they are, to interpret a signal conduct the following:
Translate the signal into data that is meaningful to the context of the program.
Incorporate control logic to handle carrying out actions based on that new meaningful data
Here is a list of things that must be understood to handle an input:
What type of IO Pin configuration is needed to properly receive the signal from the device in the field.
Safety Risks
How to write code to make decisions based on input state changes
How to compile that code into a format that is recognizable to the target microcontroller
How to move that code onto the controller (write / flash)
How to wire up the GPIO to the sensor or device that will provide the input signal.
Tell the Microcontroller How to Interpret Incoming Signals
Just like we covered in the last post, the GPIO on the Pico need to be configured in the program. They are very general, and explicit instruction on how to behave is a requirement.
let gp15 = pins.gpio15.into_pull_down_input();
In this code above, GPIO Pin 15 is configured to act as a pull down input.
When a pin is a pull-down input, the goal is for the reference voltage at rest to be as near 0VDC as possible. When a voltage from a field device goes high, that’s becomes a logical high for the input, and it will be recognized by the controller as being active. The button we mentioned before will provide 5VDC to the input pin, and while it’s pressed, that pins value will read as true.
Setting Up Pins using a Hardware Abstraction Layer (HAL)
The below example shows how the HAL is imported into the file, then used to configure a variable called pins. This variable has all the power once created over how the pins will be configured.
If you’re interested to write your own code straight away, you can download my Super Blank Pico Project Repo, and start monkeying around with the pins variable in there to get some stuff happening on your own pico. The HAL I’m using is rp-hal from the rp-rs team.
// A shorter alias for the Peripheral Access Crate, which provides low-level
// register access
use hal::pac;
// The single-cycle I/O block controls our GPIO pins
let sio = hal::Sio::new(pac.SIO);
// Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS
);
// Configure a pin to be used as an output pin
let gp15 = pins.gpio15.into_pull_down_input();
I’ll once again link to a previous post for more information on what the above code is doing. For our purposes today, the value we’ll want to read is from the variable gp15 and will contain the true/false value we’d be expecting to represent our button state.
Writing Control Logic
Handling a button is mostly just figuring out what the button should do in the context of the program, and what should happen when it changes from true -> false or from false -> true.
// is_high would mean the button is pressed (if it’s a normally open button)
if gp15.is_high().unwrap() {
// Do something when the button is pressed
}
You can also check directly if the input is low
// is_low would mean the button is not pressed (if it’s a normally open button)
if gp15.is_low().unwrap() {
// Do something when the button is not pressed
}
The decision on what to do when the button is high or low it up to the designer. Could be setup for immediate effect, or just for logical effect like a counter.
Conclusion
We've covered what an input is, how to configure them, and some basics of handling them. With this information, it’s possible to start getting project work done with the Raspberry Pi Pico and Rust.
If you’ve got questions or if something in this article wasn’t clear, please let me know by one of the contact methods listed below, and I’ll come back through and update the article for clarity.