I was pretty pleased with my serial level shifting board – right up to the point where I tried to use it.
The tl;dr version of this post is that the board works, but not well enough. It has severe limitations that, I think, make it useless for the intended purpose. Let me explain…
The purpose of the board is simple. The SmartParallel board runs at 5V, and that includes the signals on the serial communications port. But I intend to connect this board to a Raspberry Pi, which has 3.3V GPIO pins that are not 5V-tolerant.
I toyed with the idea of having two serial ports, at the two different voltage levels, or maybe a couple of jumpers that would allow the desired level to be set on the port. But it was starting to add a lot of complication to an already complex board.
So I decided to leave the serial port at 5V and make level conversion a problem to be dealt with elsewhere.
That elsewhere was a small daughterboard that would plug right on to the right-angle header pins of the serial port. The serial level shifter board uses a TXB0104 bidirectional level translation IC. I’ve used these (usually in the form of Adafruit’s handy breakout board) many times, mostly for I2C signals. And it’s worked a treat.
The reason for spinning up my own board, rather than using Adafruit’s, is that I could power the board with 5V from the SmartParallel but have an LM1117 regulator on the daughterboard to also provided the necessary 3.3V power source. Plus I could chuck on some blinkenlights. Very neat.
I’ve been through a couple of iterations of the board. And I thought I’d properly tested it – but maybe not.
Recently, I hooked up the stripboard prototype of the SmartParallel to a Raspberry Pi, via the level shifter board. That didn’t go so well. The text coming from the SmartParallel was arriving totally garbled at the RPi end. (I was running Minicom on the Pi.)
I chucked the oscilloscope on the level shifter board with RS232 decoding selected and, once I got all the settings right (LSB first, idle high, etc) confirmed that the text was arriving in good shape at the level shifter board. But what was coming out – not so great.
If I removed the connections to the Pi, I could see the text coming out, although text going in only on the TX line was coming out on both TX and RX lines. Huh?
To see if somehow there was a short of some kind, I fired up the function generator. A signal going in on either the TX or RX line on the 5V side would come out only on the corresponding pin on the 3V3 side, and very cleanly at that – no short or crosstalk.
That only made things more confusing.
Next, I tried connecting the SmartParallel to my iMac via the level shifter board and an FTDI-based USB-serial cable. On the Mac I saw garbage been received.
To the Arduino!
Perhaps there is an issue with the SmartParallel. I grabbed an Arduino (actually, the very handy TinyLab kit which poses as an Arduino Leonardo). A quick sketch caused “Hello world” to be sent out over the serial once a second.
Still the iMac was receiving garbage – albeit synchronised with the outgoing message.
If I removed the level shifter board and connected the Arduino’s serial output direct to the FTDI cable (just for a moment, mind, as the FTDI works at 3.3V), the message came through loud and clear. So it was definitely my board causing the issues.
The version of the TXB0104 I’d used on the level shifter board comes in the TSSOP-14 package. The pins on those things are tiny and the pitch minuscule. Maybe my problem was bad soldering (although I tested four boards in two different revisions, all with identical results).
Luckily, I have some SOIC-14 versions of the chip – much easier to solder. So I threw one of those on a SOIC-20 to DIP breakout board and rigged up a breadboard version of the level shifter board.
And I got the exact same results.
During all of this, however, I did take time to revisit the datasheet for the TXB0104. There is an output enable (OE) pin on the chip. This needs to be pulled high via a resistor to make the chip work – if it’s low, the pins go into high-impedance mode.
I realised I’d pulled this pin to 5V, but it’s meant to be referenced to VCCa, which is 3.3V in this case. Oops. I made the change on the breadboard. Still no joy.
But… a few times, amid all the junk appearing on the terminal on the iMac, I saw the word “Hello”. Dammit, it was almost working. That basically ruled out a logic problem. Something else was going on.
More Googling. And finally a clue. Someone commented in a forum that the output power on the TXB0104 pins is feeble. In fact, Adafruit itself warns, on the page for the TXB0104 breakout board:
Since this chip is a special bi-directional level shifter it does not have strong output pins that can drive LEDs or long cables, it’s meant to sit on a breadboard between two logic chips! If you do not need instant bi-directional support, we suggest the 74LVX245 as below which has stronger output drive.
Some of that was even in bold. Then I thought back. When testing with the oscilloscope, I could see text coming out of the 3V3 pins only when there was nothing connected to them – no load. And, as I said, sometimes part of the message would get through.
So this is a power problem. The TXB0104 simply isn’t capable of driving the signals over the connections I’m using.
That said, things would be very different on the SmartParallel. The level shifter board would be plugged directly into the header pins of the serial port – PCB to PCB. And the wires on the 3V3 side, running between the level shifter board and the Raspberry Pi, would be very short (I’m planning on building a Pi, possibly a Zero, into the same box as the SmartParallel to turn it into a printer server).
So, in the final configuration, the level shifter board might work. It’s just that, on my prototype, I have too many long wires.
The simpler solution
As a fallback, I’m designing a different daughterboard. This consists of nothing but four resistors (not counting connectors). I’m using resistor dividers to bring down the outputs from the SmartParallel – TX and CTS – to 3.3V. The only input is RX (because I’m not planning to use RTS) and, although it’s expecting 5V signals, it should work fine with 3.3V.
It took ten minutes to cobble together a stripboard prototype, and it works great, so far. The incoming 5V signals for TX and CTS first go through a 180Ω resistor. The opposite side of that is linked both to the outgoing signal and a 330Ω resistor to GND. Here’s a schematic.
Not much to it, is there?
The picture above (click on it for a closer view) shows the text coming through clear on the scope. The signal is at about 3.1V, which should be good enough. Certainly the transmission is appearing fine on the iMac now.
It’s a much simpler solution, and maybe one I should have gone with in the first place. I just liked the idea of all the signals being at the right voltage levels. That’ll teach me to be picky…