Stress testing 5.3Mbit/sec serial debug-stream from Arduino

I got the idea for Debugging @ 5.3Mbit/sec (5333333 Baud) on Arduino and other Embedded systems  which basicly let embedded CPU transmit as fast as possible and let the rest of the world adjust to whatever speed that happened to be.  I was a little skeptical at first. but I needed to get an out-off-band debug-stream from my 3D-printer.

3D-printers are often Arduino compatible with an Atmega2560 and so is mine. The Atmega2560 has 4 serial ports, Serial-0 is used to communicate to the host, but the pins for  Serial 1-3 are used for other purposes Serial-1 for the Z endstops, and Serial-3 for the Y endstops.  Since I already modify my printing software (Marlin) it was quite easy to move the endstops other pins.

I made some changes to the Marlin source to get the other serial ports working, and as usual with Arduino you always end up in deep water when you want to change the underlying system, and Marlin have their own custom Serial driver, but I got something working on an Arduino Mega I had lying around and was now ready to install the software on the 3D-printer.

The printer controller on my 3D-printer is a MKS-base-v1.4 which should be very close to a standard RepRap controller. But my changes which worked on the stock Arduino did not work here.  After getting my multimeter out I found that the Y/Z stop inputs had resistors in series with them probably do avoid noise picked up by the lead to the endstop. But it also ruined my 115200 baud debug-serial stream.

What now – get the soldering iron out or ? the resistors are tiny so I was looking for another solution and here we have underlying reason for these blog-posts.

Using 115200 speeds over a bitbang serial port would have crippled the 3D-printer it takes far too long. So I speed things up as much as I could ending at 5.3Mbit/sec.

I am quite pleased with my solution, 35 instruction or 2usec per byte is quite fast, probably comparable to just doing the buffering of serial output using the standard Arduino HardwareSerial code.

I was a little surprised of how good it worked so I thought I would give it some beating. to see if the host system (Linux) could sustain those speed so here we go:

I downloaded this little sketch to the arduino/MKS_base_v1.4

#include "dprint.h"

void setup()
	char *cpt;
	dprint_init(1);		// you must set TX_PORT and TX_BIT in dprint.cpp
	DPRINTLN("NAME #", cpt = "StorePeter", strlen(cpt));

