ServoInput watchdog attempt: Not counting transitions as expected
mmgood
Posts: 19
I'm using David Gregory's ServoInput.spin to read a couple of R/C receiver servo channels, then I'm doing some process control calculations before passing an R/C servo pulse to a motor controller. It's all your typical R/C servo 1 to 2 ms positive pulses, about 20 times a second.
ServoInput.spin runs its innermost loop with a waitpeq() and waitpne(), and I gather those can (will) hang indefinitely waiting for a transition. Anyone reading its output variables will see them frozen at the value of the last valid pulse durations.
My receiver stops sending pulses on loss of signal (LOS); I'd like to stop passing pulses to the motor controller when that happens. My thought was to run a watchdog cog or two (wasteful, but I'm just prototyping here, OK?) to count transitions over a period of, say, a second or so. If the counts of transitions are zero, we know the values that ServoInput has stuffed into its pulseWidths are "stale" and we can stop passing pulses along until we're getting real ones again.
So here's a couple of snippets of what I've tried. The code's ugly, the approach inefficient; I'm stuck. The code below always seems to return 0 for both transition counts (in the variables Pulses01 and Pulses02).
Have I provided enough context and info here? Please advise. Thanks.
ServoInput.spin runs its innermost loop with a waitpeq() and waitpne(), and I gather those can (will) hang indefinitely waiting for a transition. Anyone reading its output variables will see them frozen at the value of the last valid pulse durations.
My receiver stops sending pulses on loss of signal (LOS); I'd like to stop passing pulses to the motor controller when that happens. My thought was to run a watchdog cog or two (wasteful, but I'm just prototyping here, OK?) to count transitions over a period of, say, a second or so. If the counts of transitions are zero, we know the values that ServoInput has stuffed into its pulseWidths are "stale" and we can stop passing pulses along until we're getting real ones again.
So here's a couple of snippets of what I've tried. The code's ugly, the approach inefficient; I'm stuck. The code below always seems to return 0 for both transition counts (in the variables Pulses01 and Pulses02).
Have I provided enough context and info here? Please advise. Thanks.
VAR long Stack01[24] 'Stack space for new cogs: overkill? long Stack02[24] long Pulses01 long Pulses02 byte p byte pp PUB SeenPulse(Pin, Delay, tcountbuffer) | tlimit, transcount ' (Attempted) watchdog. Look at pin, xor against last value. ' Every "true" xor, increment transcount. ' Every delay's worth of seconds, plug a new value into tcountbuffer. ' If no transitions in that period, the zero value should be interpreted ' as LOS detection; wdogOK should be set to FALSE. pp := 0 p := pp repeat transcount := 0 tlimit := Delay + cnt repeat p := ina[Pin] if p ^ pp ' Spin's bitwise xor function transcount += 1 ' if change, increment transcount pp := p until cnt > tlimit tcountbuffer := transcount '... '...and then in the initialization part of my code, I fire up two cogs like so: cogsuccess := cognew(SeenPulse(k#ailepin, 80_000_000, Pulses01), @Stack01) '1 second wdog cogsuccess := cognew(Seenpulse(k#gearpin, 80_000_000, Pulses02), @stack02) ' 2 cogs is rather wasteful of resources, but "meh" for now
Comments
The first argument is the pin you want to time, the second is an extra unused pin used for the timeout, and the third is how long (e.g. clkfreq/10 for 0.1 seconds) the timeout should be. It returns -1 if the entire pulse does not fit within the timeout. It waits for the pin to go high then low - swap the two waitpne lines if this is wrong.
This line of code tells you how many microseconds have elapsed for each servo. If you want to read input from your receiver before you send the data to your motor controller you can modify "ServoInput" to read 2 pins from your receiver instead of 4 pins from servos then you can pass those values to your motor controller. The other modification I would make is to change "vga text" to the Propeller serial terminal because I don't have a vga monitor.
One other thing: "It's all your typical R/C servo 1 to 2 ms positive pulses, about 20 times a second."
About once every 20 milliseconds a 'position' pulse lasting somewhere between 0.6ms and 2.4ms tells the servo controller what position the servo should hold. That's the pulse you want to read and pass to your motor controller.
@ 20ms the refresh rate is 50 times/sec