Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   C/C++ (http://www.chiefdelphi.com/forums/forumdisplay.php?f=183)
-   -   Reading an absolute encoder via PWM in C++ (http://www.chiefdelphi.com/forums/showthread.php?t=104560)

synthmusic 13-03-2012 02:13

Reading an absolute encoder via PWM in C++
 
Hello all!

We are trying to get a reading from a sensor, the MAE3 from US Digital. Basically it outputs a PWM signial that shows its position by varying the width from 1 to 4096 uS. We're having trouble finding the right code that will grab that pulse width from the FPGA in a stable manner.

We can grab it in OperatorControl to show the signal is there, but the value varies by close to 10%, and often jumps to extreme numbers, assuming because we are in the main teleop loop.

Any pointers to the right object to use to get the PW correctly?

Thanks!!

"bBallAngle" is meant to show the number of microseconds elapsed for the width

Code:

bBallAngleSensor = new DigitalInput(2,11);

...

if (bBallAngleSensor->Get() == 1)
{
    // these for loops are to prevent a while lock.  if it loops 5000 times it will fall out
    // but a legit change will break;
    for (int i = 0; i < 5000; i++)
    {
        if (bBallAngleSensor->Get() == 0)
        {
            break;
        }
    }
    startTimeAngle = GetFPGATime();
    for (int i = 0; i < 5000; i++)
    {
        if (bBallAngleSensor->Get() == 1)
        {
            break;
        }
    }
    bBallAngle = GetFPGATime() - startTimeAngle;
}


RufflesRidge 13-03-2012 10:40

Re: Reading an absolute encoder via PWM in C++
 
You could probably use the Counter object and GetPeriod() method to make the FPGA keep track of the pulses instead of doing it in your code.

Ether 13-03-2012 10:45

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by RufflesRidge (Post 1143502)
You could probably use the Counter object and GetPeriod() method to make the FPGA keep track of the pulses instead of doing it in your code.

If you use the GetPeriod() method in a Counter object on a PWM signal, is there a way to specify that you want the elapsed time between rising and falling edges? If not, how would you use this with a PWM signal ?



RufflesRidge 13-03-2012 10:51

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by Ether (Post 1143503)
If you use the GetPeriod() method in a Counter object on a PWM signal, is there a way to specify that you want the elapsed time between rising and falling edges? If not, how would you use this with a PWM signal ?



Doh! You're right, it would give you the period between either consecutive rising or consecutive falling edges which isn't what you want.

Ether 13-03-2012 11:01

Re: Reading an absolute encoder via PWM in C++
 

There is a PWM class in WPILib but I don't know if that's only for outputting PWM or if it also supports reading PWM inputs.


RufflesRidge 13-03-2012 11:05

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by Ether (Post 1143518)

There is a PWM class in WPILib but I don't know if that's only for outputting PWM or if it also supports reading PWM inputs.


It's for output. This thread made me curious so I did a little digging and found this thread on the FIRST forums which may be helpful ("working" stuff appears to be at the end)

apalrd 13-03-2012 11:44

Re: Reading an absolute encoder via PWM in C++
 
In LabVIEW, you can configure a Counter for "Semi-Period" mode, which measures the pulse width of either high or low pulses instead of time between edges. This is what you want. Is there something similar in C++? (Since it's FPGA-level, I assume there's an interface in C++)

Alexander Meyer 13-03-2012 12:33

Re: Reading an absolute encoder via PWM in C++
 
The C++ Counter class has a semiperiod mode as well, though I have never used it.

Ether 13-03-2012 12:36

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by Alexander Meyer (Post 1143565)
The C++ Counter class has a semiperiod mode as well, though I have never used it.

Code:

/**
 * Set Semi-period mode on this counter.
 * Counts up on both rising and falling edges.
 */

I didn't look at the code, but the description doesn't sound like what is needed.



synthmusic 14-03-2012 16:53

Re: Reading an absolute encoder via PWM in C++
 
Thanks everyone!

To avoid a hail of quotes, I'll simply summarize:

I tried the Counter class, but it didn't seem to want to do much more than, well, count. Every attempt at .GetPeriod() returned infinity, clearly hitting this Counter code:

Code:

double Counter::GetPeriod()
{
        tCounter::tTimerOutput output = m_counter->readTimerOutput(&status);
        double period;
        if (output.Stalled)
        {
                // Return infinity
                double zero = 0.0;
                period = 1.0 / zero;
        }
        else ...

and I could not convince it that it wasn't stalled so it would fall into the else. I made many iterations in the attempt, so I don't have any meaningful source to post showing it not working, which was my bad, if I try again I'll put something up.

RufflesRidge, I followed that link, and it does look promising, I shall try it out tonight.

Alan Anderson 14-03-2012 17:12

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by synthmusic (Post 1144232)
and I could not convince it that it wasn't stalled

Did you start the counter before trying to read it?

Ken Streeter 14-03-2012 23:19

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by synthmusic (Post 1143376)
We are trying to get a reading from a sensor, the MAE3 from US Digital. Basically it outputs a PWM signial that shows its position by varying the width from 1 to 4096 uS. We're having trouble finding the right code that will grab that pulse width from the FPGA in a stable manner.

I know this probably isn't the answer you're looking for, but just in case you're unable to find a way to easily measure the PWM signals from the cRIO, you could instead use the MAE3 with the analog option instead.

We used the analog version of the MAE3 on robots in 2007-2009 with very good success, including a prototype swerve drive we built in the off-season.

apalrd 16-03-2012 20:28

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by Ether (Post 1143568)
Code:

/**
 * Set Semi-period mode on this counter.
 * Counts up on both rising and falling edges.
 */

I didn't look at the code, but the description doesn't sound like what is needed.



Wow. The description in LabVIEW is conflicting on this.

In LabVIEW, the Create Counter is polymorphic (there are multiple versions which you can select with a drop-down box). For the Semi-Period mode, the help says this:

Code:

Open Semi Period Mode
Opens a reference to a counter and configures the counter to measure the time between pulses in a signal. You can configure the counter to measure the time between high pulses by setting High Pulse (T) to TRUE. Otherwise the counter measures time between low pulses.

But later, in the connector description, it says this (what I read and assumed it meant pulse-width):
Code:

High Pulse (T) specifies, when TRUE, that the counter measures the length of the high time of the pulse. When FALSE, the counter measures the length of the low time of the pulse.
Since Up/Down mode can also measure single-wire encoders in a similar way to what the Semi Period mode describes, and since Semi Period mode (to me) did not act correctly when the encoder's lines were not of equal width in the light and dark spaces, I am inclined to believe that the Semi-Period mode actually measures pulse width.

The LabVIEW description of Up/Down mode says this:
Code:

Open UpDown Mode
Opens a reference to a counter and configures the counter to detect pulses on the rising or falling edges of a signal. You can specify an up source and a down source but most applications require only one signal per counter. The up source increases the counter and the down source decreases the counter.

We have a non-contact optical sensor and a custom-made disc with black tape, and the tape is not the same width as the bare aluminum space (by quite a bit). In Semi Period mode, when I configure the counter correctly and scale the output to RPM's, the numbers are not the same as the tachometer. When using Up/Down mode, they match the tachometer within 2 rpm. This leads me to believe that Semi Period mode actually measures pulse width, while Up Down mode measures time between rising edges - the time between rising edges does not care if the pulse width is different high than low.

synthmusic 19-03-2012 01:01

Re: Reading an absolute encoder via PWM in C++
 
Once again, thanks for the ideas! Given other priorities and troubleshooting, we called in an order for the analog version as noted here

Quote:

Originally Posted by Ken Streeter (Post 1144424)
I know this probably isn't the answer you're looking for, but just in case you're unable to find a way to easily measure the PWM signals from the cRIO, you could instead use the MAE3 with the analog option instead.

We used the analog version of the MAE3 on robots in 2007-2009 with very good success, including a prototype swerve drive we built in the off-season.

And it works beautifully, variances below 1%. Would've liked the detail of the digital one, but working beats detail, at least for now!

Once we get through the competition this year, we'll do some exploratory work on this, because I'd really like to get to a working and stable solution for people to use as an AbsoluteEncoder or some such thing.

Jimmy Cao 19-03-2012 09:37

Re: Reading an absolute encoder via PWM in C++
 
2 Attachment(s)
Quote:

Originally Posted by synthmusic (Post 1145984)
Once again, thanks for the ideas! Given other priorities and troubleshooting, we called in an order for the analog version as noted here



And it works beautifully, variances below 1%. Would've liked the detail of the digital one, but working beats detail, at least for now!

Once we get through the competition this year, we'll do some exploratory work on this, because I'd really like to get to a working and stable solution for people to use as an AbsoluteEncoder or some such thing.

If you want to use the analog version of the MA3, here's a little wrapper for the sensor. It's a bit easier to use than just treating the MA3 as an AnalogInput. Sorry there's no documentation, but feel free to ask me if you have any questions about it.

Ken Streeter 20-03-2012 12:38

Re: Reading an absolute encoder via PWM in C++
 
Quote:

Originally Posted by synthmusic (Post 1145984)
Once again, thanks for the ideas! Given other priorities and troubleshooting, we called in an order for the analog version as noted here.

And it works beautifully, variances below 1%. Would've liked the detail of the digital one, but working beats detail, at least for now!

I'm glad to hear that the analog version is working out for you.

As I mentioned, we had great success with the analog version of the MA3. We on 1519 only switched over to quadrature encoders (the US Digital E4P and E7P) since these encoders were easy to sample with the cRIO and easy to integrate with the gearboxes / shafts we have chosen for use on the robot in recent years.


All times are GMT -5. The time now is 14:31.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi