reading absolute position from a 4bit encoder

Hi all,

i have a rotary encoder which is a large wheel with slots cut out of it and 4 photo diodes to read the slots.

i read the values of these photo diodes with a port read and get back a range of number for a full rotation.

i want to work out the angle in degrees of the wheel by reading the photo diodes, but as far as i can see there can only be 16 unique combinations from 4 photo diodes. so i am guessing the wheel must be in motion and take a reading of the current number and the previous number to get a position.

there are 480 numbers in the pattern before they loop round again,

i can’t think of any way to turn this into a degree value other than storing all the numbers in a big array and searching the array with each update to find out where in the array the wheel is sitting. which is time consuming, and i need to capture every change in the state to get an accurate reading.

i don’t have any code at the moment i am just trying to thing of how i would do it at all. i can post the list of numbers in either binary or decimals, but the math for this is beyond me at the moment. any tips would be great. thanks!

I can't imagine why you would need a big array to store consecutive numbers. Just count up and down.

Wheel mouse has the slotted wheel per axis and only needs 2 light bridges (sensors) to know wheel movement/direction using Gray Code. You might want to look up how they do it.

"there are 480 numbers in the pattern before they loop round again,"

480 numbers for 360 degrees. I bet there's a math problem there somehow.
Like 1 degree would be more than 1 number cause 480 is bigger than 360 or something.

Do you have a data sheet and/or schematc for the encoder that you can share?

hi guys thanks for the reply,

the encoder wheel is from a steering angle sensor commonly used in VW and Audis

the encoder wheel has an inner ring of slots that are evenly spaced and then an outer ring which is random.

the result is that when reading the photo diodes doesn’t create a sequential number. otherwise that would be perfect.

what i am trying to do is find the position of the encoder, not just its rotation and direction.

i can get the rotation and direction from the inner ring alone, but i also want to work out the angle of the wheel and that is where i am having trouble.

this isn't the encoder i am using, but it is almost identical in how it is setup:

as you guys can see, there are 4 photo diodes at the top, an inner ring which is consistent, and an outer ring which is random.

by port reading the 4 photodiodes to get a binary value of their positions i get 480 different results until the pattern repeats.

Can you see how it would be absolutely impossible to answer this question without exact knowledge of the slot pattern?

With your specific encoder of interest, how many rotations of the encoder are required to to take the wheels from lock to lock (full traverse of the pinion)? Does the 480 count make more sense when considering that range of motion?

thanks for the replies guys,

i can post the binary values for one complete revolution which would define the slots in the encoder.

the 480 count is for one rotation of the encoder, which would be one rotation of the steering wheel, to do multiple rotations there is a secondary wheel that counts full rotations of the encoder wheel and that smaller wheel is monitored with hall effect sensors. it counts 6 rotations so that is easy to track

i think the reason it is 480 per rotation is because there is not enough unique positions in a 4 bit value to give 360 degrees, so instead to work out a degree it must calculate it from the previous position to the next, which must change within a degree.

here is a full rotation in binary and in decimals:

