Wednesday, January 26, 2011

New Level Shifter

Today I am going to try putting in place the serial level shifter I received from SparkFun, to replace my old hand-wired one. This will require soldering a few wires from the shifter PCB to a serial connector. After this I will observe whether the quality of the bit waveforms in the shifted serial data stream is improved, and whether the number of serial errors is reduced. I emailed Gordon to ask him to instrument his Java data-file reformatting program to count the number of serial glitches; I will collect "before" and "after" data runs which will allow us to compare the quality of the serial data streams.

First, for the record, here is the new serial level shifter, ready for soldering:


And here is my old spaghetti-wired version of the same circuit:

And here is a scope plot showing a slow rise time on the level-shifted output (light blue trace), perhaps due to parasitic capacitance, or maybe the BJT we used just had inadequate specs:

We have to make the following connections. To get straight the serial terminology, the GPS is acting in the role of DCE (data communications equipment or modem), so is using DB9 pin 2 (straight-through cable) to transmit, while the FPGA board is acting as DTE (data terminal equipment or PC), so is using DB9 pin 2 to receive. Meanwhile, pin 3 of the DB9 connectors at both ends of the cable are used to send data in the opposite direction - from DTE (FPGA board) to DCE (GPS module).
  • VCC (JP2 hole 1) = shifted high level -- bare yellow wire (to alligator-clip to 3.3V supply)
  • GND (JP2 hole 2) = RS-232 ground (hi-V DB9 pin 5) -- green wire -- lo-V DB9 pin 5 (top row, right).
  • TX-O (JP2 hole 3) = lo-V, inverted version of hi-V DB9 pin 2 (DCE->DTE) --> red wire --> lo-V DB9 pin 2 (top row, 2nd from left)
  • RX-I (JP2 hole 4) = lo-V input, inverted & raised to hi-V DB9 pin 3 (DTE->DCE) <-- white wire <-- lo-V DB9 pin 3
Here's the completed solder job:


Now we'll power off the 3.3V supply (which turns off both the OCXO and the existing level shifter, thereby pausing all data collection) and close the server, halting the data run. The data file (about two days' worth, Tuesday to today) is about 74MB in size.

Disconnected serial cables from old level shifter, connected them to new level shifter. Copied node 0 UART transcript file, restarted server (to start new transcript file) and Wi-Fi board (to re-establish server connections). Here's the new shifter rig, with cables and lo-V output probe:


The 7-segment display says "oh" acknowledging that the FW received some startup messages from the Wi-Fi board, although it didn't understand them. I should change the FW to display an error code in that case. OK, did that. Restarting FW from within Nios II IDE. OK, it is ready to go...


Turning on 3.3V supply... This will start the run (hopefully!)

OK, whoops, discovered that the level shifter is expecting the hi-V input to come in on pin 3, not pin 2, so had to switch the GPS to DTE mode, to use the opposite pin. Here are the corrections:
  • VCC (JP2 hole 1) = shifted high level -- bare yellow wire (to alligator-clip to 3.3V supply)
  • GND (JP2 hole 2) = RS-232 ground (hi-V DB9 pin 5) -- green wire -- lo-V DB9 pin 5 (top row, right).
  • TX-O (JP2 hole 3) = lo-V, inverted version of hi-V DB9 pin 3 --> red wire --> lo-V DB9 pin 2 (top row, 2nd from left)
  • RX-I (JP2 hole 4) = lo-V, inverted & raised to hi-V DB9 pin 2 <-- white wire <-- lo-V DB9 pin 3
Hm, conundrum: With this long serial cable connected to the output, the rise time seems about as bad as before,


and, worse, I am not receiving any serial data! I think maybe the output voltage is too low. It is only 2.97V, whereas it should go almost all the way to the 3.3V rail. Aha, just realized that I forgot to ground the level shifter to the power supply. OK, with that connection added (via a convenient alligator clip) now the high output level is 3.28V, as expected. However, the firmware is still not seeing any data! Perhaps the gelware UART peripheral got hosed while I was fiddling around. Let me re-compile the design the Quartus (to pull in the latest FW changes) and re-program it onto the board. Aha, that fixed it. We are getting serial data again from the GPS. Here's the UART bridge TikiTerm window on the server:

Still, since the rise time doesn't look noticeably better, I don't know if all this is going to help with the serial data glitches at all. However, one thing I noticed while testing is that if the long serial cable from the level shifter to the FPGA board wasn't present, the rise time on the low-V level shifter output was much shorter. So this suggests that perhaps the serial glitches would be eliminated if I simply used a shorter serial cable. I should run by Fouraker's and/or Radio Shack and see if I can find a shorter cable. Or, I could even plug the level shifter directly into the FPGA board, except that the hand-wired header connectors on both ends are female, so I would need a M-M gender bender. Wait, maybe we have one? No, but maybe I could rig one up using some bare DB9 connectors... Here we go:


The one connector's pair of solder flange rows is just wedged between the other connector's pair of solder flange rows, and the whole thing is bound up with electrical tape. Not the greatest connection prolly, but at least I didn't have to do more soldering!

Argh, no, that won't do it... The pin numbering is inconsistent now between the two sides. Let me just go buy a real gender bender (hopefully that will cross over the wires to keep the pin numbering consistent)! Off to the store...

UPDATE @7:20 pm: Fouraker's was closing as I arrived (@ 5:30), but Radio Shack had what I needed. I got a null modem adapter to crossover pins 2 & 3, which is to sit between the GPS and the level-shifter, so that I can just leave the GPS unit in DCE mode all the time (since it needs to be in that mode when controlling it from the PC). And I got a male-to-male DE9 gender-bender adapter, which will allow me to interconnect the hand-wired female connectors that are dangling off the FPGA board & the level shifter, and hopefully improve the rise-time on the 3.3V serial input & hopefully reduce the number of serial comm glitches.

HOWEVER, I should remark with the caveat that the serial glitches *could* conceivably be due to buffer overflows, say in a UART device somewhere, due to our near-complete lack of flow control, and not to any electrical problems with my serial connection per se. Really, I need to instrument the Nios firmware so that it verifies the checksums on the NMEA messages from the GPS before echoing them out over the Wi-Fi connection, and report an error on the diagnostic output if there is a bad or missing checksum. Then, in the Nios command shell, we can pipe the nios2-terminal output to a "tee" command to log a transcript file from the app, and then if we detect serial glitches, we can go back and refer to the transcript see whether they were already present in the NMEA lines when the FW first received them from the GPS. This will narrow down whether the glitches are occurring in the GPS->DE3 serial link (perhaps due to lack of flow control there), or in the rest of the communication path. They could also be occurring in the DE3->WiFi serial link, which has pins that could be used to implement CTS/RTS flow control, but I need to look back at the EZURiO manuals to see if/how I can configure it to use these signals. At the FPGA end, the flow control might need to be implemented manually, because if I recall, the Avalon UART core ignores the CTS/RTS signals even when configured to pass them through. Next, the characters could be getting dropped due to internal buffer overflows in the WiFi board's bridging function, perhaps due to limitations of its RTOS; if so, then this could conceivably be addressed by using the more efficient "flyover" mode instead. Next, conceivably the characters could be getting lost during network transmission, although normally I'd expect that the various PHY, data-link layer and session-level network protocols (e.g., TCP) would do enough error-checking to prevent this. I don't think the losses could possibly be happening in the server itself, since the Python language is pretty tight with respect to that sort of problem, and I don't think my Communicator classes had any arbitrary buffer-size limitations.

No comments:

Post a Comment