Shop OBEX P1 Docs P2 Docs Learn Events
Background polling of a sensor — Parallax Forums

Background polling of a sensor

4Alex4Alex Posts: 119
edited 2009-01-08 14:11 in Propeller 1
Hi all,

I am looking for some pointers in how to achieve background polling of a sensor at regular, periodic intervals of time. I want to start small but eventually I'd like to evolve this project into full home automation (and preferably not burn down my house in the process!).

Basically, I have a PC linked to a propeller using RS232 through pcFullDuplexSerial4FC.spin written by Ken Gracey and modified by Tim Moore. On the propeller side, I have a sensor linked through spi (spi.spin) that can be accessed at high bitrate. The propeller runs autonomously and monitors changes in the sensor data. When data is outside a preset range, an alarm is sent to the PC. If the range needs to be adjusted, the PC sends a command to do so. Simple. This is all working at this point but in full 'foreground' approach like with a traditional microcontroller.

I am looking at a way to have the propeller polling the sensor in the background while it still do other internal processing and responding to commands coming from the PC (or sending alarm to it). I guess the multi-cog design is what the propeller is really all about but I have no idea on how to achieve this.

The best would be if someone can point me toward an existing project doing something similar (background polling) so I can learn the ropes. I have searched the obex but with no success.

As always, many thanks in advance for any assistance.

Cheers,

Alex

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2009-01-06 15:08
    Start with the Propeller Education Kit tutorials, particularly the one on Methods and Cogs. There are other tutorials as well, all linked from the "sticky threads" at the top of the forum thread list.

    The Propeller really doesn't have a "background". It has 8 essentially identical computers (cogs) that have access to the same I/O and memory. It's simply a matter of one computer polling the SPI sensor and leaving information in the shared memory while another computer is talking to a PC and looking at the shared memory information to see if there's something to send to the PC (while another computer is actually doing the serial I/O, bit by bit based on data in a shared buffer).
  • KyeKye Posts: 2,200
    edited 2009-01-06 15:17
    As mike said, you should use the power of the·8·cog each to monitor data and respond to events.

    Mostlikely, you should have one cog doing serial. One cog doing spi, and one interpreting the data from the PC and interpreting data from the sensor. All that's left to do is then add more cogs for more sensors to interface with them.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Ken GraceyKen Gracey Posts: 7,400
    edited 2009-01-06 15:18
    Somebody said...
    . . . . ·using RS232 through pcFullDuplexSerial4FC.spin written by Ken Gracey and modified by Tim Moore.
    Thanks for the compliment, but that would be "Chip" Gracey. We share a last name but we're wired differently.

    Ken Gracey
    Parallax, Inc.

    ·
  • 4Alex4Alex Posts: 119
    edited 2009-01-06 15:22
    @Ken & Chip:

    I stand corrected! My sincere apologies to Chip. You might be 'wired differently' but you certainly both rock!

    Cheers,

    Alex
  • GeorgeCollinsGeorgeCollins Posts: 132
    edited 2009-01-08 04:52
    4Alex,

    This is something that a prop is great for. I have been working on a robot where I have on thread (or cog) update the position of servos incrementally and another thread poll a Ping sensor. Both updates can go on in the background and the main processing loop doesn't have to wait for them.

    When I start the ping I set the timing interval. The ping is read at that interval and the result goes into a ring buffer along with the servo position. So I can take a bunch of readings and then average them for more reliability. Or I can pan the head servo and see if any of the readings are dangerously close. Finally I sometimes use array of ping results and servo position to make a little obstacle plot on a TV screen. I am just learning, its amazing what I think I can do.

    Enclosed is "Ping Minder" the part that monitors a Parallax ping sensor. It uses This isn't the greatest code, but perhaps it will help you. Let me know if I can help.



    {{
      Ping Minder
    
      Do a ping every.. "PingDelay".. tics
      Store result in a buffer.
      
    }}
    
    OBJ
      Ping  : "Ping"  ' From the Parallax Object Exchange
    
    CON
    
      MAX_BUFFER    = 100           ' How many readings I save
      PING_ON       = 1
      PING_OFF      = 0
      
    VAR
      byte PingPin
      long PingDelay
      long cm
      long stack[noparse][[/noparse]512]
      long measure_ring_buffer[noparse][[/noparse]MAX_BUFFER+1]
      long servo_ring_buffer[noparse][[/noparse]MAX_BUFFER+1]
      long servo_ptr
      byte PingOn ' 1 ping is on, 0 ping is off
      byte index
      byte cog
    
    
    PUB Init(pin, delay) 
      PingPin:=pin
      PingDelay:=delay
      servo_ptr:=0  ' So I know I haven't set it
      PingOn:=1
      cog:=cognew(Main, @Stack)
      return cog
    
    PUB SetServoPtr(ptr)
      servo_ptr:=ptr
    
    PUB GetServoPtr
      return servo_ptr  
    
    PUB StartSweep
      ' Mark a sweep from one move to another
    
        repeat index from 0 to MAX_BUFFER-1
          if (servo_ptr > 0 )
           servo_ring_buffer[noparse][[/noparse]index]:=long[noparse][[/noparse]servo_ptr]         
    
        index:=0
    
    PUB GetIndex
      return index
    
    PRI Main
      repeat
        waitcnt(cnt+PingDelay)
        if (PingOn==PING_ON)
          cm:=Ping.Centimeters(PingPin)
          index:=index+1
          if (index > MAX_BUFFER-1) 
            index:=0
          measure_ring_buffer[noparse][[/noparse]index]:=cm
          if (servo_ptr > 0 )
            servo_ring_buffer[noparse][[/noparse]index]:=long[noparse][[/noparse]servo_ptr]
            
    PUB GetPingDistance
      return cm
    
     
    PUB GetPingAtLast(n)
      ' Get one of the recent pings, counting back n.  n = 0 is the last ping
        if (index - n > 0)
          return measure_ring_buffer[noparse][[/noparse]index - n]
        else
          return measure_ring_buffer[noparse][[/noparse]index + MAX_BUFFER - n]  
    
    PUB GetPingAt(n)
      if (n > -1) and (n < MAX_BUFFER)
        return measure_ring_buffer[noparse][[/noparse]n]
        
    PUB GetPanServoAt(n)  
       if (n > -1) and (n < MAX_BUFFER)
        return servo_ring_buffer[noparse][[/noparse]n]
    
    PUB GetAverageDistance(num_measure) | loop, bindex,sum
      if (num_measure > MAX_BUFFER) or (num_measure < 1)
        return 0                            ' You can't average more then you buffer or 0
        
      sum:=0
      bindex:=index ' backward index
      repeat loop from 0 to num_measure-1
        sum:=sum+measure_ring_buffer[noparse][[/noparse]bindex]
        bindex:=bindex- 1 ' go backward
        if (bindex < 0)
          bindex:=MAX_BUFFER        ' wrap it around
    
      if (num_measure > 1)
        return sum/(num_measure)
      else
        return sum
    PUB SetPingOn
      PingOn:=PING_ON
    
    PUB SetPingOff
      PingOn:=PING_OFF   
      
    PUB Stop
      cogstop(cog)
    
    
  • 4Alex4Alex Posts: 119
    edited 2009-01-08 14:11
    @GeorgeCollins:

    Thank you so much for the code! It looks like a very good start for what I am trying to do. I will study your code and adapt it to my sensor. More to come later on...

    Many thanks again.

    Cheers,

    Alex
Sign In or Register to comment.