0000,
1000,
1010,
1110,
1111,
1011,
1001,
1000,
1100,
1110,
0110,
0111,
0011,
0001,
0101,
0100,
0110,
1110,
1111,
1101,
1100,
0100,
0000,
0010,
0011,
0001,
1001,
1000,
1100,
1110,
1111,
0111,
0101,
1101,
1001,
1000,
0000,
0010,
0011,
0111,
0101,
1101,
1100,
0100,
0110,
1110,
1010,
1011,
1111,
1101,
1001,
1000,
1010,
1011,
1111,
1101,
0101,
0001,
0000,
1000,
1100,
1110,
0110,
0111,
1111,
1101,
1100,
0100,
0110,
1110,
1111,
1011,
1001,
0001,
0101,
0100,
1100,
1000,
1010,
1110,
1111,
0111,
0101,
0001,
0000,
0100,
0110,
1110,
1111,
0111,
0011,
0001,
0101,
0100,
1100,
1110,
0110,
0010,
0011,
1011,
1001,
0001,
0000,
0100,
0110,
1110,
1010,
1011,
1001,
1101,
1100,
0100,
0000,
0010,
0110,
0111,
0011,
0001,
0000,
1000,
1100,
1110,
1111,
1101,
0101,
0001,
0000,
1000,
1010,
1011,
1001,
0001,
0101,
0100,
0110,
0111,
0011,
1011,
1001,
0001,
0101,
0100,
1100,
1110,
1111,
1011,
0011,
0001,
0000,
1000,
1010,
1110,
0110,
0111,
0011,
1011,
1001,
1101,
1100,
1110,
1010,
1011,
0011,
0001,
0101,
1101,
1100,
1000,
0000,
0010,
0110,
1110,
1111,
1101,
0101,
0100,
0110,
0010,
1010,
1011,
1111,
0111,
0101,
0001,
1001,
1000,
0000,
0100,
0110,
0111,
0011,
0001,
1001,
1000,
0000,
0100,
0110,
0010,
0011,
0111,
0101,
0001,
1001,
1000,
1010,
0010,
0011,
0111,
1111,
1101,
1001,
1000,
0000,
0010,
1010,
1011,
1111,
1101,
1100,
1000,
1010,
1110,
1111,
1101,
1001,
1000,
0000,
0100,
0110,
1110,
1111,
0111,
0101,
1101,
1100,
1110,
0110,
0111,
0101,
0001,
1001,
1000,
1100,
1110,
1010,
1011,
1111,
1101,
0101,
0100,
0000,
0010,
0011,
1011,
1111,
1101,
1100,
1110,
1111,
1011,
1001,
0001,
0000,
0010,
1010,
1110,
1111,
0111,
0101,
0100,
1100,
1110,
0110,
0111,
0011,
1011,
1001,
1000,
0000,
0100,
0110,
0010,
1010,
1011,
0011,
0001,
0101,
0100,
1100,
1000,
1010,
0010,
0110,
0111,
1111,
1101,
1001,
1000,
1100,
1110,
0110,
0010,
0011,
0001,
0101,
0100,
0000,
0010,
0110,
0111,
1111,
1101,
0101,
0100,
1100,
1000,
1010,
1011,
0011,
0001,
1001,
1000,
1010,
1110,
1111,
1011,
0011,
0001,
1001,
1101,
1100,
1110,
1010,
0010,
0011,
0111,
1111,
1101,
0101,
0100,
1100,
1110,
1010,
1011,
0011,
0111,
0101,
0100,
0000,
0010,
1010,
1110,
1111,
1011,
1001,
1101,
1100,
0100,
0110,
0010,
0011,
0001,
0000,
0100,
0110,
0111,
1111,
1101,
1001,
0001,
0000,
0010,
1010,
1011,
0011,
0001,
0000,
0010,
0110,
0111,
0011,
1011,
1001,
0001,
0000,
1000,
1100,
1110,
1010,
1011,
1001,
1000,
1010,
0010,
0110,
0111,
0011,
0001,
0101,
1101,
1100,
0100,
0110,
0111,
0101,
0100,
0000,
1000,
1010,
0010,
0011,
0111,
0101,
0001,
0000,
1000,
1010,
0010,
0011,
1011,
1001,
1101,
1100,
1000,
1010,
0010,
0011,
0001,
1001,
1101,
1100,
1000,
1010,
0010,
0110,
0111,
0101,
1101,
1100,
0100,
0000,
0010,
1010,
1011,
0011,
0111,
0101,
1101,
1100,
1000,
1010,
1011,
0011,
0111,
0101,
0001,
0000,
1000,
1100,
1110,
0110,
0010,
0011,
0111,
0101,
0100,
0110,
0010,
0011,
1011,
1001,
0001,
0101,
0100,
0000,
0010,
1010,
1011,
1001,
0001,
0
8
10
14
15
11
9
8
12
14
6
7
3
1
5
4
6
14
15
13
12
4
0
2
3
1
9
8
12
14
15
7
5
13
9
8
0
2
3
7
5
13
12
4
6
14
10
11
15
13
9
8
10
11
15
13
5
1
0
8
12
14
6
7
15
13
12
4
6
14
15
11
9
1
5
4
12
8
10
14
15
7
5
1
0
4
6
14
15
7
3
1
5
4
12
14
6
2
3
11
9
1
0
4
6
14
10
11
9
13
12
4
0
2
6
7
3
1
0
8
12
14
15
13
5
1
0
8
10
11
9
1
5
4
6
7
3
11
9
1
5
4
12
14
15
11
3
1
0
8
10
14
6
7
3
11
9
13
12
14
10
11
3
1
5
13
12
8
0
2
6
14
15
13
5
4
6
2
10
11
15
7
5
1
9
8
0
4
6
7
3
1
9
8
0
4
6
2
3
7
5
1
9
8
10
2
3
7
15
13
9
8
0
2
10
11
15
13
12
8
10
14
15
13
9
8
0
4
6
14
15
7
5
13
12
14
6
7
5
1
9
8
12
14
10
11
15
13
5
4
0
2
3
11
15
13
12
14
15
11
9
1
0
2
10
14
15
7
5
4
12
14
6
7
3
11
9
8
0
4
6
2
10
11
3
1
5
4
12
8
10
2
6
7
15
13
9
8
12
14
6
2
3
1
5
4
0
2
6
7
15
13
5
4
12
8
10
11
3
1
9
8
10
14
15
11
3
1
9
13
12
14
10
2
3
7
15
13
5
4
12
14
10
11
3
7
5
4
0
2
10
14
15
11
9
13
12
4
6
2
3
1
0
4
6
7
15
13
9
1
0
2
10
11
3
1
0
2
6
7
3
11
9
1
0
8
12
14
10
11
9
8
10
2
6
7
3
1
5
13
12
4
6
7
5
4
0
8
10
2
3
7
5
1
0
8
10
2
3
11
9
13
12
8
10
2
3
1
9
13
12
8
10
2
6
7
5
13
12
4
0
2
10
11
3
7
5
13
12
8
10
11
3
7
5
1
0
8
12
14
6
2
3
7
5
4
6
2
3
11
9
1
5
4
0
2
10
11
9
1

