Communicating via SoftwareSerial

I have made up a few devices that is based on Pro Minis (5V). The Serial pins are used for data input, while they send out data by SoftwareSerial, inverted.
In one case, I want to read the output of one of the other devices, in addition to the Serial input.
So I define two SoftwareSerial, one for reading data from the other device, and one for sending out this data, in addition to it's own processed data based on data received from Serial (daisy chaining).
So far I have no success with this SoftwareSerial - SoftwareSerial communication.
The receiving device receives data if the SoftWareSerial RX pin is connected to a normal serial port and a normal serial port can receive data from the SoftwareSerial TX pin of the other device, but I don't receive anything if the two are connected together.
Since the last device in the chain only reads on one port and writes to the other, I have also tried combining them in a single SoftwareSerial port, but the result is the same.

Before digging further into this, i just wanted to ask if this should work or not? Is it perhaps related to the fact that the output is inverted? Ports on both ends are defined as inverted, though.

Fred

Are the grounds connected ?

When two SoftwareSerial ports are defined, only one software RX can be active.

The SoftwareSerial RX depends on what else the Arduino has to do. Are there more interrupts ? For example from the hardware serial port. Are interrupts sometimes disabled ? For example with a sensor that requires timing (DS18B20 or DHTxx) or NeoPixel.

I think you should do a test.
For example daisy chaining the Pro Mini boards, using normal (non-inverted) software serial, and try a few baudrates.

Do you know the AltSoftSerial ?
https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

Thanks.

They have a common power supply as they are chained with GND/5V/Signal wires.

In this particular case the receiving one has a sensor connected to Serial (115200), and polls data (47 bytes) every 125ms. It formats this data before it is sent out to a telemetry RF unit via SoftwareSerial (inverted). I wanted to add a GPS module, and since I also wanted to be able to use this directly against similar RF units, I choose to let the GPS have its own Pro Mini (Serial 9600) and put out data in the same format on SoftwareSerial (inverted). Works fine when connected directly to RF unit, but not against the SoftwareSerial on the other Pro Mini. If I connect the GPS module directly to the same SoftwareSerial RX pin (non-inverted) and have the GPS processing code added to Pro Mini #1 it works, although with some small performance problems.

I have also tested the GPS/Pro mini against a minimal sketch on a Nano (read SoftwareSerial/write Serial) with same result, so I guess it must be signal level/SoftwareSerial related rather than the code itself.

Will follow your suggestion and try with simple (non-inverted) code in both ends.

BTW, the code also uses a library that depends on SoftwareSerial when running in another output mode, so I'm not sure AltSoftSerial would be an option.

Fred

I don't understand how you have connected everything. I will write my thoughts, and hope they will help somehow :wink:

The Arduino Leonardo has a spare hardware serial port, and the Arduino Mega 2560 has 3 spare hardware serial ports. The Arduino Mega 2560 can be like a spider in a (serial) web, talking to others via serial.
The SoftwareSerial can not be used for something like that.

At 115200 baud, a hardware serial port is required. I assume you do that. The interrups from that hardware serial port will cause trouble for the SoftwareSerial. It means that every 125ms the SoftwareSerial gets into trouble.

If you have 16MHz Arduino board, the baudrates should be close enough to the actual value to make it work. However, if you have a 8MHz Pro Mini somewhere, the baudrates might differ too much.

A low baudrate output only with SoftwareSerial might work. If the RX is not used, please connect it to GND or so, or else the SoftwareSerial library might go nuts.

Something like an GPS is often done with SoftwareSerial. That will work in most (simple) situations.

Communication between Arduino boards can be done with SPI or I2C. I use I2C.

There are also hardware serial ports, that can be controlled with SPI or I2C (Sparkfun or Adafruit has a module with it).

My conclusion: Buy an Arduino Mega 2560.

Perhaps some drawings might help.

Regarding unused SoftwareSerial pins, I followed a suggestion i read somewhere, and set them to pin 255. Anyway, there are no problems until I set RX pin to a real one and connect it to the TX pin of the other Pro Mini.
Otherwise things works pretty well, considering the possible conflicts between Serial and SoftwareSerial, except when reading GPS directly with SoftwareSerial (1Hz 9600), but even then there is just a minor hickup in the Serial (HW) reading every second.
If there was an option for inverted Serial (HW), I could just switch the GPS Pro Mini interfaces, but I don’t think there is.

Mega, Teensy etc. will be too expensive for this, as I plan to make a few.

Fred

Edit: Labels added.

Setup #1 & #2
OK_1.gif

Setup #3
OK_2.gif

Setup #4
!OK.gif

Thanks for the drawings 8)

The first drawing will work, that is normal.

The second drawing will work with some luck. Perhaps the GPS is slower with a response than an Arduino, or a fault in the data is detected and ignored, or the GPS allows some changing in the pulse timing. Is the hickup detected ? In that case it could be still reliable.

The third drawing is indeed the most troublesome, and that is the setup that fails. I could be because that setup is not reliable in the first place. But it could also be an error in the sketch.

I wonder if this will ever work with SoftwareSerial.
You could continue with drawing 2. Use hardware serial for the sensor (you have to switch between uploading a sketch and the serial monitor or the sensor).
Or with drawing 3, use I2C to communicate between the Arduino boards.

I still think that the AltSoftserial could be useful.

At this point I know very little about your project. To be helpful I would like to know everything, every voltage, which Pro Mini boards at which speeds, links to the sensor, your sketch, and so on.

Did you know that the TX and RX of a serial port are not tight together ?
You can use RX from one port and TX from another (software) port. That means you can shift around all the RX and TX as you like.

Peter_n:
The second drawing will work with some luck. Perhaps the GPS is slower with a response than an Arduino, or a fault in the data is detected and ignored, or the GPS allows some changing in the pulse timing. Is the hickup detected ? In that case it could be still reliable.

Well said! I suspect the checksum fails, and one or more GPS sentences are silently ignored. You may be using locations from a previous second, when the sentences were "luckily" parsed.

@flarssen: Timing is everything! :slight_smile: With the addition of a handshake line, the Master (with the sensor) could "request" data from the Slave (with the GPS)... at the right time. Because the Master has to service the sensor every 125ms, it knows when those Serial interrupts will mess up the SoftwareSerial transfer with the Slave.

The same thing can be said of the Slave: it knows when GPS data will mess up the SoftwareSerial transfer to the Master. The GPS device sends a burst of information and then qoes quiet until the next second comes around (previous discussion here).

The Master could set a handshake line HIGH when it's between sensor samples, and the Slave could send data when it sees that and it's during the GPS quiet time. Let's call the handshake line Clear To Send, CTS.

During the GPS quiet time, the Slave could prepare a buffer of location data to send, based on the NMEA sentences that have been received during the last burst. When CTS goes high, it could start transmitting bytes to the Master, and then pause when CTS goes LOW. When the buffer has been fully transmitted, it would wait for the next GPS quiet time.

This coordinates the idle times of both processors, allowing the SoftwareSerial between them to work properly. This is also called "flow control".

Although it doesn't appear to be required, you could add a second handshake line, called Ready To Send, an output from the Slave. After it has a buffer of location data, it could raise RTS, indicating that it has data, and that it's during the quiet time. And now you can google RTS/CTS flow control. :wink:

Peter_n:
To be helpful I would like to know... which Pro Mini boards at which speeds, links to the sensor, your sketch, and so on.

+1!

For example, you don't say what the Sensor speed is... at 4800, 47 bytes would take 107ms, leaving 18ms to receive data from the Slave. If the Slave talks to the Master at 9600, That's only 15 bytes of location data every 125ms. In one second, you may get 4 to 7 intervals, so that's 60 to 105 bytes from the Slave every second.

I ASSume you are just trying to send a few pieces of the GPS information. Which leads to a library I wrote, NeoGPS. You can configure it to process only a few sentences, and just the pieces that you care about. Other sentences and other pieces are completely ignored, saving RAM, program space and CPU time. And because the information is parsed, it can be sent very efficiently to the Master: lat/long would only take 8 bytes. The example programs show how to detect the GPS quiet time. You can also send NMEA configuration commands to turn off sentences that you don't use, which would increase the quiet time in each second.

Cheers,
/dev


P.S. I have had better luck with the newer version of SoftwareSerial, part of the latest IDE or directly from here.

Well, I have to disagree with the missing info part. As I stated in post #1, they are Pro Minis, 5V = 16MHz. I also said in post #3 that the sensor is connected to Serial pins at 115200 baud.
Main reason for not going into too much details is that, as I said in post #3, I have tried to connect the GPS with Pro Mini to a Nano running a simple sketch that relays (SoftwareSerial) data to Serial, and still don’t get any SoftwareSerial - SoftwareSerial communication. This means that whatever is done in the main device has nothing to do with the actual problem.

