HC-12 code and range issue

I am using HC-12 with arduino nano to control RC car motor. Car motor for forward/reverse is controlled by a simple on off relay. For left right motor, L298 is used.

-I need to modify code that if TX is off or out of range, RX HC-12 should detect no signal and stop the car. The reason is low range of HC-12 i am facing and when out of range, car keeps on moving.

-Second issue is of low range, i am using all default values for HC-12. TX HC-12 is in a plastic case, both TX, RX HC-12 have spring antennas attached that came with it, length of spring if straighten out is 34 cm which seems ok for 433 MHz.

TX code:

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin
int buttonPinF = 4;//Moves car forward
int buttonPinR = 5;//Reverse car
int buttonPinL = 6;//Move Left
int buttonPinRt = 7;//Move Right
int  buttonStateF = 1;
int buttonStateR = 1;
int buttonStateL = 1;
int buttonStateRt = 1;
void setup() {
    pinMode(buttonPinF,INPUT_PULLUP);
    pinMode(buttonPinR, INPUT_PULLUP);
    pinMode(buttonPinL, INPUT_PULLUP);
    pinMode(buttonPinRt, INPUT_PULLUP);
    Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12
  
}
void loop() {
 
  buttonStateF = digitalRead(buttonPinF);
  buttonStateR = digitalRead(buttonPinR);
  buttonStateL = digitalRead(buttonPinL);
  buttonStateRt = digitalRead(buttonPinRt);
  
  if(buttonStateF == 0){//if forward button is down
    HC12.println(1234);//send unique code to the receiver in this case 1234
  }
else
if(buttonStateF == 1 ){//if button is up
   
    HC12.println(2222);//send unique code to the receiver in this case 2222
  }
  
if(buttonStateR == 0){//if reverse button is down
    HC12.println(1235);//send unique code to the receiver in this case 1235
  }

else
  if(buttonStateR == 1 ){//if button is up
   
    HC12.println(2223);//send unique code to the receiver in this case 2223
  }

if(buttonStateL == 0){//if Left button is down
    HC12.println(1236);//send unique code to the receiver in this case 1236
  }

else
  if(buttonStateL == 1 ){//if button is up
   
    HC12.println(2224);//send unique code to the receiver in this case 2224
  }

if(buttonStateRt == 0){//if Right button is down
    HC12.println(1237);//send unique code to the receiver in this case 1237
  }

else
  if(buttonStateL == 1 ){//if button is up
   
    HC12.println(2225);//send unique code to the receiver in this case 2225
  }

  
  delay(20);//delay little for better serial communication
}

And RX code:

#include <SoftwareSerial.h>

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

int PinF = 4;//Relay pin for forward
int PinR = 5;//Relay pin for reverse
int PinL = 6;//L298 pin for Left turn
int PinRt = 7;//L298 pin for Right turn
unsigned long last = millis();//set timer
 
void setup() {
  mySerial.begin(9600);
  pinMode(PinF, OUTPUT);
  pinMode(PinR, OUTPUT);
 pinMode(PinL, OUTPUT);
 pinMode(PinRt, OUTPUT);
 digitalWrite (PinR, HIGH);
 digitalWrite (PinF, HIGH);
// digitalWrite (PinL, LOW);
 //digitalWrite (PinRt, LOW);
}

void loop() {

  boolean PinStateF = digitalRead(PinF);//check if the Relay is turned on or off. Returns 1 or 0
   boolean PinStateR = digitalRead(PinR);//check if the Relay is turned on or off. Returns 1 or 0
 boolean PinStateL = digitalRead(PinL);//check if the L298 is turned on or off. Returns 1 or 0
   boolean PinStateRt = digitalRead(PinRt);//check if the L298 is turned on or off. Returns 1 or 0
   
  if(mySerial.available() > 1){    
    int input = mySerial.parseInt();//read serial input and convert to integer (-32,768 to 32,767)    

   //if(millis() - last > 30){//if time now is 30 milliseconds greater than last time
      if(PinStateF == 1 && input == 1234){//if Relay is off and button code is ok
          digitalWrite(PinF, LOW);}//Turn forward Relay on

else if (input == 2222){//if relay is off and button code is ok
          digitalWrite(PinF, HIGH);}
      
     if(PinStateR == 1 && input == 1235){//if reverse relay is off and button code is ok
          digitalWrite(PinR, LOW);}

else if (input == 2223){//if relay is off and button code is ok
          digitalWrite(PinR, HIGH);}

//Left and right turn code strts from here
if(PinStateL == 1 && input == 1236){//if L298 is off and button code is ok
          digitalWrite(PinL, LOW);
         //digitalWrite(PinRt, HIGH);
          
          }

else if (input == 2224){//if L298 is off and button code is ok
          digitalWrite(PinL, HIGH);
           digitalWrite(PinRt, HIGH);
          }

if(PinStateRt == 1 && input == 1237){//if L298 is off and button code is ok
        digitalWrite(PinL, HIGH);
         digitalWrite(PinRt, LOW);
          
          }

else if (input == 2225){//if L298 is off and button code is ok
          digitalWrite(PinRt, HIGH);}

    
    mySerial.flush();//clear the serial buffer for unwanted inputs   
    last = millis();//reset timer   

  //delay(20);//delay little for better serial communication
  }
}

a common approach for a receiver to confirm that the it is still in contact with a transmitter is for the transmitter to periodically send a "heartbeat" message in lieu of a normal message. The receiver might accept that 1 or 2 messages are lost and assume the transmitter is no longer available after a lapse of 3 heartbeat periods

Thanks, can you share an example for the heartbeat messages.

it’s simply another message that requires no content. looks like your messages are 1234, 2222, … add another that is sent within 1 sec if another message is not sent

The reason is low range of HC-12

no, that is not the reason

both TX, RX HC-12 have spring antennas attached that came with it,

there is your range issue.

a better antenna on either end improves the gain on both ends, TX & RX. you need an omnidirectional antenna for something agile like an RC car. the omni antenna with the most gain is a collinear array. a collinear array has a practical gain limit of 15 dbi.a dipole has a gain of 2.14 dbi. you get 20 times the power in the link by using the most efficient antenna available at just the transmitting end

commercially made collinear arrays tend to be expensive in this band. rolling your own costs chump change.

Thanks all,
I added in the code and its working:

if(mySerial.available() == 0){
digitalWrite(PinR, HIGH);
digitalWrite(PinF, HIGH);

This is now a fail safe mode, if i turn off TX, motor stops though with a gap of 1-2 seconds.

For antennas, i will look to buy omnidirectional antenna, there is no DIY work around antenna to increase range till the time ordered antennas will arrive?

What could be the reason spring antennas with 34 cm length are not a good choice? All i read on forums is a simple wire having 17 cm or 34 cm length is good for 433 MHz transmission.

Cheap spring antennas are usually much shorter than that, like 8cm., and don't perform very well, just barely okay. The reason why a collinear is better, was explained very well, in my opinion. Whether you actually need it, is uncertain. A 34cm wire would be an end-fed dipole, which is not a good choice unless you have a matching network because it has a very high driving impedance.

tractable:

if(mySerial.available() == 0){   

digitalWrite(PinR, HIGH);
digitalWrite(PinF, HIGH);

i'm surprised this works for you. it looks like you're just check for not receiving anythin.

i would have captured a timestamp when something is available and outside of that code check if more than some period of time has past since the last received message