Saving rotary encoder data for next power up

What do you mean the bitmask will ignore pins 12 and 13?

There's a table on the linked page showing the conversion.

Read about arrays: Arduino Reference - Arduino Reference

If @wvmarle's approach doesn't work for you could take a look at the
bits and bytes' section of the Arduino Reference.

1 Like

Ok thank you, @wvmarles 's approach looks straightforward. So I would still be able to use pins 12 and 13 for I/O?

Yes, of course, they're not affected by other readings.

It is actually why you must do this and operation, to ignore the status of those two pins in that statement.

Of course you can also use four pins of PORTA or PORTD (see the ATMega328 pinout to find out which pins this are exactly), or higher bits and then use a bit shift operation. Whatever is convenient for your design.

If those terms look like abracadabra to you, look up " bit manipulation". A very useful technique, which comes back time and again.

Also, remember: there are 10 kinds of people. Those that know binary, and those that don't.

2 Likes

I tried doing this, and I only get zeros in my serial monitor.

void setup() {
  // put your setup code here, to run once:
  pinMode(8,INPUT);
  pinMode(9,INPUT);
  pinMode(10,INPUT);
  pinMode(11,INPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  int position = PORTB & 0b00001111;
  delay(2000);
  Serial.print(position);
}

I am working on building a robot for my class in mechanical engineering, and it is due in two days. I need urgent assistance in getting a rotary encoder set up.
This is my encoder:

Someone on the forum recommended that I connect the 4 pins to
position = PORTB & 0b00001111;

This is only giving me zeros in the serial window.
Is there some other way to read the position? I want it to give position data from (0,16)

How do you have it wired? Did you enable pullup resistors? Do the individual pins work with the Button or StateChangeDetection example sketches? How fast will the encoder turn?

And what are you connecting it to? An Uno? Mega? Nano?

Yes I have it wired. Am using an external 10K resistor on my breadboard. I'm using an UNO. Yes the individual pins are working. The encoder can do over 600 rpm.
I have been fiddling with it, and reading the bits, and I get something like this:

Here is my code: 
bool bit1=0;
bool bit2=0;
bool bit3=0;
bool bit4=0;

void setup() {
  // put your setup code here, to run once:
  pinMode(8,INPUT);
  pinMode(9,INPUT);
  pinMode(10,INPUT);
  pinMode(11,INPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  bit1=digitalRead(8);
  bit2=digitalRead(9);
  bit3=digitalRead(10);
  bit4=digitalRead(11);
  Serial.print(bit1);
  delay(500);
  Serial.print(bit2);
  delay(500);
  Serial.print(bit3);
  delay(500);
  Serial.print(bit4);
  delay(2000);
  Serial.print(' ');

}

The encoder outputs 4 bit Gray code.

https://en.wikipedia.org/wiki/Gray_code

How? Lose the one 10K resistor, which is causing your problem.

Connect the common to ground.

Connect the four switch contacts to your input pins and use INPUT_PULLUP for you pinMode().

a7

1 Like

Could someone please provide me with an example code of how to read the position as a value from 0-16? This is way over my head.
The pins I would like to use are A0, A1, A3, A4

Why the delays? If you are running it a 600RPM, then you'd have `1000/(600/60*16) = 6.25 microseconds per change.

II'd stack the 4 bits up into a single value, like newCode = bit1<<3 | bit2<<2 | bit3 <<1 | bit4 and print only when newCode != lastCode.

(Edit to fix typos)

1 Like

Let's first get 16 different values out of the switching.

You can use the PORTB reading, that's a good idea. I do not know the port that A0..A3 are on.

Then you can google about conversion from Gray code to regular 0 to 15 as you turn the encoder.

a7

Until if the moderators combine threads, this:

Don't make a new thread w/o thinking.

a7

1 Like

This takes your code and applies the:

and the #7 advice:

bool bit1=0;
bool bit2=0;
bool bit3=0;
bool bit4=0;
int lastCode = -1;
int newCode;

void setup() {
  // put your setup code here, to run once:
  pinMode(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  bit1=digitalRead(8);
  bit2=digitalRead(9);
  bit3=digitalRead(10);
  bit4=digitalRead(11);
  newCode = bit1<<3 | bit2<<2 | bit3 <<1 | bit4;
  if (newCode != lastCode) {
    lastCode = newCode;
    Serial.println(newCode);
  }
}

If your connections bounce, you could add a delay(2);

Ok, I tried this and also used the pullup resistor, and am reading values from 0-15. They are not in the correct order thought; for example, I turn once tick and it jumps up by 5. How do I have to have the wires hooked up? I want to use A0,A1,A3,A4. Thanks

That's how gray code works. Only one bit changes per move. Maybe try:

Serial.println(newCode,BIN);

to see the bits toggle.

There were a few reference up above about decoding from gray code into other codes.

... it depends on what lines you have hooked to which pin. You could change the order of the pins by changing the bit-shifting operator <<.

So how do I get it to go up by one each click? I would want to know my position as just an integer 0-15 so I can convert into an angle.

If you have 0-15 numbers and want a different 0-15 numbers out as per,

the easiest way is to make and use a "look up table".

const int untangled[] = {8, 12, .....};
...
Serial.print(untangled[newCode]);

https://forum.arduino.cc/t/reading-an-absolute-encoder-4-bit-gray-code-16-position-solved/641618

1 Like