Rambo's Water Fountain
My bird, Rambo, would always land on the side of his fountain and wait for me to plug it in so water would run. Instead of having him wait all the time, I made the fountain capacitive touch, so that when he lands on it, he can drink! Running the fountain all the time not only wasted energy and splashed water everywhere, but I was also worried about the longevity of the cheap water pump inside the fountain. This simple project made life better for my birdie and myself!
The methodology here was straightforward. The system would remain plugged into the wall at all times, however there is a mosfet blocking current until it is activated by the capacitive touch. Rambo's feet are like the "signal" wire of a relay. When he lands on the fountain, the electrical signal changes and the pump get activated. This project was by no means difficult, but I did run into some unexpected issues. When I first built the system and tested the code, I made the activation threshold of the pump quite high. On the serial plotter on the Arduino, when I touch the signal wire, I would see the response go from about 15-40 all the way to 1200+. So, I had set the activation threshold to around 500. This works flawlessly for me, even without any hysteresis. Then I placed Rambo onto the sensor wire. The signal went from 15-40 to 35-50. This posed a few issues. Sometimes the pump wouldn't activate, and if it did, it was not continuous due to the ranges overlapping. I tried solving this using hysteresis, but still did not have success. Instead, I though of an algorithm that could work with overlapping values.
I decided on using a rolling average algorithm. This would make the sensor response significantly smoother and have less variance whether Rambo was on the sensor wire or not. When I first implemented this, I did not account for the small size of "int" that the Arduino could store. I had a rolling average of 100 samples, and it kept going negative. After some debugging, I noticed the value was overflowing and the solution was to use a "long." I chose the circular buffer moving average over an exponentially weighted moving average due to how clear the operation is to see in the code. There are no time constants to deal with.