aioscilloscope / Learn / Decode a serial signal

Decode a serial (UART) signal with an oscilloscope: an XBee radio, step by step

A serial port sends one bit after another on a single wire. An oscilloscope can show you those bits and turn them back into the characters that were sent. Here is how, with a real radio and a real scope, from the wiring to the decoded answer.

An XBee-PRO S3B's serial line on CH1, decoded at 57,600 baud. On our setup the probed line carried both the command, ATVR, and the radio's answer, 8075 (its firmware version).

CH1What you need

CH2What a serial character looks like

The line rests high: 3.3 V on an XBee. To send a character the transmitter pulls it low for one bit time (the start bit), sends the 8 data bits, lowest bit first, and returns the line high for at least one bit time (the stop bit). That is "8N1": 8 data bits, no parity bit, 1 stop bit, so 10 bit times a character.

idlestart0D01D10D20D30D40D50D61D70stop1idle
The letter A (0x41, binary 01000001) as 8N1: the start bit, then D0 to D7 lowest bit first, then the stop bit.

The baud rate sets how long each bit lasts: one bit is 1 / baud rate. At 57,600 baud that is 1 / 57,600 = 17.4 µs, and a character is 10 × 17.4 µs = 174 µs. There is no clock wire: the receiver times every bit from the falling edge of the start bit. That is why the scope triggers on that edge, and why both ends must agree on the rate. Do not know it? Find the baud rate with the scope.