void loop()
	static uint16_t n, m;
	if (n > 10000) {	// around 100 times a second when idle
		n = 0;
		if (m > 100) {	// every second when idle
			m = 0;
			DPRINTLN("\n1,000,000 loops");
		// dwheel();	// wheel moves at 100Hz
	// stress test move: dwheel() here
	// a missing Backspace or other char would easily be seen

connecting to the USB-uart

  • picocom -l /dev/ttyPL2302 -b5333333 –imap lfcrlf

show a very stable output of the wheels running and a the million loop line printing at regular intervals so everything looks good, but is it perfect? and what speed do we actually see?

Lets find out.  This one-liner should give us some data to look at:

while true; do date;sleep 1;done & hexdump -c < /dev/ttyPL2303

the output looked like this

Mon Feb 12 21:23:29 EST 2018
01256a0  \b   /  \b   |  \b   \  \b   -  \b   /  \b   |  \n   1   ,   0
01256b0   0   0   ,   0   0   0       l   o   o   p   s  \n  \b   \  \b
01256c0   -  \b   /  \b   |  \b   \  \b   -  \b   /  \b   |  \b   \  \b
Mon Feb 12 21:23:30 EST 2018
Mon Feb 12 21:23:31 EST 2018
Mon Feb 12 21:23:32 EST 2018
Mon Feb 12 21:23:33 EST 2018
Mon Feb 12 21:23:34 EST 2018
Mon Feb 12 21:23:35 EST 2018
Mon Feb 12 21:23:36 EST 2018
Mon Feb 12 21:23:37 EST 2018
0312a20   -  \b   /  \b   |  \b   \  \n   1   ,   0   0   0   ,   0   0
0312a30   0       l   o   o   p   s  \n  \b   -  \b   /  \b   |  \b   \
0312a40  \b   -  \b   /  \b   |  \b   \  \b   -  \b   /  \b   |  \b   \
Mon Feb 12 21:23:38 EST 2018
Mon Feb 12 21:23:39 EST 2018
Mon Feb 12 21:23:40 EST 2018
Mon Feb 12 21:23:41 EST 2018
Mon Feb 12 21:23:42 EST 2018
Mon Feb 12 21:23:43 EST 2018
Mon Feb 12 21:23:44 EST 2018
Mon Feb 12 21:23:45 EST 2018
04ffda0  \b   -  \n   1   ,   0   0   0   ,   0   0   0       l   o   o
04ffdb0   p   s  \n  \b   /  \b   |  \b   \  \b   -  \b   /  \b   |  \b
04ffdc0   \  \b   -  \b   /  \b   |  \b   \  \b   -  \b   /  \b   |  \b
Mon Feb 12 21:23:46 EST 2018
Mon Feb 12 21:23:47 EST 2018
Mon Feb 12 21:23:48 EST 2018
Mon Feb 12 21:23:49 EST 2018
Mon Feb 12 21:23:50 EST 2018
Mon Feb 12 21:23:51 EST 2018
Mon Feb 12 21:23:52 EST 2018
Mon Feb 12 21:23:53 EST 2018
06ed110   \  \b   -  \b   /  \b   |  \b   \  \b   -  \b   /  \n   1   ,
06ed120   0   0   0   ,   0   0   0       l   o   o   p   s  \n  \b   |
06ed130  \b   \  \b   -  \b   /  \b   |  \b   \  \b   -  \b   /  \b

Here we have 3 execution cycles of a million loop() calls.

  1. second 29-37 position 01256ad-0312a28  diff 8 seconds 2020219 (base10)
  2. second 37-45 position 0312a28-04ffda3 diff 8 seconds 2020219 (base10)
  3. second 45-53 position 04ffda3-6ed11e diff 8 seconds 2020219 (base10)

They are all the same as is 1001*101*2+17=2020219. so we didn’t loose a single byte !

How about the speed ?

2020219 bytes /  8 seconds = 252527 bytes/sec.  Each byte is comprised of a start-bit, 8bit data, and a stop bit , hence we have an effective datarate of about 2.5Mbit/sec – impressive

ttyUSB0  or ttyUSB1 which is the Arduino and which is the debug stream

In my case all my arduinos use either a CH340 serial chip or an FTDI232 while all my loose  USB-serial-TTL adapters use PL2303. to get the system to present the devices based on their type I have created this file:

cat <<EOF >/etc/udev/rules.d/99-ttyUSB.rules 
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyFTDI"
ACTION=="add", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="ttyPL2303"
ACTION=="add", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyCH340"

Hence to open a terminal to the Arduino do:

picocom -l /dev/ttyCH340 -b 115200

and to see the debug-stream do:

picocom -l /dev/PL2303 -b5333333 --imap lfcrlf

And the FreeBee Bonus

I wish I could say that this bonus is by design, but it is more of lucky coincidence.

If you have a look at dprint_init() from the last post, you see that I disable debug-prints all together when the serial output pin is pulled low with f.ex. a 2k2 resistor.

If you leave the USB-uart connector plugged into you system with a ground and serial connection, USB-uart will pull the pin down when it not powered by it USB connection. Hence:

  • If the USB-uart is unplugged (on the USB side) debugging is disabled altogether.
  • When the USB-uart is connected to your computer, debugging will be enabled.

As it is now you need to restart the unit to have it detect the change but you could make it dynamic by calling dprint_init(LEVEL) regularly from you main loop.

(note to the early adopters: There was a missing ‘()’ when it was first published this is fixed now)

From now on, all my projects will contain a permanent USB-uart for the debug-stream. it is an extra cost of 50 cent, two wires and a pin. I can afford that.

Happy hacking


Print Friendly, PDF & Email
This entry was posted in 3D printer, Arduino, Embedded, on Hackaday. Bookmark the permalink.

2 Responses to Stress testing 5.3Mbit/sec serial debug-stream from Arduino

  1. Pingback: Debugging @ 5.3Mbit/sec (5333333 Baud) on Arduino and other Embedded systems | Peter Lorenzen

  2. Pingback: Debugging with Serial Print at 5333333 Baud - Big4All.Org

Comments are closed.