|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools |
Rating:
|
Display Modes |
|
#61
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
So there is no uncertainty here... you are purposely causing an error of 1 tick but it is warranted because it signals to whomever is watching that you have reversed direction which allows tighter control. My algorithm lacks that signal so the control must be delayed until a new edge is detected. I believe that if a "direction" sense was outputted from a decoder with my algorithm, one could design a controller that would not suffer the hysteresis problem while not needing to cause an error on a same edge event. I think we all agree that both algorithms will have a max error of 1 count and this will occur at different times. If you demand exact repeatability with angle, then Joe's is the way to go. However, it introduces large rate spikes when oscillating over an edge. Mine will always be 1 count different on the return trip, but it tolerates an oscillating edge and its control can never be tighter than +_1 one count.... unless modified to output a direction sense (TBD). With today's high resolution encoders, a 2 count error band might be very acceptable. Quote:
Last edited by vamfun : 26-04-2010 at 17:50. |
|
#62
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Quote:
It also seems to me that your algorithm will give a false speed... Lets say the true shaft is 0.4 when you make your first speed sample. You then move to 1.4 and then back to 0.4 to take your second speed measurement. Your encoder will have changed from 0 to 1, so your speed will report forward 1 tick / period. My algorithm will report 0 speed. Am I missing something? -Joe |
|
#63
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Quote:
Quote:
Quote:
Quote:
The number that a quadrature decoder yields does not represent an edge. It represents a region between edges. Does that help you understand the explanations here? |
|
#64
|
||||
|
||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Quote:
Quote:
Quote:
Last edited by vamfun : 27-04-2010 at 17:47. |
|
#65
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Quote:
|
|
#66
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
I think we all understand the problems associated with quantization and my characterization of the error is perhaps clouding the discussion a bit too much. So here is a thumbnail of the problem: The two algorithms simply take the high road or the low road to rectify the count on a return trip. Taking the low road (joe) rectifies the count immediately on start of return, where the high road(chris) delays rectification until the return trip is completed. Joe's leads, mine lags. Joe's conveys directional sense by creating a high but erroneous initial rate, mine does not. Joe's lead hurts if the return never occurs because of a reversal. Mine gets in trouble if the return occurs quickly since I delay the rectification count ,however, if there is a reversal, mine then creates a smoother transition since I never changed direction. Mine creates delay which makes control more difficult. It creates a control dead zone of +_ 1 count. The problems occur in both algorithms because we are trying to describe position and speed states with one variable. At the initial reversal, joe's is good at showing direction at the expense of accurate position. Mine is good at position, but lousy at direction. The quadrature encoder gives us access to the B channel which allows us to know both position and direction on a same edge reversal. I'm thinking about creating a GetState() which outputs the position ,direction and speed states at the edge event. I suspect this would be close to using joes GetDistance(), GetRate() output pair , but slightly different algorithms. I'll post more when I've done a little more thinking. Quote:
How did you guys use Kevin's type encoder algorithm that solved the oscillating edge problem? Was the encoder information used in a closed loop controller? Doesn't that algorithm use a "hysterical" scheme? |
|
#67
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
I'm confused. I'm getting the impression you don't understand how quadrature encoding works, but I can't believe that's the case.
Quote:
Quote:
Quote:
(And I think it's Joe's algorithm that accurately reflects the position, and it's your algorithm that has the inaccurate position issue, but we've been through that already.) Quote:
|
|
#68
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Quote:
Probably at that time you did not have a need for special rate processing of your decoded heading unless heading rate was involved in your loop...right? |
|
#69
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
I really hope that I can end this thread with this post, but I'm not holding my breath.
Lets examine the Rate and Position functions separately - assume that selecting one implementation of Position does not necessitate selecting the matching implementation of Rate. Position JoeMethod - . Error is bounded to [-.5, .5] . Uncertainty is bounded to [-.5, .5] . Position is repeatable (no hysteresis). ChrisMethod - . Error is bounded to [-.5, .5] . Uncertainty is bounded to [-1.5, 1.5] . Position is dependent on direction (hysteresis). View the position as a circle divided into quadrants. A true quadrature decoder tells you which quadrant you are currently in. You then make the optimal assumption that you are right in the middle of that quadrant. Thinking in terms of assuming that you are on the border is non-optimal. Joe will always report the correct quadrant. You will be off by one half of the time, depending on which direction you are traveling. As far as I'm concerned, that is a clear win towards using an actual quadrature encoder, such as the one currently implemented. Arguments as to 'free hysteresis' are bunk as far as I'm concerned. I don't want features that belong in my controller sneaking into my sensor. Tell me what is happening, and I'll work with it from there. Rate JoeMethod GetRate . Given an oscillating edge, no rate is reported JoeMethod GetPosition+hand derivative . Given an oscillating edge, the correct rate is reported for the time period. ChrisMethod . Given an oscillating edge, zero rate is reported. These all stink in their own way. But, none of them report rate "spikes". I'd rather get the GetPosition delta at fixed time intervals as rate, if I could choose. I'm not saying that every aspect of the FPGA is perfect, but I will assert that the encoder implementation is what I hoped it would be. If it was implemented per your suggestion, I'd be disappointed. |
|
#70
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
![]() Personally, I would like to see it end with Joe's report on the GetPeriod() problem. Your summary is a nice place to break on the algorithm discussion subject but I would feel better about the table with the following amendments: Quote:
Quote:
. Given an oscillating edge, an amplified rate is reported for the time period. I rationalize this as follows: If the true oscillating edge amplitude is A , it will always cause an average GetPosition() oscillation amplitude of 0.5. Since this is a single edge oscillation, A < .5 , so any rate derived will be amplified by a factor of .5/A. E.g. A = .05 will amplify by 10 the true rate. This is the main reason that the Joe rate method and mine are in the ball game is to prevent these amplifications from tainting the rate output. Quote:
Quote:
What I would like, though is an option to modify the algorithms which I could do if the A/B interrupt count and timing was transparent. But Joe /Ni have elected to not make this code open source. We can write our own routines from scratch, but I would be satisfied if a GetEdgeState() function was implemented that provided edge count, direction and time_since_last_edge for the 1x case. This state captures all the information available from the A/B channels and could be easily modified to create whatever distance/rate algorithms you wanted. One could argue that these are available with GetRaw(), GetDirection() and GetPeriod() or their visible subfunctions.. but if called in sequence, I don't think they can guarantee to be synchronized to the same edge event. Maybe Joe can comment on this. Last edited by vamfun : 29-04-2010 at 21:24. |
|
#71
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
|
|
#72
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Here is pseudo simulation code that I would write to illustrate the error amplification
Code:
Param:
T = edge oscillation period
A = edge oscillation amplitude
dt = T/20, sample rate small enough to measure oscillation
variables:
t = time,
x = encoder input
y = encoder output
x_dot = encoder input rate
y_dot= encoder output rate
Run Simulation:
while(t < runtime){
Encoder input movement:
x = A*sin(2*pi*t/T); Small oscillation movement , A < 1 to be on same edge.
x_dot = A*2*pi/T*cos(2*pi*t/T)
Encoder output change when x is centered on a threshold:
If(x > 0 ) {y = .5 } //sample
else {y = -.5 }
y_dot = (y-y_last)/dt //Derive simple rate
y_last = y;
t= t + dt;
}
The output amplitude will oscillate between -.5 and .5 The amplitude ratio y/x = .5/A. peak |y_dot| = 1/dt, average |y_dot| = 2/dt/(20)= 2/T Average over oscillation period Then (avg |y_dot|)/(x_dot amplitude) = 1/(A*pi) (this is slightly less than my .5/A approximation.) |
|
#73
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Here's how: The DMA packet contains the position, direction, period, and "stalled" indicator (the configurable counter-inactivity timer). Each packet also includes a timestamp. You can configure DMA packets to be sent periodically or you can configure a digital source as the packet clock. If you use one of the encoder phases as the packet clock, then you can just use the timestamp in the packet for your timing. If you hook the packet clock to some unused digital output, you can request DMA packets on demand. You can also use periodic timing and use the distance and direction only. You can also hook one or both of the encoder phases to interrupts. This will not only notify your code, but also timestamp the event (using the same timestamp source as the DMA packets) so you can compare the timestamps of interrupts and DMA packets as needed. That being said, the one that is built in for you is WAY easier to use so at least for me I would have to have a pretty big problem with that implementation to want to reimplement it on the RTOS using DMA and Interrupts. The reason for including DMA and Interrupts was to make the system be super flexible to support interesting sensor interface requirements. BTW, you can get the same results that you get with your algorithm by simply adding 1 to the distance if direction is false with the built-in counter and you don't need any of that fancy stuff. But it will be worse! ![]() -Joe |
|
#74
|
|||
|
|||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
-Joe |
|
#75
|
|||||
|
|||||
|
Re: Unexpected results from Encoder::GetRate()
Quote:
Anyway, so far as I can tell, your proposal is worse than what you're pointing out here. Ignoring the first edge after a change in direction gives an unchanging output for any input oscillation amplitude less than 1, right? |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| [BB] An unexpected change in plans | yodameister | General Forum | 22 | 01-12-2009 21:26 |
| Inconsistent reading from encoder get rate | rwood359 | National Instruments LabVIEW and Data Acquisition | 5 | 13-01-2009 19:10 |
| Results from Drexel, thanks from 365. | archiver | 2001 | 1 | 24-06-2002 02:44 |
| Results from GLR? | archiver | 2001 | 0 | 24-06-2002 02:44 |
| results from regionals | archiver | 2000 | 0 | 23-06-2002 22:31 |