Shop OBEX P1 Docs P2 Docs Learn Events
C code review for SF02 Laser Rangefinder to Propeller — Parallax Forums

C code review for SF02 Laser Rangefinder to Propeller

Ken GraceyKen Gracey Posts: 7,386
edited 2014-05-12 19:15 in Propeller 1
Hello,

If anybody ever felt afraid to post, I'm here to pave the way for you. From time to time I show off my own programming "skills" on behalf to the many people I encounter who might be afraid to post on our forums. I've only learned to program a little bit of C thanks to Andy's tutorials and a couple of recommended books, but I never make enough time to evolve the skill. I do have the interest, however.

I decided to work from home today and experiment with the SF02 Laser Rangefinder (http://www.lightware.co.za/shop/en/lrf-modules/7-sf02f.html), a 0-40m sensor that seems to work flawlessly. Little seems to bother this sensor: smoke, wind, angle of reflection, or sunlight. Considering limitations of ultrasonic, infrared, beacons and everything else I've used, this is the cat's meow and I can imagine it being useful on UAVs and outdoor robots. I'm just a little concerned that Erco won't be buy one at $349, however. But for those willing, this sensor appears to be worth every dollar!

The Lightware Terminal software lets me configure the hardware's analog output, so I made 0.0 m = 0.0V and 40.0 m = 3.3V.

I need some review of my C code. I'm trying to produce a simple analog input example with the Propeller Activity Board's A/D converter. My code is below:

[FONT=courier new]/*
  SF02 Distance - Analog.c


  Display analog output voltage and distance from SF02 Laser Rangefinder 
  connected to Propeller Activity Board (PAB). SF02 configured using 
  Lightware software 0.0V = 0.00 m and 3.3V = 40.0 m. 


    SF02        PAB
    ====        ==== 
    2           GND
    3           5V
    4           GND
    7           A/D0           
*/


#include "simpletools.h"                      // Include simpletools
#include "adcDCpropab.h"                      // Include adcDCpropab


int main()                                    // main function
{
  adc_init(21, 20, 19, 18);                   // CS=21, SCL=20, DO=19, DI=18
  float v0, meters;                           // Voltage and distance variables


  while(1)                                    // Repeat
  {             
    v0 = adc_volts(0);                        // Check A/D 0
    meters = 12.12*v0;                        // 40.00m / 3.3V = 12.12V/m

    putChar(HOME);                            // Cursor -> top-left "home"
    print("Lightware SF02 to Propeller Activity Board \n");
    print("A/D0 = %f V%c\n", v0, CLREOL);     // Display volts
    print("Distance = %f m%c\n", meters, CLREOL);
    pause(100);                               // Wait 1/10 s
  }  
}[/FONT]

The datasheet states the resolution to be 1 cm, 12 readings/second with accuracy of +/-(0.1 +1%) m. In my code example I'm claiming a huge number of significant digits and I'd like the example to show the right calculation, which I think is to a hundredth of a meter. Is this correct, and what's the right way to show the math routine in C with only two sig digits?

By the way, I really love having access to the floating point library.

Thanks,

Ken Gracey

Lightware-Software.png


SF02-Display.png


SF02-Photo.jpg
884 x 510 - 54K
1024 x 768 - 93K
880 x 499 - 52K

Comments

  • PublisonPublison Posts: 12,366
    edited 2014-05-12 11:58
    Pretty neat Ken. I knew you where going to get one of these when we spoke a couple of weeks ago.

    Unfortunate, I do not speak C, (yet), but it looks like a great potential product, (hang it off the bottom of a Elev-8 for precise landings).
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 12:01
    Hey Jim, I couldn't resist.

    Ken Gracey
  • PublisonPublison Posts: 12,366
    edited 2014-05-12 12:11
    Maybe erco got a good tax refund?
  • SRLMSRLM Posts: 5,045
    edited 2014-05-12 13:22
    Here's how I would do that with fixed point:
    #include "simpletools.h"                      // Include simpletools
    #include "adcDCpropab.h"                      // Include adcDCpropab
    
    
    int main()                                    // main function
    {
      adc_init(21, 20, 19, 18);                   // CS=21, SCL=20, DO=19, DI=18
      int v0, meters;                             // Voltage and distance variables
      
      while(1)                                    // Repeat
      {             
        v0 = adc_in(0);                           // Check A/D 0, range 0-4096
        
        // Maximum distance is at 3.3v, so 3.3/5 * 4096 == 2703
        // 40m / 2703 = 0.014798m/lsb
        // We'll store the distance in 10,000th's, so
        // 400,000m / 2703 = 148 m/lsb
       
        meters = 148*v0;
        
        int metersDigits = meters/10000;
        int metersDecimal = meters%10000;
        
        putChar(HOME);                            // Cursor -> top-left "home"
        print("Lightware SF02 to Propeller Activity Board \n");
        print("A/D0 = %i V%c\n", v0, CLREOL);     // Display volts
        print("Distance = %i.%i m%c\n", metersDigits, metersDecimal, CLREOL);
        pause(100);                               // Wait 1/10 s
      }
    }
    
  • jazzedjazzed Posts: 11,803
    edited 2014-05-12 13:36
    Gee Ken,

    You never took a C programming class?
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 13:45
    SRLM wrote: »
    Here's how I would do that with fixed point:

    Thanks Cody! If I could paraphrase what your example does, would this be correct?

    - with a 0-5V A/D and 12-bit A/D, we get 2703 samples over 0-3.3V
    - you worked in all positive numbers, fixed point, multiplying by 10,000
    - whole digit and remainder were handled separately, so no floating point library required

    But, what if I wanted to use floating point and I want to display the output to only two significant digits? Is there a way to format the output in this line:

    print("Distance = %f m%c\n", meters, CLREOL);

    To include only two significant digits?

    Thanks,

    Ken Gracey
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 13:50
    jazzed wrote: »
    Gee Ken,

    You never took a C programming class?

    Oh, you're back with that question again. . .how do I reply to this inquiry? No, but I bought this little colorful book http://ineasysteps.com/products-page/all_books/c-programming-in-easy-steps-4th-edition-2/ and it seemed to be suitable for my goal of developing enough background to be barely functional. While nobody should discount the value of an actual course, I really need to learn this on my own with web resources around me. I can't make the time to go to and from a college to take such a class at this stage.

    Ken Gracey
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-05-12 13:54
    If you want 2 digits to the right of the decimal point you would use "%.2f".
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 14:02
    Dave Hein wrote: »
    If you want 2 digits to the right of the decimal point you would use "%.2f".

    Thanks Dave! Now I have two ways of doing the same thing, with and without floating point. This little example is very useful to me.

    Ken Gracey
  • jazzedjazzed Posts: 11,803
    edited 2014-05-12 14:20
    Ken Gracey wrote: »
    Oh, you're back with that question again. . .how do I reply to this inquiry?
    To me, it's probably good that you never took a class.

    That way you get to test the Parallax offering to see if it helps you as an entry level student.

    You've done pretty good so far.

    It's nice that Cody (SRLM) demonstrates floating point is not really necessary in such an application. People tend to jump on floating point only because it's possible.
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 14:24
    jazzed wrote: »
    It's nice that Cody (SRLM) demonstrates floating point is not really necessary in such an application. People tend to jump on floating point only because it's possible.

    Yeah, people like me. For such an application I'm happy to waste resources as much as I want to make it simple.

    Bloated code oinker I am.

    Ken Gracey
  • SRLMSRLM Posts: 5,045
    edited 2014-05-12 15:23
    Ken Gracey wrote: »
    - with a 0-5V A/D and 12-bit A/D, we get 2703 samples over 0-3.3V
    - you worked in all positive numbers, fixed point, multiplying by 10,000
    - whole digit and remainder were handled separately, so no floating point library required

    But, what if I wanted to use floating point and I want to display the output to only two significant digits? Is there a way to format the output in this line:

    print("Distance = %f m%c\n", meters, CLREOL);

    To include only two significant digits?

    What it does is assume that the number in the `meters` variable is in units of 1/10,000th of a meter. We've fixed the point at 4 decimal places. Therefore, to extract the characteristic (the portion before the point) we get rid of the first 4 digits of the number. To the decimal portion we get rid of the characteristic.

    An example. Suppose that the reading came back as 1274. If each bit represents 0.014798m, then the current distance reading is 18.852m. But rather than multiply by the float 0.014798, we multiply by 148 to get 188552. This number is now in units of 1/10000th of a meter. For human consumption we can extract the characteristic by dividing by 10000 (=18) and the decimal remainder by taking the modulus (=8552). For algorithm consumption we might as well leave it as an integer.

    Note that the entire distance value is handled in a single number. Normally, when we work with integers, we assume that the decimal place is on the right hand side after the last digit. But, with fixed point, we treat it as if the decimal place is some number of digits to the left.

    Remember that significant digits has a specific scientific meaning. What I think you're really asking for is how to limit it to a specific number of digits after the decimal point. In that case, you would simply take the decimal portion and divide by 10,100, or 1000 for 1,2, or 3 digits.
    print("Distance = %i.%i m%c\n", metersDigits, metersDecimal/100, CLREOL)
    

    ps: Are you going to carry their products in your store?
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-05-12 15:44
    SRLM wrote: »
    ps: Are you going to carry their products in your store?

    Thanks Cody. Now I understand the example completely.

    Yes, we have these SF02 units in stock at Parallax and they'll be available in the web shop this week.

    Ken Gracey
  • macrobeakmacrobeak Posts: 354
    edited 2014-05-12 19:15
    It is good to see Laser ranging/scanning entering the hobby market! 3D laser scanning It has truly revolutionized the field I work in - Brownfields Project Management of upgrades and modifications to existing process plants. Equipment can now be fabricated offsite, brought onsite and fitted accurately without all the tedious mechanical hacking, contractual drama and downtime hysteria that we used to have with mis-matching during installation. 3D drawings are accurate to millimeters and we can see the existing plant as a point clouds and conduct 3D client reviews and options analysis in the design office without expensive site visits. Congratulations to Parallax for documenting the SF02 Laser Rangefinder, but the main game is really 3D laser scanning. I saw this low cost 3D laser scanner over at Seeed. It looks like it has real potential. http://www.seeedstudio.com/depot/RPLIDAR-360-degree-Laser-Scanner-Development-Kit-p-1823.html Could Parallax investigate and document one of this type of low cost laser scanner as well as pure laser ranging? It will really put you ahead of the hobby pack - and you will get plenty of industry interest as well! It will also feed in nicely into 3D printing. Best wishes - keep up the cutting edge work!
Sign In or Register to comment.