A quick update -- the capacitive touch wheel is working great!
I've been working through verifying the hardware (since there's a lot of it), and ensuring all the critical hardware bits are working before shifting focus to the software and user interface. This is largely to make my mistakes cheaply -- it takes two weeks for new sets of boards to arrive, so it's important to figure out any issues sooner rather than later so that they can be sent out for another turn.
The capacitive touch board was one of the first of the half-dozen modular Arducorder Mini boards that I assembled, and one that I've been excited to get working -- it's the first capacitive touch sensor that I've designed. I mentioned that in an earlier post I'd had trouble contacting the MPR121 capacitive touch sensor on these boards, even after putting together several capacitive touch boards (with progressively less of the board populated, to try and isolate the issue):
Making expensive (in terms of time) mistakes
My normal debug process is to try and isolate the problem -- first to determine if it's a hardware or software issue, then narrow it down to figure out what's going on. Eagle footprints -- check. Schematic verified -- check. Three boards, three different MPR121 Arduino libraries, and one touch board jumpered to an Arduino Due later, the MPR121 still didn't appear to be communicating (while the real time clock on the same board seemed to be communicating fine). This is a really unusual problem, and I'd convinced myself that as unlikely as it was, it was possible that the MPR121 chips had simply arrived dead, or that they were particularly heat sensitive and not amenable to being reflowed in a toaster oven (although the one I hand soldered made this last alternative less likely).
To test this I ordered more touch boards (with slight revisions) from OSHPark, more MPR121 ICs from a different supplier, and an MPR121 breakout board from Sparkfun. The boards arrived this past weekend, and I put one together with the new parts -- same issue, it didn't communicate. I wired up the Sparkfun MPR121 breakout, and tried three MPR121 libraries (I2CDev, Sparkfun, and Adafruit, who just released one and a breakout to match) and two boards (Chipkit Max32 and Arduino Due) -- same issue. It's extremely unlikely that parts from two different batches would be bad, and the Sparkfun breakout board should be tested during assembly -- What was going on?
For debugging purposes, I decided to try the same code and wiring on an Arduino Uno, not because I had any reason to expect that it'd be different, but just to see -- being their flagship product, it was likely it'd work, and maybe there was something subtly different with the timings. And it did work! On goes the logic analyzer to see what's going on!
The MPR121 communicates over I2C, which is a two wire master/slave protocol with a bidirectional data line (SDA) and a clock line (SCL) that's clocked from the master. Above we see the waveforms for the first communication to the MPR121 using the Adafruit library, with the Due on the top, and the Uno on the bottom. The interesting thing is that the waveforms are nearly identical, and in both cases the MPR121 is acknowledging the communications by sending the ACK bit at the end of each transfer, but in the case of the Due (and Chipkit), the read commands are not returning data.
There is one notable difference in the waveforms for the Due and Uno -- during the command to read data from the MPR121, the Uno is correctly sending an I2C "Repeated Start" condition between telling the device it wants to read and actually performing the read, where as the Due is instead sending an I2C "End" followed by a "Start". In most cases that I've encountered this doesn't appear to be an issue, but the MPR121 datasheet clearly appears to show a "Repeated Start" condition for this transaction, so it's likely this is the culprit.
Both devices (Uno and Due) were using virtually the same code -- so why was the Due behaving differently? Some quick searching on the Arduino forum showed that this is apparently a known issue, that Repeated Starts are a new feature in the Wire library, and that they don't appear to be functioning correctly (or are unimplemented) for the Due. The Chipkit is based on an older version of the Arduino platform (I believe it's around Arduino 0023 compatible), so this feature hadn't yet been implemented.
I opened up the Chipkit Wire and TwoWireInterface (TWI) libraries and implemented the Repeated Start functionality exposed through the new Wire.endTransmission(sendStop:Boolean) function, and it ended up communicating and working fantastically! A software issue after all, but rarely do you expect that part of the issue lies with the peripheral libraries -- and it's a great opportunity to push the changes back to the latest Chipkit release so that other folks can benefit. Open source at work!
I've been expanding the Adafruit library (the simplest one that seemed to just work) with functionality for handling capacitive touch wheels, and calculating the touch angle by finding the center of mass on the N-electrode array, and seeing how it's distributed on the neighbouring electrodes. I wrote a quick visualization that would display this angle (pictured above, and in the video at the top), and it works beautifully! I opted to use an 8-electrode capacitive touch wheel to get as much resolution as possible, and it works far better than I had hoped -- it detects even very subtle changes in angle as you slide your finger around the wheel. Fantastic!
This is a major milestone, and now the Arducorder Mini can finally get some input instead of scrolling through test displays from various sensors automatically. I still have to implement some of the other MPR121 functionality to the Adafruit library, like GPIO buttons and LEDs, but now that I've verified the critical bits of the MPR121 and that the wheel is working, that's something that can likely wait a little bit while I move on to verify other hardware, like the CC3000.
Other Quick Updates (Hardware)
- MPU9150 IMU: I wrote some code to test the MPU9150 3-axis accelerometer/gyro/magnetometer using the I2CDev library, and to graph the 6 axes on the same coloured graph. It seems to be working great!
Open Mini Spectrometer / Thermal Camera board: I wanted to have this board sent off this week -- it's one of the sensor boards that I'm most excited about -- but it's also one of the most complex.
- Open Mini Spectrometer: I've been trying to redesign this to lay the whole spectroscope down (so requires less height), improve the spatial translation invariance, potentially move to a more sensitive detector, and potentially move to a laser-cuttable design (with a ~0.2mm laser-cut slit). I've also been trying to avoid as many prescription-ground optical surfaces as possible, which add fantastic amounts to the cost. Some very tiny and inexpensive front-silvered mirrors arrived today, so I'm excited to get back to this. I have to be careful though -- the first open mini spectrometer was designed in an afternoon, and this new version has to be kept tractable and similarly inexpensive. I think rapid iteration is especially important here -- I'd rather get something running end-to-end quickly than take months to work out the perfect spectroscope and leave the new version untested for so long.
- Low-resolution Thermal Imager: I'd initially planned on using the MLX90620 16x4 thermal sensor, both because it looks to have great thermal/resolution characteristics, and (until recently) was really the only game in town for the sub-$100 imager price range. Recently the Panasonic Grid Eye 8x8 array, as well as a similar (but slightly larger) offering from Omron have popped up. A really great Inexpensive Thermal Imager project arrived on Hackaday.io recently, and I've been really impressed that he posted his evaluations of each of these three sensors to verify their thermal characteristics. In his tests, the Omron appears to come out as the most stable, followed by the smaller Grid Eye and the MLX90620, both having largely similar characteristics despite the Grid Eye being half the price. I'd started redesigning the Spectrometer/Thermal Camera board to use the Grid Eye instead, only to find that they're out of stock nearly everywhere, and additional stock doesn't look like it'll arrive for another 3 months -- way too late for me. I think the Omron is too big, so it's back to the MLX90620, which still looks to be an excellent sensor with a larger temperature range than the Grid Eye, and a large range of framerates.
In preparation for the Hackaday Prize Quarter Finals, I've been preparing to put all the source files (as they currently are) on github. Since the HDP quarterfinals now only requires a single video that shows the prototype, I'll likely use the Arducorder Mini Project Concept Video that I put together for the first deadline a few weeks ago, since shooting the videos is so fun that it ropes me in for much longer than I should spend on it -- I'm only one person and there's plenty of code and hardware left to develop! :)
Speaking of which, the other night I was /dreaming/ about writing code (this is usually a sign that I need to take a few days off), and my alarm went off before I'd had the chance to finish it. In my half-asleepness, I grabbed my alarm and set it to half an hour later so I could go back to sleep, finish up the code, and commit it to github before waking up again. Made the whole lab at school laugh this morning. You know you're committed to open source when... :)
Thanks for reading, and stay tuned!