Do you have access to a logic analyzer? Maybe if you could display graphically the signals from each sensor you could better see their relationships. I believe you're right, the inner ring looks like a quadrature setup to yield speed and direction. Possibly it also provides timing information to decode the signals from the outer ring.

That code is called a grey code. Note that from one code to the next only one bit changes. So that outer ring is not random is is a specific code that repeats several times per revolution. This makes it impossible to get an absolute angle from a sensor like this.

thanks for the replies guys,

i have a logic analyser i can try but i feel there should be some software somewhere i can feed the binary in and get some data back that might be easier to read.

i understand that the ring doesn't have enough unique slots to give an absolute position when stationary, but it is an angle sensor and originally did feed back some kind of position angle, so i am assuming that it can track its position after a bit of rotation then it can work out where it is in the list of possible combinations and simply keep track after that.

if not then i don't see the purpose of the outer ring, surely if it can only measure travel and direction then the inner ring would be enough.

so i guess what i am trying to do is work out a bit of code that can find out what angle the ring is at from a few readings and after that keep track so it can give an accurate angle measurement.

so i am assuming that it can track its position after a bit of rotation then it can work out where it is in the list of possible combinations and simply keep track after that.

No you can't because you will never have a reference position.

if not then i don't see the purpose of the outer ring,

The outer ring is part of the code generation, the two rings work together to give you the grey code you are seeing.

so i guess what i am trying to do is work out a bit of code that can find out what angle the ring is at from a few readings and after that keep track so it can give an accurate angle measurement.

Which as I say is not possible with what you have described so far. Normally things like this have a reference signal at once or twice per rotation. Once you see that you can then use the relative code to work out your angle from that reference signal.

thanks for the reply,

the way i was thinking is, lets say you read the wheel and get the number 0000, then you look at the array of numbers which includes all the combinations for an entire rotation, you search the array for 0000, then when the wheel moves again and you get something like 1000, you search the array for a place where 0000 is followed by 1000, then maybe do that a third time and that will give you a reference point in the array, from that point, as long as all movement is recorded it should stay in sync and should be able to give an accurate degree measurement, based on the current location in the array.

