Serial1 communication between Teensy 3.6 and Raspberry Pi 3B

Status
Not open for further replies.

famisano

New member
Hi all.

I am working on a project involving a light sensor driven by Teensy 3.6 and using Raspberry Pi 3B as mini-computer.
Basically, the sensor data are collected by Teensy 3.6 and serially transmitted to Raspberry where a Python script reads them with the Python serial library and process them with several algorithms.

Everything works very well when Teensy and Raspberry are connected by a micro USB-USB cable and data communication is performed by using "Serial" instruction. When light source changes at the sensor, Teensy collects the signal and transmits it to Raspberry where the output is updated near in real time.

Now I'm testing "Serial1" on Teensy by using the Teensy pins 0 and 1 (RX1 and TX1) and Raspberry GPIO pins TXD and RXD.
I've updated Raspberry settings so that all data are read by Python script at Raspberry "ttyS0" serial port.
Indeed data transmission from Teensy to Raspberry is performed but it happens much more slowly than with USB communication. The strange thing is that commands I send by Raspberry to Teensy (through the Python graphic interface I've set on Raspberry), that are single bytes, are actually read by Teensy near in real time (I understand this because they enable/disable leds driven by Teensy).

Is this a problem of data transmission speed and/or buffering between Teensy and Raspberry with the Serial1 interface that requires some setting different from the case with Serial/USB communication? I would be very happy to have some indications.

Thanks in advance.
Best regards

Franco
 
Difficult to say without you respecting the forum rule to post code which allows others to reproduce the problem...

First, you have to understand that the data transmission over the virtual serial port over USB on the Teensy might reach several MBit/s (even if you set it at 9600 baud which will be gracefully ignored) while using the classic UARTs like Serial1 are somewhat limited in terms of speed, especially if you use only TX and RX without further handshaking, which will most times limit the successful data rate to about 500000 baud which makes (after start and stop bits) about 50kByte/second of effective payload. Higher baud rates require additional handshaking through RTS/CTS signals.

Thus, I'd start checking my Teensy and my Raspberry code if the baud rate is really set to 500000baud on both sides, and I'd check the communication on the Teensy's TX pin with a logic analyzer to see if the baud rate is really obtained.
 
Hi,

many thanks for your suggestion, I'll do the tests you have indicated.

I also apologize for the code. I'll prepare a short version of it with only the relevant parts, most of the content is not really useful to understand the problem.
Indeed the script does not use RTS/CTS signals for handshaking, anyway the baud rate is limited to 115200.

Kind regards

Franco
 
With 115200baud, you shouldn't expect an effective payload of more than 11.5kByte/s.

It is obvious that the virtual serial ports over USB which ignore the baud rate setting work much more quicker at the same settings.
 
Indeed data transmission from Teensy to Raspberry is performed but it happens much more slowly than with USB communication.

Yup, 12 Mbit/sec USB with ~25% protocol overhead is ~100 times faster than 0.1152 Mbit/sec Serial with 20% overhead for start & stop bits.

The strange thing is that commands I send by Raspberry to Teensy (through the Python graphic interface I've set on Raspberry), that are single bytes, are actually read by Teensy near in real time

This is a design decision in the Linux drivers running on Raspberry Pi.

The serial port on Raspberry Pi can only buffer 16 bytes, so the drivers are designed for low latency because you risk data loss for incoming bytes and inefficient output if the driver doesn't move data before the buffers fill/empty.

USB uses DMA into large buffers directly in the system memory. While it's possible to write low latency USB host drivers, this is almost never done, especially on lower power CPUs like Raspberry Pi. Often the drivers are designed to limit to only a single interrupt per 1ms USB frame. If you're moving large amount of data in continuous streams, as USB disks, webcams and other data-heavy USB devices do, this works out very efficiently. If you send small packets or only a single byte, then wait for a reply from the other side, this USB driver design gives terrible performance.
 
Thanks for your answer. It has clarified most of my doubts.

In the end, the use of USB connection seems the best option for my configuration.

I would like to know if USB data speed performances are achieved also if USB connection is done by directly soldering the two signal wires of a USB cable to the D+ and D- points on the backside of Teensy board, and soldering the 5V and GND wires to the matching points. This would be useful for reasons of space, it would avoid the use of the usual micro-USB plug; in the end, this has been the reason of my tests with hardware serial communication option. A further advantage of this solution is that it would leave the micro-USB socket free in case I have to reload the script.

Thank you again and my congratulations for the Teensy project - really great!
 
Yes, soldering the cable directly should work, as long as it's a cable meant for USB. Using ordinary wires would be asking for trouble, especially if the data pair isn't twisted together.
 
> "...it would leave the micro-USB socket free in case I have to reload the script."
Depending on the length of the wires, it is not guaranteed that the USB connection would work to reload the script, when there is an additional length of cable soldered to the socket D+,D- meaning you have the cable capacitance electrically in parallel, plus transmission-line effects.
 
Well a couple of thoughts occur to me:

  • Consider using a UART -> USB converter between the Teensy and the Pi (i.e. you would use Serial1, add appropriate RTS/CTS connections, and the device makes a USB serial terminal on the Pi);
  • If you want the ability to reload your Teensy, you could add the Pi version of the Teensy loader, and copy the .EXE file from your development system (or use the Pi as a development system if speed is not an issue);
  • It is probably too much work, but consider using i2c or SPI to connect the Pi and the Teensy instead of serial devices -- if you are just sending an on/off indication, you could just use other connected pins (i.e. digitalWrite/digitialRead, and the equivalent Pi inputs);
  • Check that your Python code is setup to flush output quickly instead of buffering it up.
 
Hi all,

thanks for your suggestions, they have been really useful to me.

Indeed I have done some changes to my Python code on Raspberry.
Essentially, I have introduced a flushInput() instruction in the serial data read routine that was not in place with the USB serial data connection.
I see that the data read speed and display at the script has improved.

Now I'm doing more tests to check if this may be the solution.

Have a nice day!:)
 
Status
Not open for further replies.
Back
Top