Construye redes Arduino de largo alcance fiables con el módulo HC‑12
En este tutorial de Arduino aprenderemos a utilizar el módulo de comunicación serial inalámbrica HC-12, capaz de establecer comunicación inalámbrica de largo alcance entre varias placas Arduino, con distancias de hasta 1,8 km. Puedes ver el siguiente vídeo o leer el tutorial escrito a continuación para más detalles. Para este tutorial he preparado dos ejemplos básicos que explican cómo conectar el módulo HC-12 y realizar una comunicación básica entre dos Arduinos, y un ejemplo adicional donde, usando un sensor acelerómetro en el primer Arduino, controlo de forma inalámbrica la posición de un motor paso a paso en el segundo Arduino. Veamos más de cerca el módulo de puerto serial inalámbrico HC-12. Aquí están sus especificaciones: Estos valores dependen en realidad de la velocidad en baudios serial y over-the-air seleccionada, como se muestra en la tabla. El módulo HC-12 tiene un microcontrolador que no necesita ser programado por el usuario. Para configurar el módulo simplemente utilizamos comandos AT, que pueden enviarse desde un Arduino, un PC o cualquier otro microcontrolador usando el puerto serial. Para entrar en el modo de comandos AT solo tenemos que poner el pin "Set" del módulo a nivel lógico bajo. Ahora conectemos el módulo HC-12 al Arduino y hagamos el primer ejemplo. Aquí está el esquema del circuito. El voltaje de operación del módulo es de 3,2 V a 5,5 V y para un funcionamiento más estable se recomienda usar un capacitor de desacoplamiento y una fuente de alimentación externa. Sin embargo, usé la alimentación USB del PC para los tres ejemplos de este tutorial y no tuve ningún problema. Conecté el primer módulo a un Arduino UNO y el segundo a un Arduino MEGA, pero por supuesto puedes usar cualquier placa que quieras. Puedes conseguir los componentes necesarios para este tutorial de Arduino en los enlaces a continuación: Aquí está el código de Arduino para el primer ejemplo, una comunicación básica entre los dos módulos usando el Monitor Serial. El mismo código se usa para ambos Arduinos. Podemos conectar los dos Arduinos en dos ordenadores separados, pero también podemos usar un solo ordenador. En ese caso, una vez conectado el primer Arduino al ordenador, debemos seleccionar el modelo y el puerto COM y subir el código al Arduino. Luego conectamos el segundo Arduino y tenemos que iniciar el IDE de Arduino de nuevo para poder seleccionar el otro puerto COM al que está conectado nuestro segundo Arduino, y luego subir el mismo código. Así que una vez que tenemos los dos IDEs de Arduino funcionando, podemos iniciar los monitores seriales y probar si la comunicación funciona correctamente. Cualquier cosa que escribamos en el monitor serial se enviará de uno al otro Arduino. Cómo funciona el código: Cuando escribimos algo en el monitor serial y pulsamos el botón Enviar, en el primer Arduino el bucle while con la función Serial.available() se vuelve verdadero y usando la función HC12.write() enviamos los datos del monitor serial al módulo HC-12. Este módulo transferirá los datos inalámbricamente al segundo módulo HC-12, por lo que en el segundo Arduino el bucle while con la función HC12.available() se volverá verdadero y usando la función Serial.write() los datos se enviarán al monitor serial. Podemos usar el mismo código para enviar comandos AT y configurar los parámetros del módulo. Todo lo que tenemos que hacer es conectar el pin "Set" del módulo a GND o a cualquier pin digital del Arduino y poner el pin a nivel lógico bajo. Para probar si hemos entrado correctamente en el modo, en el monitor serial podemos escribir "AT" y deberíamos obtener un mensaje de respuesta "OK". Hay un total de 12 comandos AT, y se utilizan para cambiar varios parámetros como la velocidad en baudios, el canal, la potencia de transmisión, etc. Por ejemplo, si escribimos "AT+B38400", la velocidad en baudios del módulo se establecerá en 38400. 1. AT – Comando de prueba. Ejemplo: Enviar "AT" al módulo, y el módulo devuelve "OK". 2. AT+Bxxxx – Cambiar la velocidad en baudios del puerto serial. Velocidades disponibles: 1200 bps, 2400 bps, 4800 bps, 9600 bps, 19200 bps, 38400 bps, 57600 bps y 115200 bps. Por defecto: 9600 bps. Ejemplo: Enviar "AT+B38400" al módulo, y el módulo devuelve "OK+B19200". 3. AT+Cxxxx – Cambiar canal de comunicación inalámbrica, de 001 a 100. Por defecto: Canal 001, con frecuencia de trabajo de 433,4 MHz. Cada canal siguiente es 400 KHz más alto. Ejemplo: Si queremos poner el módulo en el canal 006, debemos enviar el comando "AT+C006" al módulo, y el módulo devolverá "OK+C006". La nueva frecuencia de trabajo será 435,4 MHz. Ahora pasemos al segundo ejemplo. Aquí usaremos dos pulsadores para seleccionar diferentes canales de comunicación y ver un método diferente de almacenar los datos entrantes. Nota: Los pines "Set" de ambos módulos HC-12 están conectados a los pines número 6 de los dos Arduinos y los dos pulsadores, en el primer Arduino, a los pines 4 y 3. Código del primer Arduino: Código del segundo Arduino: Descripción de los códigos: Primero definimos los pines y ponemos el pin "Set" a nivel alto para que el módulo funcione en modo normal, transparente. Con el primer bucle while almacenamos los datos entrantes en una variable String, para poder manejarlos mejor. Los datos entrantes siempre llegan byte a byte, así que si enviamos la cadena "Test123" desde el segundo Arduino, este bucle while hará 7 iteraciones. En cada iteración, usando la función HC12.read() leeremos cada byte o carácter entrante y lo añadiremos a la variable String llamada "readBuffer". Veamos cómo cambiar el canal de comunicación usando el primer pulsador. Si pulsamos el primer pulsador, usando la función HC12.print() enviaremos la cadena "AT+C001" al módulo HC-12 o al segundo Arduino. Cuando esta cadena se reciba en el segundo Arduino, pondremos el módulo HC-12 en modo comando AT, y luego escribiremos la misma cadena "AT+C001" en él, lo que configurará el módulo al canal de comunicación número uno. Usamos el siguiente bucle while para imprimir el mensaje de respuesta del módulo HC-12 indicando si el canal se ha cambiado correctamente. De vuelta en el primer Arduino, hacemos el mismo procedimiento de enviar el comando AT al primer módulo HC-12. De la misma manera, pulsando el segundo botón, configuramos el canal de comunicación número dos. Así que usando este método podemos seleccionar, en cualquier momento, con qué módulo HC-12 nos comunicaremos. Al final, la función personalizada checkATCommand() comprueba si el mensaje recibido es un comando AT, verificando si la cadena empieza con "AT". Si es así, el módulo entra en modo comando AT y ejecuta el comando. Ahora veamos el tercer ejemplo. Aquí controlamos la posición del motor paso a paso en el segundo Arduino, usando el módulo acelerómetro en el primer Arduino. El circuito también contiene un microinterruptor para encontrar la posición inicial del motor paso a paso a 0 grados. Puedes conseguir los componentes necesarios para este ejemplo en los enlaces a continuación: Ten en cuenta que ya tengo tutoriales detallados sobre cómo conectar y usar tanto el acelerómetro como el motor paso a paso, así que para este ejemplo solo explicaré la parte del código del HC-12. Primer Arduino – Código transmisor: Segundo Arduino – Código receptor: Descripción de los códigos: Primero definimos los pines e inicializamos los módulos en la sección setup. Luego leemos los valores de los ejes X e Y del acelerómetro y los mapeamos a valores de 0 a 180 grados. Los valores del acelerómetro a veces pueden ser inestables, así que para suavizar el resultado usé el valor promedio de cien lecturas. Para un suavizado aún mayor, enviaré el nuevo valor del ángulo solo si difiere del anterior en 2. Ten en cuenta que al enviar el ángulo al módulo HC-12, también envío el carácter "s" al principio y el carácter "e" al final, lo que me ayudará al recibir los datos en el segundo Arduino. En el segundo Arduino esperamos hasta que llegue el marcador de inicio "s", luego leemos el valor del ángulo hasta que llegue el marcador de fin "e". Así nos aseguramos de recibir solo el valor del ángulo. Luego convertimos el valor a entero, y mapeamos el valor de 0 a 1600 pasos, que corresponde a la resolución de dieciseisavos de paso seleccionada en el driver A4988. Luego giramos el motor paso a paso al ángulo actual. Esto sería todo para este tutorial de Arduino. Siéntete libre de hacer cualquier pregunta en la sección de comentarios a continuación.Resumen

