Timer-Interrupt-Encoders
This example reads multiple encoders using a timer interrupt, on an Arduino Uno or Nano.
- Boards:
- AVR
The ATmega328P microcontroller only has two interrupt pins (2 and 3), so if you want to use more than two interrupt-driven encoders, you'll either have to use a timer interrupt to continuously poll the encoders, or use the chip's pin change interrupts. This example demonstrates the former.
- See also
- Pin-Change-Interrupt-Encoders.ino
Familiarity with direct port manipulation is assumed.
Connections
Connect three encoders to the pins of port C as follows:
- A0: pin A of encoder #0
- A1: pin B of encoder #0
- A2: pin A of encoder #1
- A3: pin B of encoder #1
- A4: pin A of encoder #2
- A5: pin B of encoder #2
Connect the common pins to ground, the internal pull-up resistors will be enabled.
Behavior
When the position of one of the encoders changes, it is printed to the Serial monitor.
Written by PieterP, 2021-08-11
https://github.com/tttapa/Arduino-Helpers
#include "TimerHelpers.hpp"
constexpr uint8_t num_enc = 3;
const uint8_t pin_mask = 0x3F;
ISR (TIMER2_COMPA_vect) { encoders.
update(PINC & pin_mask); }
void setup() {
DDRC &= ~pin_mask;
PORTC |= pin_mask;
setTimer2Prescaler(Timer2Prescaler::S8);
setTimer2WGMode(Timer2WGMode::CTC);
OCR2A = 250 - 1;
bitSet(TIMSK2, OCIE2A);
Serial.begin(115200);
}
void loop() {
static int32_t prevPos[num_enc] {};
for (uint8_t i = 0; i < num_enc; ++i) {
int32_t newPos = encoders[i].
read();
if (newPos != prevPos[i]) {
Serial <<
'[' << i <<
"] " << newPos <<
endl;
prevPos[i] = newPos;
}
}
}
Dummy header file for Arduino builder.
Class for keeping track of the position of multiple rotary encoders.
EncoderPositionType read(uint8_t idx) const
Read the position of the given encoder.
bool update(RegisterType newstate)
Update the encoder positions based on the new state.
Print & endl(Print &printer)