Well, maybe not so much aha! More like FFS.
Weird as it sounds, debugging errors is one of the things I enjoy about both coding and electronics. I’m an amateur in both fields and waste little time on planning my projects. I prefer just to delve right in. Rather than sketch out a circuit first, for example, I just get the soldering iron hot and start plugging those little bastards right into the stripboard.
Of course, this means things don’t always work. A lot.
After the first disappointment comes the careful tracking down of the culprit. And then finally that moment of discovery and joy. Weirdly, I often find this happens just before I go to bed.
And so it was with my Dreambox project. Part of the architecture looks like this: there’s a Teensy (my favourite Arduino-compatible microcontroller) driving the interface and lights.
- The Teensy controls a small TFT display (working).
- It monitors and responds to three buttons and an encoder (working).
- It controls an Adafruit PWM board to control four RGB LEDs (working).
- It turns on and off a strip of LEDs via a Mosfet (working).
- It controls a bank of 16 white LEDs via an MCP23017 I2C port expander chip (dammit! dammit! dammit!).
It’s not like I haven’t used the MCP23017 before – there are four of them doing daily duty in my Dawnclock. Mind you, those are controlled by a Raspberry Pi – but still…
And it’s not like I haven’t used the Teensy with I2C devices. That’s how I control the LED matrix on my HMV1960 project.
To make life difficult for myself, the current project is currently split into two boards joined by a ribbon cable. The Teensy is on one board and the MCP23107 on the other. I used the continuity setting on my multimeter to buzz out all the connections and they all seemed good. But clearly there was a problem somewhere.
So I recreated part of the project on a breadboard – a Teensy, an MCP23017 and some LEDs – to eliminate some of the complexity I’d introduced. Somehow it still wouldn’t work.
So here’s where the process of debugging comes in – isolate each part of the system.
There couldn’t be much wrong with the Teensy, so long as I had the SDA and SCL connections the right way around. I stuck my primitive oscilloscope on the I2C pins and…
Here’s the FFS moment. I’d carefully connected the wires according to the pinout card supplied with the Teensy. But then I realised the Teensy itself was plugged into the breadboard the other way up. Doh!
A quick rewiring and I had the wires connected to the right pins, confirmed by seeing clock and data pulses coming out of the Teensy and arriving at the correct pins on the MCP23017. A quick check of the circuit board I was trying to debug confirmed that I hadn’t made the same mistake there, so that wasn’t the source of my problem.
Still nothing doing with the LEDs, though.
According to the Adafruit info for the MCP23017, it’s safe to supply it with 5V even when connecting to, say, the Raspberry Pi or other devices that have 3.3V pins. And, indeed, I was feeding the MCP23017 chip with 5V.
I looked at the scope trace for the SDA line. With I2C you need to use pullup resistors. The pins on the Teensy (or whatever) then pull the lines low to form the clock and data pulses. I could see (just about) that sometimes, in between being pulled low, the voltage was not quite getting back to the high state before being sent low again.
A value of 4.7KΩ is broadly recommended for external pullup resistors for the Teensy’s I2C (pulled to 3.3V). But it looked to me like this wasn’t quite strong enough in this case, possibly due to the distance the signals were having to travel. So I switched to 10KΩ resistors and the trace looked much better.
But the MCP23017 still wasn’t working.
What I’d read suggested to me that the port expander should be fine working with 3.3V signals. But maybe it’s a little pickier than some people think. And I remembered that, on the Dawnclock project, I’d used a level shifter to bring the I2C signals up to 5V.
I tried introducing a level shifter on the breadboard. Still nothing.
Then something else popped into my consciousness. The level shifter I’d used in the Dawnclock is described by Adafruit as ‘I2C safe’. This uses FETs (if that means anything to you) along with its own 10K pullups. The one I’d used on the breadboard was some cheap piece of crap from eBay whose capabilities are a mystery (probably to everyone). Took that out, put in the Adafruit one and…
My god, it works!
So yeah, it turns out the MCP23017 is a bit picky about signal levels. And it turns out that the ‘design’ of my boards, cobbled together on the fly, weren’t that bad after all.
And it took me less than four months to work all this out.
(Hmm, just a thought… given that the level shifter has its own 10K pullups, does that mean I could remove the ones I’ve got attached to the Teensy? I could try, but that would mean unsoldering the buggers, and the damn thing’s working, so leave it alone…)