Zuverlässige Arduino-Funknetze mit großer Reichweite mit dem HC‑12-Modul aufbauen
In diesem Arduino-Tutorial lernen Sie, wie Sie das HC-12-Funkmodul für serielle Kommunikation einsetzen, um eine langstreckenfähige drahtlose Verbindung zwischen mehreren Arduino-Boards herzustellen – mit Entfernungen bis zu 1,8 km. Sie können das folgende Video ansehen oder die schriftliche Anleitung unten lesen. Für dieses Tutorial habe ich zwei grundlegende Beispiele erstellt: Zunächst zeige ich, wie man das HC-12-Modul anschließt und eine einfache Kommunikation zwischen zwei Arduinos realisiert. Im dritten Beispiel steuere ich mithilfe eines Beschleunigungssensors am ersten Arduino die Position eines Schrittmotors am zweiten Arduino kabellos. Sehen wir uns das HC-12-Modul genauer an. Hier die wichtigsten technischen Daten: Diese Werte hängen von der gewählten seriellen Baudrate und der Over-the-Air-Baudrate ab (siehe Tabelle). Das HC-12-Modul besitzt einen eigenen Mikrocontroller, der nicht vom Benutzer programmiert werden muss. Die Konfiguration erfolgt über AT-Befehle, die per serieller Schnittstelle von einem Arduino, PC oder einem anderen Mikrocontroller gesendet werden. Für den AT-Befehlsmodus muss der „Set“-Pin des Moduls auf Low-Pegel gezogen werden. Verbinden wir das HC-12-Modul mit dem Arduino für das erste Beispiel. Hier ist der Schaltplan. Die Betriebsspannung liegt zwischen 3,2 V und 5,5 V; für stabileren Betrieb wird ein Entkopplungskondensator und eine externe Stromversorgung empfohlen. In allen drei Beispielen dieses Tutorials habe ich jedoch die USB-Stromversorgung des PCs genutzt und hatte keine Probleme. Ich habe das erste Modul an einen Arduino UNO und das zweite an einen Arduino MEGA angeschlossen, aber Sie können jedes beliebige Board verwenden. Die benötigten Komponenten finden Sie in den Links unten: Hier ist der Arduino-Code für die erste Beispielanwendung: eine grundlegende Kommunikation zwischen den beiden Modulen über den Serial Monitor. Derselbe Code wird für beide Arduinos verwendet. Sie können die beiden Arduinos an zwei getrennten Computern betreiben oder einen einzigen Computer nutzen. Im letzteren Fall: Nach dem Verbinden des ersten Arduinos wählen Sie Board und COM-Port aus und laden den Code hoch. Dann verbinden Sie den zweiten Arduino, starten die Arduino IDE erneut, um den anderen COM-Port auszuwählen, und laden denselben Code hoch. Sobald beide Serial Monitors laufen, können Sie testen, ob die Kommunikation funktioniert. Alles, was Sie in einem Serial Monitor eingeben, wird zum anderen Arduino gesendet. Funktionsweise des Codes: Tippen Sie etwas in den Serial Monitor und klicken Sie auf Senden, wird an Arduino 1 die while-Schleife mit Derselbe Code kann auch zum Senden von AT-Befehlen und zur Konfiguration der Modulparameter verwendet werden. Dazu muss der „Set“-Pin des Moduls auf GND oder einen digitalen Pin des Arduinos gelegt und auf Low-Pegel gesetzt werden. Um zu prüfen, ob der AT-Modus aktiv ist, geben Sie „AT“ im Serial Monitor ein – die Antwort sollte „OK“ lauten. Es gibt insgesamt 12 AT-Befehle zum Ändern von Parametern wie Baudrate, Kanal, Sendeleistung usw. Beispiel: „AT+B38400“ setzt die Baudrate auf 38400. 1. AT – Testbefehl. 2. AT+Bxxxx – Serielle Baudrate ändern. 3. AT+Cxxxx – Funkkanal ändern (001 bis 100). Im zweiten Beispiel nutzen wir zwei Taster, um verschiedene Kommunikationskanäle auszuwählen, und demonstrieren eine alternative Methode zum Speichern eingehender Daten. Hinweis: Die „Set“-Pins beider HC-12-Module sind an Pin 6 der beiden Arduinos angeschlossen; die beiden Taster am ersten Arduino an Pin 4 und 3. Code für den ersten Arduino: Code für den zweiten Arduino: Code-Erläuterung: Zuerst definieren wir die Pins und setzen den „Set“-Pin auf High, damit das Modul im normalen, transparenten Modus arbeitet. Die erste while-Schleife speichert eingehende Daten in einer String-Variable, um sie besser verarbeiten zu können. Eingehende Daten kommen byteweise an. Wenn wir z. B. „Test123“ senden, durchläuft die Schleife 7-mal; jedes Byte wird gelesen und an „readBuffer“ angehängt. Sehen wir uns den Kanalwechsel per Taster 1 an. Wird Taster 1 gedrückt, senden wir per Empfängt der zweite Arduino diesen String, versetzt er sein HC-12 in den AT-Modus und sendet denselben Befehl „AT+C001“, woraufhin das Modul auf Kanal 1 schaltet. Die nächste while-Schleife gibt die Antwort des HC-12-Moduls aus, ob der Kanalwechsel erfolgreich war. Am ersten Arduino wiederholen wir den Vorgang für das erste HC-12-Modul. Analog dazu schaltet Taster 2 auf Kanal 2. So können wir jederzeit auswählen, mit welchem HC-12-Modul wir kommunizieren. Am Ende prüft die benutzerdefinierte Funktion Im dritten Beispiel steuern wir die Position eines Schrittmotors am zweiten Arduino mithilfe eines Beschleunigungssensors am ersten Arduino. Die Schaltung enthält zudem einen Mikroschalter zum Ermitteln der Nullposition des Schrittmotors bei 0 Grad. Benötigte Komponenten: Hinweis: Ich habe bereits detaillierte Tutorials zum Anschließen und Verwenden von Beschleunigungssensor und Schrittmotor. Hier erkläre ich nur den HC-12-Teil des Codes. Erster Arduino – Sender-Code: Zweiter Arduino – Empfänger-Code: Code-Erläuterung: Zuerst werden Pins definiert und Module initialisiert. Dann lesen wir X- und Y-Achse des Beschleunigungssensors aus und mappen sie auf 0–180°. Da die Werte instabil sein können, glätten wir durch Mittelung von 100 Messwerten. Zusätzlich senden wir den neuen Winkel nur, wenn er sich um mehr als 2° vom vorherigen unterscheidet. Beim Senden fügen wir das Start-Zeichen „s“ vor und das End-Zeichen „e“ nach dem Winkelwert ein. Am Empfänger warten wir auf „s“, lesen dann bis „e“ – so erhalten wir ausschließlich den Winkelwert. Anschließend wandeln wir den Wert in Integer um, mappen 0–180° auf 0–1600 Schritte (16-fach Microstepping am A4988) und drehen den Schrittmotor auf den aktuellen Winkel. Das war es für dieses Arduino-Tutorial. Fragen gerne in den Kommentaren!Überblick

HC-12 Funkkommunikationsmodul

Arduino und HC-12

Beispiel 01 – Arduino-Code
/* Arduino Long Range Wireless Communication using HC-12 Example 01 by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
void setup() {
Serial.begin(9600); // Serialport zum Computer
HC12.begin(9600); // Serialport zum HC12
}
void loop() {
while (HC12.available()) { // Wenn HC-12 Daten hat
Serial.write(HC12.read()); // Sende Daten an Serial Monitor
}
while (Serial.available()) { // Wenn Serial Monitor Daten hat
HC12.write(Serial.read()); // Sende diese Daten an HC-12
}
}Code language: Arduino (arduino)

Serial.available() wahr. Mit HC12.write() werden die Daten an das HC-12-Modul gesendet, das sie drahtlos an das zweite HC-12 überträgt. Dort wird die while-Schleife mit HC12.available() wahr, und per Serial.write() erscheinen die Daten im Serial Monitor des zweiten Arduinos.
AT-Befehle:
Beispiel: Senden Sie „AT“, das Modul antwortet „OK“.
Verfügbare Baudrates: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bps. Standard: 9600 bps.
Beispiel: „AT+B38400“ → Antwort „OK+B19200“.
Standard: Kanal 001 (433,4 MHz). Jeder weitere Kanal ist 400 kHz höher.
Beispiel: Für Kanal 006 senden Sie „AT+C006“, Antwort „OK+C006“, neue Frequenz 435,4 MHz.Beispiel 02

/* Arduino Long Range Wireless Communication using HC-12 Example 02 - Changing channels using push buttons - Buttons side by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#define setPin 6
#define button1 4
#define button2 3
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
byte incomingByte;
String readBuffer = "";
int button1State = 0;
int button1Pressed = 0;
int button2State = 0;
int button2Pressed = 0;
void setup() {
Serial.begin(9600);
HC12.begin(9600);
pinMode(setPin, OUTPUT);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
digitalWrite(setPin, HIGH); // HC-12 normaler, transparenter Modus
}
void loop() {
// ==== Eingehende Daten in einen String speichern
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
// ==== Daten via Serial Monitor von einem HC-12 zum anderen senden
while (Serial.available()) {
HC12.write(Serial.read());
}
// ==== Wenn Taster 1 gedrückt: Kanal 01 setzen
button1State = digitalRead(button1);
if (button1State == HIGH && button1Pressed == LOW) {
button1Pressed = HIGH;
delay(20);
}
if (button1Pressed == HIGH) {
HC12.print("AT+C001"); // AT-Befehl an anderes Modul senden
delay(100);
digitalWrite(setPin, LOW); // HC-12 in AT-Modus versetzen
delay(100);
HC12.print("AT+C001"); // AT-Befehl an HC-12 senden
delay(200);
while (HC12.available()) {
Serial.write(HC12.read()); // Antwort an Serial Monitor
}
Serial.println("Channel successfully changed");
digitalWrite(setPin, HIGH); // AT-Modus verlassen
button1Pressed = LOW;
}
// ==== Wenn Taster 2 gedrückt: Kanal 02 setzen
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("Channel successfully changed");
digitalWrite(setPin, HIGH);
button2Pressed = LOW;
}
checkATCommand();
readBuffer = "";
}
// ==== Eigene Funktion: Prüfen, ob AT-Befehl über Serial Monitor empfangen wurde
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);
}
}Code language: Arduino (arduino)/* Arduino Long Range Wireless Communication using HC-12 Example 02 - Changing channels using push buttons 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 Normalmodus
}
void loop() {
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}
delay(100);
while (Serial.available()) {
HC12.write(Serial.read());
}
// === Wenn Taster 1 gedrückt: Kanal 01 setzen
if (readBuffer == "AT+C001") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Channel successfully changed");
digitalWrite(setPin, HIGH);
readBuffer = "";
}
// === Wenn Taster 2 gedrückt: Kanal 02 setzen
if (readBuffer == "AT+C002") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Channel successfully changed");
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);
}
}Code language: Arduino (arduino)// ==== Eingehende Daten in einen String speichern
while (HC12.available()) {
incomingByte = HC12.read();
readBuffer += char(incomingByte);
}Code language: Arduino (arduino)
HC12.print() den String „AT+C001“ an das HC-12-Modul bzw. an den zweiten 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("Channel successfully changed");
digitalWrite(setPin, HIGH);
button1Pressed = LOW;
}Code language: Arduino (arduino)// Am zweiten Arduino
if (readBuffer == "AT+C001") {
digitalWrite(setPin, LOW);
delay(100);
HC12.print(readBuffer);
delay(200);
while (HC12.available()) {
Serial.write(HC12.read());
}
Serial.println("Channel successfully changed");
digitalWrite(setPin, HIGH);
readBuffer = "";
}Code language: Arduino (arduino)while (HC12.available()) {
Serial.write(HC12.read());
}Code language: Arduino (arduino)checkATCommand(), ob die empfangene Nachricht ein AT-Befehl ist (String beginnt mit „AT“). Falls ja, wird der AT-Modus aktiviert und der Befehl ausgeführt.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);
}
}Code language: Arduino (arduino)HC-12 Funkkommunikation: Schrittmotorsteuerung mit Beschleunigungssensor


/* Arduino Long Range Wireless Communication using HC-12 Example 03 - Stepper Motor Control using Accelerometer - Transmitter, Accelerometer 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;
//--- Beschleunigungssensor Register-Adressen
#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); // Bit D3 High für Messaktivierung
Wire.endTransmission();
}
void loop() {
// X-Achse
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) {
X0 = Wire.read();
X1 = Wire.read();
X1 = X1 << 8;
X_out = X0 + X1;
Xa = X_out / 256.0;
}
// Y-Achse
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;
}
// X- und Y-Werte kombinieren für Winkel 0-180°
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);
// 100 Messwerte mitteln für glatteres Ergebnis
angleSum = angleSum + angleInt;
count++;
if (count >= 100) {
angleInt = angleSum / 100;
angleSum = 0;
count = 0;
// Weiteres Glätten: nur senden, wenn Differenz > 2
if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
Serial.println(angleInt);
String angleString = String(angleInt);
// Senden mit Start-Marker 's' und End-Marker 'e'
HC12.print("s" + angleString + "e");
delay(10);
lastAngle = angleInt;
angleSum = 0;
count = 0;
}
}
}Code language: Arduino (arduino)/* Arduino Long Range Wireless Communication using HC-12 Example 03 - Stepper Motor Control using Accelerometer - Receiver, Stepper Motor 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;
// Eingehenden Winkel lesen
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) {
// Winkel in Schritte umrechnen (16-fach Microstepping)
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;
}
}Code language: Arduino (arduino)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;
}
}Code language: Arduino (arduino)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;
}
}Code language: Arduino (arduino)
Herstellungsprozess
- Wireless Communication Range meistern: Wie Power, Data Rate und Interferenz Konnektivität formen
- Wie batteriebetriebenes Long-Range Wireless Konnektivität transformiert
- LCD-Animationen & Spiele mit Arduino UNO erstellen
- JX Wave Generator – Arduino-kompatibler DDS-Oszillator mit OLED-Display
- u-blox LEA-6H 02 GPS-Modul: Arduino & Python Integrationsanleitung
- Kabelloser IR-Temperaturscanner – Arduino Nano mit Bluetooth & MLX90614
- Python 3 zu Arduino UNO: Einfache Steuerung & LED-Demo
- Kompaktes FM-Radio mit Arduino Nano und RDA5807M selbst bauen
- Fortschrittliches Sturz-Erkennungssystem mit Arduino, Windows IoT & Azure Cloud
- ArduRadio: DIY Arduino-Wecker mit FM-Radio (TEA5767)