Teensy 4.0/4.1 Serial1.AttachCts

This subject has been covered in prior years, but I'm not clear on the solution. Please forgive the redundancy.

I have a circuit board controlled by a Teensy 4.1, and a daughter card with Teensy 4.0. I need them to talk to each other. I have connected the Serial1 ports and RTS/CTS pins per the PJRC website reference as follows:

TEENSY 4.1 (CLIENT) TEENSY 4.0 (SERVER)
00 (TX)---------------------01 (RX)
01 (RX)---------------------00 (TX)
32 (CTS-XBAR)------------17 (RTS)
27 (RTS)--------------------02 (CTS-XBAR)

Serial communication works in both directions without flow control, but fails when flow control is enabled.

Here are the test sketches:

Teensy 4.1 (CLIENT):

Code:
void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
//  Serial1.attachRts(27);
//  Serial1.attachCts(32);
  delay(10);
  Serial1.clear();
  delay(1000);
}

void loop() {
  byte inByte;
  byte x;

  Serial1.clear();

  for(x=0;x<255;x++)
  {
  delay(1000);
  Serial.print("Sending: ");
  Serial.print(x);
  Serial.println("");
  Serial1.write(x);
  delay(20);
 
  if(Serial1.available()>0)
    {
    inByte = Serial1.read();
    Serial.print("Received: ");
    Serial.print(inByte);
    Serial.println("");
    Serial.println("");
    }
  else
    {
    Serial.println("No Incoming Bytes Available.");
    Serial.println("");
    }
  }
}

Here is the sketch for the Teensy 4.0 (SERVER)

Code:
void setup() {

  Serial1.begin(9600);
//  Serial1.attachRts(17);
//  Serial1.attachCts(2);
  delay(1);
  Serial1.clear();
}

void loop() {

  byte inByte;
 
  if(Serial1.available()>0)
  {
    inByte = Serial1.read();
    Serial1.write(inByte);
  }
}

With the hardware flow control disabled, the sketch works correctly:

WITHOUT HARDWARE.jpg


When hardware control is enabled, there is no communication:

WITH HARDWARE.jpg


Have I wired incorrectly, or not invoked hardware control in the proper code sequence? There is a discussion of this issue on the forum late last year, but it's a little over my head and I'm not clear what the recommended solution is. The PJRC reference calls attention to the CTS inversion, but it doesn't indicate you can't make hardware flow control work.

https://forum.pjrc.com/index.php?threads/teensy-4-1-and-attachcts.74141/

Would it help to put a inverting buffer on the CTS outputs? Would that cause a timing problem?

Thanks for your guidance.
 
You will indeed need to invert the CTS output. If you switch to Serial3 instead of Serial1 you can use pin 19 for CTS and not need an inverting buffer. If you can't use Serial3 and have two unused pins on your teensy you can build your own inverter in software, just tie your CTS pin to an used pin, then sense the pin change on an interrupt. Output the inverted signal on yet another pin with a digitalWrite() call.
 
Thank you 'dundakitty' for your informed response. It's unimaginable that a major chip manufacturer could make such an overt design error. Unfortunately, the Serial3 dedicated pins are unavailable to me, as I could not main sketch backwards compatibility with prior generation boards.

It's no trouble to add a inverter. I usually use the 74HC14 Schmidt Trigger Inverter. Unfortunately, inverters are one-way devices. As I understand it, CTS/RTS connections are bi-directional, so it would probably have to done over a buss, which gets too complicated. Please let me know what you think.

So for now, I guess I'll go without flow control. I'm not moving large amounts of data. Mostly just setting and retrieving numerical values and internal variables via short text-based strings. I see from previous discussions, that a baud rate of 250K is considered safe, and Paul S. once speculated that 500K might be OK with CAT6 wires. My project is wired over 12 mil circuit board traces, so I expect the lines will be pretty stable and low noise.

I'm curious about baud rates with UART on Teensy. I come from the motion picture and broadcast video industry. We commonly used RS232 and RS-422 in the old days, but the baud rates were specific, such as 9600, 115200, etc. With Teensy-to-Teensy serial communications, can you define any number, or are there specific baud rates that are standard or optimal?
 
As I understand it, CTS/RTS connections are bi-directional, so it would probably have to done over a buss, which gets too complicated. Please let me know what you think.
They are not bi-directional because there are separate signals for each device - RTS from one device connects to CTS on the other. When a device is ready to receive it asserts RTS which the other device receives as its CTS signal.
 
I've used Teensy Teensy ---> TTL USB Serial Adaptor ---> PC at up to 2Mb/s without character loss.
I grew up with RS232 on Z80 systems and still think that it is imaginable that serial comms can take place at 2Mb/s.
I have systems working at 115200b/s over PCB tracks ---> 6" wires ---> pc tracks without problem.
 
CTS is an input, RTS is an output. The output of an 74HC14 inverter connects to the CTS-XBAR pin. The RTS signal from the other teensy connects to the input of the 74HC14 inverter. The diagram here: uart flow control may help. You can ignore the "Legacy Hardware Flow Control" section.
 
Maybe it is just me, but since I believe all of this is controlled by software:

Code:
// Configure RTS flow control.  The pin will be LOW when Teensy is able to
    // receive more data, or HIGH when the serial device should pause transmission.
    // All digital pins are supported.
    bool attachRts(uint8_t pin);
    // Configure CTS flow control.  Teensy will transmit when this pin is LOw
    // and will pause transmission when the pin is HIGH.  Only specific pins are
    // supported.  See https://www.pjrc.com/teensy/td_uart.html
    bool attachCts(uint8_t pin);

