Arduino Remote At 433 MHz with HC-12 Module – Beta

Arduino Remote – Beta Testings

Arduino remote is an attempt to use relatively cheap HC-12 module, which has plenty of options, ranging from 100 channels, power setting from 0.8 mW up to 100 mW at 433.4 to 437.4 MHz.

remote

Out there exist up to 1 W transceivers, but this will come later as long range will be needed, just for sake of simplicity, I will say that 100 mW is more than sufficient for decent range. Datasheet.

Complete datasheet.

Why 433 MHz instead 2.4 GHz?!

The reason is simple: 2.4 GHz is too much “crowded” with all that WiFi signals and it has more dependence of humidity, obstacles, and other factors. All what is currently present on this band is wireless car keys, humidity and temperature sensors, and maybe other unknown low power transmitters.

Is this legal?

Note that this frequency as well as 2.4 GHz and 5.8 GHz are under ISM bands. So, no any licence needed, just pay attention of your local regulations. For example, while most of the world accept 100 mW power, in UK is allowed only 1/4 of that: 25 mW maximum. Keep in mind that HC-12 has 100 channels, with 400 kHz spacing, which means that channel 100 will be at 437.400 MHz, well above legal limit of 434.790 MHz (from 433.050 MHz to 433.790 MHz, so only first four channels are “legal” by any means. This “huge” spacings are made because this module can work on really wide modulation on high speeds. But, since we need mostly decent speed, say 15 kbps in air, less than 400 kHz will be more appropriate, but this module just has not this option.

Limitations?

Yes, it has few bad things. First at all, this module has no RSSI, so telemetry and feedback about how good signal is at other end is not possible. Only telemetry is possible for battery status, GPS coordinates and various other things, since it is actually transceiver, not simple transmitter or receiver – both modules on remote and your vehicle or any other apparatus (for example, you want to trigger camera by this remote) are capable to send some data back.

Another limitation is speed of changing parameters, lack of hopping ability and few others. When sending AT commands for changing parameters, 80 milliseconds needed to module back information whether your command is okay or received in error. The same is for changing channel, at least 80 mS needed for module to change channel. This is because this module has MCU for dealing with all needed parameters, while main RF chip inside is Si4463, beautiful chip, yet pretty difficult to make it to work due to lack of documentation. So, someone made HC-12 module, which has “as-is” functions. (I started to work on Si4432 and Si4463 alone, but it is not so easy to understand how it really works, an modules has pin raster of just 1.27 mm, so not easy to manipulate…)

Some codes?

Yes, here are my first working codes for Arduino nano and Arduino pro mini (Although it may work with other versions too). Note that this is just beta version, which means that it has just essential functions, not fully developed and just for sake of testing, and showing how it works. Currently I am using it as a remote for my car and my “weirdo-boat”, which didn’t touch water (yet), except some bath water. 😀

Arduino nano/pro mini sketch for remote:

/*
 * All codes by Milan Karakas, https://wildlab.org
 * So far, I use library "SoftwareSerial.h", but later it will be changed
 * with manual UART protocol to allow me various tricks and more reliable
 * work. This code(s) are protected by fictive "beerware union", where you may
 * use all codes, change it, copy, sell, exchange, etc. In other words, no
 * any copyright, but no waranty that it will work properly as well, so as-is.
 */

#include <SoftwareSerial.h>

SoftwareSerial mySerial(4, 5); // RX, TX
//Remember that TX of the HC-12 goes to RX of the Arduino board, 
//and RX of the HC-12 goes to the TX of the same board!
float volt;
int P1, P2, P3, P4;
byte packet[20];
int j;

void setup()
{
  pinMode(A6, INPUT); //just a reminder - it is input by default
  pinMode(6, OUTPUT); //set mode AT command, connected to RX of the HC-12 module
  pinMode(13, OUTPUT);//debug LED onboard Arduino nano or Arduino pro mini
  Serial.begin(9600);
  mySerial.begin(9600);
  analogReference(EXTERNAL); //not used exactly for displaying status of the local battery. 
                             //it is planed to use with resistive voltage divider 2:1
                             //and 3.3 V input on "REF" pin on Arduino nano, but on 
                             //Arduino pro mini, such pin does not exist, or at least
                             //it is not on pin header - require delicate soldering
                             //on board... If used "default" option, then pay attention
                             //to 5V power supply - if in error (for example 4.8V instead 5V),
                             //then voltage readings may be wrong as well
  while (!mySerial);
  digitalWrite(6,0);
  delay(280);
  mySerial.print("AT+B9600");
  delay(40);
  if  (mySerial.read() != 79) digitalWrite(13,1);// if first letter is not "O" from HC-12 feedback "OK+B9600"
  //Serial.println("Error setting speed of 9600 bps ");
  else digitalWrite(13,0);
  // Serial.println("Uart speed is 9600 ");
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
  delay(40);
  mySerial.print("AT+C001");
    delay(40);
  if  (mySerial.read() != 79) digitalWrite(13,1);// if first letter is not "O" from HC-12 feedback "OK+C001"
  //Serial.println("Error setting channel");
  else digitalWrite(13,0);
  //Serial.println("Channel is 001 - 433.400 MHz ");
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
  delay(40);
  mySerial.print("AT+P5");
  /* P1=0.8 mW
   * P2=1.6 mW
   * P3=3.2 mW
   * P4=6.3 mW
   * P5=12.6 mW
   * P6=25.1 mW
   * P7=50 mW
   * P8=100 mW
   */
  delay(40);
  if  (mySerial.read() != 79) digitalWrite(13,1);// if first letter is not "O" from HC-12 feedback "OK+P1"
  //Serial.println("Greska kanala");
  else digitalWrite(13,0);
  //Serial.println("Power is 12.6 mW "); //only if P5 is set, your choice. 
  //For indoor testing, please set P1 or 0.8 mW, then for field you may test at higher power
  //Pay attention to good antennas on TX, to prevent damage! 0.8 mW is "error free" even with
  //shitty spring antennas, but those antennas are small and handy - just for testings
  
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
    delay(80);
   mySerial.print("AT+U8N2");
    delay(80);
  if  (mySerial.read() != 79) //digitalWrite(13,1);// if first letter is not "O" from HC-12 feedback "OK+U8N2"
  Serial.println("Errpr setting 1 startbit, 8 data bits, no parity, and 2 stop bits");
  else digitalWrite(13,0);
  //Serial.println("8 bits, no parity, 2 stop bits ");
  delay(80);
  delay(40);
  digitalWrite(6,1);
  delay(80);
}
/* =====================main loop=========================== */
void loop()
{
      batteryStatus();  //jump to subroutine for testing local battery status. Here not used, so may be excluded
      readPots();       //this routine read remote pots, and prepare it for sending
      Send();           //sending packets of data about pot values
      delay(60);        //Some delay... no need to send packets too often,
                        //also, later it will require some space for telemetry packet,
                        //but so far, it is not implemented. 
}
/* =====================function for testing local battery============================= */
void batteryStatus()
{
    volt = ((float)3.273 / 1024 * analogRead(A6) * 2); //planed for external 3.3V on pin "REF", o
                                                       //only available on Arduino nano, not on pro mini...
    //float v = ((1 - (4.3 - volt)) * 100); //should be float for correct math
	  //math above is for indicator bar, not for real value - works from 3.3 to 4.2 volts only
    //this math is intended to be present on Nextion display, but so far I did not manage
    //to use this display properly. Many reasons... many bugs on Nextion...
    //so, feel free to delete this funcion and call to this function ("batteryStatus();") if needed
    return;
}
/* =====================function for reading remote pots======================== */
void readPots()
{
  P1 = analogRead(A0); //camera up/down
  P2 = analogRead(A1); //not used for now
  P3 = analogRead(A2); //throttle pot for forward/backward - center is no motion
  P4 = analogRead(A3); //differential thrust - rudder
  // later will be added trim buttons
  // this codes are intended for my boat with camera moving down into water, 
  // so change this comments so that fit your needs, for example car or similar.

  return;
}
/* ==================function for sending data from pots to HC-12 transceiver===================== */
void Send()
{ 
  /*
   * just debug options...
   * uncomment when testing values. If pots are reversed, then you will see wrong values,
   * as you move pots. Require little bit fiddling until get proper range for receiver
   * requirement, please experiment, and if needed - swap + power supply with GND on pots,
   * while center tap remains at analog input. Do not jump to the conclusion until receiver
   * end is finished. I found that it may be confusing, for example, throttle may be set so
   * that 0 is maximum forward, while 1023 is maximum backward. Or vice voersa.
  Serial.print("Camera up/down = ");
  Serial.print(P1);
  Serial.print(" Not used pot on right stick = ");
  Serial.print(P2);
  Serial.print(" Throttle value = ");
  Serial.print(P3);
  Serial.print(" Differential thrust/rudder = ");
  Serial.println(P4); 
  */  

for (j=0;j<20;j++)
{
  //"splitting" integer into two separate bytes for sending over HC-12 UART protocol
  packet[0]=(P1); packet[1]=(P1>>8);
  packet[2]=(P2); packet[3]=(P2>>8);
  packet[4]=(P3); packet[5]=(P3>>8);
  packet[6]=(P4); packet[7]=(P4>>8);
  int okay=P1+P2+P3+P4; //summ all pots for error checkings
  packet[8]=(okay); packet[9]=(okay>>8);//"splitting" integer into two separate bytes for testings
  packet[10]=(P1); packet[11]=(P1>>8); //The best option for error checking (CRC is okay, but...)
  packet[12]=(P2); packet[13]=(P2>>8); //Values of pots are send twice, and on receiver end
  packet[14]=(P3); packet[15]=(P3>>8); //it is checked whether first set of data are equal
  packet[16]=(P4); packet[17]=(P4>>8); //with sending the same data again. If error (RF noise, out of range),
  packet[18]=255; packet[19]=255;      //then whole packet of 20 bytes (will be shorten later) are discarded
  mySerial.write(packet[j]);           //for sake of secure drive
  //this write finally sending UART data to HC-12 transceiver
}
  return; //with or without "return;" it will work, but it is easier to follow if it is there. :D
}
/* ==================end of sending function======================= */

Arduino nano/pro mini for receiver end:

//Atmega328p based Arduino code (should work withouth modifications with Atmega168/88), tested on RBBB Arduino clone by Modern Device:
#include <SoftwareSerial.h>

SoftwareSerial mySerial(4, 5); // RX, TX
//const byte joysticYA = A2; //Analog Jostick Y axis //removed, because replaced with Pa2
//const byte joysticXA = A3; //Analog Jostick X axis //removed, because replaced with Pa2
byte joysticYA; //Analog Jostick Y axis
byte joysticXA; //Analog Jostick X axis

const byte controllerFA = 10; //PWM FORWARD PIN for OSMC Controller A (left motor)
const byte controllerRA = 9;  //PWM REVERSE PIN for OSMC Controller A (left motor)
const byte controllerFB = 6;  //PWM FORWARD PIN for OSMC Controller B (right motor)
const byte controllerRB = 3;  //PWM REVERSE PIN for OSMC Controller B (right motor)
//const byte disablePin = 2; //OSMC disable, pull LOW to enable motor controller //removed, because ISR is on pin 2!!!

int analogTmp = 0; //temporary variable to store 
int throttle, direction = 0; //throttle (Y axis) and direction (X axis) 

int leftMotor,leftMotorScaled = 0; //left Motor helper variables
float leftMotorScale = 0;

int rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;

float maxMotorScale = 0; //holds the mixed output scaling factor

int deadZone = 10; //jostick dead zone 

volatile byte packet[20];

volatile byte b;

unsigned int P1,P2,P3,P4;
unsigned int Pa1=512;
unsigned int Pa2=512;
unsigned int Pa3=512;
unsigned int Pa4=512;

void setup()  { 

  //initialization of pins  
  Serial.begin(9600);
  mySerial.begin(9600);
  pinMode(controllerFA, OUTPUT);
  pinMode(controllerRA, OUTPUT);
  pinMode(controllerFB, OUTPUT);
  pinMode(controllerRB, OUTPUT);  
  pinMode(7, OUTPUT);
  pinMode(5, OUTPUT);
//  pinMode(disablePin, OUTPUT); //removed, because it uses ISR pin 2...
//  digitalWrite(disablePin, LOW);//the same reason
  pinMode(13, OUTPUT); //debug LED onboard MCU
  //following codes are for set HC-12 receiver (and transmitter if used), because
  //sometimes it just goes to default values, so I wanted to be sure that
  //every time it is on again - has the same parameters, else it may be in error.
  
  while(!mySerial);
  digitalWrite(7,0);
  delay(201);
  mySerial.print("AT+B9600");
  delay(80);
  if  (mySerial.read() != 79) digitalWrite(13,1); //if first letter is not "O" from ("OK+B9600"), then it is error
  //Serial.println("Error setting speed");
  else digitalWrite(13,0);
  // Serial.println("Uart speed is 9600 ");
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
  delay(80);
  mySerial.print("AT+C001");
  delay(80);
  if  (mySerial.read() != 79) digitalWrite(13,1); //if first letter is not "O" from ("OK+B9600"), then it is error
  //Serial.println("Greska kanala");
  else digitalWrite(13,0);
  //Serial.println("Channel is 001 - 433.400 MHz ");
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
  delay(80);
  mySerial.print("AT+P1");
  /* P1=0.8 mW
   * P2=1.6 mW
   * P3=3.2 mW
   * P4=6.3 mW
   * P5=12.6 mW
   * P6=25.1 mW
   * P7=50 mW
   * P8=100 mW
   */
   //On receiver, transmitter is off. But, it gives ability to add telemetry. Work in progress...
  delay(80);
  if  (mySerial.read() != 79) digitalWrite(13,1); //if first letter is not "O" from ("OK+C001"), then it is error
  //Serial.println("Error setting channel");
  else digitalWrite(13,0);
  //Serial.println("Power is 0.8 mW ");
  for (int i=0;i<12;i++) mySerial.read(); //just read 12 bytes to flush out RX buffer
  delay(80);
  mySerial.print("AT+U8N2");
  delay(80);
  if  (mySerial.read() != 79) digitalWrite(13,1); //if first letter is not "O" from ("OK+U8N2"), then it is error
  //Serial.println("Error setting 1 start bit, 8 data bites, no parity, and 2 stop bites");
  else digitalWrite(13,0);
  //Serial.println("8 bits, no parity, 2 stop bits ");
  delay(80);
  digitalWrite(7,1);
  delay(80);
  //next routine is essential - HC-12 RX pin is connected to pin 2 on Arduino nano or pro mini...
  attachInterrupt(digitalPinToInterrupt(2), uartISR, FALLING); //very important ISR to sync and detect incomming UART
                                                               //pulses at 8N2 at 9600 bps, where two stop bites are
                                                               //used for debug purpose only. DO NOT change anything,
                                                               //else it will be "out of sync"! Work in progress...
                                                               //So far, HC-12 is used. Later will be some other chip...
} 

void loop()  { 
  readRadio(); //jump to routine for "decoding" radio signal into useful integer (global) variables
  //After return, Pa1 to Pa4 are changed by this routine. If out of range, all four are set to 512 
  //because it gives "iddle" state of the motors until connection is re-established. So far, no failsave... Work in progress...
  //=========================================================================================================================== 
  //Original code (below) of mixing by:
  //http://electronics.stackexchange.com/questions/19669/algorithm-for-mixing-2-axis-analog-input-to-control-a-differential-motor-drive
  //modified by me, Milan Karakas, https://wildlab.org - Pa1, Pa2, Pa3 and Pa4 are inputs from remote (potentiometers 1 to 4)
  //here only channels Pa3 (throttle) and Pa4 (dirrection) are used - other channels for camera servo, and other stuff if needed
  //aquire the analog input for Y  and rescale the 0..1023 range to -255..255 range
  
  analogTmp =Pa3; //global variable Pa3 = throttle value in integer (0 to 1023), by me :D
  throttle = (512-analogTmp)/2;

  delayMicroseconds(100);
  //...and  the same for X axis
  analogTmp = Pa4; //global variable Pa4 = throttle value in integer (0 to 1023), by me :D
  direction = -(512-analogTmp)/2;

  //mix throttle and direction
  leftMotor = throttle+direction;
  rightMotor = throttle-direction;

  //print the initial mix results
  Serial.print("LIN:"); Serial.print( leftMotor, DEC);
  Serial.print(", RIN:"); Serial.print( rightMotor, DEC);

  //calculate the scale of the results in comparision base 8 bit PWM resolution
  leftMotorScale =  leftMotor/255.0;
  leftMotorScale = abs(leftMotorScale);
  rightMotorScale =  rightMotor/255.0;
  rightMotorScale = abs(rightMotorScale);

  Serial.print("| LSCALE:"); Serial.print( leftMotorScale,2);
  Serial.print(", RSCALE:"); Serial.print( rightMotorScale,2);

  //choose the max scale value if it is above 1
  maxMotorScale = max(leftMotorScale,rightMotorScale);
  maxMotorScale = max(1,maxMotorScale);

  //and apply it to the mixed values
  leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
  rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);

  Serial.print("| LOUT:"); Serial.print( leftMotorScaled);
  Serial.print(", ROUT:"); Serial.print( rightMotorScaled);

  Serial.print(" |");

  //apply the results to appropriate uC PWM outputs for the LEFT motor:
  if(abs(leftMotorScaled)>deadZone)
  {

    if (leftMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(leftMotorScaled),DEC);

      analogWrite(controllerRA,0);
      analogWrite(controllerFA,abs(leftMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(leftMotorScaled),DEC);

      analogWrite(controllerFA,0);
      analogWrite(controllerRA,abs(leftMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFA,0);
  analogWrite(controllerRA,0);
  } 

  //apply the results to appropriate uC PWM outputs for the RIGHT motor:  
  if(abs(rightMotorScaled)>deadZone)
  {

    if (rightMotorScaled > 0)
    {
      Serial.print("F");
      Serial.print(abs(rightMotorScaled),DEC);

      analogWrite(controllerRB,0);
      analogWrite(controllerFB,abs(rightMotorScaled));            
    }
    else 
    {
      Serial.print("R");
      Serial.print(abs(rightMotorScaled),DEC);

      analogWrite(controllerFB,0);
      analogWrite(controllerRB,abs(rightMotorScaled));  
    }
  }  
  else 
  {
  Serial.print("IDLE");
  analogWrite(controllerFB,0);
  analogWrite(controllerRB,0);
  } 

  Serial.println("");

  //To do: throttle change limiting, to avoid radical changes of direction for large DC motors

  delay(10);

}

void readRadio()
{
   //original code by: me, Milan Karakas, https://wildlab.org
   //it is just four channel receiver with some weird check for channels - whether
   //they are correctly received or not. Used just two of four channels. Sending
   //20 bytes, but uses just few... work in progress for more...
   //
   P1=(packet[0])|(packet[1]<<8); //moving bytes into integers
   P2=(packet[2])|(packet[3]<<8); //moving bytes into integers
   P3=(packet[4])|(packet[5]<<8); //moving bytes into integers
   P4=(packet[6])|(packet[7]<<8); //moving bytes into integers
  
   int okay=P1+P2+P3+P4;                 //receiver end sum of all four channels for testing for errors (out of range, etc.)
   int okay2=(packet[8])|(packet[9]<<8); //at transmitter end, all four channels are added as a sum on those two bytes
   if (okay!=packet[10]|(packet[11])<<8|packet[12]|(packet[13])<<8|packet[14]|(packet[15])<<8|packet[16]|(packet[17])<<8&&okay!=okay2)
   //Code above: if this math is not satisfied, then notify us that some error occured...
   //Complete and too complicated test for lost packets in the case of noise or out of range. So far, no failsafe option. Work in progress...
   //Sum of all channels will be removed later, it is sufficient to send four channels twice, compare first sending with repeated sending, and
   //if it does not match, this means that something is in error (RF noise, out of range...). Sum of four thingies will be removed later...
    {
      //error
      //Serial.println("Error in receiving packets");
      //digitalWrite(13,1); //debug red LED pulse - error on (disabled, because ISR uses the same LEDs for debug)
      Pa1=512;Pa2=512;Pa3=512;Pa4=512; //In the case of lost range - it just put all "virtual sticks" in middle position
                                       //This is better than vehicle gound out of range even further...
                                       //In the case of stray RF noise from motors will cause motors will jumps...
                                       //That is: no motor running, no noise, once start, if noises are higher than
                                       //incoming signal from remote, it will cause error, so values of 512 will stop them
                                       //After stopping, and removing RF noise (if present), it will continue with acutal 
                                       //received data from remote. 
      return;
    }
   Pa1=P1;Pa2=P2;Pa3=P3;Pa4=P4; //transfer of temporary datas P1 to P4 into Pa1 to Pa4 for PWM uses above... 
   //digitalWrite(13,0); //debug red LED pulse - error off (disabled, because ISR uses the same LEDs for debug)
   return; //Well, for the convenience - Arduino code may wrok without "return" statement, but it is easier to follow code...
}

void uartISR()
{ 

  //ISR routine for "decoding" incoming packets from HC-12 (received from remote). Instead using "not reliable"
  //Serial.read() or mySerial.read(), I made this routine for synchronized and reliable reading of UART
  //signal from HC-12 (433 MHz band). This is NOT "flexible" routine, and it is made so far only for 9600 bps.
  //Later will consider to make other speeds as well, and if possible automatic change, depending of your needs. :D
  //So, for now, please use it "as-is". 
  //
  detachInterrupt(0);     //very important to forbid triggering interrupt inisde interrupt!!!
                          //Else, second time false triggered - will yield wrong readings between
                          //two adjacent packets, instead reading just one packed as planned.
  digitalWrite(13,1);     //debug pulses for oscilloscope - DO NOT remove, because it is accounted for timings
  delayMicroseconds(122); //delay 1.5 times one bite (start bit + half first bit, read in the middle)
  digitalWrite(13,0);     ////debug pulses for oscilloscope - DO NOT remove, because it is accounted for timings
  //note: leave debug pulses as is, LED at pin 13 will rapidly blink. If not blinking... check for connections.
  //If this few lines of code are removed,all timing will be wrong - so leave it as-is
  
  for (int j=0;j<20;j++)    //20 packets so far, 0 to 20 (4 channels, 1 sum all channels, repeated first 4 channels + 2 0xFF test bytes)
                            //Note that one channel is integer made of two consecutive bytes, sum is integer as well, and two end bytes
                            //are just for my unhappy debugging... will be removed later in next version. Sorry for the inconvenience. :D
  { 
    packet[j]=0; //delete all previous values in packet[] array, else it will "remember" previous values,
                 //then codes below will add new values next to old ones, and complete thingy will be in error. :D
    for (int i=0;i<8;i++)   //8 bites per packet, 0-7
    {
      digitalWrite(13,1); delayMicroseconds(1);digitalWrite(13,0); //debug pulses - leave it, else it will not work properly
      b=digitalRead(4); //above and below is just test pulses for centering
      digitalWrite(13,1); delayMicroseconds(1);digitalWrite(13,0); //debug pulses - leave it, else it will not work properly
      packet[j]|=(b<<i); //equal as this: packet[j]=packet[j]+(b<<i)
      delayMicroseconds(78);  //delay one bite - read next one
      asm ("nop");asm ("nop");asm ("nop");asm ("nop"); //some 62.5 ns "nop" or "no operand" for precise
      asm ("nop");asm ("nop");asm ("nop");             //adjustment of UART read pulses exactly in center
    }
    delayMicroseconds(300); //delay three bites until next bite after startbit (skipped two stop bites, and next start bit)
                            //Future development will probably check those two (or single, maybe) stop bites for errors,
                            //but for now, just skipped in precise maner
  }
   EIFR = 0x01;  //clear interrupt queue
 attachInterrupt(digitalPinToInterrupt(2), uartISR, FALLING); //re-enabling interrupt routine for next receiving packet
}

Is that all?!

No! All of that require more work. Especially for remote purposes. Also, my old projects on Arduino altimeter and other suffer from some intrinsic bugs related to “SoftwareSerial” and “VirtualWire” libraries. Now, I am using this library just to set HC-12, but soon it will be changed so that no any library will be needed. So far, it looks like it has double system, which is true: “mySerial” sending data to module, receiving message, and then in second part with manual codes dealing with “time critical” pulses. This part is not used in my altimeter project, and there are many bugs for this reason. Now, ISR part of the receiver take care of proper synchronization of incoming data and fill array exactly as it should be, instead random “mess”, and other weirdness with classical SoftwareSerial protocol(s). Soon (not sure how soon exactly), all my old project will be re-viewed and repaired, but I need lot of work on it. HC-12 module uses GFSK modulation, which is excellent – it is just enough wide as it should be, while for example ASK (A.K.A. OOK) modulation can spread on whole 433 MHz band. For this reason you may find that almost all ASK modules has the same frequency of 433.920 MHz, which is center of allowed frequency range from 433.050 MHz up to 434.790 MHz (simple math: (433.050+434.790)/2=433.920 MHz). So, all that wide mess is within legal limits.

Science and more

%d bloggers like this: