HC-12 serial hardware comms not working below 4800 baud

Two Arduino’s communicate using HC-12 transceivers: one is only sending, the other is only receiving.

Everything fully works as long as baud rates higher than 2400 are used.
I tested the HC-12 modules separately in an independent testing jig and they work fine at all specified baud rates.

However, when I set both transmitter and receiver at 2400 or 1200 baud in the actual hardware environment for which the software is written, there are no communications. Yes, I make sure both the hardware serial and the HC-12 baud rates are identical (and for the HC-12 also identical channels are programmed).

What is wrong that prevents transmission to take place at 2400 or 1200 baud?

Full below is the main part of the program for the transmitting part (the code is way too long to be accepted in full by the forum rules), which contains the most important parts of the program.

Rigth here below here is the part used to transmit the actual data (courtesy of the most famous Serial Basics Tutorial by Robin2):

    Serial.print('<'); // this section for HC-12 transmission
    Serial.print(cycleValue);  // ref Robin2's Serial Output Basics
    Serial.print(',');   // http://forum.arduino.cc/index.php?topic=396450.0
    Serial.print(temperatureT1); // send temperature read from analog input temperaturePin
    Serial.print(',');
    Serial.print(batteryVoltage); // send battery voltage
    Serial.print(',');
    Serial.print(now.minute(), DEC); // send minute
    Serial.print(',');
    Serial.print(now.hour(), DEC); // send hour
    Serial.print(",B>"); // send sensor identifier

The main part of the sketch:

#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>
// #include <DS3231RTC.h>
// #include <SPI.h> //Thingspeak
#define DS3231_I2C_ADDRESS 0x68
RTC_DS3231 RTC;      //we are using the DS3231 RTC

// Variable Setup
// NOTE: pin D8 is used for reading incoming square wave for duty cycle measurement

#define wakePin 2    //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
#define ledPin 13   //use arduino on-board led for indicating sleep or wakeup status
#define wakeStatus 9 //use D9 to drive 5V power to sensor module and HC-12 with MOSFET, 1=wake
#define measureStatus 10 //use to show measurements take place
#define temperaturePin A0 // analog input for LM35 temperature sensor
#define dutyCycleStatus 8 // Input Capture Pin
#define batteryPin A1
float temperatureT1;
float batteryVoltage;
byte goToSleepNow = 1;
byte ledStatus = 1;
volatile word timerValue[4];
volatile byte testState = 0;
volatile boolean signalPresent = false;
boolean newValuesAvailable = false;
float pwmPeriod, pwmWidth, pwmFrequency, pwmDutyDisplay;
unsigned long pwmDuty;
const byte x = 10; // loop value: loop amount = x, number of dutycycle measurements in one run

//-------------------------------------------------
void wakeUp()        // here the interrupt is handled after wakeup
{
}
//------------------------------------------------------------

void setup() {
  //Set pin D2 as INPUT for accepting the interrupt signal from DS3231
  Serial.begin(4800);
  pinMode(wakePin, INPUT);
  //switch-on the on-board led for 1 second for indicating that the sketch is ok and running
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(measureStatus, OUTPUT);
  digitalWrite(measureStatus, LOW);
  //Set MOSFET gate drive to output
  pinMode(wakeStatus, OUTPUT);
  digitalWrite(wakeStatus, LOW);
  analogReference(DEFAULT);
  delay(500);
  //Initialize communication with the clock
  Wire.begin();
  RTC.begin();
  // A convenient constructor for using "the compiler's time":
  // DateTime now (__DATE__, __TIME__);
  // uncomment following line when compiling and uploading,
  // then comment following line and immediately upload again

  // RTC.adjust(DateTime(__DATE__, __TIME__));   //set RTC date and time to COMPILE time, see instructions above

  //clear any pending alarms
  RTC.armAlarm(1, false);
  RTC.clearAlarm(1);
  RTC.alarmInterrupt(1, false);
  RTC.armAlarm(2, false);
  RTC.clearAlarm(2);
  RTC.alarmInterrupt(2, false);
  //Set SQW pin to OFF (in my case it was set by default to 1Hz)
  //The output of the DS3231 INT pin is connected to this pin
  //It must be connected to arduino D2 pin for wake-up
  RTC.writeSqwPinMode(DS3231_OFF);
  //example: Set alarm1 every day at 18:33: 00 seconds, 33 minutes, 18 hours, 0 = every day;
  // if for example Sunday then: dowSunday if a date then date of the month
  //
  // see for explanation: https://github.com/JChristensen/DS3232RTC#alarm-methods
  RTC.setAlarm(ALM1_MATCH_SECONDS, 01, 00, 0, 0);   //set your wake-up time here:
  RTC.setAlarm(ALM2_MATCH_MINUTES, 0, 10, 0, 0);  //where "xx" is minutes
  // every 00 minutes past the hour;
  // if every second is needed change MINUTES to SECONDS (only for ALM1)
  // matches seconds AND minutes when _MINUTES is used. Sequence of time:
  // first seconds, then minutes, hours, daydate
  // or: seconds (but enter 00, is ignored), minutes then hours, daydate for ALM2
  // zero's mean: always
  // example: Set alarm1 every day at 18:33
  // RTC.setAlarm(ALM1_MATCH_HOURS, 33, 18, 0);  set your wake-up time here
  // RTC.alarmInterrupt(1, true);
  RTC.alarmInterrupt(1, true); //set alarm1
  RTC.alarmInterrupt(2, true); //set alarm2
}