Referring to the setups in the pictures, what I want is #1, #2 and #4. #3 was just to illustrate that the main device is capable of receiving data, as long as it is connected to a proper serial device (GPS) and not a SoftwareSerial TX pin.

By having a dedicated Pro Mini for the GPS, I get #2 og #4 (if I get communication to work). In the #4 setup, I then only need to send 49 bytes (lat, lon, course, speed and altitude) every second to the main unit, and the format is still the same that the RF unit expects, so its just a matter of passing it on.
I use the TinyGPS library for GPS data and have switched off sentences not needed in the U-center tool.

I have the same experience with latest version. I got some problems after upgrading to 1.6.0 and after upgrading to 1.6.3 the problems was gone and it seemes to work very well. Some changes in timing, I read somewhere.

Time for more testing :slight_smile:

Fred

Well, I have to disagree with the missing info part… post #3 that the sensor is connected to Serial pins at 115200 baud.

Sorry, it’s harder when we have to scan across multiple posts for the whole picture. So, at 115200, the 47 bytes take about 5ms, leaving the rest of the 125ms for other things.

Forwarding the GPS bytes from one Arduino to the other was just a test, I think:

put out data in the same format

Pic #3, right? And it didn’t work. Then you say:

I then only need to send 49 bytes (lat, lon, course, speed and altitude)

I think that means the final sketch will send a formatted string with something like ss.print( lat ), not the raw bytes. I’d guess you did this for Pic #1, but the code would have told us for sure.

Referring to the setups in the pictures, what I want is #1, #2 and #4.

I’ll be danged if I can see #4. I only see 3 pics attached.

Regardless, I think we’re trying to point out the problems with SoftwareSerial and other interrupts. Because the sensor only emits 47 characters, they can all be buffered by Serial interrupts, even if the Arduino is busy doing an RF transmit, or receiving location data from GPS (or the other Arduino).

The problem comes when SoftwareSerial RX is listening. One interrupt from something else at the wrong time, and you lose a bit or a whole character. AltSoftSerial is a little more forgiving in that regard, but it’s a little more restrictive of which pins you can use (I think).

Alternatively, you could time it so the SoftwareSerial RX can only happen when there are no other interrupts. That would be between sensor readings (a 120ms window), and/or the GPS quiet time (maybe 800ms window). If there are two Arduinos, “timing” can be achieved with a handshake line between them.

This may also be why you’re getting a hiccup once per second, even if you use HardwareSerial. The input buffers for the GPS are only 64 bytes, while the two sentences are a 140-byte burst at the beginning of every GPS second. Doing Serial.print to the sensor or ss.print to the RF may block you from getting to the GPS data, and the 65th byte gets dropped. This is a common problem when trying to log GPS to an SD card.

You could probably get everything in one Arduino if the different activities were coordinated, and if you had a really efficient GPS library. :wink:

Cheers,
/dev

In my mind, picture #1 had two setups. I have edited the post. Sorry for the confusion.

The 49 bytes GPS data is the binary format that the RF unit (actually a FrSky RC receiver with telemetry feedback) is expecting (Data type IDs, data + start/separator/tail characters). All data, gathered by the sensor (temperature, voltage, etc.), is sent to the RF unit in this format. That's what I meant by GPS data being in "same format".

In setup #4, the Arduino connected to the RF unit should just read these 49 bytes and pass them on to the RF unit, in between the data from the sensor.

As i have said a couple of times, I was not able to read the GPS Arduino, even if it was connected to a Nano with a simple sketch reading a SoftwareSerial pin. Yet it worked fine in setup #2.

That was why I asked in first post if SoftwareSerial - SoftwareSerial communication should work or not.
Yesterday I put a simple sketch on the GPS arduino, sending on SoftwareSerial to the Nano and it worked, so the answer to the question above is "it should work", and the problem is somewhere in the GPS Arduino code, making it work when connected to a HW serial, but not when connected to a SoftwareSerial pin.
I think it might be related to the fact that the there is an alternative output mode, where data must be polled. Will take a closer look tonight.

Fred

