Reading the XV11 Neato Botvac LIDAR with the Raspberry Pi and C++

39575581_10213365014982719_2509514958299987968_n
Behold! The pillaged XV11 Neato Botvac’s LIDAR range finding unit!

I really, really couldn’t contain my excitement (ask my wife) when I learned that Ebay prices on these bad boys have come down to under $100.  Without hesitating a moment, I ordered and quickly received an affordable option that makes it possible for a robot to draw its own maps of its environment with centimeter-precision!  Two days later – with my new toy in hand – I threw together a mount and set out to learn how to use it and write some C++ code that I could drop into the autonomous robot project.  I thought I’d fill in some minor gaps in the web-knowledge base out there about these little units, and share some hiccups and successes I had reading the data with a serial bitbang read, and then getting the data into a useful format for my Autonomous Robot Project.  Have to give much thanks and credit to the fine folks at the raspberrypi.org forums – They are always a great help when my hair-pulling debugging attempts become unbearable and seemingly hopeless. Extra thanks to Joan for her PIGPIO library – making serial (and especially bitbanging) a mostly simple matter.

 

The first thing I’d recommend is to use your physical GPIO UART if you can – data seems to come in much less corrupted than with a serial bitbang off a regular GPIO pin. My UART is tied up for communicating with another Raspberry Pi, so bitbang it is for me. I could have used a USB FTDI serial device, but I’ve already got one talking to the Roomba. That wouldn’t really stop me from using another, but I thought I’d try out this bitbang thing. If you don’t know, “bitbanging” is a method of reading a GPIO pin fast enough and timed well enough that you create a virtual UART com port with software. It works, but like I said – I was having an easier time getting packets to check out as accurate by way of checksum with the physical UART.  BTW if you ARE going to use the physical GPIO UART, there has been some changes in the Raspberry Pi’s hardware and software and, thus, no shortage of tutorials that are outdated and don’t work. Here are two pro-tips I picked up if you are using a Raspberry Pi and need to use the official GPIO serial pins for communications for another part of the project:

1. Don’t waste time with your old notes trying to reconfigure by hand, someone wrote a sweet script that does it for you – giving you some options to choose from. For me it just ended up confirming that I was all set and my problem was elsewhere – great for troubleshooting. Just copy the text of the file from this git page into an empty text file (from command line try sudo leafpad whatevernameyouwant.sh), then make sure you’re in the directory with that file. Then sudo chmod 755 whatevernameyouwant.sh to make it executable. Then run it with ./whatevernameyouwant.sh Script is(as for the options, you do need to choose to disable the serial console for this sort of thing) Here: https://github.com/lurch/rpi-serial-console
Tip 2. Pay attention to the little details! They’ve made some software changes since the last time I used serial uart communications, and the I used to open /dev/ttyAMA0. Then they changed it to /dev/ttyS0. Since then, they’ve added a feature that will point to the correct place called /dev/serial0. The entire day I wasted trying to get data in and out was because I mindlessly assumed I needed to use /dev/ttyserial0. That’s what I get for skimming instructions on almost everything…

 

For figuring everything else out, https://xv11hacking.wikispaces.com/LIDAR+Sensor was a tremendous help. A few things it didn’t make clear:

  1. The page lists a list of commands you can send the LIDAR unit, but you don’t NEED to send it anything – the unit automatically starts sending data when powered up and the turret gets into an acceptable RPM range.
  2. Everyone talks about reading turret speed and making a closed-loop speed control thing with PWM and blah blah blah – I don’t see much benefit for this effort. It functions in a big enough RPM range that I think we can get away with setting it up with a fixed voltage somewhere in the middle of its acceptable range. I think I have the supply to the motor at 3.2 volts and it sits around 240 RPM.  For all the bugs I’ve had to work out, this has been a non-issue – I’ll check the RPMs if it ever stops sending data.
  3. Probably because of my American-bred cranial thickness (we won’t give up our English measurements, after all), but I presumed I was looking for the data packets index to come out counter-clockwise like a compass – where 90 degrees is to the right of 0 degrees. I thought I was getting bad data and it gave me a good afternoon of headache before I realized that I had my turret spinning counter-clockwise because that’s how Neato does it. I suspect (but haven’t confirmed because I’m not curious enough to switch the wires and run more tests) that if you run the turret clockwise your packets will come out clockwise. Of course, I don’t know what they are doing with firmware under the hood…
  4. The wiki page says “index is the index byte in the 90 packets, going from 0xA0 (packet 0, readings 0 to 3) to 0xF9 (packet 89, readings 356 to 359)” but mine were coming out 160-259. I just subtract 160 in my code.
  5. The page suggests that the outputs may be offset 10 degrees from the natural axis of the device – I do not find this to be the case with my unit and line up zero as straight ahead.

 

HARDWARE SETUP:

I really don’t recommend powering this with your PI power bus – it draws way more current than the Pi is designed to handle. Also I need two different voltages, so I took power from a spare 5 volt supply point I already had on the robot and ran that through a cheap Sainsmart-type relay (These are awesome, they come with opto-isolators and driver transistors built in and they’re cheeeeeap). I use a GPIO pin on the pi to turn the relay on and off – powering up the LIDAR only when I need it. The output of the relay goes to two places: 1 – to the LIDAR units little brain, and 2 – the adjustable power supply I had in my box o’ goodies. This is what I use to drive the motor. I put it all on a little board and it’s pretty ugly, but I thought I’d be needing to perhaps add a PWM speed controller and maybe an FTDI so I could command the thing, but none of it was necessary and my ugly test board just works -so I’ll keep it for now.

20180827_194229
There is enough friction between wood plates that it holds firmly but can easily be rotated for easy aligning. There is also just enough clearance that the turret spins freely. 

Everyone else that talks about this thing also seems to think you need to 3d print or order a mount…maybe they are selling them? I found it super easy to use two standoffs to make an extra tall standoff (per each of 4 screw holes – Make the all the same height and the thing ends up perfectly level). Then I used a hole saw to make a round piece of 1/2 plywood, used a 1/4 in bolt and nut to fasten it to the robot base and snugged it up enough that it stays put but can rotate it to proper alignment. Find just the right diameter drill bit (5/32?) and you can screw an m2 or m3 standoff right into plywood – pretty darn secure.

So with 5 volts to the brain (Check yours – some are 3.3 volt units. Details in the wiki) and 3.2 volts to the motor, I just needed to run a single wire from the LIDAR’s tx to the Pi’s GPIO pin. (Technically, you do need to connect the grounds too, but mine already are) I use pin 17 to start the lidar via that relay, and read the data with pin 18.

So from there is software and putting the data together. I use the PIGPIO C interface library in my code, which is written in C++. There is a readme in my GitLab project you can read for more info, but you can compile the 3 files together and run the code as is for testing, or drop the two include files (lidar.cpp and lidar.h) into your own project and use the lidar class (don’t forget to compile with -lpigpio or pigpio.so in your IDE’s linker settings). There is more I want to do with the code, but it is working and adequate to get my project moving along.  You can see my code HERE: https://gitlab.com/lbrombach2/lidarClass.git

As most of my projects are still works in progress, please report any bugs you notice or suggestions and feel free to ask questions. I am in school (again, at 42) but so far 90% self-taught at programming, so if I don’t follow conventions that probably explains it. Constructive criticism always welcome – let me know what you think.

39453522_10213365015262726_7144183823469641728_n
The first tests of the XV11 LIDAR with a RaspberryPi 3 on my Hacked Roomba Robot with Raspberry Pi and C++. This was when I naively thought it would spit out data in plain English – turns out you have to combine two bytes to get a distance measurement.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s