Dieses Tutorial ist Teil von: WiFi LoRa 32 Tutorials
Alle Videos zum Thema Heltec WiFi LoRa 32 gehören zu dieser Gruppe. Links zu weiteren Videos finden Sie unter diesem Artikel.
Steuere einen Servo-Motor aus großer Entfernung! Heltec WiFi LoRa 32 V3 Arduino Tutorial (TX)
In diesem Leitfaden verwenden wir die genauen Skizzen unseres Heltec ESP32 LoRa V3 Servo-Projekts und erklären, wie sie funktionieren - kein zusätzlicher Code hinzugefügt. Sie erfahren, wie der Sender einen Drehgeber liest, den Winkel sichert und über LoRa sendet, und wie der Empfänger ihn entschlüsselt und einen Mikroservo antreibt. Alle Teile- und Code-Links sind unten, und wenn Sie über unsere Affiliate-Links bestellen, hilft uns das, weiterhin diese Tutorials zu erstellen.
Installation von Heltec ESP32-Boards
Fügen Sie diesen Pfad in die Einstellungen Ihrer Arduino IDE ein, wie im Video gezeigt:https://resource.heltec.cn/download/package_heltec_esp32_index.json
1. Transmitter (TX) Hardware und Einrichtung
Auf der TX-Seite benötigen Sie:
-
Heltec WiFi LoRa 32 V3 Platine (im Meshnology N33 Gehäuse, betrieben von einem 3000 mAh Akku)
-
Rotary-Encoder, verdrahtet an GPIO 6 (CLK), GPIO 5 (DT), GPIO 4 (SW)
-
OLED-Display über I²C (SDA= 4, SCL= 15)
Die Skizze beginnt damit, alles genau wie in einzuschließen und zu initialisieren.Heltec_ESP32_LoRa_V3_Sevo_TX_AiRotaryEncoder.ino:
cppCopyEdit#include "AiEsp32RotaryEncoder.h"
#include "HT_SSD1306Wire.h"
#include "LoRaWan_APP.h"
#include "mbedtls/aes.h"
// …
static SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY, RST_OLED);
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(
PIN_A, PIN_B, SW_PIN, ROTARY_ENCODER_VCC_PIN, false, true, true);
const int homePosition = 90;
const int MAX_ANGLE = 180;
int servoAngel = homePosition;
Insetup(), der Code:
-
Leistungsanzeige, Schriftart einstellen
-
Anrufe
rotaryEncoder.begin(),rotaryEncoder.setup(readEncoderISR),rotaryEncoder.setBoundaries(0, MAX_ANGLE, true)undrotaryEncoder.setAcceleration(20) -
Setzt den Encoder zurück auf
homePosition -
Initialisiert LoRa über
Mcu.begin(HELTEC_BOARD, SLOW_CLK_TPYE)und richtet einRadioEvents, Kanal und Parameter genau wie im bereitgestellten Entwurf.
2. Den Winkel sicher senden
Jeder Schleifenzyklus läuftrotary_loop(), welches:
-
Liest den Encoder im ISR.
-
Wenn
servoAngelÄnderungen, verpackt sie in einen 16-Byte-Puffer, verschlüsselt mit AES-128encryptAES()Von der Skizze), und ruftcppCopyEditRadio.Send(data, sizeof(data)); -
Sets
lora_idle = falsebisOnTxDone()löscht und setzt es zurück.
3. Empfänger (RX) Hardware & Installation
Auf der RX-Seite benötigen Sie:
-
Heltec WiFi LoRa 32 V3 Board (gleiche Gehäuse/Batterie)
-
Mikro-Servo (z.B. SG90) an GPIO 6 (oder jedem getesteten PWM-Pin)
-
OLED-Display
Die Skizze inHeltec_ESP32_LoRa_V3_Sevo_RX.inobeginnt mit:
cppCopyEdit#include <ESP32Servo.h>
#include "HT_SSD1306Wire.h"
#include "LoRaWan_APP.h"
#include "mbedtls/aes.h"
// …
const int servoPin = 6;
const int SERVO_DUTY_MIN = 400; // us
const int SERVO_DUTY_MAX = 2400; // us
Servo myservo;
int servoAngel = homePosition;
Insetup(), it:
-
Powers on Vext für das Display/LoRa-Modul (
VextON()) -
Anrufe
Radio.Init(&RadioEvents)und konfiguriert RX mit denselben LoRa-Parametern -
Befestigt den Servo mit
myservo.attach(servoPin, SERVO_DUTY_MIN, SERVO_DUTY_MAX)und zentriert es beihomePosition.
4. Empfang, Entschlüsselung und Steuerung des Servos
Der Kern ist derOnRxDone(uint8_t *payload, …)Rückruf:
cppCopyEditdecryptAES((uint8_t*)rxpacket, userKey);
if (isNumber(rxpacket)) {
servoAngel = atoi(rxpacket);
myservo.write(servoAngel);
delay(15);
}
Serial.println("Angle: " + String(servoAngel));
lora_idle = true;
Es entschlüsselt den 16-Byte-Block, konvertiert ihn in eine Ganzzahl und aktualisiert sofort den Servo.
5. PWM-Pin-Unterstützung & Servo-Abstimmung
Wir haben diese ESP32-Pins für PWM-Ausgang getestet und sie funktionieren alle zur Steuerung eines Mikro-Servos:
CopyEdit1, 2, 3, 4, 5, 6, 19, 35, 36, 38, 39, 40, 41, 42, 45, 47, 48
Für einen Standard SG90 verwendet unser Code einen Pulsbereich von400 µs(0°) zu2400 µs(180°), was eine sanfte, volle Bewegung ohne Ruckeln ergibt.
6. Schaltplan
Unten finden Sie Platzhalter, in die Sie Ihre TX- und RX-Schemata einfügen können:


Code & Affiliate-Links
Alle oben genannten Skizzen sind im Abschnitt "Code & Ressourcen" unten zum Download verfügbar. Wenn Sie dies selbst bauen möchten, ziehen Sie bitte in Betracht, Ihr Heltec LoRa32 V3-Modul, das Meshnology N33-Gehäuse, den Drehgeber und den SG90-Servo über unsere Affiliate-Links zu kaufen. Es kostet Sie nichts extra und hilft uns, weiterhin kostenlose Tutorials wie dieses zu erstellen!
Video-Kapitel zur Referenz
-
00:00 Einführung & Übersicht
-
00:05 Fernbedienungskonzepte
-
00:19 Grundlagen der LoRa-Kommunikation
-
00:23 Hardware-Vorschau
-
00:28 Gehäuse- & Batterie-Präsentation
-
01:03 Modulmerkmale
-
01:42 Spezifikationen & Konnektivität
-
02:54 Servoantrieb aktivieren
-
03:05 Verdrahtung & Pinbelegung
-
09:35 Antennenplatzierung
-
11:04 Fallmontage
-
29:26 Skizzen hochladen
-
35:09 Reichweitentest 1,2 km
-
36:38 Reichweitentest 1,4 km
-
38:41 Leistungszusammenfassung
-
43:04 Schlussfolgerung & Unterstützung
Dieses Tutorial ist Teil von: WiFi LoRa 32 Tutorials
- Verwendung des Heltec WiFi LoRa 32 V3 zur Übertragung der Temperatur mittels DHT22 über 1,4 km
- 13 Meilen 20 km ohne WiFi? Wie LoRa Spannung über verrückte Distanzen sendete! (Heltec WiFi LoRa 32 V3)
- Schalte ein Gerät aus 13 Meilen (21 km) Entfernung ein – Das ultimative Off-Grid LoRa-Projekt mit WiFi LoRa 32!
- Fernzugangswarnsystem aus 21 km (13 Meilen) Entfernung mit LoRa – Unabhängig vom Stromnetz! (Heltec WiFi LoRa 32 V3)
- DIY-Fernsteuerrelaisprojekt: 21 km No-Wi-Fi/No-SIM Heltec LoRa 32 Modul
- How to Use the Heltec LoRa CubeCell Development Board HTCC-AB01
/*
* Datei: Heltec_ESP32_LoRa_V3_Sevo_TX_AiRotaryEncoder.ino
* geschrieben am 24. Jun, 2025 von Ahmad Shamshiri
*
* =====================================================================
* ARDUINO CODE BESCHREIBUNG: SICHERES LoRa SERVO STEUERUNGSSYSTEM (TX)
* =====================================================================
*
* HARDWAREKOMPONENTEN:
* -------------------
* - Hauptsteuerung: Heltec WiFi LoRa 32 V3
* - Gehäuse: Meshnology N33 Gehäuse mit 3000mAh Batterie
* - Eingabe: Drehgeber mit Druckknopf
* - Rückmeldung: Eingebaute OLED-Anzeige
* - Ausgabe: Servomotor + LoRa-Drahtlosübertragung
*
* SYSTEMFUNKTIONALITÄT:
* -------------------
* [1] DREHGEBERSTEUERUNG:
* - Im Uhrzeigersinn/Gegen den Uhrzeigersinn Drehung passt den Zielwinkel an (0°-180°)
* - Echtzeitanzeige des Winkels auf dem OLED-Bildschirm
* - Druckknopf bringt den Servomotor in die Home-Position (Standard: 90°)
*
* [2] SICHERE DRAHTLOSÜBERTRAGUNG:
* - Alle Winkelwerte werden vor der LoRa-Übertragung verschlüsselt
* - Kommando für die Home-Position wird als spezielles sicheres Paket übertragen
* - Verwendet das 433MHz LoRa-Band für zuverlässige Kommunikation
*
* [3] ENERGIEVERWALTUNG:
* - Optimiert für den Batteriebetrieb (3000mAh)
* - Energiesparmodi zwischen den Übertragungen
*
* FÜR VOLLSTÄNDIGE EINRICHTUNGSANLEITUNGEN:
* Bitte sehen Sie sich das Tutorial-Video an: https://youtu.be/EPynuJ7sasY
* =====================================================================
*
* Vollständige Videoerklärung ansehen: https://youtu.be/EPynuJ7sasY
* Ressourcenseite: https://robojax.com/T635
*
* HAFTUNGSAUSSCHLUSS:
* Dieser Code wird "WIE BESEHEN" ohne jegliche Gewährleistung bereitgestellt. Der Autor
* kann nicht für Schäden haftbar gemacht werden, die aus der Nutzung dieses Codes entstehen.
*
* LIZENZ:
* Dieses Werk ist unter der GNU General Public License v3.0 lizenziert.
* Genehmigungen, die über den Umfang dieser Lizenz hinausgehen, sind möglicherweise auf Robojax.com erhältlich.
*
* TEILENBEDINGUNGEN:
* Sie dürfen diesen Code für nicht-kommerzielle Zwecke teilen, kopieren und modifizieren,
* VORAAUSGESEZT, dass Sie:
* 1. Dieses gesamte Kommentarblock mit dem Originalcode intakt halten
* 2. Den Originallink von Robojax.com einfügen
* 3. Den YouTube-Tutorial-Link (falls zutreffend) beibehalten
* 4. Alle vorgenommenen Änderungen deutlich angeben
*
* Originaltutorial unter: https://robojax.com/T635
* YouTube-Video: https://youtu.be/EPynuJ7sasY
*/
#include <Wire.h>
#include "HT_SSD1306Wire.h"
#include "WiFi.h"
static SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst
const int TX_POWER = 2; // dBm from 2 to 20. when powered via battery 2 to 14dBm is the best option
const int MAX_ANGLE = 180; // the most common is 180, but you can set it as needed
String labelAngle = "Angle";
const int homePosition = 90; // initial position
// endcoder
const int SW_PIN = 4; // define a pin for rotary encode switch
const int PIN_A = 6;
const int PIN_B = 5;
const int ANGLE_STEP = 6;
const bool debug= false; // to print debug data in serial moinitor set it to true, else false
int servoAngel = homePosition;
int oldAngleValue = servoAngel;
#include "mbedtls/aes.h" // for securing data
#include <cstring> // For memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_1a"; // Security key.
#include "LoRaWan_APP.h"
#include "AiEsp32RotaryEncoder.h"
#include "Arduino.h"
#define ROTARY_ENCODER_VCC_PIN -1
// instead of changing here, rather change numbers above
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(
PIN_A,
PIN_B,
SW_PIN,
ROTARY_ENCODER_VCC_PIN,
ANGLE_STEP);
#define RF_FREQUENCY 915432000 // Hz
#define TX_OUTPUT_POWER TX_POWER // dBm from 2 to 20. when powered via battery 2 to 14dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 64 // Define the payload size here
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
double txNumber;
bool lora_idle=true;
static RadioEvents_t RadioEvents;
unsigned long lastTxTime = 0;
void OnTxDone( void );
void OnTxTimeout( void );
void decryptAES(uint8_t *data, const char *key);
void encryptAES(uint8_t *data, const char *key);
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize);
void VextON(void);
void rotary_loop(); // prototyp function: rotary encoder
void IRAM_ATTR readEncoderISR(); // prototyp function: rotary encoder
void rotary_onButtonClick(); // prototyp function: rotary encoder
void setup() {
Serial.begin(115200);
Serial.println();
VextON();
delay(100);
// we must initialize rotary encoder
rotaryEncoder.begin();
rotaryEncoder.setup(readEncoderISR);
bool circleValues = false;
rotaryEncoder.setBoundaries(0, MAX_ANGLE, circleValues); // minValue, maxValue, circleValues true|false (when max go to min and vice versa)
/*
* Rotary acceleration introduced 25.2.2021.
* in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
* without accelerateion you need long time to get to that number
* Using acceleration, faster you turn, faster will the value raise.
* For fine tuning slow down.
*/
// rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
rotaryEncoder.setAcceleration(20); // or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
rotaryEncoder.reset(homePosition); // set home position
// Initialising the UI will init the display too.
display.init();
display.setFont(ArialMT_Plain_10);
// LoRa stuff
Mcu.begin(HELTEC_BOARD,SLOW_CLK_TPYE);
txNumber=0;
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
}
void displayAngle() {
display.clear(); // Clear display before new content
// Line 1: Text: Angle
display.setTextAlignment(TEXT_ALIGN_LEFT);
// Line 2: Temperature value in 24pt font
display.setFont(ArialMT_Plain_24);
// Format
String angleString = String(servoAngel) + "°";
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, labelAngle);
display.setFont(ArialMT_Plain_24);
display.drawString(0, 15, angleString);
display.display(); // Update OLED
}
void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) // Vext default OFF
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void sendData()
{
String txData = String(servoAngel) ;
uint8_t data[BUFFER_SIZE];
memset(data, 0, sizeof(data)); // Zero-padding
strncpy((char*)data, txData.c_str(), sizeof(data) - 1); // Copy string safely
encryptAES(data, userKey); // Encrypt before sending
if(lora_idle == true)
{
// delay(1000);
Radio.Send(data, sizeof(data));
if(debug){
Serial.print("Sending: ");
Serial.println((char *)data);
}
lora_idle = false;
oldAngleValue =servoAngel; // keep record of angle change
}
Radio.IrqProcess( );
}
void loop() {
rotary_loop();
// clear the display
display.clear();
displayAngle();
if(oldAngleValue != servoAngel)
{
sendData();
}
// delay(100);
}
void OnTxDone( void )
{
if(debug){
Serial.println("TX done......");
}
lora_idle = true;
}
void OnTxTimeout( void )
{
Radio.Sleep( );
if(debug){
Serial.println("TX Timeout......");
}
lora_idle = true;
}
/*
* Converts a user-provided plaintext key into a fixed-length 16-byte (128-bit)
* or 32-byte (256-bit) key.
*/
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
memset(processedKey, 0, keySize); // Fill with zeros
size_t len = strlen(userKey);
if (len > keySize) len = keySize; // Truncate if too long
memcpy(processedKey, userKey, len); // Copy valid key part
}
/*
* Encrypts a 16-byte (one block) message using AES-128.
*/
void encryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, data, data);
mbedtls_aes_free(&aes);
}
/*
* Decrypts a 16-byte (one block) message using AES-128.
*/
void decryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_dec(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, data, data);
mbedtls_aes_free(&aes);
}
void rotary_onButtonClick()
{
static unsigned long lastTimePressed = 0;
// ignore multiple press in that time milliseconds
if (millis() - lastTimePressed < 500)
{
return;
}
lastTimePressed = millis();
if(debug){
Serial.print("button pressed ");
Serial.print(millis());
Serial.println(" milliseconds after restart");
}
}
void rotary_loop()
{
// dont print anything unless value changed
if (rotaryEncoder.encoderChanged())
{
if(debug){
Serial.print("Value: ");
Serial.println(rotaryEncoder.readEncoder());
}
servoAngel = rotaryEncoder.readEncoder();
}
if (rotaryEncoder.isEncoderButtonClicked())
{
rotaryEncoder.reset(homePosition);
servoAngel = homePosition;
rotary_onButtonClick();
}
}
void IRAM_ATTR readEncoderISR()
{
rotaryEncoder.readEncoder_ISR();
}
Common Course Links
Common Course Files
Ressourcen & Referenzen
-
ExternHeltec WiFi Kit 32 Website-Linkheltec.org
Dateien📁
Keine Dateien verfügbar.