I think you are right. A SoftwareSerial can communicate with another SoftwareSerial. But SoftwareSerial gets easily disturbed by other things and it does disturb the rest of the sketch.
Therefor I can't tell if it just won't work, or if there is an error in the sketch or library. Did you show your sketch ?

No, will do later.

I have found what caused the problem, but have no idea why it does so.

As I mentioned earlier, the units supports two types of RF units. One type just reads the data. The other type requests data from different types of sensors on a single wire (so they can be chained).

To avoid the need to select the type manually, I implemented auto detection by first reading the signal pin (12). If I get some data within 1 second, it will support the requesting type (type-X). If not it will support the other type (type-D). This is done in isTelemetryTypeX().

The problem seems to be that SoftwareSerial gets upset if I read pin 12 first, and later use it to transmit data:

SoftwareSerial serialD(PIN_SerialTelemetryRX, PIN_SerialTelemetryTX, true);
SoftwareSerial telemetryTypeCheck(PIN_SerialTelemetryTX, PIN_SerialTelemetryRX, true); // Get input from Tx pin

The really strange part is that, as mentioned in previous posts, there is no problem if the pin transmits data to HW serial (setup #2), only if it transmits to SoftwareSerial on the other Pro Mini (setup #4). Data never gets available() there.

If I use another pin for SoftwareSerial telemetryTypeCheck(), the call to isTelemetryTypeX() causes no problems, but obviously becomes useless.

Anyone have an idea why this happens?

/*
  Author: flarssen, 05/2015
  GPS to FrSky Telemetry interface,
  using 
  FrSky S-Port Telemetry library http://www.rcgroups.com/forums/showthread.php?t=2245978
  TinyGPS library http://arduiniana.org/libraries/tinygps/
*/
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include "FrSkySportSensor.h"
#include "FrSkySportSensorGps.h"
#include "FrSkySportSingleWireSerial.h"
#include "FrSkySportTelemetry.h"

#define LED_PIN 13                     // the pin connected to onboard LED
#define PIN_SerialTelemetryRX 255      // dummy
#define PIN_SerialTelemetryTX 12       // the pin to use for serial data to the FrSky receiver

FrSkySportSensorGps gps;     // GPS sensor
FrSkySportTelemetry telemetry; // Telemetry object
TinyGPS tinyGps;
SoftwareSerial serialD(PIN_SerialTelemetryRX, PIN_SerialTelemetryTX, true);
SoftwareSerial telemetryTypeCheck(PIN_SerialTelemetryTX, PIN_SerialTelemetryRX, true); // Get input from Tx pin

uint32_t currentTime, sentenceTime1, sentenceTime2;
boolean telemetryTypeX;
byte gpsSentences = 0;
byte X[] = {3,1,1,3,0};     // -..-
byte D[] = {3,1,1,0};       // -..

void morse(byte values[])
{
  for(int i=0; values[i]; i++) {
    digitalWrite(LED_PIN, HIGH);
    delay(values[i]*100);
    digitalWrite(LED_PIN, LOW);
    delay(100);
  }
  delay(300);
}  

boolean isTelemetryTypeX(void) {
  unsigned long lastTime;
  boolean x = false;
  
  telemetryTypeCheck.begin(115200);
  lastTime = millis();
  while (millis() < lastTime + 1000) {
    while (telemetryTypeCheck.available()) {
      if(telemetryTypeCheck.read() == FRSKY_TELEMETRY_START_FRAME) {
        x = true;
        break;
      }
    }
  }
  telemetryTypeCheck.end();
  return x;
}

void SendDValue(uint8_t ID, uint16_t Value) {
  uint8_t lsb = Value & 0x00ff;
  uint8_t msb = (Value & 0xff00)>>8;
  serialD.write(0x5E);
  serialD.write(ID);
  if(lsb == 0x5E) {
    serialD.write(0x5D);
    serialD.write(0x3E);
  }
  else if(lsb == 0x5D) {
    serialD.write(0x5D);
    serialD.write(0x3D);
  }
  else {
    serialD.write(lsb);
  }
  if(msb == 0x5E) {
    serialD.write(0x5D);
    serialD.write(0x3E);
  }
  else if(msb == 0x5D) {
    serialD.write(0x5D);
    serialD.write(0x3D);
  }
  else {
    serialD.write(msb);
  }
  serialD.write(0x5E);
}

void SendDGpsData(void) {
  float flat, flon, falt, fc, fk, fmins;
  
  unsigned long fix_age;
  uint16_t degr, mins;
 
  tinyGps.f_get_position(&flat, &flon, &fix_age);
  falt = tinyGps.f_altitude(); // +/- altitude in meters
  fc = tinyGps.f_course(); // course in degrees
  fk = tinyGps.f_speed_mps(); // speed in m/sec
  degr = (uint16_t)flat;
  fmins = (flat-degr)*60;
  mins = (uint16_t)fmins;
  SendDValue(0x13, degr*100+(uint16_t)fmins);              // Latitude (DDMM)
  SendDValue(0x1B, (uint16_t)((fmins-mins)*10000));        // Latitude (.MMMM)
  SendDValue(0x23, (uint16_t)(flat < 0 ? 'S' : 'N'));
  degr = (uint16_t)flon;
  fmins = (flon-degr)*60;
  mins = (uint16_t)fmins;
  SendDValue(0x12, degr*100+(uint16_t)fmins);              // Longitude (DDMM)
  SendDValue(0x1A, (uint16_t)((fmins-mins)*10000));        // Longitude (.MMMM)
  SendDValue(0x22, (uint16_t)(flon < 0 ? 'W' : 'E'));
  SendDValue(0x01, (int16_t)falt);                        // Altitude m
  SendDValue(0x09, (uint16_t)((abs(falt)-(uint16_t)abs(falt))*100)); // Altitude centimeter 
  SendDValue(0x11, (uint16_t)fk);                          // Speed knots
  SendDValue(0x19, (uint16_t)((fk-(uint16_t)fk)*100));     // Speed decimals
  SendDValue(0x14, (uint16_t)fc);                          // Course degrees
  SendDValue(0x1C, (uint16_t)((fc-(uint16_t)fc)*100));     // Course decimals
}

void SetXGpsData(void)
{
  float flat, flon, falt, fc, fmps;
  unsigned long fix_age;
 
  tinyGps.f_get_position(&flat, &flon, &fix_age);
  falt = tinyGps.f_altitude(); // +/- altitude in meters
  fc = tinyGps.f_course(); // course in degrees
  fmps = tinyGps.f_speed_mps(); // speed in m/sec
  gps.setData(flat, flon, falt, fmps, fc, 14, 9, 14, 12, 00, 00);
}

void setup()
{
  pinMode(LED_PIN, OUTPUT); 

  telemetryTypeX = isTelemetryTypeX();  
  if (telemetryTypeX) {
    telemetry.begin(FrSkySportSingleWireSerial::SOFT_SERIAL_PIN_12, &gps);
    morse(X);
  }
  else {
    serialD.begin(9600);
    morse(D);
  }
  Serial.begin(9600);
}

void loop() {
  while (Serial.available() > 0) {
    if (tinyGps.encode(Serial.read())) { // if a NMEA sentence is complete 
      if (!gpsSentences)  // if first of two sentences
        sentenceTime1 = millis();  // timestamp sentence 1
      else
        sentenceTime2 = millis();  // timestamp sentence 2
      gpsSentences++;
    }
    if (gpsSentences > 1) { // if more then one sentence
      if (sentenceTime2 - sentenceTime1 > 175) {// sentences not from same dataset, resync
        sentenceTime1 = sentenceTime2;
        gpsSentences = 1;
      }
      else { // process GPS data
        digitalWrite(LED_PIN, HIGH);
        if (telemetryTypeX) 
          SetXGpsData();
        else 
          SendDGpsData();
        digitalWrite(LED_PIN, LOW);
        gpsSentences = 0; 
      }
    }
  }
  if (telemetryTypeX)
    telemetry.send();
}

Fred

You use 115200 baud with SoftwareSerial. For some that will work, for others it will never work, depending on the sketch.
Using pin 255 might cause trouble. I would have to check the source code of the SoftwareSerial. It can be used for a normal digital port (although it is bad programming), but I doubt if it is valid for SoftwareSerial.

I don't understand the code very well. Sorry.
The mix of TinyGPS, SerialD and telemetryTypeCheck is too confusing for me.
A "telemetryTypeCheck.end()" stops the SoftwareSerial on those pins, and the pins can be used for other things. That I understand. But using only pin 12 for everything seems weird. And perhaps the .begin() function is called twice. I don't know where I can find the telemetry code. And that is an emulation ? Many emulation of things go wrong, when used in a different way with other timings.
I would have to study the telemetry library to say something useful about your project.

The way millis() is used in "isTelemetryTypeX()" might cause an rollover problem. I'm not sure, but I think it should be used in a different way.

Boy, that code helps me understand the situation much better. Thanks for that, and I’m glad you isolated the quirk.

From a code-inspection point-of-view, SoftwareSerial.end appears to undo everything done in begin, except for the PCINT mask:

    // Enable the PCINT for the entire port here, but never disable it
    // (others might also need it, so we disable the interrupt by using
    // the per-pin PCMSK register).
    *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));

