Converting sin/cos encoder outputs into position

I am using arduino uno to read 2 voltage ouputs from a magnetic encoder but I am stuck at finding an algorithm for converting those voltages into a position.

Doing some research I found that these 2 voltages are sin and cos and the angle (position) is angle = atan(sin/cos)

If the encoder shaft turns 360 deg, I have 36 cycles (voltages going up and then down to the starting value), so each cycle is 10 deg.

My voltages are reading between 0.8 and 3.9V for one cycle. The numbers below are V1, V2 and angle for one cycle (10 deg movement) calculated with the above formula.

I can see that angle value is going up and then down to the starting value in one complete cycle (like sin and cos).

The third column does not seem to be an actual angle, how can I convert it into an actual angle?

Here is what I was thinking :

  • my min value for 3rd column is 0.3
  • my max val for 3rd column is 1.3
  • interval between min and max is 1.3 - 0.3 = 1
  • since the value goes up and then down, in one cycle it goes through 2 intervals, so 1 cycle corresponds to 2 "units" on my 3rd column
  • since 1 cycle is 10 degrees and it covers 2 "units" on the 3rd column, each variation of 0,2 on the 3rd column means 1 degree encoder shaft movement (right?)
  • loop until i get a change of 0.2 on the 3rd column and that means 1 deg encoder shaft movement. The problem now is, how do I detect the direction of movement in order to find the new position?

I was reading that once I find a movement (increment or decrement) i can detect the direction based of which voltage is "leading" but I really couldn't understand the meaning of it and how to find which one is leading.

Any help is appreciated.

V1 V2 atan(V1/V2)
0.89 - 2.85 0.30
0.99 - 3.10 0.31
1.10 - 3.28 0.32
1.20 - 3.41 0.34
1.31 - 3.53 0.35
1.41 - 3.59 0.38
1.52 - 3.67 0.39
1.62 - 3.71 0.41
1.73 - 3.75 0.43
1.83 - 3.79 0.45
1.94 - 3.82 0.47
2.04 - 3.83 0.49
2.15 - 3.85 0.51
2.26 - 3.87 0.53
2.36 - 3.88 0.55
2.47 - 3.86 0.57
2.57 - 3.87 0.59
2.68 - 3.85 0.61
2.79 - 3.83 0.63
2.89 - 3.80 0.65
2.99 - 3.78 0.67
3.10 - 3.74 0.69
3.20 - 3.67 0.72
3.31 - 3.59 0.74
3.41 - 3.52 0.77
3.52 - 3.40 0.80
3.62 - 3.26 0.84
3.72 - 3.05 0.88
3.83 - 2.58 0.98
3.72 - 1.72 1.14
3.62 - 1.46 1.19
3.52 - 1.29 1.22
3.41 - 1.17 1.24
3.31 - 1.09 1.25
3.16 - 0.98 1.27
3.02 - 0.90 1.28
2.92 - 0.87 1.28
2.81 - 0.83 1.28
2.71 - 0.79 1.29
2.41 - 0.74 1.27
2.31 - 0.73 1.26
2.20 - 0.72 1.25
2.10 - 0.72 1.24
1.99 - 0.74 1.21
1.89 - 0.73 1.20
1.78 - 0.75 1.17
1.68 - 0.76 1.14
1.57 - 0.81 1.10
1.47 - 0.85 1.05
1.37 - 0.90 0.99
1.26 - 0.97 0.92
1.15 - 1.03 0.84
1.05 - 1.15 0.74
0.95 - 1.31 0.63
0.84 - 1.62 0.48
0.95 - 2.98 0.31

You may want to give this a read which hopefully will clarify the encoder signals.

If you have questions about the link ask but give the link a read first. It's more about pulse counting for position than voltage and whether A leads B or B leads A for rotation direction.

Ron

Looks like an offset problem.

First subtract a value of 0.8 so the signal goes from +0.5 to -0.5V

Second, you need atan2(V2,V1); for this

The returned angle is from +PI to -PI. This solves your direction problem.

Make it easy on yourself...use a lookup table.

Thank you for all replies.

Ron, i did read that page before posting my question and I just read it again, but I get lost at pulse counting. There is something I am missing, maybe the gap between my knowledge and that document is too big :slightly_frowning_face: I can't even ask a question. I kind of understand all of what they are saying there, but not sure how to achieve it in "that way".

femmeverbeek, after subtracting a value from voltage, the readings are going from minus to plus and using atan2, I get the angle nicely going in one direction for each cycle. Mapping the angle to an actual value is possible now.

I didn't put the numbers in a graph yet, but It should look similar with this:

MK1888, yes, I might use a mapping table.

Thank you guys.

Pulse count or actually frequency is used to calculate speed. Matters not if it is A or B. The Frequency of A or B in Hertz = N (Encoder line count as in how many pulses per revolution) * V[RPM] * 1/60. Page 4 of the link. So if we know the frequency and we know how many pulses we get per revolution we can get shaft speed. A tachometer.

Ron

Thanks for the explanation, Ron. For some reason I thought the sin/cos signals are converted in multiple pulses for each line count and then use those pulses to calculate the position in increments.

debugger2000:
Thanks for the explanation, Ron. For some reason I thought the sin/cos signals are converted in multiple pulses for each line count and then use those pulses to calculate the position in increments.

That too least I forget. When I was using rotary encoders quite a bit line count was how we knew exact position. Many of the sensors were like 3600 lines (pulses) per revolution Really good rotary encoders (Baldwin) comes to mind were expensive sensors. They were also just a pulse out so no sine. :slight_smile:

Ron