{"id":909,"date":"2016-07-21T23:17:27","date_gmt":"2016-07-21T22:17:27","guid":{"rendered":"http:\/\/wildlab.org\/?page_id=909"},"modified":"2019-05-24T22:20:32","modified_gmt":"2019-05-24T21:20:32","slug":"arduino-remote-433-mhz-hc-12-module-beta","status":"publish","type":"page","link":"https:\/\/wildlab.org\/index.php\/arduino-remote-433-mhz-hc-12-module-beta\/","title":{"rendered":"Arduino Remote At 433 MHz with HC-12 Module &#8211; Beta"},"content":{"rendered":"<h2>Arduino Remote &#8211; Beta Testings<\/h2>\n<p style=\"text-align: justify;\">Arduino remote is an attempt to use relatively cheap <a href=\"http:\/\/www.banggood.com\/HC-12-433-SI4463-Wireless-Serial-Module-Remote-1000M-With-Antenna-p-973522.html?p=EH10221611330201505Q\">HC-12<\/a> 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.<\/p>\n<p><a href=\"https:\/\/wildlab.org\/wp-content\/uploads\/2016\/07\/433_1.jpg\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-910\" src=\"https:\/\/wildlab.org\/wp-content\/uploads\/2016\/07\/433_1.jpg\" alt=\"remote\" width=\"474\" height=\"355\" srcset=\"https:\/\/wildlab.org\/wp-content\/uploads\/2016\/07\/433_1.jpg 474w, https:\/\/wildlab.org\/wp-content\/uploads\/2016\/07\/433_1-300x225.jpg 300w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">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. <a href=\"http:\/\/www.seeedstudio.com\/wiki\/images\/b\/b0\/HC-12_User_Manual.pdf\">Datasheet.<\/a><\/p>\n<p style=\"text-align: justify;\"><a href=\"https:\/\/wildlab.org\/wp-content\/uploads\/2016\/07\/HC-12-2016-01-14_122335_HC-12_v2.3B.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">Complete datasheet.<\/a><\/p>\n<h2>Why 433 MHz instead 2.4 GHz?!<\/h2>\n<p style=\"text-align: justify;\">The reason is simple: 2.4 GHz is too much &#8220;crowded&#8221; 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.<\/p>\n<h2 style=\"text-align: justify;\">Is this legal?<\/h2>\n<p style=\"text-align: justify;\">Note that this frequency as well as 2.4 GHz and 5.8 GHz are under <a href=\"https:\/\/en.wikipedia.org\/wiki\/ISM_band\">ISM bands<\/a>. 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 <a href=\"http:\/\/www.banggood.com\/HC-12-433-SI4463-Wireless-Serial-Module-Remote-1000M-With-Antenna-p-973522.html?p=EH10221611330201505Q\">HC-12<\/a> has 100 channels, with 400 kHz spacing, which means that channel 100 will be at 437.400\u00a0MHz, well above legal limit of 434.790 MHz (from 433.050 MHz to 433.790 MHz, so only first four channels are &#8220;legal&#8221; by any means. This &#8220;huge&#8221; 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.<\/p>\n<h2 style=\"text-align: justify;\">Limitations?<\/h2>\n<p style=\"text-align: justify;\">Yes, it has few bad things. First at all, this module has no <a href=\"https:\/\/en.wikipedia.org\/wiki\/Received_signal_strength_indication\">RSSI<\/a>, 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 &#8211; 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.<\/p>\n<p style=\"text-align: justify;\">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 <a href=\"http:\/\/www.ebay.com\/itm\/E10-SMD-433MHz-SI4463-Wireless-Transmission-Module-Professional-100mW-NEW-\/311585430495?hash=item488bf05bdf:g:4M4AAOSwwIZXS9hT\">Si4463<\/a>, beautiful chip, yet pretty difficult to make it to work due to lack of documentation. So, someone made <a href=\"http:\/\/www.banggood.com\/HC-12-433-SI4463-Wireless-Serial-Module-Remote-1000M-With-Antenna-p-973522.html?p=EH10221611330201505Q\">HC-12<\/a> module, which has &#8220;as-is&#8221; functions. (I started to work on <a href=\"http:\/\/www.ebay.com\/itm\/SI4432-470MHz-1000m-Wireless-Module-470M-433mhz-Wireless-Communication-Module-\/200932667345?hash=item2ec8852fd1:g:-ccAAOSw7ehXSPMY\">Si4432<\/a> and <a href=\"http:\/\/www.ebay.com\/itm\/E10-SMD-433MHz-SI4463-Wireless-Transmission-Module-Professional-100mW-NEW-\/311585430495?hash=item488bf05bdf:g:4M4AAOSwwIZXS9hT\">Si4463<\/a>\u00a0alone, 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&#8230;)<\/p>\n<h2 style=\"text-align: justify;\">Some codes?<\/h2>\n<p style=\"text-align: justify;\">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 &#8220;weirdo-boat&#8221;, which didn&#8217;t touch water (yet), except some bath water. \ud83d\ude00<\/p>\n<h2 style=\"text-align: justify;\">Arduino nano\/pro mini sketch for remote:<\/h2>\n<pre class=\"theme:classic lang:c++ decode:true \">\/*\r\n * All codes by Milan Karakas, https:\/\/wildlab.org\r\n * So far, I use library \"SoftwareSerial.h\", but later it will be changed\r\n * with manual UART protocol to allow me various tricks and more reliable\r\n * work. This code(s) are protected by fictive \"beerware union\", where you may\r\n * use all codes, change it, copy, sell, exchange, etc. In other words, no\r\n * any copyright, but no waranty that it will work properly as well, so as-is.\r\n *\/\r\n\r\n#include &lt;SoftwareSerial.h&gt;\r\n\r\nSoftwareSerial mySerial(4, 5); \/\/ RX, TX\r\n\/\/Remember that TX of the HC-12 goes to RX of the Arduino board, \r\n\/\/and RX of the HC-12 goes to the TX of the same board!\r\nfloat volt;\r\nint P1, P2, P3, P4;\r\nbyte packet[20];\r\nint j;\r\n\r\nvoid setup()\r\n{\r\n  pinMode(A6, INPUT); \/\/just a reminder - it is input by default\r\n  pinMode(6, OUTPUT); \/\/set mode AT command, connected to RX of the HC-12 module\r\n  pinMode(13, OUTPUT);\/\/debug LED onboard Arduino nano or Arduino pro mini\r\n  Serial.begin(9600);\r\n  mySerial.begin(9600);\r\n  analogReference(EXTERNAL); \/\/not used exactly for displaying status of the local battery. \r\n                             \/\/it is planed to use with resistive voltage divider 2:1\r\n                             \/\/and 3.3 V input on \"REF\" pin on Arduino nano, but on \r\n                             \/\/Arduino pro mini, such pin does not exist, or at least\r\n                             \/\/it is not on pin header - require delicate soldering\r\n                             \/\/on board... If used \"default\" option, then pay attention\r\n                             \/\/to 5V power supply - if in error (for example 4.8V instead 5V),\r\n                             \/\/then voltage readings may be wrong as well\r\n  while (!mySerial);\r\n  digitalWrite(6,0);\r\n  delay(280);\r\n  mySerial.print(\"AT+B9600\");\r\n  delay(40);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1);\/\/ if first letter is not \"O\" from HC-12 feedback \"OK+B9600\"\r\n  \/\/Serial.println(\"Error setting speed of 9600 bps \");\r\n  else digitalWrite(13,0);\r\n  \/\/ Serial.println(\"Uart speed is 9600 \");\r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n  delay(40);\r\n  mySerial.print(\"AT+C001\");\r\n    delay(40);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1);\/\/ if first letter is not \"O\" from HC-12 feedback \"OK+C001\"\r\n  \/\/Serial.println(\"Error setting channel\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"Channel is 001 - 433.400 MHz \");\r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n  delay(40);\r\n  mySerial.print(\"AT+P5\");\r\n  \/* P1=0.8 mW\r\n   * P2=1.6 mW\r\n   * P3=3.2 mW\r\n   * P4=6.3 mW\r\n   * P5=12.6 mW\r\n   * P6=25.1 mW\r\n   * P7=50 mW\r\n   * P8=100 mW\r\n   *\/\r\n  delay(40);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1);\/\/ if first letter is not \"O\" from HC-12 feedback \"OK+P1\"\r\n  \/\/Serial.println(\"Greska kanala\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"Power is 12.6 mW \"); \/\/only if P5 is set, your choice. \r\n  \/\/For indoor testing, please set P1 or 0.8 mW, then for field you may test at higher power\r\n  \/\/Pay attention to good antennas on TX, to prevent damage! 0.8 mW is \"error free\" even with\r\n  \/\/shitty spring antennas, but those antennas are small and handy - just for testings\r\n  \r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n    delay(80);\r\n   mySerial.print(\"AT+U8N2\");\r\n    delay(80);\r\n  if  (mySerial.read() != 79) \/\/digitalWrite(13,1);\/\/ if first letter is not \"O\" from HC-12 feedback \"OK+U8N2\"\r\n  Serial.println(\"Errpr setting 1 startbit, 8 data bits, no parity, and 2 stop bits\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"8 bits, no parity, 2 stop bits \");\r\n  delay(80);\r\n  delay(40);\r\n  digitalWrite(6,1);\r\n  delay(80);\r\n}\r\n\/* =====================main loop=========================== *\/\r\nvoid loop()\r\n{\r\n      batteryStatus();  \/\/jump to subroutine for testing local battery status. Here not used, so may be excluded\r\n      readPots();       \/\/this routine read remote pots, and prepare it for sending\r\n      Send();           \/\/sending packets of data about pot values\r\n      delay(60);        \/\/Some delay... no need to send packets too often,\r\n                        \/\/also, later it will require some space for telemetry packet,\r\n                        \/\/but so far, it is not implemented. \r\n}\r\n\/* =====================function for testing local battery============================= *\/\r\nvoid batteryStatus()\r\n{\r\n    volt = ((float)3.273 \/ 1024 * analogRead(A6) * 2); \/\/planed for external 3.3V on pin \"REF\", o\r\n                                                       \/\/only available on Arduino nano, not on pro mini...\r\n    \/\/float v = ((1 - (4.3 - volt)) * 100); \/\/should be float for correct math\r\n\t  \/\/math above is for indicator bar, not for real value - works from 3.3 to 4.2 volts only\r\n    \/\/this math is intended to be present on Nextion display, but so far I did not manage\r\n    \/\/to use this display properly. Many reasons... many bugs on Nextion...\r\n    \/\/so, feel free to delete this funcion and call to this function (\"batteryStatus();\") if needed\r\n    return;\r\n}\r\n\/* =====================function for reading remote pots======================== *\/\r\nvoid readPots()\r\n{\r\n  P1 = analogRead(A0); \/\/camera up\/down\r\n  P2 = analogRead(A1); \/\/not used for now\r\n  P3 = analogRead(A2); \/\/throttle pot for forward\/backward - center is no motion\r\n  P4 = analogRead(A3); \/\/differential thrust - rudder\r\n  \/\/ later will be added trim buttons\r\n  \/\/ this codes are intended for my boat with camera moving down into water, \r\n  \/\/ so change this comments so that fit your needs, for example car or similar.\r\n\r\n  return;\r\n}\r\n\/* ==================function for sending data from pots to HC-12 transceiver===================== *\/\r\nvoid Send()\r\n{ \r\n  \/*\r\n   * just debug options...\r\n   * uncomment when testing values. If pots are reversed, then you will see wrong values,\r\n   * as you move pots. Require little bit fiddling until get proper range for receiver\r\n   * requirement, please experiment, and if needed - swap + power supply with GND on pots,\r\n   * while center tap remains at analog input. Do not jump to the conclusion until receiver\r\n   * end is finished. I found that it may be confusing, for example, throttle may be set so\r\n   * that 0 is maximum forward, while 1023 is maximum backward. Or vice voersa.\r\n  Serial.print(\"Camera up\/down = \");\r\n  Serial.print(P1);\r\n  Serial.print(\" Not used pot on right stick = \");\r\n  Serial.print(P2);\r\n  Serial.print(\" Throttle value = \");\r\n  Serial.print(P3);\r\n  Serial.print(\" Differential thrust\/rudder = \");\r\n  Serial.println(P4); \r\n  *\/  \r\n\r\nfor (j=0;j&lt;20;j++)\r\n{\r\n  \/\/\"splitting\" integer into two separate bytes for sending over HC-12 UART protocol\r\n  packet[0]=(P1); packet[1]=(P1&gt;&gt;8);\r\n  packet[2]=(P2); packet[3]=(P2&gt;&gt;8);\r\n  packet[4]=(P3); packet[5]=(P3&gt;&gt;8);\r\n  packet[6]=(P4); packet[7]=(P4&gt;&gt;8);\r\n  int okay=P1+P2+P3+P4; \/\/summ all pots for error checkings\r\n  packet[8]=(okay); packet[9]=(okay&gt;&gt;8);\/\/\"splitting\" integer into two separate bytes for testings\r\n  packet[10]=(P1); packet[11]=(P1&gt;&gt;8); \/\/The best option for error checking (CRC is okay, but...)\r\n  packet[12]=(P2); packet[13]=(P2&gt;&gt;8); \/\/Values of pots are send twice, and on receiver end\r\n  packet[14]=(P3); packet[15]=(P3&gt;&gt;8); \/\/it is checked whether first set of data are equal\r\n  packet[16]=(P4); packet[17]=(P4&gt;&gt;8); \/\/with sending the same data again. If error (RF noise, out of range),\r\n  packet[18]=255; packet[19]=255;      \/\/then whole packet of 20 bytes (will be shorten later) are discarded\r\n  mySerial.write(packet[j]);           \/\/for sake of secure drive\r\n  \/\/this write finally sending UART data to HC-12 transceiver\r\n}\r\n  return; \/\/with or without \"return;\" it will work, but it is easier to follow if it is there. :D\r\n}\r\n\/* ==================end of sending function======================= *\/<\/pre>\n<h2>Arduino nano\/pro mini for receiver end:<\/h2>\n<pre class=\"theme:classic lang:c++ decode:true \">\/\/Atmega328p based Arduino code (should work withouth modifications with Atmega168\/88), tested on RBBB Arduino clone by Modern Device:\r\n#include &lt;SoftwareSerial.h&gt;\r\n\r\nSoftwareSerial mySerial(4, 5); \/\/ RX, TX\r\n\/\/const byte joysticYA = A2; \/\/Analog Jostick Y axis \/\/removed, because replaced with Pa2\r\n\/\/const byte joysticXA = A3; \/\/Analog Jostick X axis \/\/removed, because replaced with Pa2\r\nbyte joysticYA; \/\/Analog Jostick Y axis\r\nbyte joysticXA; \/\/Analog Jostick X axis\r\n\r\nconst byte controllerFA = 10; \/\/PWM FORWARD PIN for OSMC Controller A (left motor)\r\nconst byte controllerRA = 9;  \/\/PWM REVERSE PIN for OSMC Controller A (left motor)\r\nconst byte controllerFB = 6;  \/\/PWM FORWARD PIN for OSMC Controller B (right motor)\r\nconst byte controllerRB = 3;  \/\/PWM REVERSE PIN for OSMC Controller B (right motor)\r\n\/\/const byte disablePin = 2; \/\/OSMC disable, pull LOW to enable motor controller \/\/removed, because ISR is on pin 2!!!\r\n\r\nint analogTmp = 0; \/\/temporary variable to store \r\nint throttle, direction = 0; \/\/throttle (Y axis) and direction (X axis) \r\n\r\nint leftMotor,leftMotorScaled = 0; \/\/left Motor helper variables\r\nfloat leftMotorScale = 0;\r\n\r\nint rightMotor,rightMotorScaled = 0; \/\/right Motor helper variables\r\nfloat rightMotorScale = 0;\r\n\r\nfloat maxMotorScale = 0; \/\/holds the mixed output scaling factor\r\n\r\nint deadZone = 10; \/\/jostick dead zone \r\n\r\nvolatile byte packet[20];\r\n\r\nvolatile byte b;\r\n\r\nunsigned int P1,P2,P3,P4;\r\nunsigned int Pa1=512;\r\nunsigned int Pa2=512;\r\nunsigned int Pa3=512;\r\nunsigned int Pa4=512;\r\n\r\nvoid setup()  { \r\n\r\n  \/\/initialization of pins  \r\n  Serial.begin(9600);\r\n  mySerial.begin(9600);\r\n  pinMode(controllerFA, OUTPUT);\r\n  pinMode(controllerRA, OUTPUT);\r\n  pinMode(controllerFB, OUTPUT);\r\n  pinMode(controllerRB, OUTPUT);  \r\n  pinMode(7, OUTPUT);\r\n  pinMode(5, OUTPUT);\r\n\/\/  pinMode(disablePin, OUTPUT); \/\/removed, because it uses ISR pin 2...\r\n\/\/  digitalWrite(disablePin, LOW);\/\/the same reason\r\n  pinMode(13, OUTPUT); \/\/debug LED onboard MCU\r\n  \/\/following codes are for set HC-12 receiver (and transmitter if used), because\r\n  \/\/sometimes it just goes to default values, so I wanted to be sure that\r\n  \/\/every time it is on again - has the same parameters, else it may be in error.\r\n  \r\n  while(!mySerial);\r\n  digitalWrite(7,0);\r\n  delay(201);\r\n  mySerial.print(\"AT+B9600\");\r\n  delay(80);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1); \/\/if first letter is not \"O\" from (\"OK+B9600\"), then it is error\r\n  \/\/Serial.println(\"Error setting speed\");\r\n  else digitalWrite(13,0);\r\n  \/\/ Serial.println(\"Uart speed is 9600 \");\r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n  delay(80);\r\n  mySerial.print(\"AT+C001\");\r\n  delay(80);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1); \/\/if first letter is not \"O\" from (\"OK+B9600\"), then it is error\r\n  \/\/Serial.println(\"Greska kanala\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"Channel is 001 - 433.400 MHz \");\r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n  delay(80);\r\n  mySerial.print(\"AT+P1\");\r\n  \/* P1=0.8 mW\r\n   * P2=1.6 mW\r\n   * P3=3.2 mW\r\n   * P4=6.3 mW\r\n   * P5=12.6 mW\r\n   * P6=25.1 mW\r\n   * P7=50 mW\r\n   * P8=100 mW\r\n   *\/\r\n   \/\/On receiver, transmitter is off. But, it gives ability to add telemetry. Work in progress...\r\n  delay(80);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1); \/\/if first letter is not \"O\" from (\"OK+C001\"), then it is error\r\n  \/\/Serial.println(\"Error setting channel\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"Power is 0.8 mW \");\r\n  for (int i=0;i&lt;12;i++) mySerial.read(); \/\/just read 12 bytes to flush out RX buffer\r\n  delay(80);\r\n  mySerial.print(\"AT+U8N2\");\r\n  delay(80);\r\n  if  (mySerial.read() != 79) digitalWrite(13,1); \/\/if first letter is not \"O\" from (\"OK+U8N2\"), then it is error\r\n  \/\/Serial.println(\"Error setting 1 start bit, 8 data bites, no parity, and 2 stop bites\");\r\n  else digitalWrite(13,0);\r\n  \/\/Serial.println(\"8 bits, no parity, 2 stop bits \");\r\n  delay(80);\r\n  digitalWrite(7,1);\r\n  delay(80);\r\n  \/\/next routine is essential - HC-12 RX pin is connected to pin 2 on Arduino nano or pro mini...\r\n  attachInterrupt(digitalPinToInterrupt(2), uartISR, FALLING); \/\/very important ISR to sync and detect incomming UART\r\n                                                               \/\/pulses at 8N2 at 9600 bps, where two stop bites are\r\n                                                               \/\/used for debug purpose only. DO NOT change anything,\r\n                                                               \/\/else it will be \"out of sync\"! Work in progress...\r\n                                                               \/\/So far, HC-12 is used. Later will be some other chip...\r\n} \r\n\r\nvoid loop()  { \r\n  readRadio(); \/\/jump to routine for \"decoding\" radio signal into useful integer (global) variables\r\n  \/\/After return, Pa1 to Pa4 are changed by this routine. If out of range, all four are set to 512 \r\n  \/\/because it gives \"iddle\" state of the motors until connection is re-established. So far, no failsave... Work in progress...\r\n  \/\/=========================================================================================================================== \r\n  \/\/Original code (below) of mixing by:\r\n  \/\/http:\/\/electronics.stackexchange.com\/questions\/19669\/algorithm-for-mixing-2-axis-analog-input-to-control-a-differential-motor-drive\r\n  \/\/modified by me, Milan Karakas, https:\/\/wildlab.org - Pa1, Pa2, Pa3 and Pa4 are inputs from remote (potentiometers 1 to 4)\r\n  \/\/here only channels Pa3 (throttle) and Pa4 (dirrection) are used - other channels for camera servo, and other stuff if needed\r\n  \/\/aquire the analog input for Y  and rescale the 0..1023 range to -255..255 range\r\n  \r\n  analogTmp =Pa3; \/\/global variable Pa3 = throttle value in integer (0 to 1023), by me :D\r\n  throttle = (512-analogTmp)\/2;\r\n\r\n  delayMicroseconds(100);\r\n  \/\/...and  the same for X axis\r\n  analogTmp = Pa4; \/\/global variable Pa4 = throttle value in integer (0 to 1023), by me :D\r\n  direction = -(512-analogTmp)\/2;\r\n\r\n  \/\/mix throttle and direction\r\n  leftMotor = throttle+direction;\r\n  rightMotor = throttle-direction;\r\n\r\n  \/\/print the initial mix results\r\n  Serial.print(\"LIN:\"); Serial.print( leftMotor, DEC);\r\n  Serial.print(\", RIN:\"); Serial.print( rightMotor, DEC);\r\n\r\n  \/\/calculate the scale of the results in comparision base 8 bit PWM resolution\r\n  leftMotorScale =  leftMotor\/255.0;\r\n  leftMotorScale = abs(leftMotorScale);\r\n  rightMotorScale =  rightMotor\/255.0;\r\n  rightMotorScale = abs(rightMotorScale);\r\n\r\n  Serial.print(\"| LSCALE:\"); Serial.print( leftMotorScale,2);\r\n  Serial.print(\", RSCALE:\"); Serial.print( rightMotorScale,2);\r\n\r\n  \/\/choose the max scale value if it is above 1\r\n  maxMotorScale = max(leftMotorScale,rightMotorScale);\r\n  maxMotorScale = max(1,maxMotorScale);\r\n\r\n  \/\/and apply it to the mixed values\r\n  leftMotorScaled = constrain(leftMotor\/maxMotorScale,-255,255);\r\n  rightMotorScaled = constrain(rightMotor\/maxMotorScale,-255,255);\r\n\r\n  Serial.print(\"| LOUT:\"); Serial.print( leftMotorScaled);\r\n  Serial.print(\", ROUT:\"); Serial.print( rightMotorScaled);\r\n\r\n  Serial.print(\" |\");\r\n\r\n  \/\/apply the results to appropriate uC PWM outputs for the LEFT motor:\r\n  if(abs(leftMotorScaled)&gt;deadZone)\r\n  {\r\n\r\n    if (leftMotorScaled &gt; 0)\r\n    {\r\n      Serial.print(\"F\");\r\n      Serial.print(abs(leftMotorScaled),DEC);\r\n\r\n      analogWrite(controllerRA,0);\r\n      analogWrite(controllerFA,abs(leftMotorScaled));            \r\n    }\r\n    else \r\n    {\r\n      Serial.print(\"R\");\r\n      Serial.print(abs(leftMotorScaled),DEC);\r\n\r\n      analogWrite(controllerFA,0);\r\n      analogWrite(controllerRA,abs(leftMotorScaled));  \r\n    }\r\n  }  \r\n  else \r\n  {\r\n  Serial.print(\"IDLE\");\r\n  analogWrite(controllerFA,0);\r\n  analogWrite(controllerRA,0);\r\n  } \r\n\r\n  \/\/apply the results to appropriate uC PWM outputs for the RIGHT motor:  \r\n  if(abs(rightMotorScaled)&gt;deadZone)\r\n  {\r\n\r\n    if (rightMotorScaled &gt; 0)\r\n    {\r\n      Serial.print(\"F\");\r\n      Serial.print(abs(rightMotorScaled),DEC);\r\n\r\n      analogWrite(controllerRB,0);\r\n      analogWrite(controllerFB,abs(rightMotorScaled));            \r\n    }\r\n    else \r\n    {\r\n      Serial.print(\"R\");\r\n      Serial.print(abs(rightMotorScaled),DEC);\r\n\r\n      analogWrite(controllerFB,0);\r\n      analogWrite(controllerRB,abs(rightMotorScaled));  \r\n    }\r\n  }  \r\n  else \r\n  {\r\n  Serial.print(\"IDLE\");\r\n  analogWrite(controllerFB,0);\r\n  analogWrite(controllerRB,0);\r\n  } \r\n\r\n  Serial.println(\"\");\r\n\r\n  \/\/To do: throttle change limiting, to avoid radical changes of direction for large DC motors\r\n\r\n  delay(10);\r\n\r\n}\r\n\r\nvoid readRadio()\r\n{\r\n   \/\/original code by: me, Milan Karakas, https:\/\/wildlab.org\r\n   \/\/it is just four channel receiver with some weird check for channels - whether\r\n   \/\/they are correctly received or not. Used just two of four channels. Sending\r\n   \/\/20 bytes, but uses just few... work in progress for more...\r\n   \/\/\r\n   P1=(packet[0])|(packet[1]&lt;&lt;8); \/\/moving bytes into integers\r\n   P2=(packet[2])|(packet[3]&lt;&lt;8); \/\/moving bytes into integers\r\n   P3=(packet[4])|(packet[5]&lt;&lt;8); \/\/moving bytes into integers\r\n   P4=(packet[6])|(packet[7]&lt;&lt;8); \/\/moving bytes into integers\r\n  \r\n   int okay=P1+P2+P3+P4;                 \/\/receiver end sum of all four channels for testing for errors (out of range, etc.)\r\n   int okay2=(packet[8])|(packet[9]&lt;&lt;8); \/\/at transmitter end, all four channels are added as a sum on those two bytes\r\n   if (okay!=packet[10]|(packet[11])&lt;&lt;8|packet[12]|(packet[13])&lt;&lt;8|packet[14]|(packet[15])&lt;&lt;8|packet[16]|(packet[17])&lt;&lt;8&amp;&amp;okay!=okay2)\r\n   \/\/Code above: if this math is not satisfied, then notify us that some error occured...\r\n   \/\/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...\r\n   \/\/Sum of all channels will be removed later, it is sufficient to send four channels twice, compare first sending with repeated sending, and\r\n   \/\/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...\r\n    {\r\n      \/\/error\r\n      \/\/Serial.println(\"Error in receiving packets\");\r\n      \/\/digitalWrite(13,1); \/\/debug red LED pulse - error on (disabled, because ISR uses the same LEDs for debug)\r\n      Pa1=512;Pa2=512;Pa3=512;Pa4=512; \/\/In the case of lost range - it just put all \"virtual sticks\" in middle position\r\n                                       \/\/This is better than vehicle gound out of range even further...\r\n                                       \/\/In the case of stray RF noise from motors will cause motors will jumps...\r\n                                       \/\/That is: no motor running, no noise, once start, if noises are higher than\r\n                                       \/\/incoming signal from remote, it will cause error, so values of 512 will stop them\r\n                                       \/\/After stopping, and removing RF noise (if present), it will continue with acutal \r\n                                       \/\/received data from remote. \r\n      return;\r\n    }\r\n   Pa1=P1;Pa2=P2;Pa3=P3;Pa4=P4; \/\/transfer of temporary datas P1 to P4 into Pa1 to Pa4 for PWM uses above... \r\n   \/\/digitalWrite(13,0); \/\/debug red LED pulse - error off (disabled, because ISR uses the same LEDs for debug)\r\n   return; \/\/Well, for the convenience - Arduino code may wrok without \"return\" statement, but it is easier to follow code...\r\n}\r\n\r\nvoid uartISR()\r\n{ \r\n\r\n  \/\/ISR routine for \"decoding\" incoming packets from HC-12 (received from remote). Instead using \"not reliable\"\r\n  \/\/Serial.read() or mySerial.read(), I made this routine for synchronized and reliable reading of UART\r\n  \/\/signal from HC-12 (433 MHz band). This is NOT \"flexible\" routine, and it is made so far only for 9600 bps.\r\n  \/\/Later will consider to make other speeds as well, and if possible automatic change, depending of your needs. :D\r\n  \/\/So, for now, please use it \"as-is\". \r\n  \/\/\r\n  detachInterrupt(0);     \/\/very important to forbid triggering interrupt inisde interrupt!!!\r\n                          \/\/Else, second time false triggered - will yield wrong readings between\r\n                          \/\/two adjacent packets, instead reading just one packed as planned.\r\n  digitalWrite(13,1);     \/\/debug pulses for oscilloscope - DO NOT remove, because it is accounted for timings\r\n  delayMicroseconds(122); \/\/delay 1.5 times one bite (start bit + half first bit, read in the middle)\r\n  digitalWrite(13,0);     \/\/\/\/debug pulses for oscilloscope - DO NOT remove, because it is accounted for timings\r\n  \/\/note: leave debug pulses as is, LED at pin 13 will rapidly blink. If not blinking... check for connections.\r\n  \/\/If this few lines of code are removed,all timing will be wrong - so leave it as-is\r\n  \r\n  for (int j=0;j&lt;20;j++)    \/\/20 packets so far, 0 to 20 (4 channels, 1 sum all channels, repeated first 4 channels + 2 0xFF test bytes)\r\n                            \/\/Note that one channel is integer made of two consecutive bytes, sum is integer as well, and two end bytes\r\n                            \/\/are just for my unhappy debugging... will be removed later in next version. Sorry for the inconvenience. :D\r\n  { \r\n    packet[j]=0; \/\/delete all previous values in packet[] array, else it will \"remember\" previous values,\r\n                 \/\/then codes below will add new values next to old ones, and complete thingy will be in error. :D\r\n    for (int i=0;i&lt;8;i++)   \/\/8 bites per packet, 0-7\r\n    {\r\n      digitalWrite(13,1); delayMicroseconds(1);digitalWrite(13,0); \/\/debug pulses - leave it, else it will not work properly\r\n      b=digitalRead(4); \/\/above and below is just test pulses for centering\r\n      digitalWrite(13,1); delayMicroseconds(1);digitalWrite(13,0); \/\/debug pulses - leave it, else it will not work properly\r\n      packet[j]|=(b&lt;&lt;i); \/\/equal as this: packet[j]=packet[j]+(b&lt;&lt;i)\r\n      delayMicroseconds(78);  \/\/delay one bite - read next one\r\n      asm (\"nop\");asm (\"nop\");asm (\"nop\");asm (\"nop\"); \/\/some 62.5 ns \"nop\" or \"no operand\" for precise\r\n      asm (\"nop\");asm (\"nop\");asm (\"nop\");             \/\/adjustment of UART read pulses exactly in center\r\n    }\r\n    delayMicroseconds(300); \/\/delay three bites until next bite after startbit (skipped two stop bites, and next start bit)\r\n                            \/\/Future development will probably check those two (or single, maybe) stop bites for errors,\r\n                            \/\/but for now, just skipped in precise maner\r\n  }\r\n   EIFR = 0x01;  \/\/clear interrupt queue\r\n attachInterrupt(digitalPinToInterrupt(2), uartISR, FALLING); \/\/re-enabling interrupt routine for next receiving packet\r\n}\r\n<\/pre>\n<h2 style=\"text-align: justify;\">Is that all?!<\/h2>\n<p style=\"text-align: justify;\">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 &#8220;SoftwareSerial&#8221;\u00a0and &#8220;VirtualWire&#8221;\u00a0libraries. Now, I am using this library just to set <a href=\"http:\/\/www.banggood.com\/HC-12-433-SI4463-Wireless-Serial-Module-Remote-1000M-With-Antenna-p-973522.html?p=EH10221611330201505Q\">HC-12<\/a>, 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: &#8220;mySerial&#8221; sending data to module, receiving message, and then in second part with manual codes dealing with &#8220;time critical&#8221; 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 &#8220;mess&#8221;, 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.\u00a0<a href=\"http:\/\/www.banggood.com\/HC-12-433-SI4463-Wireless-Serial-Module-Remote-1000M-With-Antenna-p-973522.html?p=EH10221611330201505Q\">HC-12<\/a>\u00a0module uses GFSK modulation, which is excellent &#8211; 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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Arduino Remote &#8211; 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. Out there exist up to 1 W transceivers, but this will come later as long range &hellip; <a href=\"https:\/\/wildlab.org\/index.php\/arduino-remote-433-mhz-hc-12-module-beta\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Arduino Remote At 433 MHz with HC-12 Module &#8211; Beta<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"_links":{"self":[{"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/pages\/909"}],"collection":[{"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/comments?post=909"}],"version-history":[{"count":14,"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/pages\/909\/revisions"}],"predecessor-version":[{"id":2176,"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/pages\/909\/revisions\/2176"}],"wp:attachment":[{"href":"https:\/\/wildlab.org\/index.php\/wp-json\/wp\/v2\/media?parent=909"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}