I think you might need to undo this explicitly after the end, so that changes on the new TX pin (as part of transmitting) are not dispatched as if they were RX pin change interrupts:

  telemetryTypeCheck.end();
  // undo what listening to the RX pin did (although it's named TX, it's used for RX)
  *digitalPinToPCICR( PIN_SerialTelemetryTX ) &= ~_BV(digitalPinToPCICRbit( PIN_SerialTelemetryTX );
  return x;

…maybe?

Regarding the interval timing, I usually write

  while (millis() - lastTime < 1000UL) {

It seems easier for me to think about how millis() is always increasing, and subtracting a previous time will give a positive number, which can be compared to the positive duration value. With unsigned arithmetic, this even works for the rollover.

I also use explicit UL constants so the expression cannot be interpreted any other way, by the compiler or the reader.

Cheers,
/dev

I had a look at how the FrSkySportSingleWireSerial part of the library could both send and receive on same pin. It just calls pinMode() to change direction as needed.
So I tried this and it was a success:

  telemetryTypeCheck.end();
  pinMode(PIN_SerialTelemetryTX, OUTPUT);
  return x;

I also noticed that I have been using the wrong baud rate in isTelemetryTypeX(). Should be 57600 instead of 115200. Not sure how it could work, but it did.

Appreciate all inputs given.

Fred

At first, I couldn't believe that SoftwareSerial doesn't set the pinMode. After a quick peek, I see that it does set it... in the constructor. Unfortunately, that's the wrong place, as it should have been in begin. The pinMode(s) are set twice in your app, up here:

SoftwareSerial serialD(PIN_SerialTelemetryRX, PIN_SerialTelemetryTX, true);
SoftwareSerial telemetryTypeCheck(PIN_SerialTelemetryTX, PIN_SerialTelemetryRX, true); // Get input from Tx pin

These constructors are called way before setup() even starts! And if you had declared them in a different order, you would have had a slightly different failure. Good catch!

Hmmm... I wonder if this has been reported as a bug yet? Off to github... LOL, it was just reported two weeks ago by NickGammon, here. I think the 255 tx pin can also lead to weirdness, but your app never tries to transmit on it. Trying to receive on pin 255 appears to be guarded.

I think the shared PCINT enabling has also been discussed by the Arduino developers in a different context, but I don't remember seeing a solution. Maybe Nick knows? :wink: At least you have a work-around!

Cheers,
/dev

/dev:
I think the shared PCINT enabling has also been discussed by the Arduino developers in a different context, but I don't remember seeing a solution. Maybe Nick knows? :wink: At least you have a work-around!

The only "fix" I've seen is to edit the SoftwareSerial library and add compiler switches so you can remove some of the PCINT ports. But this largely defeats the ability to select the RX pin in the constructor since it affects all projects. It seems like a flaw in the way the Arduino IDE works, that you can't use compiler switches at the project level. Is there another way? I'd love to see a better solution to this issue.

/dev:

SoftwareSerial serialD(PIN_SerialTelemetryRX, PIN_SerialTelemetryTX, true);

SoftwareSerial telemetryTypeCheck(PIN_SerialTelemetryTX, PIN_SerialTelemetryRX, true); // Get input from Tx pin



These constructors are called way before `setup()` even starts! And if you had declared them in a different order, you would have had a slightly different failure. Good catch!

Yes, I noticed that it failed even if I did not call isTelemetryTypeX().
Still not sure how it could work directly against the RF unit (setup #2).
In fact the main device does exactly the same thing (setup #1 & #4)

Regarding pin 255, I read a suggestion about using it to save resources when doing one way communication. Not sure if it's just a matter of saving a real pin or if it's more to gain by doing so.

Fred