Since the launch of the first Roborock robot vacuum, many college students and budding engineers from around the world have reached out to Roborock asking for more information about its LDS system. Some people even purchased Roborock robot vacuums and disassembled them to gain access to the LDS system because the price of the robot is significantly less than many other LIDAR systems on the market.
However, the LDS unit was not designed for use on its own making it is difficult to use. It has a limited IO, and it requires you to make your own PWM signal for motor speed control. This is why Roborock is now developing a STEM friendly version available at a low price, or potentially for free, to students and for research purposes.
If you have a comment you would like to offer about this system or have feature suggestions, feel free to get in touch.
- 360-degree 2D laser scanner
- 150mm~6000mm detection distance
- 1.8kHz sampling rate
- 3-axis gyroscope
- 3-axis accelerometer
- A Type-C integrated signal and power supply
The Cullinan system is made up of two parts, an LDS range finder, and an IMU. The LDS system is able to scan and measure an environment in 360° to an accuracy of 6cm~15cm. It captures 360 samples each rotation, at a scanning frequency of 5Hz, corresponding to approximately a sample every 1°. As with other IMUs, the Cullinan IMU captures real-time motion data, such as acceleration and angular velocity. The IMU is able to interact with external applications through a USB port, providing an easy access point for customized implementations.
Parameter | Value | Unit |
---|---|---|
Distance Rang (D) | 0.15~6 | Meter (m) |
Angular Range (A) | 0~360 | Degree |
Angular Resolution (Ar) | 1 | Degree |
Sample Duration | 0.5 | Millisecond (ms) |
Sample Frequency | 1800 | Hz |
Scan Rate | 5 | Hz |
LDS measurement system sends distance data through serial port. The serial format is set to 115200 baud rate, 8 data bits, 1 stop bit, no parity bit, no flow control.
There are two kinds of data from LDS. One is property information, the other is distance information. The property information is sent only before rotation, and the interval is 500 ms. When LDS starts to rotate, it stops to send property information and starts to send distance sample.
Field Name | Size / byte | Description |
---|---|---|
LDS_INFO_START | 1 | synchronization character, fixed 0xAA. If the property packet contains synchronization character (0xAA), it must be escaped before sending. 0xAA is replaced by 0xA901, and 0xA9 is replaced by 0xA900. Note: 1. MSB is sent first in escape sequence. 2. When sending, calculate the checksum first, then perform the escaping operation; When receiving, perform the escaping operation first, then calculate the checksum. |
PACKET_SIZE | 2 | paceket size in byte except for LDS_INFO_START, set to 84 |
SOFTWARE_VERSION | 2 | firmware version, bit[15:12] = major versio, bit[11:0] = minor version. Example: 0x1001 is interpreted as V1.1 |
UID_SIZE | 2 | UID size, set to 18 |
UID | 18 | UID value |
RSVD | 58 | Reserved |
CHECK_SUM | 2 | packet checksum, see The checksum algorithm for property packet |
uint16_t checksum = 0;
for(i = 0; i < size; i++){ // size is 41
checksum += *(lds_info_data + i); // lds_info_data is declared as uint16_t* pointer and points to property packet buffer.
}
Note: Measurement packet does not contain escape character.
Field Name | Size / byte | Description |
---|---|---|
Start | 1 | synchronization character, fixed 0xFA |
Index | 1 | sample index, from 0xA0 to 0xF9. There are 4 samples in a measurement packet, and 90 packets for one round. |
Speed | 2 | little endian, real speed value * 64, in rpm |
Data 0 | 4 | sample data 0, see Sample data format |
Data 1 | 4 | sample data 1, see Sample data format |
Data 2 | 4 | sample data 2, see Sample data format |
Data 3 | 4 | sample data 3, see Sample data format |
Checksum | 2 | packe checksum, see The checksum algorithm for measurement packet |
Offset | Description |
---|---|
0 | distance[7:0] |
1 | bit7 = data invalid flag, bit6 = strength warning flag, bit[5:0] = distance[13:8] |
2 | strength[7:0] |
3 | strength[15:8] |
uint32_t i, checksum = 0;
for (i = 0; i < 20; i += 2)
{
checksum = (checksum << 1) + *(uint16_t *)&lds_buf[i];
}
checksum = (checksum + (checksum >> 15)) & 0x7FFF;
IMU is based on Bosch BMI160 6-axis MEMS sensor which integrates 16-bit 3-axis accelerometer with ultra-low-power 3-axis gyroscope. The BMI160 is available in a compact 14-pin 2.5 × 3.0 × 0.83 mm3 LGA package. When accelerometer and gyroscope are in full operation mode, power consumption is typically 925 μA, enabling always-on applications in battery driven devices.
Prototype:int32_t BMI160_ReadReg(uint8_t RegAddr, uint8_t *RegData)
Description: Read a register
Parameter:RegAddr
- register address
RegData
- register data pointer
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
Prototype:int32_t BMI160_ReadRegSeq(uint8_t RegAddr, uint8_t *RegData, uint8_t len)
Description: Read multiple registers
Parameter:RegAddr
- register start addrss
RegData
- register data pointer
len
- the number of register to be read
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
Prototype:int32_t BMI160_WriteReg(uint8_t RegAddr, uint8_t RegData)
Description: Write a register
Parameter:RegAddr
- register address
RegData
- register data
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
Prototype:int32_t BMI160_WriteRegSeq(uint8_t RegAddr, uint8_t *RegData, uint8_t len)
Description: Write multiple registers
Parameter:RegAddr
- register start addrss
RegData
- register data pointer
len
- the number of register to be written
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
Prototype:int32_t BMI160_SetAccelNormal(void)
Description: Set accelerometer sensor in normal power mode
Parameter: None
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
Prototype:int32_t BMI160_SetGyroNormal(void)
Description: Set gyroscope sensor in normal power mode
Parameter: None
Return:STATE_OK
- state OK
STATE_PENDING
- state pending
/* Select the Output data rate, range of accelerometer sensor */
BMI160_REG.ACC_CONF.acc_odr = BMI160_ACCEL_ODR_100HZ;
BMI160_REG.ACC_CONF.acc_bwp = BMI160_ACCEL_BW_NORMAL_AVG4;
BMI160_REG.ACC_CONF.acc_us = 0;
BMI160_REG.ACC_RANGE.acc_range = BMI160_ACCEL_RANGE_2G;
while (BMI160_WriteRegSeq(REG(ACC_CONF), (uint8_t *)&BMI160_REG.ACC_CONF, 2) == STATE_PENDING) ;
while (BMI160_SetAccelNormal() == STATE_PENDING) ; // set normal power mode
/* Select the Output data rate, range of Gyroscope sensor */
BMI160_REG.GYR_CONF.gyr_odr = BMI160_GYRO_ODR_100HZ;
BMI160_REG.GYR_CONF.gyr_bwp = BMI160_GYRO_BW_NORMAL_MODE;
BMI160_REG.GYR_RANGE.gyr_range = BMI160_GYRO_RANGE_2000_DPS;
while (BMI160_WriteRegSeq(REG(GYR_CONF), (uint8_t *)&BMI160_REG.GYR_CONF, 2) == STATE_PENDING) ;
while (BMI160_SetGyroNormal() == STATE_PENDING) ; // set normal power mode
Inertial measurement unit sends raw data to external application through an USB VCP. The serial format is not important.
Offset | Name | Size / byte | Description |
---|---|---|---|
0 | GYR_X[7:0] | 1 | Low byte of gyroscope x-axis data |
1 | GYR_X[15:8] | 1 | High byte of gyroscope x-axis data |
2 | GYR_Y[7:0] | 1 | Low byte of gyroscope y-axis data |
3 | GYR_Y[15:8] | 1 | High byte of gyroscope y-axis data |
4 | GYR_Z[7:0] | 1 | Low byte of gyroscope z-axis data |
5 | GYR_Z[15:8] | 1 | High byte of gyroscope z-axis data |
6 | ACC_X[7:0] | 1 | Low byte of accelerometer x-axis data |
7 | ACC_X[15:8] | 1 | High byte of accelerometer x-axis data |
8 | ACC_Y[7:0] | 1 | Low byte of accelerometer y-axis data |
9 | ACC_Y[15:8] | 1 | High byte of accelerometer y-axis data |
10 | ACC_Z[7:0] | 1 | Low byte of accelerometer z-axis data |
11 | ACC_Z[15:8] | 1 | High byte of accelerometer z-axis data |
12 | SENSORTIME[7:0] | 1 | Low byte of sensor time stamp |
13 | SENSORTIME[15:8] | 1 | Median byte of sensor time stamp |
14 | SENSORTIME[23:16] | 1 | High byte of sensor time stamp |
The user can enter some debug commands through serial terminal. The serial format is set to 115200 baud rate, 8 data bits, 1 stop bit, no parity bit, no flow control.
Format:
rd160 reg_addr
Description: Read a register from addressreg_addr
and print the value.
Example:
rd160 40
40=28
Format:
wr160 reg_addr reg_data
Description: Write register value reg_data
to register addressreg_addr
and read back.
Example:
wr160 40 29
read back 40=29
Format:
dump160
Description: Dump all 128 registers
Example:
dump160
0 1 2 3 4 5 6 7 8 9 A B C D E F
[00]:D1 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[10]:00 00 00 00 00 00 00 00 6F 77 2C 10 00 00 00 00
[20]:00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[30]:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[40]:29 03 28 00 0B 88 80 10 00 00 00 20 80 42 4C 00
[50]:00 00 00 00 00 00 00 00 00 00 07 30 81 0B C0 00
[60]:14 14 24 04 0A 18 48 08 11 00 00 00 00 00 00 00
[70]:00 00 00 00 51 96 09 00 00 00 15 03 00 00 00 00
Format:
set160
Description: Configure sensor as follow table
Parameter | Value |
---|---|
active high level for INT1 pin | 1 (active high level for INT1 pin) |
I/O output mode for INT1 pin | 0 (push-pull) |
Output enable for INT1 pin | 1 (output enabled) |
Data ready interrupt mapped to pin INT1 | 1 (enabled) |
accelerometer ODR | BMI160_ACCEL_ODR_100HZ |
accelerometer bandwidth | BMI160_ACCEL_BW_NORMAL_AVG4 |
accelerometer undersampling | 0 (disabled) |
accelerometer g-range | BMI160_ACCEL_RANGE_2G |
accelerometer power mode | BMI160_ACCEL_NORMAL_MODE |
gyroscope ODR | BMI160_GYRO_ODR_100HZ |
gyroscope bandwidth | BMI160_GYRO_BW_NORMAL_MODE |
gyroscope angular rate range | BMI160_GYRO_RANGE_2000_DPS |
gyroscope power mode | BMI160_GYRO_NORMAL_MODE |
Example:
set160
Format:
data160
Description: Poll bitdrdy_acc
in registerSTATUS
in endless, if set read 3-axis data from accelerometer, 3-axis data from gyroscope and time stamp, and print all data in a line.
Example:
data160
ACC.x= -0.056152 ACC.y= 0.035828 ACC.z= 1.008545 GYR.x= -0.121951 GYR.y= -0.426829 GYR.z= -0.182927 @ 7277825
ACC.x= -0.055176 ACC.y= 0.036072 ACC.z= 1.007935 GYR.x= -0.182927 GYR.y= -0.426829 GYR.z= -0.182927 @ 7278081
ACC.x= -0.056335 ACC.y= 0.032349 ACC.z= 1.007690 GYR.x= -0.121951 GYR.y= -0.426829 GYR.z= -0.182927 @ 7278337
......
Format:
temp160
Description: Read temperature data in endless loop and print in degree Celsius (°C).
Example:
temp160
T= 33.335938
T= 33.314453
T= 33.373047
......