Problem Connecting Teensy to Raspberry Pi with USB

ProfHuster

Active member
I'm going crazy trying to communicate to a Teensy 3.2 from a Raspberry Pi. I want to read from (and in another application, write to) the Teensy. Python code that works fine between a Mac & Teensy or a laptop running Linux Mint and a Teensy, fails on a Raspberry Pi. Yesterday one of my students stumbled after much experimentation a temporary fix

Plug in the Teensy then immediately start the python code!

Why does this "fix" the problem? Even then, successive reads fails.

I have searched for issues like this and nothing in the suggestions stand out.

Here is what I found. I wrote a small Teensy program that prints every second 200 bytes and every few seconds some other information. The code is below. I have tried several ways to read the data one is to `cat /dev/ttyACM0` (yes, that is the right device). The **first time** I run `cat` it grabs some data, at most about 512 bytes, then it won't read anything else from the device. Successive `cat` commands just hang.

If I run a simple python program readTeensy.py (to emphasize **it works on a Linux Mint machine**) and it reads nothing. If I unplug the Teensy while readTeensy.py is running, but get the exception below.

Teensy code:
Code:
/* 456789012345678901234567890123456789012345678901234567890123456789012
 *
 * Dann-PrintSim
 * Simulates Muon output
 * 
 * ProfHuster
 * 2019-04-07
 * 
*/
static char pgm[] = "Dann-PrintSim\nPrints every 10 s, coinc every 30s";
void blinkLED();
#define LED_PIN 13
static char bigStr[] = ""
"1234567890123456789012345678901234567890\n"
"1234567890123456789012345678901234567890\n"
"1234567890123456789012345678901234567890\n"
"1234567890123456789012345678901234567890\n"
"1234567890123456789012345678901234567890\n";

void setup()
{
  Serial.begin(115200);
  delay(1000);

  Serial.print("# ");
  Serial.println(pgm);

  pinMode(LED_PIN, OUTPUT);
  for(int i=0; i<10; i++)
  {
    blinkLED();
  }
}

volatile long nLoops = 0;
void loop(){
  if(nLoops % 10 == 0){
    Serial.print("12, 15, ");
    Serial.println(nLoops);
    blinkLED();
  }
  if(nLoops % 30 == 0){
    Serial.print(nLoops);
    Serial.println(", -1, -1");
  }
  delay(1000);
  nLoops++;
  Serial.print(bigStr);
}

void blinkLED()
{
  digitalWrite(LED_PIN, HIGH);
  delay(200);
  digitalWrite(LED_PIN, LOW);
  delay(200);
}

Output from `cat`. I type ^C after 30+ seconds.
Code:
# Dann-PrintSim
Prints every 10 s, coinc every 30s

12, 15, 0

0, -1, -1

1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
1234567890123456789012345678901234567890
^C

Exception from unplugging while python code running:
Code:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 490, in read
    'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data 
(device disconnected or multiple access on port?)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./readTeensy.py", line 7, in <module>
    serial_line = ser.readline().decode('utf-8')
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 497, in read
    raise SerialException('read failed: {}'.format(e))
serial.serialutil.SerialException: read failed: device reports readiness to read but 
returned no data (device disconnected or multiple access on port?)
 
Not sure I have the same problem, but I also have an issue communicating between an RPi and a teensy 3.5 over usb. My teensy's application continually sends messages out using Serial.Print and processes any commands that come back over the usb port. What I found is that if I establish a usb serial connection (arduino IDE's serial monitor) from an RPi AFTER the teensy has started up, some of the messages from the teensy get "reflected" back to the teensy and the teensy interprets them as commands. This behavior doesn't happen from a Windows 10 computer. I don't think its the arduino IDE's serial monitor that's at fault because another application running on the RPi does the same thing. I think there's a buffer overflow issue on the RPi that's sending the messages back out.
 
In Arduino's Tools > Ports menu, you should see the /dev/ttyACM0 port twice. One is in "Serial ports" and the other in "Teensy ports". Which one did you use? This matters for troubleshooting, because the "Serial ports" one will cause Arduino to use its normal Java JSSC library. The "Teensy ports" one will cause a helper program to run, which talks to the port using native code (no Java).
 