CH3Step by step

  1. Connect the probe. To read the radio's replies, clip the probe tip to its DOUT pin (pin 2 on a through-hole XBee); to read the commands sent to it, its DIN pin (pin 3). The ground clip goes to GND (pin 10). Plug the radio's USB adapter into a PC and open a terminal at the radio's baud rate: ours is set to 57,600; a new XBee runs at 9600.
  2. Set the channel. CH1 at 1 V/div, DC coupling, probe 10× (set the probe's switch to 10× too). Move the trace down so the whole 0 to 3.3 V swing is on screen.
  3. Trigger on the start bit. Edge trigger, source CH1, slope Falling, level 1.6 V: about half the 3.3 V swing. A serial line rests high, and every character begins by pulling it low.
  4. Pick a time base. 500 µs/div shows 5 ms: room for several characters at 57,600 baud, where one character takes 174 µs. Move the trigger point toward the left edge so the screen shows what follows it. At 9600 baud use 2 ms/div.
  5. Turn on the decoder. On a NovaOS scope: Decode, B1, bus type RS232. Tx: CH1, Threshold 1.6 V, Polarity Positive (the line idles high), Rx: OFF, Baud 57.6kbps, Data 8 bits, Parity None, Stop Bit 1 bit, format ASCII.
  6. Capture the radio's OK. Press Single, then type +++ in the terminal and wait; do not press Enter after it, which would break the second of silence the radio waits for. The radio answers OK, and the scope stops on it: O, K and CR (the carriage return that ends every reply) under their bits.
  7. Capture a real answer. Press Single again and, within 10 seconds, type ATVR and Enter. The radio answers with its firmware version in hexadecimal (our XBee-PRO S3B: 8075). ATCN leaves command mode; so do 10 seconds without a command.

The XBee listens for commands only in command mode. One second of silence, +++ and another second of silence put it there (the default guard time, GT, is one second), and it answers OK. Commands are AT plus two letters, values in hexadecimal; Enter ends each one. Source: Digi's "XBee-PRO 900HP/XSC RF Modules S3 and S3B User Guide" (90002173), Command mode; the 2.4 GHz XBees work the same way. Other devices: send them any text.

CH4Both directions at once

On our setup the probed line carried both the command, ATVR, and the answer, 8075. To be sure which is which, probe each direction on its own pin: DIN (pin 3) carries the commands sent to the radio, DOUT (pin 2) its replies. The RS232 decoder reads two lines, Tx and Rx: put CH1 on DOUT as Tx and CH2 on DIN as Rx, each with a threshold of 1.6 V, and trigger on CH2. The decoder then shows your command and the radio's answer, one after the other, in time order.

Two probes rarely fit side by side on the XBee itself: its pins are 2 mm apart. On Digi's XBee Grove Development Board, the board we use, the row of holes beside the socket, J3, repeats the XBee's left-hand pins on a 2.54 mm (0.1") pitch: pin 2 is DOUT, pin 3 is DIN and pin 10 is GND. The holes come empty, so solder in a 10-pin header first, then hook a probe on each pin. Leave the P11 jumper on UART: on Loopback the board wires the radio's output back to its input and the PC hears nothing. Source: Digi's "XBee Grove Development Board User Guide" (90001457).

XBeeModuleU1J3J1J2J4Grove DIO12Grove DIO1/DIO11/I2CGrove DIO4Grove PWM0Grove AD0/CBGrove AD2RXTXRSSIAssociateUser LEDOn/sleepResetCommissioningUser ButtonPotentiometerUSBBatteryLoopbackUARTLoopbackP11CH1 tip: J3 pin 2, DOUTthe radio's replies: decoder TxCH2 tip: J3 pin 3, DINcommands to the radio: decoder Rxboth ground clips: J3 pin 10, GNDpin 1 (square pad) is 3.3 VJ3 comes as empty holes: solderin a 10-pin 2.54 mm (0.1") header.The XBee's own 2 mm sockets (J1, J2)are too fine for two probe hooks.Keep the P11 jumper on UART.
Probing both directions on Digi's XBee Grove Development Board: CH1 on J3 pin 2 (DOUT), CH2 on J3 pin 3 (DIN), both ground clips on J3 pin 10 (GND), the P11 jumper on UART.
Both directions on one decoder: what the PC sends (DIN, CH2, the decoder's Rx) and what the radio answers (DOUT, CH1, its Tx).

If the decode looks wrong

What you seeWhy, and what to change
"Waiting for a trigger", nothing on screenNothing was sent while the scope was armed, or the level is outside the signal's swing. Arm first, then send. Why the scope waits.
Wrong characters, error marksThe baud rate does not match. Measure it (how), turn on Auto rate, or try the common rates: 9600, 19,200, 38,400, 57,600, 115,200.
Every character wrong at the right rateThe polarity is inverted. A logic-level UART idles high (Polarity Positive). A real RS-232 port idles at a negative voltage and needs Polarity Negative and a threshold near 0 V. On NovaOS the sheet says "Line idles high" or "low", and Auto polarity sets it from the line.
"Too few points a bit for 57.6 kb/s"The screen holds too few samples for each bit. Use a faster time base, or press Stop: a stopped scope decodes its whole record.
A small 60 Hz wave and no charactersThe probe is not on the serial line, or the device is off: that is mains hum on a floating input. What hum looks like.

Why we use this test

The scope captures bytes we know were sent and must decode exactly those bytes. On our Owon ADS802A running NovaOS the XBee-PRO S3B measured 57,236 to 57,724 baud over many runs, against its nominal 57,600: from 0.6 % slow to 0.2 % fast, well inside what a UART tolerates (how much). The decoder must still get every character right.

Questions

Can any oscilloscope decode UART?

Any scope can show the bits; reading them by eye is slow but works: find the start bit, then read each bit time as 0 (low) or 1 (high), lowest bit first. A serial decoder does it for you and writes the characters under the trace. Most current scopes have one, sometimes as a paid option.

What is the difference between UART, TTL serial and RS-232?

A UART is the circuit that sends and receives the characters. On a circuit board its line swings between 0 V and the logic supply (3.3 V or 5 V) and rests high: that is TTL or logic-level serial. RS-232 is an electrical standard for cables: a 1 (and the resting line) is a negative voltage, between −3 and −15 V, and a 0 a positive one. The characters are the same; the decoder's polarity and threshold differ.

Which pin do I probe, TX or RX?

Probe the output of the device you want to read: its TX. One device's TX is the other's RX. On a through-hole XBee, DOUT (pin 2) is what the radio sends (its replies) and DIN (pin 3) what it receives (the commands).

Why trigger on the falling edge?

Because every character starts with one: the line rests high and the start bit pulls it low. A falling-edge trigger at half the swing stops the scope at the start of a character, so the capture and the decode begin there.

Do I need a 10× probe?

At these rates a 1× probe works too, but a 10× probe loads the line ten times less (10 MΩ instead of 1 MΩ) and has far more bandwidth. Set the scope's probe setting to match, or every voltage reads ten times off.

More to try

Every guide