• 0
1bioKAT

Digital Steps Quadrature Encoder = Analog Angle - Plotted on Oscilloscope

Question

I am trying to set up a motor's encoder to provide rotational angle as an analog signal that I can plot along with other monitored voltages/currents, etc on the Oscilloscope.  With the encoder providing a digital signal, I have tried to modify a script used to provide numerical values of the relative step spacing into a pure step counts (I would then calibrate these degrees), but am having trouble with getting this code to work.  Additionally, I am second guessing if I am looking at the game-plan properly as even though the code that I am modifying provides analog values, I am not able to get these values to plot on the scope.  Given the somewhat basic nature of my code, it is probably clear to some that I am not an experienced coder, but I am looking forward to learning more.

Any guidance on where to look/what to try would be appreciated.

DC-Encoder - Oscilloscope Angle.PNG

DC-Encoder - Oscilloscope Angle_Digital-Script.PNG

Share this post


Link to post
Share on other sites

13 answers to this question

Recommended Posts

  • 0

Hi @1bioKAT,

The engineer best suited to answer your question is out on medical leave, but I wanted to let you know that we seen your question and have not forgotten it.

Thanks,
JColvin

Share this post


Link to post
Share on other sites
  • 0

Thanks @JColvin for the reply,

In case it helps you, or your colleague when he returns, I am providing further information of what I have continued to try.

With the Measurements tool, I can show the number of cycles seen by Encoder_A (red "A" == 667), but this shows the total number of steps on the oscilloscope screen or in a set memory window (from what I can tell), not the total accumulated step count or the step count at that time = n (continuing to increase over time if positive steps [n++], and decrease if negative steps [n--]...) which is more what I am looking for so that I can correlate power with "real" position.