I was using the latter (teensy) port, but switching to the serial port made no difference.. same behavior. It's a very repeatable problem, and its not specific to the arduino ide's serial monitor (the program interfaces to a different app running on a raspberry pi and I get similar behavior with it): If the teensy is started up with a raspberry pi connected and no serial program running on it, once the serial program (like the arduino ide's serial monitor) is started, some of the messages that are in the usb buffer appear to get sent back to the teensy. If a serial program is running and the teensy is started up, everything works fine and nothing gets "reflected". I assume its because the serial monitor app establishes a connection very quickly with the teensy and is able to clear the usb buffer. This doesn't appear to happen with a Windows 10 computer.. so I'm suspecting its an issue specific between teensy and raspberry pi. I've searched some on the forum and seen some posts regarding serial and low-performance cpu's like the raspberry pi.. but it gets a bit technical for me to follow.
 
I tried "cat /dev/ttyACM0" and I got the same behavior as the arduino ide's serial monitor.

I'd tried googling for raspberry pi usb serial buffer overflows, but to no avail. I'm really at a loss here.

And sorry for hijacking this thread.. I think the issue is at least tangentially related to the OP's issue.
 
And sorry again for spamming, but I sort of solved my issue.. The solution was to unplug and replug the usb cable into the RPi. I don't know why that worked. It still seems to get some characters reflected, but they are much fewer now (2 bytes at most).
 
Back to the Thread

My situation is that I am setting up a remote sensing box, so I can't use the Arduino IDE. I need to connect from the Raspberry Pi to the Teensy using python, or bash, or C, with python preferred. I can't find documentation on how to do the low level setting the "helper program" does, or I would try to implement those commands in my program.

The main problem is that I can't continuously read the Teensy from a program. It hangs and does not receive the data the Teensy is writing.
 
I have searched there and found that Arduinos work ok, but Teensy's are a problem. For example, I switched to an Adafruit Metro Mini (uses the Genuino/Arduino "device" in the IDE) and I do not have a problem. So for that reason I think it is a Teensy problem with the Teensy's.
 
My situation is that I am setting up a remote sensing box, so I can't use the Arduino IDE.

Does the problem happen when using the Arduino IDE's serial monitor, or only with other software?


I can't find documentation on how to do the low level setting the "helper program" does, or I would try to implement those commands in my program.

As I mentioned in msg #7, the command line program is "stty".

For direct control from C code, the type "man termios" on the command line for documentation.


I think it is a Teensy problem with the Teensy's.

I'm skeptical. But let's suppose I would spend 30 minutes look into this problem. Just getting the monitor, keyboard, mouse, and SD card and Raspberry Pi set up on my workbench is going to use about half of that time.

Can you give me an exact set of steps to follow, starting with a freshly written SD card with a particular version of Raspbian? Imagine I'll set a 15 minute timer and if any step doesn't work, or I don't manage to reproduce the problem, or other stuff goes wrong, or the timer goes off, I'll put all the gear away and abandon any more attempts to look into this.

Yeah, I know that's rigid, but please understand almost every problem ever reported with using Raspberry Pi has turned into a major time sink. I don't know what it is about Raspberry Pi, that all sorts of other Linux problems inevitably come up along the way. I'm reluctant to even set the hardware up, unless you can tell me the steps you give truly have been tested and checked against a Raspberry Pi running from a freshly written SD card. If you check the steps only on a Raspberry Pi you've already used, not a freshly written SD card, odds are probably slim I'll get the same results.

If I can reproduce the problem, then there's a lot I can do here, even using a USB protocol analyzer to watch the actual USB communication.
 
Ok. I didn't want to create a time sink, so I will keep trying on my own. But to clarify a point that is not Raspberry Pi specific:

I know the `stty` command, but how do I use it to reset the Teensy? None of the documentation on `stty` or `termios` can tell me how to reset the Teensy. That is a Teensy issue. I can't find on pjrc.com how to emulate what the Teensy helper program does to reset the Teensy. Somehow the helper program can do this; how can I write code (bash, c, or python) to do this?
 
None of the documentation on `stty` or `termios` can tell me how to reset the Teensy.

Maybe you're asking 2 unrelated questions here, and I'm getting them mixed up? Now you're asking "tell me how to reset the Teensy". But earlier, you asked:


some of the messages that are in the usb buffer appear to get sent back to the teensy. If a serial program is running and the teensy is started up, everything works fine and nothing gets "reflected".

This "reflected" problem is very likely a "unix line discipline" issue. Maybe you didn't do any searching for that phrase, to learn about line discipline settings? Or maybe the info you found didn't make any sense?

Anyway, the stty utility and unix termios API are about terminal settings. The key setting needed is "raw mode". I'm not going to write a lengthy message. If you're writing your own code to talk to hardware, I expect *you* to read up on this stuff. The idea is to give you the search terms, so you can find the info you need to learn how to write your code.


I can't find on pjrc.com how to emulate what the Teensy helper program does to reset the Teensy.

First, we need to be clear on what the word "reset" means. Sometimes people say this to mean restarting Teensy, as if the power has been cycled, so it runs your program again. But other times, this means to put Teensy into programming mode, as if you had pressed the physical button on Teensy, so it runs the bootloader and not your program.

Please, be clear saying which "reset" scenario you mean.

To get Teensy to enter bootloader mode, if you have the /dev/ttyACM device open, just set the baud rate to 134. That unusual baud rate is the signal to Teensy (which in serial mode) that it should attempt to enter bootloader mode (without needing a physical press of the reset button).

Also please keep in mind, and hopefully this is obvious, that the 134 baud rate command only works if Teensy is still successfully running a program which listens for the USB message about setting the baud rate. We make every Teensy with a pushbutton dedicated to getting back into bootloader mode, because your code can easily do things like leave interrupts disabled, or enter low power modes where the CPU is stopped, or completely shut off the USB hardware.
 
Oh, yeah, now I see these were questions from 2 different people. Must admit, recently I've been working heavily on T4 and trying to keep up with forum questions, but not spending the sort of time I normally do.

On the Raspberry Pi problems, my hope is to not spend time fiddling with Raspberry Pi testing until T4 is released. But when I do, I really need a clear set of steps which have been tested to reproduce the problem with a freshly written SD card on the RPi. If there is something wrong on the Teensy side, I can almost certainly fix it once I'm able to reproduce the problem. If it's on the Raspberry Pi side, whether I can do anything is less certain. I've written plenty of C code for Linux, but not so much with Python.
 
Paul,
Thanks again for the time. I look forward to the T4! Meanwhile I'll keep plugging along. If I find a solution, I will update the thread.
 
Paul, Prof,

I do not know if my RPi3 (running the latest 2019-04-08 release) and Teensy (3.6) problem is the same as you describe above but I believe I'm experiencing a similar issue when trying to communicate over the USB (connected as /dev/ttyACM0).

To test the connection I used a very simple Arduino sketch:
Code:
void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Hello World");
  delay(1000);
}

