Date: 04.11.2022
The last driver for the FS1027-Dg flow sensor was motivated by my MIDI-Sax build. My first prototype used this sensor and a couple of buttons to assemble the sax. The result works surprisingly well. But normal buttons tampered with the playing experience since it is not always easy to press such small buttons. My next approach was using MX-Switches (known from mechanical keyboards) to get a better key press experience. However the travel was way too long in practice. Which brings me to touch based keys.
Researching the topic brought me to Adafruit’s Mpr121 capacitive touch sensor. Its exactly what I need (I²C based and >= 10 channels). So I decided to buy the board.
While waiting for the board I had searched for Rust HAL integration.
I found two related crates mpr121 and adafruit-mpr121.
Both didn’t fit my needs. The first one targets embedded programming,
but doesn’t seem to be fully implemented at the moment. The second one
targets RaspberryPi + Linux. It doesn’t use embedded-hal
but the Linux I²C driver.
So I decided to write my own embedded-hal
implementation.
While implementing the driver I had two main references, the C++ implementation from Adafruit, and the data sheet. My goal was to mirror the C++ implementation as close as possible, since this is probably the way most people are used to interact with the board. After all its sold mostly by Adafruit. I also wanted to introduce the rusty way of handling errors and data. The result is a similar API with better error reporting and some convenience functions.
The crate is hosted on crates.io and comes with documentation. However, a quick start would be to setup a I²C connection between the sensor and your dev-board like this:
In code you have to create a valid I²C instance using
embedded-hal
and create a mpr121
instance
using that bus. This look similar to the pseudocode below.
use your_board_hal::i2c::I2C;
use mpr121-hal::Mpr121;
fn main(){
//... gpio setup code for your device
let i2c = I2C::new(gpio.sdl, gpio.sdc);
let mut mpr = Mpr121::new_default(i2c);
loop{
for channel in 0..12{
"[{}]: {}", channel, mpr.get_sensor_touch(channel));
println(}
}
//if you need back the I²C bus, or the gpio pins, use free
let i2c = mpr.free();
}
The board can be configured to respond to different addresses on the I²C line. This is helpfull if another device already uses the address on the same line, or if you use multiple mpr121 boards on the same line.
By default the address is 0x5a
. This is the address used
by Mpr121::new_default
as well. If you connect the
addr
pin of the mpr121 board to Vdd
,
Sdc
or Sdl
you change the address the board
listens on. To set the address use Mpr121::new()
where the
address mirrors your physical addr
pin connection.