This week I worked with five different inputs: a custom mutual capacitance proximity detector, a velostat pressure sensor, a KY-040 rotary encoder, the BNO085 IMU as an accelerometer for yaw sensing, and the BNO085 magnetometer as a magnetic rotary encoder. I didn't have a dedicated encoder IC like an AS5600 on hand, so I used the magnetometer directly with a small cube magnet.
I wanted to make a sensor that could detect proximity, not just touch. Mutual capacitance works by transmitting a charge on one electrode and measuring how much coupling makes it across to the receiving electrode, a nearby hand disturbs that coupling in a measurable way.
This demo was with the original simple copper pad pair, just to prove the concept worked before going further.
Since the CapacitiveSensor library only works on AVR boards, I asked Claude to write custom charge-transfer sensing logic for the ESP32. This was the first version that actually ran, values sitting around 22 at rest and spiking to about 195 on direct pad touch.
I asked Claude to try an analogRead approach with a brief charge window to simplify things. The readings came out completely inverted, the sensor was reading TOUCH at rest and dropping when I actually touched the pad.
To try to fix the inverted readings, I added a startup baseline calibration and more averaging. The delta values stayed at 0–2 regardless of where my hand was. analogRead just wasn't working.
I stripped everything back to bare analogRead with no averaging to rule out any software artifacts. The output was completely flat at around 3750, zero response to hand proximity. The ESP32-S3 ADC is just too noisy for this.
At this point I cut an interdigitated electrode pattern with a utility knife. The comb geometry puts much more shared edge between the TX and RX pads, which dramatically increases the coupling area.
I found this fanatastic document on capactive touch sensor design: Capacitive Touch Sensor Design Guide
I went back to the charge-counting approach and got real proximity data, delta 1 at 9cm, delta 2 at 3cm, delta 3 at 1cm. The signal was there but weak.
I cranked samples up to 2000 to try to average out the noise, but the response barely moved. Claude pointed out that the pad geometry itself was the bottleneck, two small squares sitting side by side don't have enough shared edge to build up a meaningful signal.
I also tested the sensor through a piece of 2mm thick PLA from a test print that was laying around and it was able to detect proximity as well as touch.
I then made my own pressure sensor from copper tape and velostat, a carbon-black film that gets more conductive when you compress it. The plan was to eventually replace the tactile button for my custom pomodoro timer watch board. I wired it as a voltage divider with a 3.3K resistor and connected it to GPIO 12 on the Barduino.
The pressure sensor readout worked well in the serial monitor, from 0-4095 depending on how much force I used.
I then mapped the pressure input reading to control the brightness of the NeoPixel on the Barduino.
The KY-040 was straightforward to wire up, CLK on GPIO 13, DT on GPIO 14, SW on GPIO 15, but had a lot of bounce. I fixed that with the ESP32Encoder library. Once it was reading cleanly I mapped the position to NeoPixel brightness, then to colour temperature.
I wanted to explore using the BNO085 as a more interesting input. It's a 9-DOF IMU with an accelerometer, gyroscope, and magnetometer all in one. My first idea was to use the accelerometer to track yaw rotation (as a make shift rotary encoder), before moving on to the magnetometer approach.
The yaw data readout was very precise and quite stable.
Since I didn't have an AS5600 or similar dedicated magnetic encoder IC on hand, I tried using the BNO085 magnetometer directly. The idea was to hold a diametrically magnetized magnet above the sensor and use the raw field values to calculate the absolute angle as it rotates. I asked Claude to help me create the code to access this data. I then had Claude add a rolling average to smooth out the noise.
I threw together a quick proof of concept from parts I had lying around to validate the BNO085 + rotating magnet approach. I also tried soldering wires directly to a NeoPixel to use as an output indicator, but held the iron on it for too long and fried it.
I decided to modify my week 02 braille learning device to accomodate the BNO085 and a magnet to be able to read the position of the knob. The magnet would be embedded in the knob print. I created a pocket for affixing the BNO085 with a threaded hatch for access to the board and a hole for the wires to go to my XIAO. This was only a concept that would be used for testing purposes as I continue to iterate on this design.