I have tried a variety of things within the Custom plot ("Math 4" in this case) to try to show current Cycle Count rather than Encoder_A pulses, but have not figured out any code to pull this yet ("Encoder_A.Cycles" and "Encoder_A.Cycle" don't error out, but they don't seem to provide a meaningful plot as it is maxing out a value, that even with extreme division or subtraction isn't pulling the value off of the max value (1TV).

In pulling Encoder_A into the Oscilloscope (not just in the bottom Digital display), I am not getting all of the steps.  I assume this is due to differing sampling rates.  Would this be the case with step counts carried in as well?  If so, I still may need to look at a different method.

Thanks,

1bioKAT

Oscilloscope_Steps.PNG

Share this post


Link to post
Share on other sites
  • 0

Hi @1bioKAT

I think you are interested in the rotation speed and direction.
You should perform Record to have many samples to work with, higher resolution over longer period.

In the following project:
- The 'Encoder' custom decoder calculates the number of samples between to two rising edges of encoder A and depending on B state considers the direction. 
- The Math1 calculates the RPM = sample_rate / number_of_samples * 60_seconds_in_minute / 6_poles_per_turn
- Channel1 measures the voltage, Math 2 applies a low pass filter
- Channel2 measures the current, attenuation of 0.162 for 6.2 Ohm shunt, Math 3 applies a low pass filter
- Math 4 power

Here you have the project: RPM.dwf3work

image.thumb.png.f492bbcdf6604cd8033368854507d45d.png

image.png.3f2380fba6597af534d4b68e1d1c6985.png

Share this post


Link to post
Share on other sites
  • 0

Thanks @attila,

The attached plots are from a different system, but gives some of the same information/idea.  On the first plot, both position (orange) and force (blue) are plotted with respect to time.  The second plot graphs force vs position.  With the orange plot below, there is a constant speed in one direction and then a constant speed in the other direction (the slope would provide speed as you provided nicely with the (Rate/Encoder*60/6).  While the rate is helpful for me, the actual step count provides me with better knowledge of what is happening (and if there is a correlation to position, where things are happening).  Depending on the gear ration, location of encoder, diameter, etc the steps per degrees (or steps per distance) will vary, but it is this steps (positional awareness) that I am after (more so than speed or rate).

 

With some modifications to what you provided, I am getting close, but am getting some results I don't understand by swapping numbers.  I would have thought I would have been just triggering negative numbers, but rather am getting numbers in the 4Billion range (and decreasing by one) for steps in what I will currently call the negative direction and steps gradually counting up from 0 in the positive direction (0, 1, 2).  Do you see what I am doing wrong for the negative direction (so that they show counting negative from 0... 0, -1, -2...).  With the positive side, it seems that there are still some odd steps where not all are integer steps, but some (not very many) are fractional steps.

Thanks,

1bioKAT

 

Positive vs Negative Steps.txt

RawData vs Time.PNG

XvsY Data.PNG

Positive Steps.PNG

Negative as 4Billion.PNG

Edited by 1bioKAT

Share this post


Link to post
Share on other sites
  • 0

Hi @1bioKAT

I forgot to mention that the values/flags are stored and represented by default as unsigned 32bit integer.
In case you use signed values have the following in the Value to Text code:
return (value > 0x7FFFFFFF) ? value - 0x100000000 : value;

image.png.41556113bc743076331597881deec20f.png

Share this post


Link to post
Share on other sites
  • 0

@attila

I tried several things yesterday and today as I feel the things that you pointed out should be getting me there, but for some reason I am still falling short.

I feel like what we have in the code should be causing positive steps (cnt++) when Encoder B (DIO 1) = 0 at the rising edge of Encoder A (fA==1 && pA==0), and then causes negative steps (cnt--) when Encoder B (DIO 1) = 1 at the rising edge of Encoder A.  I tried a few shifts in code including else statements instead of multiple stacked if's, but I'm not seeing any indication that the second scenario is ever evaluating.  I at times am swapping which ("fB==0" or "fB==1") is associated with cnt++ and cnt-- , and fB==0 always seems to be the one evaluated, as when "fB==0" leads to "cnt--" then I am displaying small negative integers that increase (and plotting integers decreasing from 0x100000000 (4.2949G), and when "fB==0" leads to "cnt++" I am displaying small positive integers that increase (and plot as increasing from 0).

In the attached image "Count direction constant.PNG", I tried to highlight a little more of the shift I should be seeing (my pseudo-code of sorts) based on the signals.  I also included an image of a debug attempt, where I would have attempted steps to have 0's or 1's depending on direction.

Please let me know if you have other thoughts of things that you feel I should try to first get it to count up and down as steps increase and decrease with Encoder B signal, and then I anticipate we would be able to plot positive and negative steps being with respect to 0.  For plotting, I started looking at custom plot signals to mathematically compensate, but saw that the directions weren't changing, so knew I needed to fix that first.

Thanks,

1bioKAT

 

Count direction constant.PNG

2020-02-20_Debug_0vs1.PNG

2020-02-20_If Else If Else.txt 2020-02-20_Increase_Decrease.txt 2020-02-20_Index_Attempt.txt

Share this post


Link to post
Share on other sites
  • 0

Hi @1bioKAT

Use the following code to follow the phase, encoder steps:

 

// Decoder
c = rgData.length
var pA = 0 // previuos encoder A value
var cnt = 0 // initial phase/counter
for(var i = 0; i < c; i++){
    fA = 1&(rgData [ i ] <<0)
    fB = 1&(rgData [ i ] <<1)
    if(fA==1 && pA==0){ // encoder A rising edge
        if(fB==1){ // encoder B label indicates direction
            cnt++
        }else{
            cnt--
        }
    }
    rgValue [ i ]  = cnt
    rgFlag [ i ]  = 1
    pA = fA
}

function Value2Text(flag, value){
  switch(flag){
    case 0: return "X";
    default:  return (value > 0x7FFFFFFF) ? value - 0x100000000 : value;
  }
}

In the Scope Math channel you also need to convert to signed value:
(Encoder > 0x7FFFFFFF ? Encoder - 0x100000000 : Encoder)

Edit:
The insert code is not working and I just notice the indexing text ( [ i ] ) was removed. Now I added these with spacing...

Edited by attila

Share this post


Link to post
Share on other sites
  • 0

@attila

I tried the new code that you sent and am still not getting proper results.  With the newest code, I am getting a flatline (midway between 0&1 similar to "ignore").  When I add array index locations ('s) like what you had in some of the other code, I am back to getting similar results as before .  Given the similarities in the new code to the old codes, I tried looking deeper to see if I could figure out anything that is causing me to not get steps, which I feel you are likely getting in your data/runs.

With yesterday's tests, I was thinking that Encoder B "fB" was never evaluating to "1" (initially thinking that meant it wasn't getting to that layer of the IF statement somehow).  Today's tests included swapping "fA" & "fB" in the code, and it seems that DIO_0 is the only one properly processing.  DIO_1 which was for "fB" is not properly processing its state 0vs1 in the signal.  I say that because while it is receiving and showing a digital signal (the top two lines), and these signals are showing values of 0 and 1 (slightly offset from the graphical representation, but still part of the data), when I swap the variables such that "fA" is tied to DIO_1 I get a flatlined output (as "fA" && "pA" are never going to show a positive step ... something is causing the code, or signal seen by the code, to never see it going "HIGH").  When "fA" = DIO_0, I get steps..., but since "fB" = DIO_1 and it never goes HIGH, the direction stays with the "fB == 0" case.  I tried things like "fB > 0" or "fB !0" to see if I could get signal/direction differentiation with these, but I am not.

After these tests, I added additional signal pins which are receiving duplicate signals via physical wired connection: DIO_0 = DIO_14 & DIO_1 = DIO_15.  Changing the code such that the signal addresses are changed (0->14 & 1->15), and I go back to flatline.  Swapping 14&15, and I stay flatlined.  I don't know if this means that only DIO_0 is properly seeing/understanding the signal within the code, or if the "rgdata<<..." or "rgdata..." is only working properly for DIO_0.

I figured a simple test would be the code in "CountSteps_1-Channel" where it only looks at one channel and counts the steps.  I don't know if you get anything different, but for me, I only get steps and step counts on DIO_0, changing the "0" (in:    "  fA = 1&(rgData<<0)  ") to the other values that I currently am sending the signal to (1, 14, & 15), the result for me is flatlined.  Have you experienced anything like this before?

NormalDIO0&1.PNG

SwappedDIO0&1.PNG

2020-02-21_AlternatePins.PNG

CountSteps_1-Channel.txt

Share this post


Link to post
Share on other sites
  • 0

@attila

I believe I have attached the items you are asking for.  If I have missed something that you need, please let me know.

I added a custom pattern on channels 12 & 13 and have those wires directly connected to 2 & 3 respectively to act as another evaluation, but am not successfully getting steps on these.

Thanks,

1bioKAT

2020-02-21_Encoder_Debug.PNG

2020-02-21_Encoder_Debug.dwf3work 2020-02-21_Encoder_Debug_Acquisition-Data.dwf3scopeacq 2020-02-21_Encoder_Debug.dwf3scope

Share this post


Link to post
Share on other sites
  • 0

Hi @1bioKAT

2020-02-21_Encoder_Debug.dwf3work

image.thumb.png.c163525668f569e335849ea860f4b91f.png

// Decoder
c = rgData.length
var pA = 0 // previuos encoder A value
var cnt = 0 // initial phase/counter
for(var i = 0; i < c; i++){
    fA = 1&(rgData [ i ] >>14) // DIO 14
    fB = 1&(rgData [ i ] >>15) // DIO 15
    if(fA==1 && pA==0){ // encoder A rising edge
        if(fB==1){ // encoder B label indicates direction
            cnt++
        }else{
            cnt--
        }
    }
    rgValue [ i ]  = cnt
    rgFlag [ i ]  = 1
    pA = fA
}

function Value2Text(flag, value){
  switch(flag){
    case 0: return "X";
    default: return (value > 0x7FFFFFFF) ? value - 0x100000000 : value;
  }
}

// Math 7
(Steps > 0x7FFFFFFF ? Steps - 0x100000000 : Steps)

Share this post


Link to post
Share on other sites
  • 0

@attila

So it looks like it is the aspect of changing the "carrot" direction from the initial code.

"<<" was working on "DIO 0", but all seem to work with ">>".  Thanks for your help in this.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now