Maybe someone should add an option to one or both of these methods to allow their pin level logic to be inverted... In the same way that RX and TX can be inverted...
 
Thanks gentlemen (or GentleCats). KurtE's idea is far too practical. It defies that natural law of Entropy!
🐕 :D

I played with this some.
Here are my modified sketches...
Code:
void setup() {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.attachRts(27, true);
    Serial1.attachCts(32);
    delay(10);
    Serial1.clear();
    delay(1000);
}

void loop() {
    byte inByte;
    byte x;

    Serial1.clear();

    for (x = 0; x < 255; x++) {
        delay(1000);
        Serial.printf("Sending: %u AFW: %u\n", x, Serial1.availableForWrite());
        Serial1.write(x);
        delay(20);

        if (Serial1.available() > 0) {
            inByte = Serial1.read();
            Serial.print("Received: ");
            Serial.print(inByte);
            Serial.println("");
            Serial.println("");
        } else {
            Serial.println("No Incoming Bytes Available.");
            Serial.println("");
        }
    }
}

And the other.

Code:
void setup() {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial1.attachRts(17, true);
    Serial1.attachCts(2);
    delay(10);
    Serial1.clear();
    delay(1000);
    pinMode(LED_BUILTIN, OUTPUT);
}


void loop() {

    byte inByte;

    if (Serial1.available() > 0) {
        digitalWriteFast(LED_BUILTIN, LOW);
        inByte = Serial1.read();
        Serial1.write(inByte);
    } else {
        digitalWriteFast(LED_BUILTIN, HIGH);
    }
}

I only added the support to attachRts as Cts is controlled by the Hardware Serial system and may not have ways to easily invert.
But one should be sufficient.

I did the work on my variants branch:
But on the very strong possibility that it's PR will not be pulled in

I then had github cherry pick it into a new branch and created an individual PR for it:

You might give it a try and see if it works well enough for you.
Note: I only added this support for T4.x
 
I see KurtE and Paul S. are in talks on an RTS inversion. Do I understand that you are making a modification to the official Teensy serial library, or this is a custom library I need to install into the existing libraries?

I'm not EE, so do I understand that you are inverting the output of the RTS pin via assembly language or register changing to create the same result as that of an external IC inverter?

I've redesigned the daughter card to provide for a TTL inverter, but it would be awesome to make my existing boards work.

Thanks again for everyone's help and please let know how this ends up.
 
Assuming we finalize the API, it would be in the main Teensy code base.

The discussion between @PaulStoffregen and myself is about what the API should be. He would prefer it
to not have a bool for the inversion... He proposed another API, and I proposed changing the bool to a
typedef enum which is more explicit on is it asserted when pin is HIGH or LOW. And maybe asserted
is not as clear of a name, could be something like: DATA_IS_TRANFERED_WHEN_PIN_IS_LOW (or HIGH)...
 
Note: I just pushed up changes to what Paul asked for...
The example sketches I was playing with the lines like:
Code:
Serial1.attachRts(17, true);

were changed to:
Code:
Serial1.attachRtsReversed(17);
 
Thank you KurtE. Is the library ready for me to test? Do you have a link to download? Is the library called "Serial", or is it more specific to the UART ports? Do I just replace the installed folder with the new one? I use a slightly older version of Arduino/Teensyduino, as my computer won't write correctly with the newest versions.

Thanks.
 
Thank you KurtE. Is the library ready for me to test? Do you have a link to download?
This is part of the core code that is released with installing Teensyduino (or the equivalent using the board manager).

So far it has not been pulled into the main core.
They are up in my branch associated with the PR:
(HardwareSerial.h and .cpp) which you can download those files and replace the one in your install (again assuming reaonsably current install)
 
I can't explain it, but if I use newer builds than Arduino 1.8.3 and Teensyduino 1.53, my writes to Teensy 4.x fails on my computer. I use an HPZ640 with Windows 10 22H2. I suppose I could install 1.59 on a bogus computer and copy the entire HardwareSerial folder.
 
The 1.8.19 IDE can be unzipped to a NEW folder and then TD 1.59 could be installed there and running the Arduino.exe from that NEW folder will start it up from that folder so you could give it a try without any change to the version in use.

If that doesn't work the files could be transferred from there perhaps.
 
I can't explain it, but if I use newer builds than Arduino 1.8.3 and Teensyduino 1.53, my writes to Teensy 4.x fails on my computer. I use an HPZ640 with Windows 10 22H2. I suppose I could install 1.59 on a bogus computer and copy the entire HardwareSerial folder.
I don’t think TD 1.59 will install on that version
Teensyduino 1.59 supports Arduino versions 1.8.5 and 1.8.9 and 1.8.13 and 1.8.15 and 1.8.16 and 1.8.19.
 
SUCCESS!!!!!

As I indicated above, I'm unable to use current Teensyduino, as the NativeEthernet doesn't work on my system. Perhaps I'll move over to QEthernet and get it working. To make the new functions work in Teensyduino 1.5.3, I copied and pasted the new function and variable 'pin_rts_inverted_' into the existing HardwareSerial.cpp and header file in the 'teensy\core\teensy4\ directory.

So I pasted the new AttachRtsInverted() into my scripts, and it's working on Serial1. I assume that because I invoked AttachRtsInverted() and AttachCts() on both client and server sketches, that hardware handshaking is being used.

I hope Paul S. and KurtE will consider informing the general Teensy users of this solution to the ARM processor CTS error.

I am always grateful for the support of this forum.
 
Back
Top