3

I'm trying to calculate the coming RPS from rotary encoder. I am trying to get it by checking the status with digitalRead. However, I can not get more than 6 RPS. Any solution? I will be obliged for your help. Following is the code.

float rps;

void setup() {
  Serial.begin(9600);
  DDRC &= ~_BV (1); // pinMode (A1, INPUT);
}

void loop() {
  static int lastReedState;
  static unsigned long lastTransition;
  int reedState = (PINC & _BV (1)) == 0; // digitalRead (A1);
  // On a rising transition of the reed switch:
  if (reedState == LOW && lastReedState == HIGH) {
    // HIGH LOW measuring the low period
    // Compute time since last valid transition.
    unsigned long now = micros();
    unsigned long revolutionTime = now - lastTransition;
    // measuring the High period
    // Compute the RPS
    rps = 1.00 / (12.00*revolutionTime) *1000000.00;
    // 12 is rotary encoders resolution
    // Remember this transition.
    lastTransition = now;
  }
  // Remember last state.
  lastReedState = reedState;
  Serial.println(rps);
}
dda
  • 1,595
  • 1
  • 12
  • 17
zalt
  • 93
  • 1
  • 2
  • 15

2 Answers2

1

Consider using code similar to that shown in answers to the following questions: Reading from a KY-040 rotary encoder with Digispark; and Read RC receiver channels using Interrupt instead of PulseIn; and Can external interrupts be OR'd together on the '328 (Uno)?.

The first answer illustrates a fast-operating state machine to handle quadrature-encoded signals, ie rotary-encoder inputs.

The second answer illustrates handling of multiple encoders via a single interrupt routine, using a pair of two pin-change-interrupt (PCI) pins per encoder. The method assumes pins of a pair are in the same port. Most Arduino IO pins are PCI capable; some are not; on some models of Arduinos, some PCI pins aren't brought out to headers, or aren't recognized as PCI by the IDE, as noted in the question Why PJ0 and PJ1 are not reporting as PCINT pins.

The third answer includes code from the first two, and also has a sketch that displays a table of PCI vectors and masks. This table assists in planning pin layouts to reduce ISR overhead. For example, if you have half a dozen encoders, you might attach three of them to six pins on one port (and one vector), and the other three to six pins on another port (and another vector). Or you might put two encoders on each of three ports. The latter method might run, on average, a little faster (eg a microsecond or so per ISR invocation).

James Waldby - jwpat7
  • 8,920
  • 3
  • 21
  • 33
0

For one channel I'd use Input Capture capability on Timer/Counter 1. Without debouncing it'll be pretty easy.

If you want to read 8 inputs simultaneously, you can use Pin Change interrupts and Timer/Counter 1 as a timebase. If you don't use Serial communication, you can use whole PORTD, otherwise you can use for example 4 channels on PORTC and 4 channels on PORTD. But again, debouncing will be little bit challenging.

KIIV
  • 4,907
  • 1
  • 14
  • 21