Shop OBEX P1 Docs P2 Docs Learn Events
Data from a sensor — Parallax Forums

Data from a sensor

Hello,

I think I may be being hard of thinking here, but...

A doppler radar sensor sends to a P1 (for example) "-26.0", i.e., a string of bytes, 45, 50, 54, 46, 48, 13.

Is there an easy way to get this as a value with which I can do things within other parts of the spin code (even if I have to scale it to -260 as an integer to be able to use the tenths part), or do I need to work it out from scratch? It's not zero-terminated as various string-handler spin files need.

I've been round in circles so many times, I'm starting to get dizzy!

Thanks,

Hugh

Comments

  • JonnyMacJonnyMac Posts: 8,997
    edited 2023-11-27 19:13

    It's easier than you think. Here's a simple method that will take serial input and convert it to a value on-the-fly. It only cares about "-" (just once), "0".."9", and the decimal point, so it's quite easy.

    pub get_sensor : result | sign, b
    
    '' Returns sensor value in 0.1 units
    
      sign := 1
    
      repeat
        b := term.rx
        case b
          "-" :
            if (sign == 1)
              sign := -1
            else
              quit                                                  ' abort on second "-"
    
          "0".."9" :
            result := (result * 10) + (b - "0")
    
          "." :
            { ignore }
    
          other :
            quit
    
      return sign * result
    

    I tested it with PST. That code is attached.

    Now... if your sensor is going to change the position of the decimal point in different readings, you'll have to do a little more work (i.e., keeping track of the digits after the decimal).

  • Thank you, Jon. I may have been over-thinking it!

    Much appreciated, :)

    Hugh

  • That has taught me quite a lot about the case statement and how strings are handled - very clever. Every day is a school-day! Thanks again.

  • Keep in mind that most string functions in Propeller libraries count on z-strings, that is, a group of ASCII characters followed by a NULL (0). The capture/convert routine is on-the-fly, so we don't really care about 0, just anything not a legal character. There are times when I need to capture input from a device and treat it like string in the Px realm. Here's a very simple string capture that would work with your sensor.

    pub capture_sensor(p_buf) : len | b
    
      repeat
        b := term.rx
        case b
          "-" :
            if (len == 0)
              byte[p_buf++] := "-"
              ++len
            else
              byte[p_buf] := 0
              return
    
          "0".."9", "." :
            byte[p_buf++] := b
            ++len
    
          other :
            byte[p_buf] := 0
            return
    

    You need to tell the routine where to store your string, and the length will be returned.

    Here's a little conversion routine that will convert your string to a number, and tell you the number of digits after the decimal point. You can use this for scaling values to the same range.

    pub asc2dec(p_buf, p_dad) : result | sign, dpf, dpd, b
    
      sign := 1                                                     ' assume positive
      dpf  := 0                                                     ' clear decimal point flag
      dpd  := 0                                                     ' no decimal point digits
    
      repeat
        b := byte[p_buf++]                                          ' get a byte from buffer
        case b
          "-" :
            if (sign == 1)                                          ' if positive
              sign := -1                                            '   change to negative
            else
              quit                                                  ' abort on second "-"
    
          "0".."9" :
            result := result * 10 + (b - "0")                       ' add digit to result
            if (dpf == 1)                                           ' if decimal point flag set
              ++dpd                                                 '   inc decimal point digits count
    
          "." :
            if (dpf == 0)                                           ' if flag not set
              dpf := 1                                              '   set it
            else
              quit                                                  ' abort on second "."
    
          other :
            quit
    
      result *= sign                                                ' finalize value
    
      long[p_dad] := dpd                                            ' set digits after decimal value
    

    To use this you pass a pointer to your buffer, and a pointer to a variable that will hold the number of digits after the decimal point (must be a long). This does work -- I wrote a little test program using the terminal to create sensor input, and then processing it.

  • Every days is a school day. As long as it is consistent, I can learn it.

Sign In or Register to comment.