Eine umfassende Arduino-Bibliothek für Slamtec RPLidar Laserscanner mit seriellem Interface.
- Getestet: RPLIDAR C1 an ESP32-S3 (Standard-Scan, 460800 Baud).
- Protokoll-korrekt implementiert: Standard-Scan, Geräte-Info/Health, Sample-Rate.
- Express-Scan ist NICHT implementiert (
startExpressScan()gibt absichtlichfalsezurück) — siehe Hinweis weiter unten. GET_LIDAR_CONF(0x84) ist nur als Konstante vorhanden, keine High-Level-API.
Das Standard-Scan-Protokoll ist bei A-, C- und S-Serie gleich; die Bibliothek sollte daher mit A1M/A2/A3, C1/C3 und S2/S2L/S3 im Standard-Scan funktionieren. Verifiziert wurde bisher nur der C1 (siehe oben). Modelle, die zwingend Express-Scan brauchen, werden derzeit nicht unterstützt.
- ✅ Standard-Scan mit Byte-Stream-Resynchronisierung (robuste Ausrichtung)
- ✅ Geräteinformationen, Gesundheitsstatus, Sample-Rate (mit Descriptor-Prüfung)
- ✅ Benutzerdefinierte Befehle (
sendCommand/readResponse) - ✅ Reiner, host-testbarer Node-Parser (
RPLidarParser.h, siehetest/) - ✅ Ohne RTTI baubar (
-fno-rtti) — läuft auf ESP32 - ⛔ Express-Scan: nicht implementiert
Diese Version behebt mehrere Protokoll- und Robustheitsfehler, durch die der C1 an ESP32 keine bzw. fehlerhafte Daten lieferte:
begin()startet die UART nicht mehr ungewollt neu.begin(Stream&)bindet nur noch den bereits konfigurierten Stream (keindynamic_cast, RTTI-frei) und lässt Baudrate und Pins unangetastet — entscheidend auf ESP32 mit eigenen RX/TX-Pins. Der neue Overloadbegin(HardwareSerial&, baudRate)hat bewusst kein Default-Argument, damitlidar.begin(Serial1)nicht versehentlich die UART auf Default-Pins neu startet.- Korrektes Node-Parsing. Die Signalqualität wird wieder aus den Bits 2–7
gelesen (vorher fälschlich
& 0x3F). Der reine Decoder liegt jetzt inRPLidarParser.h(ohne Arduino-Abhängigkeit) und ist host-getestet (test/, BeispielParserSelfTest). - Byte-Stream-Resynchronisierung in
readMeasurement(): ein 5-Byte- Sliding-Window richtet sich bei ungültigen Nodes byteweise neu aus, statt blind fünf Bytes zu lesen und so dauerhaft aus dem Takt zu geraten. - Korrektes Parsen des Response-Descriptors. Länge (30 Bit) und Send-Mode (2 Bit) werden sauber getrennt (vorher floss das Typ-Byte in das Mode-Feld); Descriptor-Typ und Mindestlänge werden für Scan/Info/Health/Sample-Rate validiert.
- Robusterer
startScan(). Sendet SCAN, validiert den Descriptor und bestätigt, dass tatsächlich Nodes eintreffen. Hängt/auto-scannt das Gerät, wird automatisch einreset()+ genau ein erneuter Versuch ausgeführt. Das frühere STOP/SCAN-„Churn" (an dem manche C1-Einheiten hängen blieben) entfällt. stop()leert bis Ruhe (_drainUntilQuiet), damit der nächste Befehls-Descriptor auf einem sauberen Puffer beginnt. Info-/Health-/ Sample-Rate-Abfragen stoppen vorher automatisch einen laufenden Scan.readFast()nutzt jetzt denselben validierten Pfad wiereadMeasurement()(vorher ungeprüftes Roh-Parsen ohne Check-Bit/Resync).- Express-Scan ist ehrlich als nicht implementiert markiert
(
startExpressScan()→false), statt mis-dekodierte Messwerte zu liefern. - Kleinkram: Null-Pointer-Checks in den Custom-Command-/Raw-APIs, A3-Baudrate
(256000) ergänzt, durchgängig
-fno-rtti-tauglich.
-
Klonen Sie dieses Repository:
git clone https://github.com/smily77/Lidar.git
-
Kopieren Sie den Ordner
Lidarin Ihr Arduino libraries Verzeichnis:- Windows:
Dokumente\Arduino\libraries\ - Mac:
~/Documents/Arduino/libraries/ - Linux:
~/Arduino/libraries/
- Windows:
-
Starten Sie die Arduino IDE neu
-
Die Bibliothek sollte nun unter
Sketch > Include Library > RPLidarverfügbar sein
- Laden Sie das Repository als ZIP herunter
- In Arduino IDE:
Sketch > Include Library > Add .ZIP Library... - Wählen Sie die heruntergeladene ZIP-Datei
RPLidar TX -> ESP32 RX (z.B. GPIO 16)
RPLidar RX -> ESP32 TX (z.B. GPIO 17)
RPLidar 5V -> 5V (externe Stromversorgung für S2L empfohlen!)
RPLidar GND -> GND
RPLidar MOTOR_PWM -> Optional für Motorsteuerung
RPLidar TX -> Arduino Mega RX1 (Pin 19)
RPLidar RX -> Arduino Mega TX1 (Pin 18)
RPLidar 5V -> 5V
RPLidar GND -> GND
Die richtige Baud-Rate ist kritisch für erfolgreiche Kommunikation:
| Modell | Baud-Rate | Konstante |
|---|---|---|
| A1M, A2 | 115200 | RPLIDAR_BAUD_A1M |
| A3 | 256000 | RPLIDAR_BAUD_A3 |
| C1, C3 | 460800 | RPLIDAR_BAUD_C1 |
| S2, S2L, S3 | 1000000 | RPLIDAR_BAUD_S2L |
#include <RPLidar.h>
RPLidar lidar;
void setup() {
Serial.begin(115200);
Serial2.begin(115200); // Für A1M
lidar.begin(Serial2, RPLIDAR_BAUD_A1M);
lidar.startScan();
}
void loop() {
RPLidarMeasurement measurement;
if (lidar.readMeasurement(measurement)) {
Serial.print("Winkel: ");
Serial.print(measurement.angle);
Serial.print(" Distanz: ");
Serial.println(measurement.distance);
}
}Bindet einen bereits konfigurierten Stream. Setzt weder Baudrate noch Pins
(wichtig auf ESP32, wo eigene RX/TX-Pins nötig sind) und prüft nicht, ob ein Gerät
antwortet — dafür getHealth()/isConnected() nutzen. Gibt true zurück.
Serial1.begin(RPLIDAR_BAUD_C1, SERIAL_8N1, 7, 8); // eigene Pins zuerst
delay(1000); // UART hochfahren lassen
lidar.begin(Serial1); // dann bindenKomfort-Overload für Boards mit Default-UART-Pins: ruft serialObj.begin(baudRate)
auf und bindet den Stream. Verwendet kein dynamic_cast (RTTI-frei). Auf ESP32
mit eigenen RX/TX-Pins stattdessen die begin(Stream&)-Variante verwenden.
Stoppt den laufenden Scan.
Setzt das RPLidar zurück (Neustart).
Startet Standard-Scan-Modus.
Nicht implementiert — gibt immer false zurück. Der Express-Cabin-Decoder
ist nicht vorhanden/verifiziert; nutzen Sie startScan() (Standard-Scan).
Startet Scan ohne Rotation Check (für Tests).
Liest Geräteinformationen.
Beispiel:
RPLidarDeviceInfo info;
if (lidar.getDeviceInfo(info)) {
Serial.print("Modell: ");
Serial.println(info.model);
Serial.print("Firmware: ");
Serial.println(info.firmware_version);
}Liest Gesundheitsstatus des Geräts.
Beispiel:
RPLidarHealth health;
if (lidar.getHealth(health)) {
if (health.status == RPLIDAR_STATUS_OK) {
Serial.println("Gerät OK");
} else {
Serial.print("Fehler: ");
Serial.println(health.error_code);
}
}Liest Abtastraten für Standard- und Express-Modi.
Liest eine vollständige Messung (Winkel, Distanz, Qualität, Start-Bit).
Beispiel:
RPLidarMeasurement measurement;
if (lidar.readMeasurement(measurement)) {
Serial.print("Winkel: ");
Serial.print(measurement.angle); // 0-360 Grad
Serial.print(" Distanz: ");
Serial.print(measurement.distance); // mm
Serial.print(" Qualität: ");
Serial.print(measurement.quality); // 0-63
if (measurement.startBit) {
Serial.println(" [NEUER SCAN]");
}
}Komfort-Variante, die nur Winkel und Distanz liefert. Delegiert intern an
readMeasurement() — verwendet also denselben validierten Parser inklusive
Check-Bit-Prüfung und Resynchronisierung (kein ungeprüftes Parsen mehr).
float angle, distance;
if (lidar.readFast(angle, distance)) {
sendViaUDP(angle, distance);
}Liest rohe Messdaten für benutzerdefinierte Verarbeitung.
Sendet benutzerdefinierten Befehl an RPLidar.
Liest Antwort auf benutzerdefinierten Befehl.
Beispiel:
// Eigenen Befehl senden
uint8_t customCmd = 0x84;
uint8_t payload[2] = {0x00, 0x01};
lidar.sendCommand(customCmd, payload, 2);
// Antwort lesen
uint8_t response[64];
if (lidar.readResponse(response, sizeof(response), 1000)) {
// Antwort verarbeiten
}Leert den Empfangspuffer.
Prüft ob Verbindung zum RPLidar besteht.
Gibt empfohlene Baud-Rate für Modellname zurück.
struct RPLidarMeasurement {
float angle; // Winkel in Grad (0-360)
float distance; // Distanz in mm (0 = ungültig / kein Echo)
uint8_t quality; // Signalqualität (0-63)
bool startBit; // true wenn Start eines neuen Scans
};Hinweis:
RPLidarMeasurementund der reine DecoderrplidarParseStandardNode()sind insrc/RPLidarParser.hdefiniert (ohne Arduino-Abhängigkeit, damit host-testbar — siehetest/).
struct RPLidarDeviceInfo {
uint8_t model;
uint16_t firmware_version;
uint8_t hardware_version;
uint8_t serialNumber[16];
};struct RPLidarHealth {
uint8_t status; // RPLIDAR_STATUS_OK, _WARNING, oder _ERROR
uint16_t error_code;
};Grundlegende Scan-Funktionalität mit vollständiger Messdaten-Ausgabe.
#include <RPLidar.h>
// ... siehe examples/BasicScan/BasicScan.ino
Zeigt alle Geräteinformationen, Gesundheitsstatus und Abtastraten.
Zeigt hohen Durchsatz mit readFast(). Hinweis: readFast() delegiert seit
1.1.0 an den validierten Parser (mit Check-Bit-Prüfung und Resync), liefert
also geprüfte statt roher Werte. Die S2L-Hinweise unten sind nicht auf C1-
Hardware verifiziert.
- Batch-Verarbeitung
- UDP-Übertragung (Beispiel)
- Performance-Statistiken
Dokumentiert, dass Express-Scan nicht implementiert ist: zeigt den
(erwarteten) false-Rückgabewert von startExpressScan() und verweist auf den
Standard-Scan (BasicScan).
Zeigt wie man benutzerdefinierte Befehle sendet und Antworten liest.
Der S2L kann bis zu 32.000 Samples/Sekunde liefern. Um diese Datenrate zu bewältigen:
// CPU auf 240 MHz setzen (in Arduino IDE: Tools > CPU Frequency > 240 MHz)
Serial2.begin(1000000, SERIAL_8N1, RX_PIN, TX_PIN);
Serial2.setRxBufferSize(2048); // Buffer vergrößernfloat angle, distance;
while (lidar.readFast(angle, distance)) {
// Keine Verzögerungen hier!
buffer[index++] = {angle, distance};
// Batch-Verarbeitung
if (index >= BUFFER_SIZE) {
processBatch(buffer, index);
index = 0;
}
}struct ScanPoint {
float angle;
float distance;
};
ScanPoint buffer[50];
int bufferIndex = 0;
void loop() {
if (lidar.readFast(angle, distance)) {
buffer[bufferIndex++] = {angle, distance};
if (bufferIndex >= 50) {
// Sende alle 50 Punkte auf einmal
udp.write((uint8_t*)buffer, sizeof(buffer));
bufferIndex = 0;
}
}
}- ❌
Serial.print()in der Loop (sehr langsam!) - ❌
delay()während des Scannens - ❌ Blockierende Operationen
- ❌ Einzelne UDP-Pakete pro Punkt
Lösung:
- Prüfen Sie die Baud-Rate (muss zum Modell passen!)
- Prüfen Sie RX/TX Verbindungen (sind sie vertauscht?)
- Motor muss sich drehen (MOTOR_PWM Anschluss prüfen)
- Gerät-Gesundheit prüfen:
lidar.getHealth()
Lösung:
- CPU-Frequenz auf 240 MHz erhöhen
readFast()stattreadMeasurement()verwenden- Serial Buffer vergrößern:
Serial2.setRxBufferSize(2048) - Batch-Verarbeitung implementieren
- Keine
Serial.print()Aufrufe in Loop
Lösung:
- Baud-Rate prüfen
- RX/TX Pins vertauscht?
- 5V Stromversorgung ausreichend?
lidar.reset()versuchen
Lösung:
- Stromversorgung prüfen (S2L braucht externe 5V!)
- USB-Kabel Qualität prüfen
- Längere Timeouts verwenden
- Serial Buffer vergrößern bei hohen Datenraten
| Modell | Max. Abtastrate | Reichweite | Baud-Rate |
|---|---|---|---|
| A1M | 2000 Hz | 12 m | 115200 |
| A2M6 | 4000 Hz | 6 m | 115200 |
| A2M8 | 4000 Hz | 8 m | 115200 |
| A3 | 8000 Hz | 25 m | 256000 |
| C1 | 8000 Hz | 12 m | 460800 |
| C3 | 8000 Hz | 12 m | 460800 |
| S2 | 15600 Hz | 30 m | 1000000 |
| S2L | 32000 Hz | 30 m | 1000000 |
| S3 | 16000 Hz | 40 m | 1000000 |
MIT License - siehe LICENSE Datei
- Basiert auf dem Slamtec RPLidar SDK
- Optimiert für Arduino und ESP32
- Entwickelt für maximale Performance mit S2L
Bei Problemen oder Fragen:
- Prüfen Sie die Beispiele
- Lesen Sie die Fehlerbehebung
- Öffnen Sie ein Issue auf GitHub
Um die Bibliothek zu klonen und in der Arduino IDE zu verwenden:
cd ~/Arduino/libraries/
git clone https://github.com/smily77/Lidar.git RPLidarOder für einen spezifischen Branch:
git clone -b claude/rplidar-arduino-library-011CUS8fWFpYoAmZxSyL4AXX https://github.com/smily77/Lidar.git RPLidarDanach Arduino IDE neu starten.
Version 1.1.0 — Protokoll- und Robustheitsfixes (siehe Behobene Probleme).
- Korrektes Node- und Descriptor-Parsing, host-getesteter Parser
- Byte-Stream-Resynchronisierung in
readMeasurement() begin(Stream&)bindet nur (RTTI-frei),startScan()mit Auto-Recovery- Express-Scan ehrlich als nicht implementiert markiert
- Verifiziert auf RPLIDAR C1 an ESP32-S3
Version 1.0.0 — Erste Release (vor den oben genannten Fixes).