How to implement an encoder with one speed clock, and one direction signal.

The encoder we are attempting to implement is not a quadrature encoder.

We are trying to use the Counter.h class in the WPILib to implement it.

When we used the Get() method in the Counter class, it returned a one or two, based on if we were using a k1X or a k2X reading.

When we used the GetDirection() method it returned a true, or false based on what direction the encoder is spinning.

We can’t get the encoder to count past one or two. Any help appreciated.

What encoder are you using? How do you have it wired to the roboRIO?

From what I’m reading, I’m guessing you’re trying to implement an encoder that just counts the # of transitions from 1 to 0 or 0 to 1 off a single digital input, rather than an encoder and its two digital inputs.

In the past, my team has implemented such a thing by just having a fast-spinning loop in a separate thread (task) constantly checking the value of a DigitalInput.


class SimpleEncoder
{
public:
  SimpleEncoder(DigitalInput* _pDigIn) : pDigIn(_pDigIn),m_last(0) {};
  void ThdProc()
  {
     bool last = false;
     while(true)
     {
       bool thisSample = !!pDigIn->Get();
       if(thisSample != last)
       {
         m_count++;
         last = thisSample;
       }
     }
     Wait(0.001); // you MUST have a wait in here, or else this thread will never let other threads run
  }
  int GetCount() {return m_count;}
  int m_count;
  DigitalInput* pDigIn;
};

I’ll leave “how to make new tasks” as an exercise for the reader, since I don’t have WPILib in front of me. Also, this implementation won’t work for things that are expected to go 01010101 extremely quickly. We usually use it for things that expected to max out at like 5 transitions per second.

Back in the day, you could implement something like this with an interrupt. You might still be able to (and it would be far more efficient than the code above), but I’m not familiar with the (C|robo)Rio method of doing it.

It’s a trackball encoder, with the clock signal wired to the first input, and the direction signal wired to the second input.

I’m not familiar with trackball encoders, and couldn’t find any description of one that uses a clock and direction outputs. Can you point to a datasheet?

No, we found this within an old keyboard, made by Cherry Switch. The trackball uses 2 encoders, one for the X, and one for the Y. With an oscilloscope we found two outputs on each encoder. The first output is a clock pulse based on the encoder wheel rotation. The second output is high for clockwise, and low for counterclockwise rotation.

We are trying to use the Counter::SetExternalDirection method. According to the source codes comments:

/**

  • Set external direction mode on this counter.
  • Counts are sourced on the Up counter input.
  • The Down counter input represents the direction to count.
    */

When setting the counter for k1X, the Get() method returns a 0 or a 1. The GetDirection() method return true or false, according to the direction of rotation. We cannot get the Get() method to count more than 0 or 1. Any help appreciated.

Now understanding your issue more, I wonder if you could make a class inheriting from DigitalSource and “fake” the 2nd digital input of a quadrature encoder. Since you know the actual situation you’re in and you know the format a quadrature encounter is expecting the 1s and 0s to flow, you can fake it:
-If input A is 1 and input B is forward, then return 0
-If input A is 0 and input B is forward, then return 1
-If input A is 1 and input B is backwards, then return 0
-If input A is 0 and input B is backwards, then return 1

Something like


class FakeQuadrature : public DigitalSource
{
public:
  // construct/pass in things, override other DigitalSource virtual functions...

  bool Get()
  {
    bool count = trackBallCount.Get();
    bool dir = trackBallDirection.Get();
    if(count && dir) return 0;
    else if(count && !dir) return 1;
    else if(!count && dir) return 1;
    else if(!count && !dir) return 0;
    return 0;
  }
private:
  DigitalInput trackBallCount;
  DigitalInput trackBallDirection;
};

Then once you’ve got that built, send it in as the 2nd DigitalInput to the Encoder class’s constructor.

I’ve never tried external direction mode on a counter, but the documentation I have read suggests that you should be able to make it work using an Encoder in 1x or 2x mode.

You shouldn’t need to fake anything like others are saying. The counter directly supports external direction. Simply select that mode.