Shop OBEX P1 Docs P2 Docs Learn Events
Looking to get more accurate results from Ping sensor readings — Parallax Forums

Looking to get more accurate results from Ping sensor readings

I guessing there is some rounding off that is happening with the standard Ping object code. For example lets say I have something in front of the Ping and it reports back 11 inches. However looking at the ticks I see 883. Taking that times 1000 and dividing by the correction factor of 73746 I get 11.9735... which is closer to 12 than 11. How do I get that better precision being able to round up / down rather than rounding off? Any examples?

Thanks.

Comments

  • Are you working indoors or outdoors. How fast are you moving, if at all.?
  • Don MDon M Posts: 1,647
    Indoors. Static measurements for dimensions. Not moving at all.
  • JonnyMacJonnyMac Posts: 8,927
    edited 2016-07-26 18:48
    Why not this:
    inches10 := ping.ticks(SONAR) * 10_000 / ping#TO_IN
    
    This changes the resolution to 1/10". Of course you'll need to verify that you max distance (ticks * 10_000) will fit into POSX. You might also look into the ** operator instead of using the simple division.
  • Don MDon M Posts: 1,647
    The objects are still. I take a measurement then done.
  • Heater.Heater. Posts: 21,230
    Wait a minute:

    (833 * 1000) / 73746 = 11.295

  • Don MDon M Posts: 1,647
    Heater. wrote: »
    Wait a minute:

    (833 * 1000) / 73746 = 11.295

    You are correct but reread the top post... it's 883 not 833

  • Heater.Heater. Posts: 21,230
    Oops....I make error.

    How about multiply by 1000 and then add 500 ?

    Then when you divide and truncate to integer inches you get a correct rounding to the nearest inch.

    But I'm with JonnyMac, any reason to not just work at a higher resolution?
  • Don MDon M Posts: 1,647
    Heater. wrote: »
    But I'm with JonnyMac, any reason to not just work at a higher resolution?

    inches10 := ping.ticks(SONAR) * 10_000 / ping#TO_IN

    Ok I messed around with this a bit. So the result is 119. If I divide it by 10 I still end up with 11 so I don't understand the premise of this exercise.

    If I add 5 and then divide by 10 I get 12 which is what I want so using your suggestion of multiplying by 1000, adding 500 then dividing by 1000 would also work.

    I was also looking at F32 object. I tried using the FRound(a) method. I'm not sure really how it should work. I tried FRound(883000 / 73746) thinking it would do the division and round it appropriately but it returns 0. If I use FRound(11.97) it returns 12. If I try FRound(11.46) it returns 11. So that works.

    So then I tried using FDiv(883000, 73746), assinging it to a long variable then using FRound on that variable but that didn't work either. In fact the FDiv(883000, 73746) returned a number 1094608486 which makes no sense to me.

    I've never used the F32 object before so I need much enlightenment as to its use. Should I use it or just do the multply by 1000, add 500 then divide? I'd like to understand what Jon was trying to suggest.

  • JonnyMacJonnyMac Posts: 8,927
    edited 2016-07-26 21:06
    Ok I messed around with this a bit. So the result is 119. If I divide it by 10 I still end up with 11 so I don't understand the premise of this exercise.

    Oh, for Pete's sake -- did you never learn how to round up numbers in school? You stated you wanted more accuracy, yet didn't state the resolution of that accuracy. If you're just going for inches, here's the trick for rounding up.
    inches := (inches10 + 5) / 10
    
    If you're wanting accuracy, why would you want to round up? Just live with units that are in 1/10 inch. If you going to output to a display, output the value divided by 10, a period, then the value // 10 -- boom, Bob is your uncle.
  • Don MDon M Posts: 1,647
    By accuracy I'm referring to the fact that as in my original example of 883 ticks equating to 11 inches from the Ping object when in actuality it is closer to 12. That's all I was looking for. Moving forward the multiply, adding 5 then dividing seems the most reasonable solution.

    I was making it way more complicated than needed. Thanks to all.
  • Regarding the Float32 part of this thread:

    Values passed to the FRound, FDiv, etc etc must be floating point values not integers. FRound returns a 32bit integer; FDiv returns a 32 bit float. A 32 bit float consists of a sign, exponent and fraction (mantissa) [see https://en.wikipedia.org/wiki/Single-precision_floating-point_format].
    I tried FRound(883000 / 73746) thinking it would do the division and round it appropriately but it returns 0. If I use FRound(11.97) it returns 12. If I try FRound(11.46) it returns 11. So that works.

    So then I tried using FDiv(883000, 73746), assinging it to a long variable then using FRound on that variable but that didn't work either. In fact the FDiv(883000, 73746) returned a number 1094608486 which makes no sense to me.

    I've never used the F32 object before so I need much enlightenment as to its use. Should I use it or just do the multply by 1000, add 500 then divide? I'd like to understand what Jon was trying to suggest.
    FRound(FDiv(8.83e+5,7.3746e+4)) should produce the expected result
    FRound(FDiv(883000.0, 73746.0)) should also produce the expected result



  • Heater.Heater. Posts: 21,230
    To be clear:

    "resolution" is the term for the smallest change your measurement can detect. For example, 1 inch, 0.1inch, 1mm or 1nm.

    "accuracy" is the term for the actual correctness of the measurement. Usually expressed as plus or minus some percentage of the full scale range or plus or minus some absolute amount. For example +/-0.1 inches.

    One can have a very high resolution with a very poor accuracy.

    For example I recently saw a demo of a sensor that could detect movements of huge steel I-beams down to a couple of nano-meters. It could not tell anything about where the I-beam actually was! Huge resolving power, no accuracy.


  • Don MDon M Posts: 1,647
    @mmowen- Thanks for explaining that. Very helpful.

    @Heater- I "resolve" to be more "accurate" in asking questions.... :smile: Thanks for your help.
  • To be more accurate (to a level consistent with a high resolution) it might be worth considering a (precise and accurate) temperature sensor.
  • Don MDon M Posts: 1,647
    Hugh wrote: »
    To be more accurate (to a level consistent with a high resolution) it might be worth considering a (precise and accurate) temperature sensor.

    Actually I plan to add that at a later point in the project. I was reading about that a couple days ago.

  • I like the Maxbotix sensors with the TTL output. The flight time with a sonar pulse changes with temperature and Maxbotix has an option for an external temp sensor if that is required. I like getting the qualified sensor data in a serial port, and the code to read it can be used for a multitude of their sensors.
  • I posted some Ping code which includes an option for temperature compensation.

    According to one of the posts I made in the above linked thread, a 30 degree F change in temperature can effect the speed of sound by about 3%.
  • Hugh wrote: »
    To be more accurate (to a level consistent with a high resolution) it might be worth considering a (precise and accurate) temperature sensor.

    The speed of sound is 331.3 + 0.6 * Temp in Celsius (yields speed in m/s). Awhile back I wrote a blog post on how to turn the problem on its head and use the pinger as a temperature sensor. Any who, correcting for temperature is really pretty easy and worth doing for sure. I like the MCP9808 for a pure temp sensor.
Sign In or Register to comment.