Problem pairing HC-12s

Hi

I have a problem with pairing 2 x HC-12.

Transmitter code:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 2); //RX, TX

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);  
}

void loop() {
  
  
  if(Serial.available() > 0){
    String input = Serial.readString();
    mySerial.println(input);
  }
 
  if(mySerial.available() > 1){
    String input = mySerial.readString();    
    Serial.println(input);    
  }
  delay(20);
}

Receiver code

#include <SoftwareSerial.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4

SoftwareSerial mySerial(3, 2); //RX, TX
Adafruit_SSD1306 display1(128, 64, &Wire, OLED_RESET);

const byte numChars = 25;
char receivedChars[numChars];
bool newData = false;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display1.setTextSize(2);
  display1.setTextColor(WHITE);
  display1.clearDisplay();
  display1.display();
  mySerial.begin(9600);
  delay(1000);
  mySerial.println("Communicating...");
  delay(1000);
}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (mySerial.available() > 0 && newData == false) {
    rc = mySerial.read();

    if (recvInProgress == true) {
      if (rc == startMarker){
        newData = false;
        return false;
      }
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) ndx = numChars - 1;
      } else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    } else {
      if (rc == startMarker) recvInProgress = true;
    }
  }
}

void loop() {  
  recvWithStartEndMarkers();
  if (newData == true){
    display1.clearDisplay();
    display1.println(receivedChars);
    display1.display;
  }
}

The transmitter receives data from a program on my computer written in Delphi, and sends it to the receiver. When I first plug in the transmitter and open the serial monitor, then plug in the receiver, the receiver sends "Communicating..." to the transmitter, which appears on the serial monitor, and then the receiver continually reads data and displays it on the OLED. So far so good.

BUT If I unplug, then plug the transmitter in again, the receiver no longer receives any data - even if I reset the Delphi program, and even if I restart the receiver. It seems to depend on the serial monitor being open when I first plug in the receiver.

Interestingly, if I unplug and replug in the receiver (while the transmitter has not been unplugged at any stage) the communication continues normally.

The computer will be off overnight, and I don't want to go through the ritual of bringing the receiver from another room each morning just to pair it!

Other than the setup configuration of baud rate, mode and channel, there is no pairing which goes on between the HC12 modules.

My suspicion is that there is an issue with the reconnection of the PC to the reopened Serial port.

One thing you can do to test/troubleshoot is to remove the HC12's and connect the two Arduinos with software serial. (Rx>Tx and Tx>Rx). You should be able to experiment with power cycles and code. I think you will be able to recreate and solve the issue without the HC12's involved.

Thanks @cattledog - I appreciate your response. I have been tinkering with your suggestion and I've got my two Arduinos linked via software serial, but so far I haven't found a solution. I think it's got to be a timing issue somehow.

How does the Delphi program deal with the Arduino reset and reopening of the Serial port?

@cattledog
The Delphi program just opens the port and after a short delay starts sending data. Very similar to the Arduino way.

mySerial.begin(9600);
delay(1000);
mySerial.println(myData);

The Delphi code

Done := False;
     StartComms;
     Delay(3000);
     StatusBar1.SimpleText := 'Ready.';
     Application.ProcessMessages;
     Repeat
       Repeat
         Application.ProcessMessages;
         If Application.Terminated then Exit;
       Until Ser.CanWrite(1000);
       GetWxStrings;         
         Ser.SendString(MyData);
         Ser.Flush;
         Delay(3000);       
     Until Done = True;
     CloseComms;

I've now got garbage (a row of back to front question marks) appearing in the serial monitor after each read.

@cattledog
I have spent a lot of time trying to figure out what is going on, and as stated in my original post it appears dependant on the serial monitor being opened within the IDE at the beginning.

I added code to the receiver so that when it is first powered up it transmits "Communicating" every 10 seconds for 2 minutes. If I open the serial monitor within the IDE I see the messages come through. I then close the serial monitor and start the transmission from the transmitter and the receiver gets the data sent.

If I unplug the transmitter and then plug it in again I have to go through the serial monitor process again. (At least now I don't have to bring the recever to the transmitter)

Surely the 2 Arduinos are not dependant on the IDE for initialising communication (using the serial monitor)?

Do you know of a way to invoke what the serial monitor "initialisation" does - without going via the IDE?

Is Delphi involved in your testing, or is it just two Arduino's with HC12's and each Arduino connected to the Serial monitor in two different instances of the IDE? How are the HC12's connected to the Arduinos?

I must say that I don't really have a full understanding of what you are describing and how everything is connected.

EDIT: I don't see where the receiver uses Serial. What if you leave out the Serial.begin()?

Are you saying that the receiver needs to be connected to the Serial monitor for it to receive from the HC12 and pass to the display after the transmitter restarts?

Thanks @cattledog
The transmitter Arduino is connected to the computer, and so is able to use the serial monitor. The receiver Arduino is stand-alone and in another room. The HC12s are connected in the usual way using pins 2 and 3 in both cases. The Rst pin is not connected, although I have also tried with it pulled high.

The test signal from the receiver (via its HC12) is picked up by the HC12 in the transmitter, and so is seen on the serial monitor.

The signal transmitted from the transmitter is from Delphi, although I can send a manual signal instead from the serial monitor, and I have tested with both.

If I restart the transmitter (and do nothing else) I see its TX led flashing, but the signal does not get received by the receiver.

Leaving out Serial.begin() makes no difference to whether reception by the receiver works or not.

With the code for the transmitter posted in #1 the only serial i/o which should flash the TX led is if a message has been received by the Arduino from USB. The Tx and Rx leds are connected to the USB converter and indicate when it is talking and receiving. It seems counter intuitive, but is you set up some simple sketchs to read and print Serial you will see which leds light up when.

if(mySerial.available() > 1){
    String input = mySerial.readString();  //will flash Tx light 
    Serial.println(input);  //will flash Rx light 
  }

@cattledog
Wow! I didn't realise about the leds. So the flashing one is the data being received from the Delphi program (Rx), and it then transmits that data to the receiver. That part must be working OK.

For some reason though the data only gets received if I open the serial monitor for the transmitter within the IDE first. I just want to bypass that step and leave the IDE out of it.

For some reason though the data only gets received if I open the serial monitor for the transmitter within the IDE first.

I would suggest that you just focus on the Transmitter and the Delphi application. I am not certain that after the Arduino is turned off and then back on, the Delphi app is re-opening the Serial port correctly, and somehow having to connect the Serial monitor with the Arduino does something to get the system going.

Can you write a test program for the Delphi and the Arduino which just receives a message and echoes it back and restarts itself when the Arduino is turned off and then back on.

Thanks again @cattledog - I really appreciate your patience with this.

Your suggestion is a good one and I will see where it leads and let you know.

@cattledog
Once again I have done a lot of experimenting both with the Delphi app and with Arduino per your latest suggestions, but I haven't been able to come up with anything conclusive.

I found another question on the forum with the same issue, and it was suggested that RTS and DTR might be the problem, so I added a capacitor between RST and GND on the Arduino but it had no noticeable effect at all.

The other question is at https://forum.arduino.cc/t/serial-port-not-reading-unless-using-ide-serial-monitor/557972, and towards the end of the discussion someone else chimes in with the same issue. The thread ends inconclusively.

Because I have spent a long time over this issue my thoughts now are to just live with it and open the Serial monitor briefly when I turn on the computer each day.

Thank you for all of your input.