Als ich in AliExpress herumwanderte, verkaufte LiDAR für satte 19 US-Dollar (einschließlich Versand). https://ja.aliexpress.com/item/4000632680397.html Diesmal habe ich mir den billigen LiDAR gekauft. Es scheint, dass Kommunikationsspezifikationen und Bibliotheken nicht offiziell veröffentlicht werden.
Die Hersteller etc. sind nicht auf der AliExpress Seite geschrieben, Es gab einen Aufkleber "Camsense X1" im Bild, also scheint dies das Modell des Sensors zu sein. Wenn Sie nach Camsense X1 suchen, sieht es aus wie ein Produkt, das 2017 von der Marke Camsense auf den Markt gebracht wurde. http://en.camsense.cn/index.php?c=article&id=116
Die Camsense-Seite enthält die folgenden einfachen Spezifikationen.
Spezifikationselemente | Spezifikationswert |
---|---|
Entfernungsmessbereich | 0.08 ~ 8m |
Wiederholen Sie die Genauigkeit | 0.5%Weniger als |
Absolute Genauigkeit | 2%Weniger als |
Messfrequenz | Über 2080Hz |
Die Messfrequenz ist nicht die Rotationsfrequenz, sondern die Anzahl der Schritte, mit denen Entfernungsdaten pro Sekunde ausgeführt werden können. Andere Spezifikationen, die ich nach der Verwendung gefunden habe, sind wie folgt.
Spezifikationselemente | Spezifikationswert |
---|---|
Stromspannung | 5V |
Derzeitiger Verbrauch | 0.4A oder weniger |
Winkelauflösung | 0.Über 75 Grad |
Rotationszyklus | 0.Ca. 2 Sekunden |
Kommunikation | UARTKommunikation(115200bps) |
UART-Ebene | 3.3V |
Die Winkelauflösung ist nicht konstant. Wenn Sie sie mit der Hand berühren, um die Motordrehung zu verlangsamen, wird die Winkelauflösung bis zu 0,5 Grad. Der Datenerfassungszyklus ist nicht mit der Drehung synchronisiert, und es scheint, dass die Zeit fest ist.
Es gibt drei Leitungen für die Verbindung nach außen: VCC, GND und TX. Ich hatte keinen Stecker und versuchte mein Bestes, um ihn anzuschließen.
Wenn Sie mit einem PC kommunizieren möchten, benötigen Sie einen USB-UART-Konverter, da die UART-Kommunikation nicht direkt möglich ist. Ich habe so etwas benutzt. (Ich habe es vor langer Zeit gekauft und vergessen, wo ich es gekauft habe)
Raspberry Pi hat einen 3,3-V-UART, daher sollten Sie ihn so verwenden können, wie er ist.
So wird der Camsense X1 mit Ihrem PC verbunden.
Camsense X1 Seite | PC-Seite |
---|---|
VCC | 5.0V |
GND | GND |
TX | RX |
Wenn unter Windows Daten kontinuierlich von der seriellen Schnittstelle stammen, werden sie als serielle Maus erkannt, und der Mauszeiger bewegt sich hier und da, und Vorgänge, die nicht ausgeführt werden sollten, können ausgeführt werden. Daher ist es im Fall von Windows besser, die Funktion zu deaktivieren, die es als serielle Maus erkennt. Eine serielle Maus ist eine sehr alte Maus, die vor USB und PS / 2 verwendet wurde. Dies bedeutet nicht, dass die aktuelle Maus nicht verwendet werden kann. Mit einem Registrierungseditor ist das ganz einfach HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\sermouse Ich denke, der Wert der Starttaste von ist 3, also habe ich ihn einfach auf 4 gesetzt. https://stackoverflow.com/questions/9226082/device-misdetected-as-serial-mouse
Die Person, die das Kommunikationsprotokoll analysiert hat, hat es auf Github erklärt, daher habe ich es als Referenz verwendet. https://github.com/Vidicon/camsense-X1
Es handelt sich um ein 36-Byte-Paket, das die folgenden Entfernungs- und Stärkedaten in jeweils 8 Schritten enthält. Es wird endlos ausgegeben.
Artikel | Anzahl der Bytes | Bemerkungen |
---|---|---|
Header | 4 | 0x55, 0xAA, 0x03,0x08 behoben |
Drehzahl | 2(Kleiner Inder) | value / 64 = rpm |
Startwinkel | 2(Kleiner Inder) | (value - 40960) / 64 = degree |
Entfernung 0 | 2(Kleiner Inder) | mm |
Stärke 0 | 1 | Das Gerät ist unbekannt |
Entfernung 1 | 2(Kleiner Inder) | mm |
Stärke 1 | 1 | Das Gerät ist unbekannt |
... | ... | ... |
Entfernung 7 | 2(Kleiner Inder) | mm |
Stärke 7 | 1 | Das Gerät ist unbekannt |
Endwinkel | 2(Kleiner Inder) | (value - 40960) / 64 = degree |
CRC? | 2 | ? |
Die letzten 2 Bytes scheinen CRC zu sein, aber ich habe versucht, mit einigen generierten Polynomen zu berechnen, und den Header aus dem Berechnungsbereich entfernt, aber ich konnte keine Übereinstimmung finden.
Ich habe den Code geschrieben, um die Daten von Camsense X1 abzurufen und mit Python zu zeichnen. Ich habe es auch auf Github gelegt. https://github.com/j-fujimoto/CamsenseX1
Da sich die Winkelauflösung in Abhängigkeit von der Drehzahl ändert, wird die Anzahl der Daten für eine Runde nicht bestimmt, sondern die Anzahl der Daten für eine Runde der Winkelauflösung zum Zeitpunkt der Stabilität ist gesichert. Es erfordert Pyserial und Matplotlib, um zu arbeiten.
Betriebsüberprüfungsumgebung
Sanft | Ausführung |
---|---|
python | 3.8.2 |
pyserial | 3.4 |
matplotlib | 3.2.2 |
camsenseX1.py
import matplotlib.pyplot as plt
import math
import serial
import sys
import struct
import time
import threading
class Capture:
def __init__(self, serialPort, dataSize = 460, isInvert = True):
self.theta = [0] * dataSize
self.distance = [0] * dataSize
self.intensity = [0] * dataSize
self.writePos = 0
self.serial = serial.Serial(port = serialPort, baudrate = 115200)
self.dataSize = dataSize
self.thread = threading.Thread(target = self.getData)
self.lock = threading.Lock()
self.isInvert = isInvert
self.dataObtained = False
self.rpm = 0
def getDataUnit(self):
#Lesen Sie zuerst den Header herunter
header = b"\x55\xAA\x03\x08"
headerPos = 0
while True:
tmp = self.serial.read(1)
if tmp[0] == header[headerPos]:
headerPos += 1
if headerPos == len(header):
break
else:
headerPos = 0
tmp = self.serial.read(4)
# "<" :Kleiner Inder, "H" :2-Byte-Daten ohne Vorzeichen, "B" :1-Byte-Daten ohne Vorzeichen
(rotationSpeedTmp, startAngleTmp) = struct.unpack_from("<2H", tmp)
self.rpm = rotationSpeedTmp / 64
startAngle = (startAngleTmp - 0xa000) / 64
#Bereiten Sie ein Array zum Speichern von Entfernungs- und Stärkedaten vor
distanceTmp = [0] * 8
intensityTmp = [0] * 8
for i in range(8):
tmp = self.serial.read(3)
(distanceTmp[i], intensityTmp[i]) = struct.unpack_from("<HB", tmp)
tmp = self.serial.read(4)
(endAngleTmp, crc) = struct.unpack_from("<2H", tmp)
endAngle = (endAngleTmp - 0xa000) / 64
return (distanceTmp, intensityTmp, startAngle, endAngle)
def getData(self):
preStartAngle = 0
while True:
(distanceTmp, intensityTmp, startAngle, endAngle) = self.getDataUnit()
#Wenn es nahe 0 Grad liegt, kann die Größenbeziehung zwischen dem Startwinkel und dem Endwinkel umgekehrt werden. Fügen Sie daher dem Endwinkel 360 Grad hinzu, um die Größenbeziehung beizubehalten.
if endAngle < startAngle:
endAngle += 360
#Wenn der Startwinkel klein wird, ist dies eine Stelle von 0 Grad. Setzen Sie daher das Datenaktualisierungsflag
if (startAngle - preStartAngle < 0):
self.dataObtained = True
preStartAngle = startAngle
#Winkel in Bogenmaß umrechnen
startAngleRad = startAngle * math.pi / 180 * (-1 if self.isInvert else 1)
endAngleRad = endAngle * math.pi / 180 * (-1 if self.isInvert else 1)
#Berechnen Sie den Winkel pro Schritt
angleIncrement = (endAngleRad - startAngleRad) / len(distanceTmp)
#Exklusiver Kontrollstart
self.lock.acquire()
for i in range(len(distanceTmp)):
self.theta[self.writePos] = startAngleRad + angleIncrement * i
self.distance[self.writePos] = distanceTmp[i]
self.intensity[self.writePos] = intensityTmp[i]
self.writePos += 1
if self.writePos >= self.dataSize:
self.writePos = 0
#Exklusive Kontrolle Ende
self.lock.release()
def run(self):
self.thread.start()
def stop(self):
self.thread.stop()
if __name__ == "__main__":
if len(sys.argv) == 1:
print("You must specify serial port! ex) " + sys.argv[0] + " COM2")
quit()
#Generieren Sie ein Diagramm der Polarkoordinaten
dist = plt.subplot(111, polar = True)
#Stellen Sie den Anfangswert der maximal anzuzeigenden Entfernung auf 2000 ein
rmax = 2000
capture = Capture(sys.argv[1], dataSize = 480, isInvert = True)
capture.run()
preTime = time.time()
while True:
if capture.dataObtained:
#Zeichnung initialisieren
plt.cla()
#Exklusiver Kontrollstart
capture.lock.acquire()
#Entfernungsdaten zeichnen(Zeichnen Sie als Streudiagramm)
dist.scatter(list(capture.theta), list(capture.distance), c = "blue", s = 5)
#Intensitätsdaten zeichnen(Zeichnen Sie durch Verbinden mit Linien)
dist.plot(list(capture.theta), list(capture.intensity), c = "orange", linewidth = 1)
#Da die Daten gezeichnet wurden, senken Sie das Datenerfassungsflag.
capture.dataObtained = False
#Exklusiver Kontrollstart
capture.lock.release()
#Stellen Sie den oberen Bildschirmrand auf 0 Grad ein
dist.set_theta_offset(math.pi / 2)
#Stellen Sie den Maximalwert des anzuzeigenden Abstandswerts ein
dist.set_rmax(rmax)
#Zeichenprozess
plt.pause(0.01)
#Ruft den aktuell eingestellten maximalen Anzeigeabstand ab
rmax = dist.get_rmax()
else:
time.sleep(0.01)
Der Zustand des Zeichnens der Daten ist wie folgt. Entfernungsdaten werden mit blauen Punkten gezeichnet, und Intensitätsdaten werden mit orangefarbenen Linien angezeigt.
Knoten für ROS1: https://github.com/Vidicon/camsense_driver Erstellt von Vidicon (Bram Fenijn) Knoten für ROS2: https://github.com/rossihwang/ros2_camsense_x1 Hergestellt von rossihwang Programm für STM32: https://github.com/anhui1995/Camsense_X1
Es ist erstaunlich, dass LiDAR mit dieser Leistung für 19 US-Dollar erworben werden kann. Mit LiDAR, das über Ethernet verbunden ist, ist die Verarbeitung mit einem kostengünstigen Mikrocomputer jedoch recht schwierig Da es sich bei Camsense X1 um einen UART handelt, kann er auch mit einem kostengünstigen Mikrocomputer problemlos verarbeitet werden. Der Rotationszyklus ist ziemlich langsam und die Entfernung, die erreicht werden kann, ist kurz. Ich denke, es ist schwierig, sie für Roboter zu verwenden, die sich schnell bewegen, aber Ich denke, es ist gut genug für Hobby
Recommended Posts