Módulo de comunicación inalámbrica HC-12

Arduino y HC-12

Ejemplo 01 – Código Arduino
/* Comunicación inalámbrica de largo alcance Arduino con HC-12 Ejemplo 01 by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // Pin TX HC-12, Pin RX HC-12
void setup() {
Serial.begin(9600); // Puerto serial al ordenador
HC12.begin(9600); // Puerto serial al HC12
}
void loop() {
while (HC12.available()) { // Si HC-12 tiene datos
Serial.write(HC12.read()); // Enviar datos al Monitor Serial
}
while (Serial.available()) { // Si Monitor Serial tiene datos
HC12.write(Serial.read()); // Enviar esos datos al HC-12
}
}Lenguaje: Arduino (arduino)


Comandos AT:
Ejemplo 02

/* Arduino Comunicación Inalámbrica de Largo Alcance con HC-12 Ejemplo 02 - Cambio de canales con pulsadores - Lado botones by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#define setPin 6
#define button1 4
#define button2 3
SoftwareSerial HC12(10, 11); // Pin TX HC-12, Pin RX HC-12
byte incomingByte;
String readBuffer = "";
int button1State = 0;
int button1Pressed = 0;
int button2State = 0;
int button2Pressed = 0;
void setup() {
Serial.begin(9600); // Abrir puerto serial al ordenador
HC12.begin(9600); // Abrir puerto serial al HC12
pinMode(setPin, OUTPUT);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
digitalWrite(setPin, HIGH); // HC-12 modo normal, transparente
}
void loop() {
// ==== Almacenar datos entrantes en variable String
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
// ==== Enviar datos de un HC-12 a otro via Monitor Serial
while (Serial.available()) {
HC12.write(Serial.read());
}
// ==== Si se pulsa botón 1, establecer canal 01
button1State = digitalRead(button1);
if (button1State == HIGH & button1Pressed == LOW) {
button1Pressed = HIGH;
delay(20);
}
if (button1Pressed == HIGH) {
HC12.print("AT+C001"); // Enviar comando AT al otro módulo
delay(100);
digitalWrite(setPin, LOW); // Poner HC-12 en modo comando AT
delay(100);
HC12.print("AT+C001"); // Enviar comando AT al HC-12
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH); // Salir modo comando AT
button1Pressed = LOW;
}
// ==== Si se pulsa botón 2, establecer canal 02
button2State = digitalRead(button2);
if (button2State == HIGH & button2Pressed == LOW) {
button2Pressed = HIGH;
delay(100);
}
if (button2Pressed == HIGH) {
HC12.print("AT+C002");
delay(100);
digitalWrite(setPin, LOW);
delay(100);
HC12.print("AT+C002");
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH);
button2Pressed = LOW;
}
checkATCommand();
readBuffer = "";
}
void checkATCommand () {
if (readBuffer.startsWith("AT")) {
digitalWrite(setPin, LOW);
delay(200);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
digitalWrite(setPin, HIGH);
}
}Lenguaje: Arduino (arduino)/* Arduino Comunicación Inalámbrica de Largo Alcance con HC-12 Ejemplo 02 - Cambio de canales con pulsadores by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#define setPin 6
SoftwareSerial HC12(10, 11);
byte incomingByte;
String readBuffer = "";
void setup() {
Serial.begin(9600);
HC12.begin(9600);
pinMode(setPin, OUTPUT);
digitalWrite(setPin, HIGH); // HC-12 modo normal
}
void loop() {
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
while (Serial.available()) {
HC12.write(Serial.read());
}
// === Si botón 1 pulsado, establecer canal 01
if (readBuffer == "AT+C001") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH);
readBuffer = "";
}
// === Si botón 2 pulsado, establecer canal 02
if (readBuffer == "AT+C002") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH);
readBuffer = "";
}
checkATCommand();
readBuffer = "";
}
void checkATCommand () {
if (readBuffer.startsWith("AT")) {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
digitalWrite(setPin, HIGH);
}
}Lenguaje: Arduino (arduino)// ==== Almacenar datos entrantes en variable String
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}Lenguaje: Arduino (arduino)
if (button1Pressed == HIGH) {
HC12.print("AT+C001");
delay(100);
digitalWrite(setPin, LOW);
delay(100);
HC12.print("AT+C001");
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH);
button1Pressed = LOW;
}Lenguaje: Arduino (arduino)// En el segundo Arduino
// === Si botón 1 pulsado, establecer canal 01
if (readBuffer == "AT+C001") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Canal cambiado exitosamente");
digitalWrite(setPin, HIGH);
readBuffer = "";
}Lenguaje: Arduino (arduino)while (HC12.available()) {
Serial.write(HC12.read());
}Lenguaje: Arduino (arduino)void checkATCommand () {
if (readBuffer.startsWith("AT")) {
digitalWrite(setPin, LOW);
delay(200);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
digitalWrite(setPin, HIGH);
}
}Lenguaje: Arduino (arduino)Comunicación inalámbrica HC-12: Control de motor paso a paso usando un acelerómetro


/* Arduino Comunicación Inalámbrica de Largo Alcance con HC-12 Ejemplo 03 - Control Motor Paso a Paso con Acelerómetro - Transmisor, Acelerómetro by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial HC12(10, 11);
float angle;
int lastAngle = 0;
int count = 0;
int angleSum = 0;
//--- Direcciones de registros del acelerómetro
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32
#define X_Axis_Register_DATAX1 0x33
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53;
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
float Xa, Ya, Za;
void setup() {
HC12.begin(9600);
Wire.begin();
Serial.begin(9600);
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Power_Register);
Wire.write(8);
Wire.endTransmission();
}
void loop() {
// Eje X
Wire.beginTransmission(ADXAddress);
Wire.write(X_Axis_Register_DATAX0);
Wire.write(X_Axis_Register_DATAX1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress, 2);
if (Wire.available() <= 2) {
X1 = Wire.read();
X1 = X1 << 8;
X_out = X0 + X1;
Xa = X_out / 256.0;
}
// Eje Y
Wire.beginTransmission(ADXAddress);
Wire.write(Y_Axis_Register_DATAY0);
Wire.write(Y_Axis_Register_DATAY1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress, 2);
if (Wire.available() <= 2) {
Y0 = Wire.read();
Y1 = Wire.read();
Y1 = Y1 << 8;
Y_out = Y0 + Y1;
Ya = Y_out / 256.0;
}
// Combinar valores X e Y para obtener ángulo de 0 a 180 grados
if (Y_out > 0) {
angle = map(Y_out, 0, 256, 90, 0);
} else if (Y_out < 0) {
angle = map(Y_out, 256, 0, 90, 0);
angle = 90 - angle;
}
if (X_out < 0 & Y_out < 0) {
angle = 180;
}
if (X_out < 0 & Y_out > 0) {
angle = 0;
}
int angleInt = int(angle);
// Hace 100 lecturas del acelerómetro y envía el promedio para resultado más suave
angleSum = angleSum + angleInt;
count++;
if (count >= 100) {
angleInt = angleSum / 100;
angleSum = 0;
count = 0;
// Más suavizado - envía nuevo ángulo solo si difiere del anterior en +-2
if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
Serial.println(angleInt);
String angleString = String(angleInt);
// envía valor del ángulo con marcador inicio "s" y fin "e"
HC12.print("s" + angleString + "e");
delay(10);
lastAngle = angleInt;
angleSum = 0;
count = 0;
}
}
}Lenguaje: Arduino (arduino)/* Arduino Comunicación Inalámbrica de Largo Alcance con HC-12 Ejemplo 03 - Control Motor Paso a Paso con Acelerómetro - Receptor, Motor Paso a Paso by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11);
char incomingByte;
String readBuffer = "";
const int dirPin = 4;
const int stepPin = 3;
const int button = 2;
int currentAngle = 0;
int lastAngle = 0;
int rotate = 0;
void setup() {
Serial.begin(9600);
HC12.begin(9600);
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(button, INPUT_PULLUP);
delay(10);
digitalWrite(dirPin, HIGH);
boolean startingPosition = true;
while (startingPosition) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(200);
digitalWrite(stepPin, LOW);
delayMicroseconds(200);
if (digitalRead(button) == LOW) {
startingPosition = false;
}
}
delay(100);
}
void loop() {
readBuffer = "";
boolean start = false;
while (HC12.available()) {
incomingByte = HC12.read();
delay(5);
if (start == true) {
if (incomingByte != 'e') {
readBuffer += char(incomingByte);
} else {
start = false;
}
} else if (incomingByte == 's') {
start = true;
}
}
currentAngle = readBuffer.toInt();
if (currentAngle > 0 && currentAngle < 180) {
currentAngle = map(currentAngle, 0, 180, 0, 1600);
digitalWrite(dirPin, LOW);
if (currentAngle != lastAngle) {
if (currentAngle > lastAngle) {
rotate = currentAngle - lastAngle;
for (int x = 0; x < rotate; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(400);
digitalWrite(stepPin, LOW);
delayMicroseconds(400);
}
}
if (currentAngle < lastAngle) {
rotate = lastAngle - currentAngle;
digitalWrite(dirPin, HIGH);
for (int x = 0; x < rotate; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(400);
digitalWrite(stepPin, LOW);
delayMicroseconds(400);
}
}
}
lastAngle = currentAngle;
}
}Lenguaje: Arduino (arduino)// Hace 100 lecturas y envía el promedio
angleSum = angleSum + angleInt;
count++;
if (count >= 100) {
angleInt = angleSum / 100;
angleSum = 0;
count = 0;
if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
Serial.println(angleInt);
String angleString = String(angleInt);
HC12.print("s" + angleString + "e");
delay(10);
lastAngle = angleInt;
angleSum = 0;
count = 0;
}
}Lenguaje: Arduino (arduino)// Lee el ángulo entrante
while (HC12.available()) {
incomingByte = HC12.read();
delay(5);
if (start == true) {
if (incomingByte != 'e') {
readBuffer += char(incomingByte);
} else {
start = false;
}
} else if (incomingByte == 's') {
start = true;
}
}Lenguaje: Arduino (arduino)
Proceso de manufactura
- Crea Animaciones y Juegos en LCD 16×2 con Arduino UNO
- Generador de Ondas JX – Oscilador DDS Compatible con Arduino con Pantalla OLED
- Módulo GPS u-blox LEA‑6H 02: Guía de integración con Arduino y Python
- Escáner de Temperatura IR Inalámbrico – Arduino Nano, Bluetooth y MLX90614
- Control Arduino UNO desde Python 3 – Envío de Comandos y Demo LED
- Construye una Radio FM Compacta con Arduino Nano y RDA5807M
- Sistema Avanzado de Detección de Caídas con Arduino, Windows IoT y Azure Cloud
- ArduRadio: Reloj Despertador con Radio FM Basado en Arduino
- Proyecto Sensor de Distancia Ultrasónico Arduino: Medidor de Rango HC-SR04
- Dominando el alcance de comunicación inalámbrica: Cómo potencia, tasa de datos e interferencia moldean la conectividad
- Cómo la Conectividad Inalámbrica de Largo Alcance y Batería Transforma la Conectividad