Rotary Encoder--Need help solving three problems

Hey guys, I'm new to Arduino and Processing and coding in general and could really use a hand. I've got a rotary encoder hooked up to a hand drill and eventually my goal is to make every every turn of the handrill spin through 12 frames or so of a 24 frame looped animation on a projector. I'm early in the project but I've come against 3 major issues which I'm not yet quite equipped to deal with. I'm sure with time I'll figure it out but any help at all I'll greatly appreciate.

Issue #1: My encoder functions great with the code below, which I found on another site. The encoder has 24 steps per rotation which is dandy and all, but the problem is that every step it prints in increments of 4. Meaning one step takes me from 0 to 3, the next from 3 to 7, and so on. My diabolical plan was that I'd name my still frames something like MyAnimation_(VARIABLE).png, and I'd just call up MyAnimation_0.png and MyAnimation_1.png and so on, but that won't work if the code is going to skip every 3 frames. How can I tame it? I imagine it's something simple like dividing something by 4 somewhere? But what exactly?

Issue #2: The encoder cranks up to 255 and then zips right back to zero. If I go backwards from 0, then it goes to 255. The behavior itself is great for my loop, but the number 255 is no good. I need to make the cap something divisible by 24, like 239 for example (That way I can save out frames for 10 consecutive loops and personalize each loop so it doesn't seem quite so...loopy.) I confess I have no idea what to do here.

Issue #3: This is more of a question for another forum and I'm more worried about taming the encoder right now, but if you guys have any ideas. What are some good ways to call on and playback the frames of the animation, preferably fullscreen? Again this is something I'm worried about more later on and at that point I'll find the appropriate forum for it, but if you just happened to have some information that points me in the right direction ahead of time. It would be most appreciated.

Thanks so much in advance. Here's the code I'm using at the moment:

/* Rotary encoder read example */
#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC
 
void setup()
{
  /* Setup encoder pins as inputs */
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  Serial.begin (115200);
  Serial.println("Start");
}
 
void loop()
{
 static uint8_t counter = 0;      //this variable will be changed by encoder input
 int8_t tmpdata;
 /**/
  tmpdata = read_encoder();
  if( tmpdata ) {
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
    counter += tmpdata;
  }
}
 
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}

could you please tell / show us what encoder you have ?

-bino-

Issue #2:

 static uint8_t counter = 0;      //this variable will be changed by encoder input
 uint8_t tmpdata;

uint8_t is an unsigned 8-bit (byte) value that can count 0-255. Change this to uint16_t to get 0-65535.

I can't see anywhere where you actually read the encoder, so you are clearly not posting ALL the code. Why hide the problem you want fixing?

You can use processing for the display but you will have trouble loading that many pictures into memory so the solution is to make it a movie and have processing play to a specific line number. This is your biggest problem.

The state-model you use to read your rotary encoder is the right approach for low-cost mechanical encoders and should give you a consistent and reliable directional count. 4-steps per detent is as expected, but you can easily limit this to one if so desired.

You would then need to rewrite your loop along the following lines:

  • Create a static int8_t variable to hold step_count (one count per detent, signed)
  • Create a static int8_t variable to hold loop_count (one count per loop, signed)
  • Create a static int8_t variable to hold read_count (replaces your temp variable)
  • Add the output from read_encode to read_count each time through the loop
  • If read_count >= 4 add one to step_count and set read_count to 0
  • If read_count <= -4 subtract one from step_count and set read_count to 0
  • if step_count >= 24 add one to loop_count and set step_count to 0
  • if step_count <= -24 subtract one from loop_count and set step_count to 0[/li][/list]

You can then act on step_count for single increments/decrements or loop_count for full rotations.

The state model (your “read_encoder “ function) requires frequent polling (not to miss steps) and this may be challenged as you add code to your sketch. To overcome this, you want to look at triggering encoder reads using pin change interrupts.

Ah, thanks so much for the prompt responses everyone. I'll reply to each one by one.

BenF: Thank you very much, this will be immensely helpful. I'll do my best to implement it immediately and get back to this thread should I fail to execute.

GrumpyMike: I apologize, but this is the entirety of the code. I've double checked it to be sure. All it does at the moment is read the encoder's outputs on pins 8 and 9 on my Arduino Uno R3 and then prints the results in the serial monitor. It does not reflect any of my desires at the moment. Thank you for the suggestion to use a movie clip instead. That makes a lot of sense.

Marco_C: That's informative, thank you. It's helpful to understand the nature of this value better.

binooetomo: Apologies, here's the link to my exact encoder: http://www.sgbotic.com/index.php?dispatch=products.view&product_id=1093 It is hooked to my Arduino Uno R3 precisely as the datasheet suggests.

I'm sorry BenF, I'm grasping the concept but the syntax of the code is beyond me. Could I possibly trouble you to phrase it in the form of code, just in the context of loop function?