SmartPin Mode %10000: Reading 360 Servo Feedback
tomcrawford
Posts: 1,126
I was able to reliably recover readings from the Parallax 360 Servo Feedback pin using smarten mode %10000 (Continuous states are counted in clock cycles).
Here is the inside loop:
In mode %10000, the pin is continuously monitored. When an edge is detected, the count is placed in the Z buffer and cleared and the state corresponding to the count is placed in the C-flag buffer. These buffers are maintained until the next edge and can be read at any time.
The program MUST read a high period and then the corresponding LOW period. If it reads a LOW period followed by a HIGH, or if there are intervening states, the results are not valid, particularly if the servo crosses zero. In the method where the program watches for edges (this is what I did on P1), it must wait until it detects a LOW-to-HIGH transition before it starts timing. This can mean as much as nearly two full feedback cycles to acquire timing in the case where the program begins searching during a HIGH period. With the P2, the program can take advantage of the buffers and never spend more than one full feedback cycles to acquire timing.
Here is the code to set the mode
Oddly, I absolutely had to invoke the Schmitt trigger in the smart pin configuration. If not, there were intermittent glitches on the HIGH-to-LOW transitions which would result in spurious readings of 1 or 2. I am unable to explain the glitches; I have never seen them before and do not see them with the Schmitt trigger. Is it remotely possible the smart pin is causing them?
The whole test program in attached.
Here is the inside loop:
loop outh #sync 'sync at the beginning rqpin temp, #servoPin wc 'get PREVIOUS high time or low time if_NC waitx #200 if_NC jmp #loop 'wait until it returns a "high" value wypin #10, #SYellow 'process high wrlong temp, HiAdrs L2 rqpin temp, #ServoPin wc 'now we look for a LOW value if_C waitx #200 if_C jmp #L2 if_NC wypin #10, #SGreen 'process low if_NC wrlong temp, LoAdrs outl #sync waitx ##1000 jmp #loop
In mode %10000, the pin is continuously monitored. When an edge is detected, the count is placed in the Z buffer and cleared and the state corresponding to the count is placed in the C-flag buffer. These buffers are maintained until the next edge and can be read at any time.
The program MUST read a high period and then the corresponding LOW period. If it reads a LOW period followed by a HIGH, or if there are intervening states, the results are not valid, particularly if the servo crosses zero. In the method where the program watches for edges (this is what I did on P1), it must wait until it detects a LOW-to-HIGH transition before it starts timing. This can mean as much as nearly two full feedback cycles to acquire timing in the case where the program begins searching during a HIGH period. With the P2, the program can take advantage of the buffers and never spend more than one full feedback cycles to acquire timing.
Here is the code to set the mode
timerMode = %0100_000000000_00_10000_0 'continuous states are counted (schmitt trigger) dirl #servoPin wrpin MMode, #ServoPin 'set smart pin timer mode dirh #ServoPin 'Remove Reset
Oddly, I absolutely had to invoke the Schmitt trigger in the smart pin configuration. If not, there were intermittent glitches on the HIGH-to-LOW transitions which would result in spurious readings of 1 or 2. I am unable to explain the glitches; I have never seen them before and do not see them with the Schmitt trigger. Is it remotely possible the smart pin is causing them?
The whole test program in attached.
Comments
What do you mean by spurious readings of 1 or 2 ? Does that mean measurement LSB variations, or something else ?
If the servo signal is sufficiently fast, schmitt should make little difference - what is the Servo out rise/fall time ?
Very slow edges, with some noise present, & no schmitt, could possibly glitch to give a single-sysclk pulse, which could bump the smart-pin state and give large variations.
With an async signal, some LSB sampling +/-1 effect is expected.
If you report raw capture values, (SysCLK units) those should drift with the Parallax 360 generating clock, but the ratio should have higher stability.
If you have more than one Parallax 360 Servo, it would be useful to see the absolute variations from unit to unit, and the (better?) ratio.
IIRC the output resolves to ~12b, so you should report to better than that, to avoid losing precision inside P2.
By spurious readings of 1 or 2, I meant just that. The P2 was interpreting the noise on the input as valid inputs as short as 1 sysclk.
For SetPosition and GetPosition, I use degrees; internally I use 1/4096ths. Similarly, for SetVelocity and GetVelocity, I use rpm; internally I use 1/4096ths over 20 millisecs. Usually I call this clicks per tic; on Wednesdays I call it tics per click.
At 180MHz, it has ~ 5.5ns to move some noise level away from the pin threshold.
evanh's suggestion of enable the filter is a good one, as that widens the noise tolerance for unwanted impulse noise as well.
Schmitt + filter would be the most robust combination.
If you wanted to resolve to ~16 bits (to allow for other sensors, and ensure the capture is not losing precision) a tap of 1 and Length of 8, would give just over 16b timing, and ~90ns of filtering window.
Bitstream processing will add significant lag but, given the control pulse is only 50 Hz, there is something like 19 feedback pulses to play with before even one control pulse is needed.
I'm not sure what you mean by externally clocked bit streams, but the streamer does not have any externally clocked modes.
I had pondered what it would take to do synchronous PWM input with the same but that always needs dual readings. Not something a single smartpin is suited to.