LEDDAR testing results

I’ve got the LEDDAR One prototype working well using the minimalmodbus python library and fantastic customer support from LEDDAR themselves.

I’ve had to put in a nasty hack to kill off the Raspberry Pi console tied to the UART pins; for some reason I couldn’t stop it across reboot.

The pin layout is nice and tidy: RPi pins 4,6,8,10,12 (5v, GND, TX, RX, GPIO 18) connect to Leddar Pins 3,1,4,5,2 respectively – that’s a convenient 5 consecutive pins on RPi side to attach a standard connector.  Unfortunately I do need to run another batch of PCBs as there’s no access to these pins on my current PCB.

Once the PCBs are done, I’ll be adding the LEDDAR to Phoebe; her motion processing happens at ≈100Hz; the default for LEDDAR is 8.8Hz (it can be increased if necessary).  Each LEDDAR distance measurement also comes with an accurate timestamp.  This means I can differentiate the LEDDAR readings to produce a Z-axis velocity which can then be fused with the integrated accelerometer readings to provide long term vertical stability.  A simple complementary filter (like the one I already have for angles) will do the job nicely.

The LEDDAR also provides a data ready interrupt which I’ve connected to GPIO 18.  This means I don’t have to poll the serial port every motion loop; instead I can use the GPIO edge detection code (like the one used for FIFO overflow on the IMU) to let the motion code know when there’s new data on the serial port.

Together, this means adding the new function to the HoG code is trivial – I’ve done all the tricky bits before in different contexts.  The only gating factor is the new PCB requirement, and (as always) my overdraft limit!

My one warning if you are in the UK and interested in using LEDDAR: its price is very reasonable given the technology and its support is excellent; sadly the UK import duties and UPS fees added another 40% to the costs!  Ouch!  My advice is to get a friend in Canada to buy it, and send it to you by normal international post!

Here’s the code in case you’re interested:

#!/usr/bin/env python

from __future__ import division
import serial
import minimalmodbus
import os
import time
import RPi.GPIO as GPIO

def main():
    minimalmodbus.BAUDRATE=115200
    mmb = minimalmodbus.Instrument("/dev/ttyAMA0", 1, 'rtu')
    mmb.BAUDRATE=115200

    temp = mmb.read_register(22, 0, 4, True)
    print "temp: %f" % (temp / 256)

    time.sleep(0.1) # ARBITRARY SLEEP REQUIRED WHY?

    num_detections = mmb.read_register(23, 0, 4)
    print "num_detections: %d" % num_detections

    time_lss = mmb.read_register(20, 0, 4)
    time_mss = mmb.read_register(21, 0, 4)
    start_time = (time_mss << 16) + time_lss
 
    #----------------------------------------------------------------------------------
    # Create GPIO 18 as input, pull down
    #----------------------------------------------------------------------------------
    GPIO_INT = 18
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(GPIO_INT, GPIO.IN, GPIO.PUD_UP)

    #----------------------------------------------------------------------------------
    # Clear the already existing interrupt by reading data from the modbus link
    #----------------------------------------------------------------------------------
    dist_leddar = mmb.read_register(24, 0, 4)

    for ii in range(10):

        #------------------------------------------------------------------------------
        # Add GPIO pin 18 rising edge interrupt and then get new data
        #------------------------------------------------------------------------------
        GPIO.wait_for_edge(GPIO_INT, GPIO.RISING)

        time_lss = mmb.read_register(20, 0, 4)
        time_mss = mmb.read_register(21, 0, 4)
        current_time = (time_mss << 16) + time_lss

        dist_leddar = mmb.read_register(24, 0, 4)

        print "Proximity @ %f: LEDDAR %f;" % ((current_time - start_time) / 1000, dist_leddar / 1000)

if __name__ == "__main__":
    os.system("systemctl stop serial-getty@ttyAMA0.service")
    main()

P.S. As expected above, I’ve pretty much coded the LEDDAR into Phoebe’s HoG in about half an hour. There is also a way to bodge the current PCB to get the LEDDAR wires connected to the 5V, TX, RX, GND and interrupt pins, so I could be installing the LEDDAR soon and start testing. I’ll let you know when the job’s done.

P.P.S. If you want to buy a LEDDAR One, it’s in stock at robotshop.

9 thoughts on “LEDDAR testing results

  1. Hello, I am a newbie in coding, RaspberryPi and Modbus. I want to know how do you know the register address eg 22, 23, 24. Is there some information I do not know?
    Thank you so much. Have a nice day/

  2. Hello,
    Can you please give a sample code for only mesuring level with leddarone via raspberry pi3. We want to use it for measuring level of a tank. If you can supply any help, we’d be very thankful.

  3. It looks like you have new cool toy to play with. I’m looking forward to seeing how your LEDDAR experiments will turn out.

    BTW, did you see that they released an update to Jessie that includes pigpio libraries and python bindings by default. I’ve been using pigpio in my project and I’m pretty happy with it. It uses DMA for GPIO operations, which is very useful for driving motors directly from Pi pins.

    I also have a question about your code. I’ve been working on getting my PIDs calculated correctly and took a look at your code to compare notes. I’ve noticed that you are adding lastError to your integral part of PID and I was wondering why. It doesn’t seem to be what the standard PID calculations call for. The line of code I’m talking about is this:

    self.i_error += (error + self.last_error) * dt

    Is this by design? Why do you want to add last error here? I would think it would contribute to Integral component wind-up issues…

    Thank you.

    • The use of self.i_error… could well be a bug – I’m not a genius, just persistent. It might explain the integral wobbles I’m seeing. I’ve looked at pigpio, but RPIO also uses DMA but without the daemon so it’s faster (I think, but again, not a genius opinion). I’ll take a look at the PID integral code tomorrow when I’ve not had too many beers 😉

      • I fixed a number of very nasty mistakes in my (very simple) code over the last 10 days. I guess it’s a part of the process. Sometimes it takes another pair of eyes to find the bugs. I hope what I spotted will help you with wobbles. I am far from wobbles. I can’t even get off the ground yet. 🙂

        You are correct about RPIO. It does use DMA, but I couldn’t get it to run on RPi2, so I switched to pigpio.

        In any case, enjoy your beers and good luck with your project.

        • About RPIO, have a look at mine on GitHub github.com/PiStuffing/Quadcopter – RPIO code hasn’t been updated to recognise new product IDs from the B2, B3 and Zero. Have a look at source/c_gpio/cpuinfo.c – I reworked this code so it’s more like the RPi.GPIO version checking, and added the B+ and Zero in there.

          The PID integral isn’t a problem (I don’t think): instead of integrating just the error, I thought averaging (error + previous_error)/2 might be more accurate – I then threw away the /2 and instead halved all my I gains. I wish it was a bug, but actually, I think it’s fine.

          Hope your quad takes off soon!

          • Thank you. I will take a look at your RPIO changes. Maybe I can use it instead.

            As for the PID code, I’m glad it’s not a bug and works as expected. I hope you will find the real source of wobbles soon. Thank you for taking the time to explain the logic behind your decisions.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.