CygLiDAR-ROS / cyglidar_d1

CygLiDAR D1 - ROS(SDK) Package (ROS1 / ROS2)
https://www.cygbot.com/
BSD 3-Clause "New" or "Revised" License
21 stars 25 forks source link

Connecting Cyglidar to RPI doesn't work #31

Open MallakAbunimeh opened 1 year ago

MallakAbunimeh commented 1 year ago

Hello. I followed the steps of the article you provided in cygbot downloads website about how to connect CygLiDAR D1 directly to Raspberry Pi via UART without USB Converter but it didn't work for me. There were 3 codes provided to use and when I tried to run code 2 on RPI it's showing that it's sending the [90, 119, 255, 2, 0, 8, 0, 10] data bytes but it is not receiving any complete data. So, I tried to run code2 on ubuntu instead to check it using USB connection and I got the same issue. I checked the baud rate of the cyglidar, type of USB port am connecting to and installed the needed libraries but still am not being able to connect the lidar on RPI nor Ubuntu.

This is the output that I got on Ubuntu after running code2:

image

I added a print statement after the while loop to trace the code, and it showed after executing the code, but the code halted after this print statement, and it didn't get any complete data.

When I run the code on RPI, I got the same output as well.

cygbot commented 1 year ago

There were 3 codes provided to use and when I tried to run code 2 on RPI it's showing that it's sending the [90, 119, 255, 2, 0, 8, 0, 10] data bytes but it is not receiving any complete data.

In Code2, baudrate originally set to 250,000. We guess you executed the code using cyglidar d1 with 3,000,000 baudrates. So the code in the while loop. Please one more check your cyglidar d1's baudrate and try to change the speed.

image

3,000,000 baudrate speed will not work proper data in Python. So, after set up with 250,000 baudrate, try the other code again.(revise the code as well)

MallakAbunimeh commented 1 year ago

I changed the baudrate of the cyglidar d1 to 115200 and ran the code again, but it still didn't work, and I received the following error:

image

I also tried changing the baudrate to 250000 then got this error:

image

I tried running this code, but it's still not working, and I'm not sure what should be done in it to solve the issue that I'm getting.


import serial import cv2
import numpy as np

RUN_3D  = [0x5A, 0x77, 0xFF, 0x02, 0x00, 0x08, 0x00, 0x0A] 
COMMAND_STOP = [0x5A, 0x77, 0xFF, 0x02, 0x00, 0x02, 0x00, 0x00]

HEADER1, HEADER2, HEADER3, LENGTH_LSB, LENGTH_MSB, PAYLOAD_HEADER, PAYLOAD_DATA, 
CHECKSUM = 0, 1, 2, 3, 4, 5, 6, 7
NORMAL_MODE = 0x5A 
PRODUCT_CODE = 0x77 
DEFAULT_ID = 0xFF

normalizeDistanceLimit = 4080
dataLength3D = 14400

def ReceivedCompleteData(receivedData): 
    global dataLength3D
    print(f'receive complete data : {len(receivedData)}') 
    if len(receivedData) == dataLength3D:
        Visualize(receivedData)

def Visualize(receivedData):
distanceData = Get3DDistanceDataFromReceivedData(receivedData) 
image = DistanceDataToNormalizedNumpyArray(distanceData)
image = np.array(image, dtype=np.uint8) 
image = image.reshape(60, 160)
image = cv2.resize(image, dsize=(480, 180), interpolation=cv2.INTER_NEAREST) 
cv2.imshow('test', image)
cv2.waitKey(1)

def Get3DDistanceDataFromReceivedData(receivedData): 
    global dataLength3D,normalizeDistanceLimit
    index = 0
    distanceData = [0 for i in range(int(dataLength3D / 3 * 2))] 
    for i in range(0, dataLength3D-2, 3):
        pixelFirst = receivedData[i] << 4 | receivedData[i+1] >> 4 
        pixelSecond = (receivedData[i+1] & 0xf) << 8 | receivedData[i+2]

        if pixelFirst > normalizeDistanceLimit: 
            pixelFirst = normalizeDistanceLimit
        if pixelSecond > normalizeDistanceLimit: 
            pixelSecond = normalizeDistanceLimit

        distanceData[index] = pixelFirst
        index += 1
        distanceData[index] = pixelSecond 
        index += 1
    return distanceData

def DistanceDataToNormalizedNumpyArray(distanceData): 
    global normalizeDistanceLimit
    result = np.array(distanceData)
    result = result / normalizeDistanceLimit * 255 
    return result

#baud = 57600
baud = 115200
#baud = 250000
#baud = 3000000 # recommend baudrate under 3,000,000 
ser = serial.Serial( # port open
                    port="/dev/ttyUSB0", # <- USB connection 
                    #'/dev/ttyAMA1',# <- GPIO connection
                    # "COM14", #<- Windows PC
                    baudrate=baud, 
                    parity=serial.PARITY_NONE, 
                    stopbits=serial.STOPBITS_ONE, 
                    bytesize=serial.EIGHTBITS
)
if  name == " main ": 
    ser.write(RUN_3D) 
    print("send : ", RUN_3D) 
    step = HEADER1
    CPC = 0

