Announcement

Collapse
No announcement yet.

WPILIB Encoder SetMinRate() problem

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Re: WPILIB Encoder SetMinRate() problem

    Originally posted by vamfun View Post
    What is the default pulse averaging count?
    1

    Originally posted by vamfun View Post
    How do we as users modify this to optimize it for our use when setting up the encoder constructor?
    Edit WPILib to support calling writeTimerConfig_AverageSize on the tCounter or tEncoder object. The minimum value is 1 and the maximum is 127.

    Originally posted by vamfun View Post
    I have a IIR exponential filter implemented currently, but I would rather have a moving average. I suggest we update the Encoder documentation to clarify that this filtering is going on (hidden to most of us) and hopefully get us a SetPulseAveragingCount() method in the encoder class.
    The filtering is disabled by default (since it is 1).

    Comment


    • #17
      Re: WPILIB Encoder SetMinRate() problem

      Thanks Joe. Lets conclude this thread and continue further discussions on a new thread called "Encoder period/rate moving average"

      http://forums.usfirst.org/showthread...7995#post27995

      Comment


      • #18
        Re: WPILIB Encoder SetMinRate() problem

        Joe,
        Sad to say, we have some hiccups in the Encoder data when we tested the SetMinRate. We hooked one encoder up and made two x1 instances of it...A) with SetMinRate(1) as a reference and B) with SetMinRate(10) as a test case. We expected to see no rates on B when A was below 10 and when A was greater than 10 we expected to see output on B too.

        The data showed intermittent failures in both cases. I have enclosed an excel spread sheet showing the data we took. I have no clue why this occuring...so I defer to you for possible suggestions or wonder if you can duplicate the test.
        Attached Files
        Last edited by vamfun; 03-05-2009, 10:43 PM.

        Comment


        • #19
          Re: WPILIB Encoder SetMinRate() problem

          I need to know a couple things about your experiment to try to reproduce it. What decoding mode are you using? Do you have any averaging enabled? What is your DistancePerCount scaling configured to? Perhaps you can post a code snippet that shows your configuration.

          Comment


          • #20
            Re: WPILIB Encoder SetMinRate() problem

            Originally posted by Joe Hershberger View Post
            I need to know a couple things about your experiment to try to reproduce it. What decoding mode are you using? Do you have any averaging enabled? What is your DistancePerCount scaling configured to? Perhaps you can post a code snippet that shows your configuration.
            We used a vex motor to drive a kit encoder. Sample code looks like this
            class OurRobot : public SimpleRobot
            {
            RobodoxEncoder *A;
            RocodoxEncoder *B;
            etc.
            }


            Constructor:

            A = new RobodoxEncoder(4,1,4,2, false, Encoder::k1X);
            B = new RobodoxEncoder(4,1,4,2, false, Encoder::k1X);
            A->SetDistancePerPulse((6.0*PI)/250);
            B->SetDistancePerPulse((6.0*PI)/250);
            A->SetReverseDirection(true);
            A->SetMinRate (1.);//sets minimum rate to 1 in/sec
            B->SetMinRate (10.);//sets minimum rate to 10 in/sec
            // we had these reference wheels programmed but no encoders installed
            rightRef = new RobodoxEncoder (4,5,4,6, false, Encoder::k1X);
            leftRef = new RobodoxEncoder (4,7,4,8, false, Encoder::k1X);
            leftRef->SetDistancePerPulse((3.0*PI)/250);
            rightRef->SetDistancePerPulse((3.0*PI)/250);
            rightRef->SetMinRate(1.);
            leftRef->SetMinRate(1.);
            // no moving average pulses set.. used default one pulse

            .....
            Simple robot
            void OurRobot::OperatorControl(void) {

            while ( IsOperatorControl() )
            {
            GetWatchdog().Feed();
            FilterEncoderSpeeds(); // this just reads encoders and provides a low pass filter..no data from this was used in test. We have seen the minrate problem without this operational.
            printf("%f\t %f\t %f\t\n", (float)time->Get(),(float)A->GetRate(), (float)B->GetRate();//source of excel data
            DriveCode();
            LiftCode();
            RollerCode();
            }
            } // end operator control

            void FilterEncoderSpeeds(){
            float v_l_raw;
            float v_r_raw;
            float v_lref_raw;
            float v_rref_raw;
            static const float weight = 1.;// Weight values must range between [0 , 1];

            //read the wheel speeds
            v_l_raw=A->GetRate();
            v_r_raw=B->GetRate();
            v_lref_raw=leftRef->GetRate();
            v_rref_raw=rightRef->GetRate();
            //check for stall condition just in case old encoder cpp is running. If stalled, this output was + or - inf. So set to zero if > 10*max rate.
            if(fabs(v_l_raw>120.))v_l_raw=0.;
            if(fabs(v_r_raw>120.))v_r_raw=0.;
            if(fabs(v_lref_raw>120.))v_lref_raw=0.;
            if(fabs(v_rref_raw>120.))v_rref_raw=0.;
            //now filter with weighted average between existing global value and new encoder read value
            v_l = v_l + weight*(v_l_raw - v_l);
            v_r = v_r + weight*(v_r_raw - v_r);
            v_lref = v_lref + weight*(v_lref_raw - v_lref);
            v_rref = v_rref + weight*(v_rref_raw - v_rref);
            }

            The RobodoxEncoder is the same as given in this post: http://forums.usfirst.org/showpost.p...43&postcount=5 . We have had similar results with the unmodified WPILIB Encoder class. We did not call the SetMovingAveragePulseCount() function.

            Not sure why, but the printf statement was using 60ms per pass. Seemed a little high to me. It ran the first seven passes with less than 1ms per pass and then jumped to 60ms per pass for the rest. Is this a buffer filling up and causing extra delays?
            Last edited by vamfun; 03-06-2009, 04:50 PM.

            Comment


            • #21
              Re: WPILIB Encoder SetMinRate() problem

              For peace of mind, could you explicitly set the averaging to 1 to ensure that it is actually 1?

              As for the samples that show zero when they should be non-zero (according to the other timer), that's pretty easy to explain... since your timeout is longer on the other timer, it will continue to report an old rate past when the shorter timeout has already expired and switched to 0. This is especially true when the rate that the slower timeout timer is reporting is close to the faster timer's timeout.

              If there is a glitch in the signal, that could cause the behavior... when the encoder detects a direction change, the rate is invalidated (the same thing that happens when it times out). I don't think that's what's happening here, though.

              As for the lower rates that are coming through, I'm not sure. I'll have to look closer into the logic to see when and how that could happen. My gut says it's related to an averaging cycle since the timer and the sliding-window averaging engine are independent logic that communicate through a fifo, and the timeout is communicated to the averaging engine synchronous to the average cycle. It's probably a bug, but it seems harmless. The key to that feature is that if the sensor stops moving, your code is updated in a timely manner with a valid, current value. Getting an actual value instead of an approximate value (zero) should not have a negative impact. However, I will continue to look into it.

              As for the printf rate... do you have the "Console Out" dip switch on the controller switched on? If you do, then it is running at 9600 baud. At that rate you can print 960 characters per second (8-n-1 means 10 symbols per byte). If your printed lines are around 35 characters each, that's about 37ms per line... and that's assuming constant transmission. 60ms per pass certainly seems reasonable. You should really put a delay in that main while loop so you don't just swamp the processor... preferrably a bit longer than the printing takes.

              Comment


              • #22
                Re: WPILIB Encoder SetMinRate() problem

                As usual Joe, you always give a thoughtful response and it is much appreciated.

                For peace of mind, could you explicitly set the averaging to 1 to ensure that it is actually 1?
                If you mean the moving average pulse count...I'm 97% sure we used the default Encoder constructor to set that. We didn't set any pulse count. But, if I get a chance to take more data, I'll give it a try. We want your mind at peace.

                As for the samples that show zero when they should be non-zero (according to the other timer), that's pretty easy to explain... since your timeout is longer on the other timer, it will continue to report an old rate past when the shorter timeout has already expired and switched to 0. This is especially true when the rate that the slower timeout timer is reporting is close to the faster timer's timeout
                Not sure I understand how this explains the differences. So long as the MinRate=1 encoder is not stalled, I would consider it as a good reference for rate. The MinRate=10in/sec period is 7.5ms. The encoder reads are consecutive in the print statement so there should be much less than a ms difference in their reads so the timers should have a high probability of timing the same two pulse edges. So it would seem that the biggest factor should be how well two timers can track the same pulse. I believe the clock lsb is 1 usec , but if I ran an accurate square wave into an encoder port..what would the period error be for two timers on that port?

                There are 47 suspect data points which are zero for the MinRate=10 encoder and perhaps a small percentage are readings from edges on a different pulse and we might expect a discrepancy (but its duration should only last for one 60 ms printout interval.)

                It's probably a bug, but it seems harmless. The key to that feature is that if the sensor stops moving, your code is updated in a timely manner with a valid, current value
                .
                I agree unless you are expecting a dead zone which we are doing. Of course we can add our own dead zone to ensure this happens.

                Hopefully, you will be able to provide some check data. I have a feeling something is still not right here or there are some significant timer errors that explain the hiccups.

                I will start another thread on the printf... have a few questions there.

                .
                Last edited by vamfun; 03-15-2009, 07:48 PM. Reason: Revised thinking on pulse timeout variation

                Comment


                • #23
                  Re: WPILIB Encoder SetMinRate() problem

                  Originally posted by vamfun View Post
                  Hopefully, you will be able to provide some check data. I have a feeling something is still not right here or there are some significant timer errors that explain the hiccups.
                  I've used DMA in LabVIEW to capture the timer output at a high and consistent rate. I was able to capture a sample every 200us. This gives a much clearer view into what is going on.

                  In the data I captured, I used a DistancePerCount value of 0.02. This means that (since the samples are captured every 200us) a MinRate=10 timer will time out after 10 samples. A MinRate=1 timer will time out after 100 samples.

                  [QUOTE=vamfun;28498]Not sure I understand how this explains the differences. So long as the MinRate=1 encoder is not stalled, I would consider it as a good reference for rate. The MinRate=10in/sec period is 7.5ms. The encoder reads are consecutive in the print statement so there should be much less than a ms difference in their reads so the timers should have a high probability of timing the same two pulse edges. So it would seem that the biggest factor should be how well two timers can track the same pulse.[QUOTE=vamfun;28498]

                  I don't think you are following the meaning of the MinRate. If the MinRate=1 timer is not stalled, it says nothing about the validity of a timer with a higher MinRate, by definition. Consider the case where the encoder stops abruptly. After 10 samples on the MinRate=10 timer, the timer value goes to 0. After 100 samples, the MinRate=1 timer value goes to 0. As such, any sample acquired between the 10th and 100th samples will show 0 on the MinRate=10 timer and the most recent rate on the MinRate=1 timer. This can be seen plainly at row 2316 in the attached data as well as many other places in the data.

                  Originally posted by vamfun View Post
                  I believe the clock lsb is 1 usec , but if I ran an accurate square wave into an encoder port..what would the period error be for two timers on that port?
                  The clock lsb is 1us, but the resolution it is read from the timer is 2us. Therefore only by using averaging can you get benefit from that extra 1bit of resolution. Another thing to consider is that the hardware sample rate for digital inputs is 153kHz. You can expect that timing will be impacted by the 6.525us sampling period between edges.

                  Originally posted by vamfun View Post
                  There are 47 suspect data points which are zero for the MinRate=10 encoder and perhaps a small percentage are readings from edges on a different pulse and we might expect a discrepancy (but its duration should only last for one 60 ms printout interval.)
                  You will not see the counters measuring edges from different pulses in the same sample when DMA is used, and yet that phenomenon is still seen there. I think we can conclude that seeing different edges is not the cause.

                  Originally posted by vamfun View Post
                  I agree unless you are expecting a dead zone which we are doing. Of course we can add our own dead zone to ensure this happens.
                  I'm not sure what you are talking about here. Why do you need a dead zone? Why is it not sufficient to simply look for the rate to be less than some value instead of exactly 0?

                  One thing that is much more clear in the data I captured is that when an edge triggers an event and the timer captures it, even when the timing is below the MinRate (the bug that I mentioned last week), you can see that after the timeout period for that timer expires once more, the rate returns to 0. This means that while the behavior is not intuitive, it certainly should not cause any problems and actually gives more accurate data.
                  Attached Files

                  Comment

                  Working...
                  X