When viewing the output using the Serial Monitor I receive:
Code:
Hello World

Hello World

Hello World

Hello World

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

At which point the Monitor no longer outputs text and, although able to immediately respond to a the “Clear Output” button, takes approximately 20 seconds to close the window.

If, however, I physically unplug the Teensy and re-insert it while the Monitor is running then “Hello World” is printed once a second, ad infinitum, as I’d expect.

After seeing this correct behaviour in the Serial Monitor I am then able to execute the following C code, and it outputs the data correct to the console:
Code:
#include <errno.h>
#include <stdint.h>    
#include <stdio.h>     
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <fcntl.h>
#include <termios.h>

int main(void){

    int fd, rdlen, counter = 20;	
    struct termios options; 
	char buffer[100];

    if ((fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY))<0) 
	{
        fprintf(stderr, "open() failed: %s\n",strerror(errno));
        return EXIT_FAILURE;
    }

    if (tcgetattr(fd, &options)<0)
	{
        fprintf(stderr, "tcgetattr() failed: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    cfmakeraw(&options);
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CRTSCTS;
    options.c_cc[VMIN]  = 1;
    options.c_cc[VTIME] = 2;

    if (tcsetattr(fd, TCSANOW, &options)<0)
	{
        fprintf(stderr, "tcsetattr() failed: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

	do 
	{
		memset(buffer, 0, sizeof(buffer));
		rdlen = read(fd, buffer, sizeof(buffer));
		if (rdlen>0) 
		{
			printf("Read: %s\n", buffer);
			counter--;
		}
	} while (counter);


    close(fd);
    return EXIT_SUCCESS;
}
However, if I try running the same executable directly after a reboot then I find the same odd behaviour displayed by the Serial Monitor (before physically disconnecting and reconnecting the Teensy). Specifically, it provides a few lines of text output but then the executable hangs:
Code:
pi@raspberrypi:~ $ ./serial_port_test 
Read: Hello World

Hello World

Hello World

Hello World
Hello World
Hello World
Hello World

Read: Hello World
Hello World
Hello World
I also find similar behaviour when using the cat or screen commands.
I’m new to POSIX and Teensy coding so please forgive me if I’ve missed something obvious. :)

Some of the things I’ve tried so far:
  • No other components are connected to the Teensy
  • Made sure to use cfmakeraw() when setting the serial options
  • Made sure the user pi was in the dialup group
  • Made sure the udev rules were the latest from pjrc.com and were copied to the correct folder
  • Tried chmod to give access directly to /dev/ttyACM0
  • Used stty with various settings (including sane, raw, -iexten, -echo, -echoe, -echok, -echoctl, -echoke, -onlcr and “min 1”)
Prof, have you been able to achieve any progress in overcoming these problems that you’ be willing to share?
 
I am using tytools for serial monitoring on the pi. Had similar issues just using basic code like this:

void setup() {

Serial.begin(57600);
delay(1000);

}

void loop() {


Serial.println("Working!!!");
delay(1000);

}

I was unable to get consistent results and mostly no output at all.

However

Using this code

Code:
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(57600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.println("CONNECTED!!!");


}

void loop() { // run over and over
 byte i; 
  if (Serial.available()) {
    
    i = Serial.read();

    Serial.println(i);
  }

  Serial.println("Working!!!");
  delay(1000);

}

It works perfect and keeps outputting as expected.

See if it helps in either of your cases.....

crees
 
Good Heavens, crees, it looks like you've cracked it!

Adding the
while(!Serial);
during setup() fixed the problems I was seeing in every test case: using my own code, the Serial Monitor, cat and screen commands, both on a Pi and on a PC running Ubuntu (both after a reboot with a previously attached Teensy and a for newly attached Teensy after system-up).

Many thanks for that great tip! :)

I just need to try transferring it to my headless Pi setup when I get the chance but, as it seems to have cured the problem in all my other test situations, I am very hopeful.

Thanks again and all the best,

Dax
 
If the Teensy ever needs to run without SerMonitor connected remember to remove the while(!Serial); or change it to while(!Serial && millis()<4000); - in which case it will wait 4 seconds then run.

The other thing that might help - as it seems the transfer shuts down when the SerMon watching Teensy is not pulling data - like in the last code block of post #17 perhaps something like this that might work as well as the while() in setup() in this case:
Code:
loop() {
 // ...
 if ( Serial ) {
   Serial.println("Working!!!");
 }
 else {
   // blink LED ???
 }
 delay(1000);
}
 
If the Teensy ever needs to run without SerMonitor connected remember to remove the while(!Serial); or change it to while(!Serial && millis()<4000); - in which case it will wait 4 seconds then run.

That’s a great suggestion! I also wonder if triggering the serial print after a serial read value would help in their situation.
 
I ended up trying some other things and noticed that if I change USB type to "Serial + Midi" that I can get my code to read the serial! without the wait statement. Still more testing but wanted to let others here know and see if that setting helps.

crees
 
Ran into similar problem again, and thought I'd leave a reference here in case this is helpful for someone searching about how to capture serial data in linux.

This works really well:
https://github.com/tbird20d/grabserial

You can likely install it like this:
sudo apt install grabserial

Also, this simple python script seems to work, but did have difficulty parsing the file for outputting to csv file. python script here ends up putting quotes around the entire row of values.

Code:
#!/usr/bin/python3                                                                                                                       

import serial
import time
import csv

ser = serial.Serial('/dev/ttyACM0',baudrate=115200)
ser.flushInput()
ser.flushOutput()

while True:
    try:
        ser_bytes = ser.readline()
        print(ser_bytes)
        with open("test_data.csv","a") as f:
            writer = csv.writer(f,delimiter=",")
            writer.writerow([time.time(),ser_bytes])

    except:
        print("Keyboard Interrupt")
        break

When running this, curiously, I'm not sure why this is the output of "Serial.println(59,38);":
b'59,38\r\n'

Don't know where the prepended "b" comes from. In any case, thought I'd post this in case it's useful for anyone when searching for this problem.
 
Python3 bytestrings are not the same as unicode strings (Python3 strings are unicode). A bytestring is notated b'xxxxxxxx'
Python3 strings can be interconverted <-> bytestrings if you give the encoding to use.

This is an area that's different between Python2 and Python3
 
Back
Top