bufferCounter = 0
receivedData = [0 for i in range(dataLength3D)] 
while True:
    try:
        for byte in ser.readline(): parserPassed = False
        # Parse Start
        if step != CHECKSUM:
            CPC = CPC ^ byte
        if step == PAYLOAD_DATA: 
            receivedData[bufferCounter] = byte 
            bufferCounter += 1
            if bufferCounter >= dataLength : 
                step = CHECKSUM
        elif step == HEADER1 and byte == NORMAL_MODE: 
            step = HEADER2
        elif step == HEADER2 and byte == PRODUCT_CODE: 
            step = HEADER3
        elif step == HEADER3 and byte == DEFAULT_ID: 
            step = LENGTH_LSB
            CPC = 0
        elif step == LENGTH_LSB: 
            step = LENGTH_MSB 
            lengthLSB = byte
        elif step == LENGTH_MSB: 
            step = PAYLOAD_HEADER
            lengthMSB = byte
            dataLength = (lengthMSB << 8) | lengthLSB - 1 
        elif step == PAYLOAD_HEADER:
            step = PAYLOAD_DATA
            if dataLength == 0: step = CHECKSUM
            bufferCounter = 0
            receivedData = [0 for i in range(dataLength)] # clear 
        elif step == CHECKSUM:
            step = HEADER1 
            if CPC == byte:
                parserPassed = True
        else:
            step = HEADER1 parserPassed = False
            # Parse End
        if parserPassed: 
            ReceivedCompleteData(receivedData)
except KeyboardInterrupt: 
    ser.write(COMMAND_STOP) 
    ser.close()
MallakAbunimeh commented 1 year ago

I'm trying to run code 2 from the pdf in Visual Studio, and I used COM3 with baud rate 38400. It shows that it's entering the while loop, but it fails to display the OpenCV window with the 2D_image. Also, when I tried to print the data received from the cyglidar_d1, it displayed zeros.

This is the output that I got:

image image

@cygbot

cygbot commented 1 year ago

@MallakAbunimeh

Q1.

There were 3 codes provided to use and when I tried to run code 2 on RPI it's showing that it's sending the [90, 119, 255, 2, 0, 8, 0, 10] data bytes but it is not receiving any complete data.

A1 : 'baudrate' operates with value entered in the python code.

Some baud rates used by Cyglidar D1 may be the "baud rates not supported" by the serial driver of the linux system being used as non-standard baud rates. If you try to change the baudrates to the serial driver with the stty speed command, you will get an error.

if you specify is not one of the standard ones on pyserial, it calls _set_special_baudrate.

If the platform(like Ubuntu) has not implemented it, the base class throws NotImplementedError('non-standard baudrates are not supported on this platform').

So if you're not seeing that error, then the platform (attempts to) supports it.

The below is the contents of the Pyserial documents.

The parameter baudrate can be one of the standard values: 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200. These are well supported on all platforms.

Standard values above 115200, such as: ##230400##, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000 also work on many platforms and devices.

Non-standard values are also supported on some platforms (GNU/Linux, MAC OSX >= Tiger, Windows). Though, even on these platforms some serial ports may reject non-standard values.

Custom baudrates are set the same way as standard baudrates, with the baudrate option. Pyserial will open the port, and set baudrate to the given value, and then Pyserial will read the baudrate back from the serial, to get the actual obtained setting.

So if it does not match, then it is likely that the port does not support non-standard baud rates.


Q2.

I changed the baudrate of the cyglidar d1 to 115200 and ran the code again, but it still didn't work, and I received the following

A2 : ser = serial.Serial() -> If you encounter an error when opening the port, make sure that the port is correctly set to the port of cyglidar D1.

When connecting from Raspberry Pi to GPIO, the port is "/dev/ttyAMA1".

Please connect to "/dev/ttyUSB0" when connecting to the usb converter we provided with Cyglidar D1.(Number is variable)

If there is an error in the serial port open when connecting to "/dev/ttyUSB0", it is highly likely that you tried to connect to a USB device other than the Cyglidar D1, so please check it. (Mostly Mouse, Keyboard, etc.)

Q3.

I'm trying to run code 2 from the pdf in Visual Studio, and I used COM3 with baud rate 38400. It shows that it's entering the while loop, but it fails to display the OpenCV window with the 2D_image. Also, when I tried to print the data received from the cyglidar_d1, it displayed zeros.

A3 : If OpenCV fails to display in Window, it is likely that OpenCV installation has not been done properly on your PC. Please check the installation of OpenCV, and recommend to try on Raspberry Pi, cause the example code is based on Raspberry Pi with OpenCV installed.