//------------------------------------------------------------

void loop() {

  //On first loop we enter the sleep mode
  if (goToSleepNow == 1) {                                 // value 1 = go to sleep
    attachInterrupt(0, wakeUp, LOW);                       //use interrupt 0 (pin PD2) and run function wakeUp when pin 2 gets LOW
    digitalWrite(ledPin, LOW);                             //switch-off the led for indicating that we enter the sleep mode
    ledStatus = 0;                                         //set the led status accordingly
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);   //arduino enters sleep mode here
    detachInterrupt(0); //execution resumes from here after wake-up
    //When exiting the sleep mode we clear the alarm
    RTC.armAlarm(1, false);
    RTC.clearAlarm(1);
    RTC.alarmInterrupt(1, false);
    RTC.armAlarm(2, false);
    RTC.clearAlarm(2);
    RTC.alarmInterrupt(2, false);
    goToSleepNow = 0;                                      // value 0 = do not go to sleep
  }
  //cycles the led to indicate that we are no more in sleep mode
  if (ledStatus == 0) {
    ledStatus = 1;
    digitalWrite(ledPin, HIGH);
  }
  digitalWrite(wakeStatus, HIGH);  // set wakeStatus to HIGH, wake mode, activate moisture sensor electronics
  //
  // read current time
  // reset alarm clock to new values: enable wake-up more than once per minute or once per hour: next 2 lines
  // write (now.minute() + x) where x = every x minutes to wake up
  // wakeUpInterval = time in minutes until next wake-up
  // set your new wake-up time here
  // if the above is not needed then following two lines to be commented out
  // DateTime now = RTC.now();
  // RTC.setAlarm(ALM1_MATCH_MINUTES, 00, (now.minute() + 5) % 60, 0, 0);   //set your wake-up time here: x = every x minutes
  // wait following delay between power to sensor electronics and measurements
  delay (50);
  measure(); //execute duty cycle measurement during wakeUp
  Serial.flush();
  delay (50);
  digitalWrite(wakeStatus, LOW); //initiate wake status LOW, sleepmode, de-activate moisture sensor electronics
  goToSleepNow = 1; // go back to sleep
  RTC.alarmInterrupt(1, true);
  RTC.alarmInterrupt(2, true);
}

I don't have any HC12s so I can't help with that part. However if it was my project I would check that the communication works at the baud rate you want when the two Arduinos are connected by wires rather than using the HC12s.

...R

Robin2:
I don’t have any HC12s so I can’t help with that part. However if it was my project I would check that the communication works at the baud rate you want when the two Arduinos are connected by wires rather than using the HC12s.

…R

ok, good idea, thank you

The 2xHC12 setup of this link does not work at Bd below 9600? |500x189

|375x500

GolamMostafa: The 2xHC12 setup of this link does not work at Bd below 9600? |500x189

|375x500

As I said both hc12 perform fully in a test jig. My question concerns a very specific and project related issue.

Are you sure the modules don't mind being so close to each other.

There are some counterfeit HC-12 modules around that work ok with another counterfeit one, but not with an official one. The printing on the crystals must be exacly the same for a pair to reliable work. Leo..

Wawa: Are you sure the modules don't mind being so close to each other.

There are some counterfeit HC-12 modules around that work ok with another counterfeit one, but not with an official one. The printing on the crystals must be exacly the same for a pair to reliable work. Leo..

Both hc12 in the testing jig perform 100% in all baud rates, as well close together or spaced metres apart.

Robin2:
I don’t have any HC12s so I can’t help with that part. However if it was my project I would check that the communication works at the baud rate you want when the two Arduinos are connected by wires rather than using the HC12s.

…R

I checked the HC-12 first: communications work well at 1200 baud (testing with software serial). There is a delay of almost 100ms between the first bit being transferred to the transmitting HC-12 and the time when that first bit arrives on the receiving HC-12 output.
The total message length for what I want to transmit is about 200 bytes, so when using serial.flush(); I still have to take into account the time needed for the HC-12 to transmit all that, even after serial.flush() did it’s job. What I don’t know is how fast the Arduino serial output buffer is transferring to the HC-12. I did some testing without serial.flush, and anything less than 100ms cut-off (power down) prevents full message transmission. The message being about 200ms long it is safe to assume serial.flush() takes care of the last 100ms.
My conclusion is that at 2400 baud a 100ms delay is needed to allow the HC-12 to do its job before power can be cut to the HC-12 when using serial.flush();.

Next “to-do” is Robin2’s suggestion to test without HC12 but with straight hardwared serial connections. I have to figure out a way to that without interfering with the hardware setup that cuts power in the sleep mode by opening the ground wire (instead of cutting VCC).

Robin2: I don't have any HC12s so I can't help with that part. However if it was my project I would check that the communication works at the baud rate you want when the two Arduinos are connected by wires rather than using the HC12s.

...R

The issue was an incorrect transmitting Arduino baud rate setting. Somehow a bug set the baud rate forever at 115200, the HC12 automatically compensates for that but not below 4800. I solved the bug in the Pro Mini, issue gone. I found out after connecting a scope to the Pro Mini TX. Very usefull learning curve, and thanks for the help here!