3G GSM and HC-12 on the same controller

I am working on a small project where I intend to control some equipment with an sms message. Some of the equipment is some distance from the Master controller. I have a 3G GSM module on top of an Arduino Leonardo. I also have a HC-12 module and a relay module running on the same base.
I have set up and tested the 3G GSM module to control some equipment local to the Master controller. It all works perfectly well. An sms is received and with some conditional statements I can operate the relays.
Independently I have tested an HC-12 network from the Master controller to two slave controllers some distance away (40 m and 80 m). Transmit and receive codes seem to work well.

Transmit function is a simple print (or write) using software serial. Receive script reads the individual bytes and accumulates them. When finished the code is copied into a string variable. Both shown below.

Separately the scripts work fine but when combined the HC-12 transmit code crashes the 3G GSM.

I am using the FONA library to run the 3G GSM module. Any .print or . write command to the Software.Serial HC-12 leads to a loss of the GSM connection. To restart the connection I have to power the unit down and reboot.

Has anyone had any experience with running a 3G GSM module and an HC-12 (or any other) radio network?

Any other ideas would be welcome.


//Receive function 
void get_message()
  while (HC12.available()) {  // While Arduino's HC12 soft serial rx buffer has data
  HC12ByteIn = HC12.read();  // Store each character from rx buffer in byteIn
  HC12ReadBuffer += char(HC12ByteIn);  // Write each character of byteIn to HC12ReadBuffer
  if (HC12ByteIn == '\n') {  // At the end of the line
  HC12End = true;  // Set HC12End flag to true

  if (HC12End) {  // If HC12End flag is true
  //Serial.print(HC12ReadBuffer);  // Send message to screen.  Not required handle in loop
  ControlMessage = HC12ReadBuffer;  // Store temporary message as control message
  ControlMessage.replace("\n","");  // Remove new line command from string
  HC12ReadBuffer = "";  // Empty buffer
  HC12End = false;  // Reset flag

I don’t have a good reason why it would not work. It is a typical design pattern.

Just to confirm; you have stacked the software like this; a 3G GSM library using the Arduino hardware Serial library, and a HC12 library using the Arduino SoftwareSerial library. Your top level sketch then links the two together.

Sounds like a conflict in resources used by the libraries; I’ve had that happen before, and needed to make some library changes; though not with those two device libraries. I suggest opening each library up and reviewing what resources are used; the pins, interrupts, timers, and other on-chip peripherals of the Leonardo.

Another test you might try is to write a few brief sketches to help isolate the cause, with a computer acting as the serial devices instead of the 3G GSM module and the HC-12 module;

  1. use the Arduino Serial library directly at the same time as using the Arduino SoftwareSerial library; read from one and write to the other, and vice versa; which would normally work fine but it is worth testing all the same,

  2. use the Arduino Serial library directly at the same time as using the HC12 library on top of Arduino SoftwareSerial library, and make sure that the attached computer continues to see the expected Serial data,

  3. use the 3G GSM library at the same time as using the Arduino SoftwareSerial library, and make sure that the attached computer continues to see the expected data.

Also check that the USB serial is or is not being used. The ATmega32u4 on the Leonardo is capable of USB serial (chip pins D- and D+), hardware serial (Arduino pins D0 and D1), and software serial.

Thanks for your suggestions. I need to think about how to implement them. I am no brianiac in this field. I will try over the weekend.

To clarify my current setup.
The 3G GSM is run on hardware serial Serial1 using the FONA library, pins 0,1 on the Leonardo.
The HC-12 is run as a software serial device under SoftwareSerial library, pins 8,9 on the Leonardo.
A small complication that I did not tell you about is that I also have a small 433 MHz transmitter running on an RCSwitch library on pin 10. This transmitter operates a short range remote start for a motor. This bit of the operation cohabits well with both the GSM and the HC-12.
All the testing I have done with the stack works except when I Serial.print to the HC-12. Perhaps interestingly the HC-12 sends it message but the GSM shield then then stalls (the blue light goes on solid rather than flashing if that helps).

I have made a change already to the FONA library to get the GSM module to save sms’s to the memory rather than the sim card. I will look carefully to see if I can find any potential conflicts.

I am happy to send you the sketch if you like, it is a bit long to include in the text.

Thanks. The RCSwitch and transmitter shouldn’t cause any problem.

You might attach a serial adapter to the hardware pin TXD1 on the Leonardo, or the receive pin on the 3G GSM module, run a terminal program on your computer, and check to see if there is any unexpected data flow at the instant of Serial.print to the HC-12.

You might attach an oscilloscope and probe the 3G GSM power bus at the time of Serial.print to the HC-12; to capture any momentary collapse of system voltage due to the HC-12 transmission.

You might use github gist for code fragments. I’m @quozl there. If you send it to me here in the discourse forum, please quote it with three backticks so the formatting is kept.

Now I did not do what you suggested but your suggestions got me thinking and I seem to have a reasonable solution.  As you suggested this appears to be a library conflict.  I read around a bit and SoftwareSerial appears to have some issues with some libraries and with some interupts.  The GSM script I am using uses an interupt pin, in my case 2, to signal a new message.  It seems that the relative baud of the three serial communications is also important.  I need to run the HC-12 at 1200 to get the range, so that is locked.  I played around with the  speed of Serial and Serial1.  No change, it still crashed the GSM module.  Then I read about AltSoftSerial.  
A minor code conversion to AltSoftSerial and hey it all works.  
AltSoftSerial is a bit of a pain because the Tx and Rx pins are locked.  On my stack Pin 5 (Tx) has a stackable relay shield hanging off it but perhaps amazingly the serial comms still seem to work fine.  I was thinking of bending pins etc but if it works I will just leave it alone.

On a philosophical point, I am new to Arduino and this little project has been an interesting journey.  It is definitely three steps forward and two back.  I think I have jumped most of  the hurdles now, but it seems that with this platform what seems simple can be an intellectual challenge.

Thank you for your intelligent suggestions, they really did get me thinking on a path to what appears to be a solution.

Good to hear you have it working.

On the philosophical; yes, integrating different libraries can seem to waste time, because some of what you have written isn’t in the final outcome. But you do end up with knowledge in your head, or written in notes, with potential future use.

An alternate practice is to dip into the libraries and copy the code you will need instead of use the library directly. That gives you full control of resources. I’ve done that with several Arduino projects; they end up with no #includes of significance.

It reminds me of a conference talk a couple of weeks ago; on youtube with id i3nJR7PNgI4; although it was at a Linux conference it applies to all open source software, and the Arduino libraries and the libraries you are using are open source; where one of the points was about the tendency to use a library of code rather than integrate the best bits of the library with your own code. It’s a fun talk. By Robert M. “r0ml” Lefkowitz.

An excellent video, the points are well made. And I will add some more evidence.
I had more of a play with my system over the weekend. Libraries do not always play nice together.
My project used 3 libraries, SoftwareSerial, AdafruitFONA and RCSwitch. On the Leonardo SoftwareSerial and AdafruitFONA do not play well together. So I swapped the software serial to AltSoftSerial fixing most of the problems with FONA. But on further testing I have found that AltSoftwareSerial does not play nice with RCSwitch.
I am using RCSwitch to transmit a 24 bit code to remote start a generator. If my sketch includes SoftwareSerial this runs perfectly but if I change to AltSoftSerial the 433MHz transmission sometimes gets garbled (start code mostly works, stop code never works).
A couple of other points of weirdness with RCSwitch and AltSoftSerial is that if you place the transmitter on dig pin 9 it crashes the 3G GSM connection. On Pins 6,7,8,9,10 or 11 it is OK. I did not test 2,3,4,5. Also the RCSwitch function .setProtocol appears to crash RCSwitch if called.
So what did I learn? Using whole libraries can be an easy solution to a problem but they come at a cost. There is a significant risk of libraries interfering with each other, the more you include the greater the risk of a problem.
As you and r0ml suggest, a better solution would be to understand the library and extract the code that is applicable to your task.
Because I am lazy I will probably continue to use libraries, but I am now much more wary.

For this project I have now decided to separate the functions. I have a central communications stack running AdafruitFONA and AltSoftSerial. The task of this module is simply to read (and in future, write) sms messages and distribute control code via HC-12 to slave stacks in the field. The stack controlling the generator uses SoftwareSerial and RCSwitch. To date the code is reliable.
Thanks for the video link, I suggest anyone thinking about writing code watch r0ml.