but what does the grey code do if you can get just as much information from the inner ring on its own?

sorry i mentioned somewhere before that there is a secondary wheel that advances one step for every full revolution of the encoder wheel, it has a magnet on it and hovers above some hall effect sensors. so the start of a new rotation can be measured but only after the wheel has turned enough to trigger the smaller wheel.

You may be correct in that a particular sequence of values gives you an absolute position.

My first thought was to make up a 12, 16 or 20 bit number out of three to five successive entries and check for uniqueness. I did that in a spreadsheet and discovered that this approach doesn't work because, after sorting the values, duplicates are found.

The columns below are code, 16*(16a1+a2)+a3, those sorted, 16(16*(16*a1+a2)+a3)+a4, those sorted, etc for up to 5 entries. EDIT: doesn't work using 6 successive entries either.

Tell us more about this inner wheel.

0,25,19,2222,561,527087,66151
8,2049,19,35567,567,1183483,66219
10,2688,19,44795,571,1576889,66222
14,3752,19,61369,615,1903512,66663
15,4074,21,64408,615,1706380,66670
11,3070,21,47500,615,1312974,66670
9,2495,21,39118,622,1117414,67746
8,2203,21,36070,683,1314407,67755
12,3209,21,52839,683,1705587,67758
14,3784,25,58995,683,1312561,67758
6,1772,25,26417,683,852757,67790
7,1902,25,29461,686,655700,67790
3,886,25,12628,686,263494,67790
1,311,25,5446,1122,394350,67790
5,1299,69,21614,1122,591599,131865
4,1105,69,18159,1127,659197,131957
6,1605,69,28413,1127,1314780,132031
14,3684,69,61404,1134,1904068,132723
15,4070,69,64964,1134,1838144,132723
...

Maybe there’s an index sensor, the car must have some way to know where the wheel is oriented on startup if it can be turned with power off.

OK I took another approach, I noted a number and then how many steps were made before that number was encountered again. I then counted that number. However I have not got too many done. It might be that for any given number the number of steps before a repeat gives some clue to the angle.

The attached excel spread sheet is a start, scroll down to the bottom to see the count. Some one might like to complete it and see if a pattern emerges but so far I can’t see one.

What car is it and have you tried looking for the information on this encoder. It is likely it is sitting in a patent somewhere if the encoder is marked with a patent number.

sequence.zip (17.3 KB)

thanks again for the replies guys,

i am assuming that the reason that using math to get a higher bit number isn't working because there are only 16 possible numbers every time so its would be more likely that there would be duplicates, but i appreciate the effort.

i was wondering if it could work by reducing the possible variables each step. so on boot up you have the current position of the wheel and an array with all the different positions in order in an array.

because you boot on a position we can already narrow that down to a few places in the array where the wheel might be,

as soon as it moves we can zero in a second time, until we know exactly where it is and then start tracking its position by using the array as a reference. problem is i have no idea how to use the array as a sort of look up table, or how the code would work to search through the array to zero in on the position.

i have looked around the original board and i can't seem to see anything that could give an absolute position, and saving it in memory wouldn't work because the wheel could always be moved when the power is off.

on page 1 the picture i put up of the smart car encoder is basically all i have to work with, there is the 4 optical sensors giving the grey code from the wheel, which has an inner ring of consistently spaced holes and an outer ring with inconsistent holes. then to the edge (the image actually has a red circle to indicate it) there is a secondary wheel which is rotated by 1/6th for every full rotation of the large wheel. this moves a magnet over 6 hall effect sensors. from what i can tell this magnet covers two sensors at a time which means you also get directional information from this wheel.

NeX:
there is a secondary wheel which is rotated by 1/6th for every full rotation of the large wheel. this moves a magnet over 6 hall effect sensors. from what i can tell this magnet covers two sensors at a time which means you also get directional information from this wheel.

I suspect this wheel, in addition to providing direction (although that may not be its primary function), is also part of the code generated by turning the wheel. The MSB part, if you will.

Guessing: going by the SMDs on the board the encoder may well be pretty smart. Is it possible the angle information is being encoded and sent serially out one of the connector pins? Meaning you might not have to do that part, just interpret the sent codes.