Add arduino encoder test stuff

This commit is contained in:
Samuel Prevost 2026-03-11 19:00:05 +01:00
parent 0a9d215fa6
commit 344ef2b3f8
17 changed files with 2138 additions and 1 deletions

View File

@ -0,0 +1,227 @@
/*
* CDJ-1000 MK3 Jog Wheel + Touch Sensor Test
* =============================================
* Board: Arduino Pro Micro (ATmega32U4, 5V/16MHz)
* Wiring: JOG1 D2 (INT1 hardware interrupt)
* JOG2 D3 (INT0 hardware interrupt)
* TCH D4 (active LOW, pull-up on JOGB PCB)
* V+5 VCC (5V)
* GND GND
*
* Both encoder pins use hardware interrupts no missed
* pulses even at full scratch speed.
*
* Touch sensor is a pressure-sensitive sheet switch (DSX1065)
* with 22 pull-up (R2007) and 22nF debounce cap (C2002)
* already on the JOGB PCB. TCH is HIGH when not touched,
* LOW when platter is pressed down.
*
* Install: Sketch > Include Library > Manage Libraries >
* search "Encoder" by Paul Stoffregen (PJRC)
*
* Flash: Board = "Arduino Leonardo", then Upload as normal.
* Rename this file to .ino or add it to an .ino
* wrapper if your IDE requires it.
*/
#include <Encoder.h>
// --- Pin Definitions ---
#define JOG1_PIN 2
#define JOG2_PIN 3
#define TOUCH_PIN 4
// --- Encoder Object ---
Encoder jogWheel(JOG1_PIN, JOG2_PIN);
// --- Known PPR (measured: 13000 ticks / 4x decoding = 3250) ---
#define KNOWN_PPR 3250
// --- State Variables ---
long oldPosition = 0;
unsigned long lastPrintTime = 0;
unsigned long lastChangeTime = 0;
// Touch state
bool lastTouchState = false;
// Rolling velocity calculation
long lastVelocityPos = 0;
unsigned long lastVelocityTime = 0;
const unsigned long VELOCITY_INTERVAL_MS = 50;
// Statistics
long minPosition = 0;
long maxPosition = 0;
unsigned long totalTicks = 0;
bool firstRevolution = true;
long revolutionStartPos = 0;
void setup() {
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port (Pro Micro native USB)
}
delay(500);
// Touch pin — external pull-up on JOGB PCB (R2007 22kΩ to 5V)
pinMode(TOUCH_PIN, INPUT);
Serial.println(F("========================================"));
Serial.println(F(" CDJ-1000 MK3 Jog Wheel + Touch Test"));
Serial.println(F(" Pro Micro (ATmega32U4)"));
Serial.println(F("========================================"));
Serial.println(F("Wiring: JOG1→D2, JOG2→D3, TCH→D4, 5V, GND"));
Serial.println(F(""));
Serial.println(F("Encoder: hardware interrupts — full speed."));
Serial.println(F("Touch: active LOW (press platter to trigger)"));
Serial.println(F("PPR: 3250 (13000 ticks / 4x decoding)"));
Serial.println(F(""));
Serial.println(F("Commands (send via Serial Monitor):"));
Serial.println(F(" 'r' - Reset position counter to 0"));
Serial.println(F(" 's' - Show statistics"));
Serial.println(F(" 'p' - Start PPR measurement (rotate exactly 1 turn)"));
Serial.println(F(" 't' - Read touch sensor state"));
Serial.println(F(""));
Serial.println(F("Rotate the jog wheel..."));
Serial.println(F("----------------------------------------"));
lastVelocityTime = millis();
}
void loop() {
unsigned long now = millis();
// --- Read Encoder ---
long newPosition = jogWheel.read();
// --- Read Touch Sensor ---
bool touched = !digitalRead(TOUCH_PIN); // Active LOW — invert
// Print on touch state change
if (touched != lastTouchState) {
if (touched) {
Serial.println(F(">>> TOUCH: PRESSED — vinyl mode <<<"));
} else {
Serial.println(F(">>> TOUCH: RELEASED <<<"));
}
lastTouchState = touched;
}
// --- Handle Serial Commands ---
if (Serial.available()) {
char cmd = Serial.read();
switch (cmd) {
case 'r':
case 'R':
jogWheel.write(0);
oldPosition = 0;
newPosition = 0;
minPosition = 0;
maxPosition = 0;
totalTicks = 0;
Serial.println(F("\n>>> Position RESET to 0 <<<\n"));
break;
case 's':
case 'S':
Serial.println(F("\n--- Statistics ---"));
Serial.print(F(" Current position: ")); Serial.println(newPosition);
Serial.print(F(" Min position: ")); Serial.println(minPosition);
Serial.print(F(" Max position: ")); Serial.println(maxPosition);
Serial.print(F(" Total range: ")); Serial.println(maxPosition - minPosition);
Serial.print(F(" Total ticks: ")); Serial.println(totalTicks);
Serial.print(F(" Touch state: ")); Serial.println(touched ? "PRESSED" : "released");
Serial.println(F("-----------------\n"));
break;
case 'p':
case 'P':
revolutionStartPos = newPosition;
firstRevolution = false;
Serial.println(F("\n>>> PPR Measurement Started <<<"));
Serial.println(F("Slowly rotate EXACTLY one full turn, then press 'p' again."));
Serial.print(F("Start position: ")); Serial.println(revolutionStartPos);
break;
case 't':
case 'T':
Serial.print(F("Touch sensor: "));
Serial.print(touched ? "PRESSED" : "released");
Serial.print(F(" (raw pin: "));
Serial.print(digitalRead(TOUCH_PIN));
Serial.println(F(")"));
break;
}
}
// --- Detect Encoder Changes ---
if (newPosition != oldPosition) {
long delta = newPosition - oldPosition;
lastChangeTime = now;
// Update statistics
totalTicks += abs(delta);
if (newPosition > maxPosition) maxPosition = newPosition;
if (newPosition < minPosition) minPosition = newPosition;
// Print position change
Serial.print(F("Pos: "));
Serial.print(newPosition);
Serial.print(F(" Δ: "));
Serial.print(delta);
Serial.print(F(" Dir: "));
Serial.print(delta > 0 ? "CW >>>" : "<<< CCW");
// Show touch state inline when spinning
if (touched) {
Serial.print(F(" [SCRATCH]"));
}
// PPR measurement helper
if (!firstRevolution) {
long pprDelta = abs(newPosition - revolutionStartPos);
Serial.print(F(" [PPR ticks: "));
Serial.print(pprDelta);
Serial.print(F("]"));
}
Serial.println();
oldPosition = newPosition;
}
// --- Velocity Calculation (periodic) ---
if (now - lastVelocityTime >= VELOCITY_INTERVAL_MS) {
long velocityDelta = newPosition - lastVelocityPos;
unsigned long dt = now - lastVelocityTime;
if (velocityDelta != 0) {
float ticksPerSec = (float)velocityDelta / dt * 1000.0;
float rpm = (ticksPerSec / (KNOWN_PPR * 4.0)) * 60.0;
Serial.print(F(" >> Velocity: "));
Serial.print(ticksPerSec, 1);
Serial.print(F(" ticks/sec RPM: "));
Serial.print(rpm, 2);
if (touched) {
Serial.print(F(" [VINYL]"));
}
Serial.println();
}
lastVelocityPos = newPosition;
lastVelocityTime = now;
}
// --- Idle detection ---
if (lastChangeTime > 0 && (now - lastChangeTime > 2000) && (now - lastPrintTime > 5000)) {
Serial.print(F(" [idle at position "));
Serial.print(newPosition);
Serial.print(F(", touch: "));
Serial.print(touched ? "PRESSED" : "released");
Serial.println(F("]"));
lastPrintTime = now;
}
}

View File

@ -0,0 +1,10 @@
#include "Encoder.h"
// Yes, all the code is in the header file, to provide the user
// configure options with #define (before they include it), and
// to facilitate some crafty optimizations!
Encoder_internal_state_t * Encoder::interruptArgs[];

View File

@ -0,0 +1,980 @@
/* Encoder Library, for measuring quadrature encoded signals
* http://www.pjrc.com/teensy/td_libs_Encoder.html
* Copyright (c) 2011,2013 PJRC.COM, LLC - Paul Stoffregen <paul@pjrc.com>
*
* Version 1.2 - fix -2 bug in C-only code
* Version 1.1 - expand to support boards with up to 60 interrupts
* Version 1.0 - initial release
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef Encoder_h_
#define Encoder_h_
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#elif defined(WIRING)
#include "Wiring.h"
#else
#include "WProgram.h"
#include "pins_arduino.h"
#endif
#include "utility/direct_pin_read.h"
#if defined(ENCODER_USE_INTERRUPTS) || !defined(ENCODER_DO_NOT_USE_INTERRUPTS)
#define ENCODER_USE_INTERRUPTS
#define ENCODER_ARGLIST_SIZE CORE_NUM_INTERRUPT
#include "utility/interrupt_pins.h"
#ifdef ENCODER_OPTIMIZE_INTERRUPTS
#include "utility/interrupt_config.h"
#endif
#else
#define ENCODER_ARGLIST_SIZE 0
#endif
// Use ICACHE_RAM_ATTR for ISRs to prevent ESP8266 resets
#if defined(ESP8266) || defined(ESP32)
#define ENCODER_ISR_ATTR ICACHE_RAM_ATTR
#else
#define ENCODER_ISR_ATTR
#endif
// All the data needed by interrupts is consolidated into this ugly struct
// to facilitate assembly language optimizing of the speed critical update.
// The assembly code uses auto-incrementing addressing modes, so the struct
// must remain in exactly this order.
typedef struct {
volatile IO_REG_TYPE * pin1_register;
volatile IO_REG_TYPE * pin2_register;
IO_REG_TYPE pin1_bitmask;
IO_REG_TYPE pin2_bitmask;
uint8_t state;
int32_t position;
} Encoder_internal_state_t;
class Encoder
{
public:
Encoder(uint8_t pin1, uint8_t pin2) {
#ifdef INPUT_PULLUP
pinMode(pin1, INPUT_PULLUP);
pinMode(pin2, INPUT_PULLUP);
#else
pinMode(pin1, INPUT);
digitalWrite(pin1, HIGH);
pinMode(pin2, INPUT);
digitalWrite(pin2, HIGH);
#endif
encoder.pin1_register = PIN_TO_BASEREG(pin1);
encoder.pin1_bitmask = PIN_TO_BITMASK(pin1);
encoder.pin2_register = PIN_TO_BASEREG(pin2);
encoder.pin2_bitmask = PIN_TO_BITMASK(pin2);
encoder.position = 0;
// allow time for a passive R-C filter to charge
// through the pullup resistors, before reading
// the initial state
delayMicroseconds(2000);
uint8_t s = 0;
if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1;
if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2;
encoder.state = s;
#ifdef ENCODER_USE_INTERRUPTS
interrupts_in_use = attach_interrupt(pin1, &encoder);
interrupts_in_use += attach_interrupt(pin2, &encoder);
#endif
//update_finishup(); // to force linker to include the code (does not work)
}
#ifdef ENCODER_USE_INTERRUPTS
inline int32_t read() {
if (interrupts_in_use < 2) {
noInterrupts();
update(&encoder);
} else {
noInterrupts();
}
int32_t ret = encoder.position;
interrupts();
return ret;
}
inline int32_t readAndReset() {
if (interrupts_in_use < 2) {
noInterrupts();
update(&encoder);
} else {
noInterrupts();
}
int32_t ret = encoder.position;
encoder.position = 0;
interrupts();
return ret;
}
inline void write(int32_t p) {
noInterrupts();
encoder.position = p;
interrupts();
}
#else
inline int32_t read() {
update(&encoder);
return encoder.position;
}
inline int32_t readAndReset() {
update(&encoder);
int32_t ret = encoder.position;
encoder.position = 0;
return ret;
}
inline void write(int32_t p) {
encoder.position = p;
}
#endif
private:
Encoder_internal_state_t encoder;
#ifdef ENCODER_USE_INTERRUPTS
uint8_t interrupts_in_use;
#endif
public:
static Encoder_internal_state_t * interruptArgs[ENCODER_ARGLIST_SIZE];
// _______ _______
// Pin1 ______| |_______| |______ Pin1
// negative <--- _______ _______ __ --> positive
// Pin2 __| |_______| |_______| Pin2
// new new old old
// pin2 pin1 pin2 pin1 Result
// ---- ---- ---- ---- ------
// 0 0 0 0 no movement
// 0 0 0 1 +1
// 0 0 1 0 -1
// 0 0 1 1 +2 (assume pin1 edges only)
// 0 1 0 0 -1
// 0 1 0 1 no movement
// 0 1 1 0 -2 (assume pin1 edges only)
// 0 1 1 1 +1
// 1 0 0 0 +1
// 1 0 0 1 -2 (assume pin1 edges only)
// 1 0 1 0 no movement
// 1 0 1 1 -1
// 1 1 0 0 +2 (assume pin1 edges only)
// 1 1 0 1 -1
// 1 1 1 0 +1
// 1 1 1 1 no movement
/*
// Simple, easy-to-read "documentation" version :-)
//
void update(void) {
uint8_t s = state & 3;
if (digitalRead(pin1)) s |= 4;
if (digitalRead(pin2)) s |= 8;
switch (s) {
case 0: case 5: case 10: case 15:
break;
case 1: case 7: case 8: case 14:
position++; break;
case 2: case 4: case 11: case 13:
position--; break;
case 3: case 12:
position += 2; break;
default:
position -= 2; break;
}
state = (s >> 2);
}
*/
public:
// update() is not meant to be called from outside Encoder,
// but it is public to allow static interrupt routines.
// DO NOT call update() directly from sketches.
#if defined(IRAM_ATTR)
static IRAM_ATTR void update(Encoder_internal_state_t *arg) {
#else
static void update(Encoder_internal_state_t *arg) {
#endif
#if defined(__AVR__)
// The compiler believes this is just 1 line of code, so
// it will inline this function into each interrupt
// handler. That's a tiny bit faster, but grows the code.
// Especially when used with ENCODER_OPTIMIZE_INTERRUPTS,
// the inline nature allows the ISR prologue and epilogue
// to only save/restore necessary registers, for very nice
// speed increase.
asm volatile (
"ld r30, X+" "\n\t"
"ld r31, X+" "\n\t"
"ld r24, Z" "\n\t" // r24 = pin1 input
"ld r30, X+" "\n\t"
"ld r31, X+" "\n\t"
"ld r25, Z" "\n\t" // r25 = pin2 input
"ld r30, X+" "\n\t" // r30 = pin1 mask
"ld r31, X+" "\n\t" // r31 = pin2 mask
"ld r22, X" "\n\t" // r22 = state
"andi r22, 3" "\n\t"
"and r24, r30" "\n\t"
"breq L%=1" "\n\t" // if (pin1)
"ori r22, 4" "\n\t" // state |= 4
"L%=1:" "and r25, r31" "\n\t"
"breq L%=2" "\n\t" // if (pin2)
"ori r22, 8" "\n\t" // state |= 8
"L%=2:" "ldi r30, lo8(pm(L%=table))" "\n\t"
"ldi r31, hi8(pm(L%=table))" "\n\t"
"add r30, r22" "\n\t"
"adc r31, __zero_reg__" "\n\t"
"asr r22" "\n\t"
"asr r22" "\n\t"
"st X+, r22" "\n\t" // store new state
"ld r22, X+" "\n\t"
"ld r23, X+" "\n\t"
"ld r24, X+" "\n\t"
"ld r25, X+" "\n\t"
"ijmp" "\n\t" // jumps to update_finishup()
// TODO move this table to another static function,
// so it doesn't get needlessly duplicated. Easier
// said than done, due to linker issues and inlining
"L%=table:" "\n\t"
"rjmp L%=end" "\n\t" // 0
"rjmp L%=plus1" "\n\t" // 1
"rjmp L%=minus1" "\n\t" // 2
"rjmp L%=plus2" "\n\t" // 3
"rjmp L%=minus1" "\n\t" // 4
"rjmp L%=end" "\n\t" // 5
"rjmp L%=minus2" "\n\t" // 6
"rjmp L%=plus1" "\n\t" // 7
"rjmp L%=plus1" "\n\t" // 8
"rjmp L%=minus2" "\n\t" // 9
"rjmp L%=end" "\n\t" // 10
"rjmp L%=minus1" "\n\t" // 11
"rjmp L%=plus2" "\n\t" // 12
"rjmp L%=minus1" "\n\t" // 13
"rjmp L%=plus1" "\n\t" // 14
"rjmp L%=end" "\n\t" // 15
"L%=minus2:" "\n\t"
"subi r22, 2" "\n\t"
"sbci r23, 0" "\n\t"
"sbci r24, 0" "\n\t"
"sbci r25, 0" "\n\t"
"rjmp L%=store" "\n\t"
"L%=minus1:" "\n\t"
"subi r22, 1" "\n\t"
"sbci r23, 0" "\n\t"
"sbci r24, 0" "\n\t"
"sbci r25, 0" "\n\t"
"rjmp L%=store" "\n\t"
"L%=plus2:" "\n\t"
"subi r22, 254" "\n\t"
"rjmp L%=z" "\n\t"
"L%=plus1:" "\n\t"
"subi r22, 255" "\n\t"
"L%=z:" "sbci r23, 255" "\n\t"
"sbci r24, 255" "\n\t"
"sbci r25, 255" "\n\t"
"L%=store:" "\n\t"
"st -X, r25" "\n\t"
"st -X, r24" "\n\t"
"st -X, r23" "\n\t"
"st -X, r22" "\n\t"
"L%=end:" "\n"
: : "x" (arg) : "r22", "r23", "r24", "r25", "r30", "r31");
#else
uint8_t p1val = DIRECT_PIN_READ(arg->pin1_register, arg->pin1_bitmask);
uint8_t p2val = DIRECT_PIN_READ(arg->pin2_register, arg->pin2_bitmask);
uint8_t state = arg->state & 3;
if (p1val) state |= 4;
if (p2val) state |= 8;
arg->state = (state >> 2);
switch (state) {
case 1: case 7: case 8: case 14:
arg->position++;
return;
case 2: case 4: case 11: case 13:
arg->position--;
return;
case 3: case 12:
arg->position += 2;
return;
case 6: case 9:
arg->position -= 2;
return;
}
#endif
}
private:
/*
#if defined(__AVR__)
// TODO: this must be a no inline function
// even noinline does not seem to solve difficult
// problems with this. Oh well, it was only meant
// to shrink code size - there's no performance
// improvement in this, only code size reduction.
__attribute__((noinline)) void update_finishup(void) {
asm volatile (
"ldi r30, lo8(pm(Ltable))" "\n\t"
"ldi r31, hi8(pm(Ltable))" "\n\t"
"Ltable:" "\n\t"
"rjmp L%=end" "\n\t" // 0
"rjmp L%=plus1" "\n\t" // 1
"rjmp L%=minus1" "\n\t" // 2
"rjmp L%=plus2" "\n\t" // 3
"rjmp L%=minus1" "\n\t" // 4
"rjmp L%=end" "\n\t" // 5
"rjmp L%=minus2" "\n\t" // 6
"rjmp L%=plus1" "\n\t" // 7
"rjmp L%=plus1" "\n\t" // 8
"rjmp L%=minus2" "\n\t" // 9
"rjmp L%=end" "\n\t" // 10
"rjmp L%=minus1" "\n\t" // 11
"rjmp L%=plus2" "\n\t" // 12
"rjmp L%=minus1" "\n\t" // 13
"rjmp L%=plus1" "\n\t" // 14
"rjmp L%=end" "\n\t" // 15
"L%=minus2:" "\n\t"
"subi r22, 2" "\n\t"
"sbci r23, 0" "\n\t"
"sbci r24, 0" "\n\t"
"sbci r25, 0" "\n\t"
"rjmp L%=store" "\n\t"
"L%=minus1:" "\n\t"
"subi r22, 1" "\n\t"
"sbci r23, 0" "\n\t"
"sbci r24, 0" "\n\t"
"sbci r25, 0" "\n\t"
"rjmp L%=store" "\n\t"
"L%=plus2:" "\n\t"
"subi r22, 254" "\n\t"
"rjmp L%=z" "\n\t"
"L%=plus1:" "\n\t"
"subi r22, 255" "\n\t"
"L%=z:" "sbci r23, 255" "\n\t"
"sbci r24, 255" "\n\t"
"sbci r25, 255" "\n\t"
"L%=store:" "\n\t"
"st -X, r25" "\n\t"
"st -X, r24" "\n\t"
"st -X, r23" "\n\t"
"st -X, r22" "\n\t"
"L%=end:" "\n"
: : : "r22", "r23", "r24", "r25", "r30", "r31");
}
#endif
*/
#ifdef ENCODER_USE_INTERRUPTS
// this giant function is an unfortunate consequence of Arduino's
// attachInterrupt function not supporting any way to pass a pointer
// or other context to the attached function.
static uint8_t attach_interrupt(uint8_t pin, Encoder_internal_state_t *state) {
switch (pin) {
#ifdef CORE_INT0_PIN
case CORE_INT0_PIN:
interruptArgs[0] = state;
attachInterrupt(0, isr0, CHANGE);
break;
#endif
#ifdef CORE_INT1_PIN
case CORE_INT1_PIN:
interruptArgs[1] = state;
attachInterrupt(1, isr1, CHANGE);
break;
#endif
#ifdef CORE_INT2_PIN
case CORE_INT2_PIN:
interruptArgs[2] = state;
attachInterrupt(2, isr2, CHANGE);
break;
#endif
#ifdef CORE_INT3_PIN
case CORE_INT3_PIN:
interruptArgs[3] = state;
attachInterrupt(3, isr3, CHANGE);
break;
#endif
#ifdef CORE_INT4_PIN
case CORE_INT4_PIN:
interruptArgs[4] = state;
attachInterrupt(4, isr4, CHANGE);
break;
#endif
#ifdef CORE_INT5_PIN
case CORE_INT5_PIN:
interruptArgs[5] = state;
attachInterrupt(5, isr5, CHANGE);
break;
#endif
#ifdef CORE_INT6_PIN
case CORE_INT6_PIN:
interruptArgs[6] = state;
attachInterrupt(6, isr6, CHANGE);
break;
#endif
#ifdef CORE_INT7_PIN
case CORE_INT7_PIN:
interruptArgs[7] = state;
attachInterrupt(7, isr7, CHANGE);
break;
#endif
#ifdef CORE_INT8_PIN
case CORE_INT8_PIN:
interruptArgs[8] = state;
attachInterrupt(8, isr8, CHANGE);
break;
#endif
#ifdef CORE_INT9_PIN
case CORE_INT9_PIN:
interruptArgs[9] = state;
attachInterrupt(9, isr9, CHANGE);
break;
#endif
#ifdef CORE_INT10_PIN
case CORE_INT10_PIN:
interruptArgs[10] = state;
attachInterrupt(10, isr10, CHANGE);
break;
#endif
#ifdef CORE_INT11_PIN
case CORE_INT11_PIN:
interruptArgs[11] = state;
attachInterrupt(11, isr11, CHANGE);
break;
#endif
#ifdef CORE_INT12_PIN
case CORE_INT12_PIN:
interruptArgs[12] = state;
attachInterrupt(12, isr12, CHANGE);
break;
#endif
#ifdef CORE_INT13_PIN
case CORE_INT13_PIN:
interruptArgs[13] = state;
attachInterrupt(13, isr13, CHANGE);
break;
#endif
#ifdef CORE_INT14_PIN
case CORE_INT14_PIN:
interruptArgs[14] = state;
attachInterrupt(14, isr14, CHANGE);
break;
#endif
#ifdef CORE_INT15_PIN
case CORE_INT15_PIN:
interruptArgs[15] = state;
attachInterrupt(15, isr15, CHANGE);
break;
#endif
#ifdef CORE_INT16_PIN
case CORE_INT16_PIN:
interruptArgs[16] = state;
attachInterrupt(16, isr16, CHANGE);
break;
#endif
#ifdef CORE_INT17_PIN
case CORE_INT17_PIN:
interruptArgs[17] = state;
attachInterrupt(17, isr17, CHANGE);
break;
#endif
#ifdef CORE_INT18_PIN
case CORE_INT18_PIN:
interruptArgs[18] = state;
attachInterrupt(18, isr18, CHANGE);
break;
#endif
#ifdef CORE_INT19_PIN
case CORE_INT19_PIN:
interruptArgs[19] = state;
attachInterrupt(19, isr19, CHANGE);
break;
#endif
#ifdef CORE_INT20_PIN
case CORE_INT20_PIN:
interruptArgs[20] = state;
attachInterrupt(20, isr20, CHANGE);
break;
#endif
#ifdef CORE_INT21_PIN
case CORE_INT21_PIN:
interruptArgs[21] = state;
attachInterrupt(21, isr21, CHANGE);
break;
#endif
#ifdef CORE_INT22_PIN
case CORE_INT22_PIN:
interruptArgs[22] = state;
attachInterrupt(22, isr22, CHANGE);
break;
#endif
#ifdef CORE_INT23_PIN
case CORE_INT23_PIN:
interruptArgs[23] = state;
attachInterrupt(23, isr23, CHANGE);
break;
#endif
#ifdef CORE_INT24_PIN
case CORE_INT24_PIN:
interruptArgs[24] = state;
attachInterrupt(24, isr24, CHANGE);
break;
#endif
#ifdef CORE_INT25_PIN
case CORE_INT25_PIN:
interruptArgs[25] = state;
attachInterrupt(25, isr25, CHANGE);
break;
#endif
#ifdef CORE_INT26_PIN
case CORE_INT26_PIN:
interruptArgs[26] = state;
attachInterrupt(26, isr26, CHANGE);
break;
#endif
#ifdef CORE_INT27_PIN
case CORE_INT27_PIN:
interruptArgs[27] = state;
attachInterrupt(27, isr27, CHANGE);
break;
#endif
#ifdef CORE_INT28_PIN
case CORE_INT28_PIN:
interruptArgs[28] = state;
attachInterrupt(28, isr28, CHANGE);
break;
#endif
#ifdef CORE_INT29_PIN
case CORE_INT29_PIN:
interruptArgs[29] = state;
attachInterrupt(29, isr29, CHANGE);
break;
#endif
#ifdef CORE_INT30_PIN
case CORE_INT30_PIN:
interruptArgs[30] = state;
attachInterrupt(30, isr30, CHANGE);
break;
#endif
#ifdef CORE_INT31_PIN
case CORE_INT31_PIN:
interruptArgs[31] = state;
attachInterrupt(31, isr31, CHANGE);
break;
#endif
#ifdef CORE_INT32_PIN
case CORE_INT32_PIN:
interruptArgs[32] = state;
attachInterrupt(32, isr32, CHANGE);
break;
#endif
#ifdef CORE_INT33_PIN
case CORE_INT33_PIN:
interruptArgs[33] = state;
attachInterrupt(33, isr33, CHANGE);
break;
#endif
#ifdef CORE_INT34_PIN
case CORE_INT34_PIN:
interruptArgs[34] = state;
attachInterrupt(34, isr34, CHANGE);
break;
#endif
#ifdef CORE_INT35_PIN
case CORE_INT35_PIN:
interruptArgs[35] = state;
attachInterrupt(35, isr35, CHANGE);
break;
#endif
#ifdef CORE_INT36_PIN
case CORE_INT36_PIN:
interruptArgs[36] = state;
attachInterrupt(36, isr36, CHANGE);
break;
#endif
#ifdef CORE_INT37_PIN
case CORE_INT37_PIN:
interruptArgs[37] = state;
attachInterrupt(37, isr37, CHANGE);
break;
#endif
#ifdef CORE_INT38_PIN
case CORE_INT38_PIN:
interruptArgs[38] = state;
attachInterrupt(38, isr38, CHANGE);
break;
#endif
#ifdef CORE_INT39_PIN
case CORE_INT39_PIN:
interruptArgs[39] = state;
attachInterrupt(39, isr39, CHANGE);
break;
#endif
#ifdef CORE_INT40_PIN
case CORE_INT40_PIN:
interruptArgs[40] = state;
attachInterrupt(40, isr40, CHANGE);
break;
#endif
#ifdef CORE_INT41_PIN
case CORE_INT41_PIN:
interruptArgs[41] = state;
attachInterrupt(41, isr41, CHANGE);
break;
#endif
#ifdef CORE_INT42_PIN
case CORE_INT42_PIN:
interruptArgs[42] = state;
attachInterrupt(42, isr42, CHANGE);
break;
#endif
#ifdef CORE_INT43_PIN
case CORE_INT43_PIN:
interruptArgs[43] = state;
attachInterrupt(43, isr43, CHANGE);
break;
#endif
#ifdef CORE_INT44_PIN
case CORE_INT44_PIN:
interruptArgs[44] = state;
attachInterrupt(44, isr44, CHANGE);
break;
#endif
#ifdef CORE_INT45_PIN
case CORE_INT45_PIN:
interruptArgs[45] = state;
attachInterrupt(45, isr45, CHANGE);
break;
#endif
#ifdef CORE_INT46_PIN
case CORE_INT46_PIN:
interruptArgs[46] = state;
attachInterrupt(46, isr46, CHANGE);
break;
#endif
#ifdef CORE_INT47_PIN
case CORE_INT47_PIN:
interruptArgs[47] = state;
attachInterrupt(47, isr47, CHANGE);
break;
#endif
#ifdef CORE_INT48_PIN
case CORE_INT48_PIN:
interruptArgs[48] = state;
attachInterrupt(48, isr48, CHANGE);
break;
#endif
#ifdef CORE_INT49_PIN
case CORE_INT49_PIN:
interruptArgs[49] = state;
attachInterrupt(49, isr49, CHANGE);
break;
#endif
#ifdef CORE_INT50_PIN
case CORE_INT50_PIN:
interruptArgs[50] = state;
attachInterrupt(50, isr50, CHANGE);
break;
#endif
#ifdef CORE_INT51_PIN
case CORE_INT51_PIN:
interruptArgs[51] = state;
attachInterrupt(51, isr51, CHANGE);
break;
#endif
#ifdef CORE_INT52_PIN
case CORE_INT52_PIN:
interruptArgs[52] = state;
attachInterrupt(52, isr52, CHANGE);
break;
#endif
#ifdef CORE_INT53_PIN
case CORE_INT53_PIN:
interruptArgs[53] = state;
attachInterrupt(53, isr53, CHANGE);
break;
#endif
#ifdef CORE_INT54_PIN
case CORE_INT54_PIN:
interruptArgs[54] = state;
attachInterrupt(54, isr54, CHANGE);
break;
#endif
#ifdef CORE_INT55_PIN
case CORE_INT55_PIN:
interruptArgs[55] = state;
attachInterrupt(55, isr55, CHANGE);
break;
#endif
#ifdef CORE_INT56_PIN
case CORE_INT56_PIN:
interruptArgs[56] = state;
attachInterrupt(56, isr56, CHANGE);
break;
#endif
#ifdef CORE_INT57_PIN
case CORE_INT57_PIN:
interruptArgs[57] = state;
attachInterrupt(57, isr57, CHANGE);
break;
#endif
#ifdef CORE_INT58_PIN
case CORE_INT58_PIN:
interruptArgs[58] = state;
attachInterrupt(58, isr58, CHANGE);
break;
#endif
#ifdef CORE_INT59_PIN
case CORE_INT59_PIN:
interruptArgs[59] = state;
attachInterrupt(59, isr59, CHANGE);
break;
#endif
default:
return 0;
}
return 1;
}
#endif // ENCODER_USE_INTERRUPTS
#if defined(ENCODER_USE_INTERRUPTS) && !defined(ENCODER_OPTIMIZE_INTERRUPTS)
#ifdef CORE_INT0_PIN
static ENCODER_ISR_ATTR void isr0(void) { update(interruptArgs[0]); }
#endif
#ifdef CORE_INT1_PIN
static ENCODER_ISR_ATTR void isr1(void) { update(interruptArgs[1]); }
#endif
#ifdef CORE_INT2_PIN
static ENCODER_ISR_ATTR void isr2(void) { update(interruptArgs[2]); }
#endif
#ifdef CORE_INT3_PIN
static ENCODER_ISR_ATTR void isr3(void) { update(interruptArgs[3]); }
#endif
#ifdef CORE_INT4_PIN
static ENCODER_ISR_ATTR void isr4(void) { update(interruptArgs[4]); }
#endif
#ifdef CORE_INT5_PIN
static ENCODER_ISR_ATTR void isr5(void) { update(interruptArgs[5]); }
#endif
#ifdef CORE_INT6_PIN
static ENCODER_ISR_ATTR void isr6(void) { update(interruptArgs[6]); }
#endif
#ifdef CORE_INT7_PIN
static ENCODER_ISR_ATTR void isr7(void) { update(interruptArgs[7]); }
#endif
#ifdef CORE_INT8_PIN
static ENCODER_ISR_ATTR void isr8(void) { update(interruptArgs[8]); }
#endif
#ifdef CORE_INT9_PIN
static ENCODER_ISR_ATTR void isr9(void) { update(interruptArgs[9]); }
#endif
#ifdef CORE_INT10_PIN
static ENCODER_ISR_ATTR void isr10(void) { update(interruptArgs[10]); }
#endif
#ifdef CORE_INT11_PIN
static ENCODER_ISR_ATTR void isr11(void) { update(interruptArgs[11]); }
#endif
#ifdef CORE_INT12_PIN
static ENCODER_ISR_ATTR void isr12(void) { update(interruptArgs[12]); }
#endif
#ifdef CORE_INT13_PIN
static ENCODER_ISR_ATTR void isr13(void) { update(interruptArgs[13]); }
#endif
#ifdef CORE_INT14_PIN
static ENCODER_ISR_ATTR void isr14(void) { update(interruptArgs[14]); }
#endif
#ifdef CORE_INT15_PIN
static ENCODER_ISR_ATTR void isr15(void) { update(interruptArgs[15]); }
#endif
#ifdef CORE_INT16_PIN
static ENCODER_ISR_ATTR void isr16(void) { update(interruptArgs[16]); }
#endif
#ifdef CORE_INT17_PIN
static ENCODER_ISR_ATTR void isr17(void) { update(interruptArgs[17]); }
#endif
#ifdef CORE_INT18_PIN
static ENCODER_ISR_ATTR void isr18(void) { update(interruptArgs[18]); }
#endif
#ifdef CORE_INT19_PIN
static ENCODER_ISR_ATTR void isr19(void) { update(interruptArgs[19]); }
#endif
#ifdef CORE_INT20_PIN
static ENCODER_ISR_ATTR void isr20(void) { update(interruptArgs[20]); }
#endif
#ifdef CORE_INT21_PIN
static ENCODER_ISR_ATTR void isr21(void) { update(interruptArgs[21]); }
#endif
#ifdef CORE_INT22_PIN
static ENCODER_ISR_ATTR void isr22(void) { update(interruptArgs[22]); }
#endif
#ifdef CORE_INT23_PIN
static ENCODER_ISR_ATTR void isr23(void) { update(interruptArgs[23]); }
#endif
#ifdef CORE_INT24_PIN
static ENCODER_ISR_ATTR void isr24(void) { update(interruptArgs[24]); }
#endif
#ifdef CORE_INT25_PIN
static ENCODER_ISR_ATTR void isr25(void) { update(interruptArgs[25]); }
#endif
#ifdef CORE_INT26_PIN
static ENCODER_ISR_ATTR void isr26(void) { update(interruptArgs[26]); }
#endif
#ifdef CORE_INT27_PIN
static ENCODER_ISR_ATTR void isr27(void) { update(interruptArgs[27]); }
#endif
#ifdef CORE_INT28_PIN
static ENCODER_ISR_ATTR void isr28(void) { update(interruptArgs[28]); }
#endif
#ifdef CORE_INT29_PIN
static ENCODER_ISR_ATTR void isr29(void) { update(interruptArgs[29]); }
#endif
#ifdef CORE_INT30_PIN
static ENCODER_ISR_ATTR void isr30(void) { update(interruptArgs[30]); }
#endif
#ifdef CORE_INT31_PIN
static ENCODER_ISR_ATTR void isr31(void) { update(interruptArgs[31]); }
#endif
#ifdef CORE_INT32_PIN
static ENCODER_ISR_ATTR void isr32(void) { update(interruptArgs[32]); }
#endif
#ifdef CORE_INT33_PIN
static ENCODER_ISR_ATTR void isr33(void) { update(interruptArgs[33]); }
#endif
#ifdef CORE_INT34_PIN
static ENCODER_ISR_ATTR void isr34(void) { update(interruptArgs[34]); }
#endif
#ifdef CORE_INT35_PIN
static ENCODER_ISR_ATTR void isr35(void) { update(interruptArgs[35]); }
#endif
#ifdef CORE_INT36_PIN
static ENCODER_ISR_ATTR void isr36(void) { update(interruptArgs[36]); }
#endif
#ifdef CORE_INT37_PIN
static ENCODER_ISR_ATTR void isr37(void) { update(interruptArgs[37]); }
#endif
#ifdef CORE_INT38_PIN
static ENCODER_ISR_ATTR void isr38(void) { update(interruptArgs[38]); }
#endif
#ifdef CORE_INT39_PIN
static ENCODER_ISR_ATTR void isr39(void) { update(interruptArgs[39]); }
#endif
#ifdef CORE_INT40_PIN
static ENCODER_ISR_ATTR void isr40(void) { update(interruptArgs[40]); }
#endif
#ifdef CORE_INT41_PIN
static ENCODER_ISR_ATTR void isr41(void) { update(interruptArgs[41]); }
#endif
#ifdef CORE_INT42_PIN
static ENCODER_ISR_ATTR void isr42(void) { update(interruptArgs[42]); }
#endif
#ifdef CORE_INT43_PIN
static ENCODER_ISR_ATTR void isr43(void) { update(interruptArgs[43]); }
#endif
#ifdef CORE_INT44_PIN
static ENCODER_ISR_ATTR void isr44(void) { update(interruptArgs[44]); }
#endif
#ifdef CORE_INT45_PIN
static ENCODER_ISR_ATTR void isr45(void) { update(interruptArgs[45]); }
#endif
#ifdef CORE_INT46_PIN
static ENCODER_ISR_ATTR void isr46(void) { update(interruptArgs[46]); }
#endif
#ifdef CORE_INT47_PIN
static ENCODER_ISR_ATTR void isr47(void) { update(interruptArgs[47]); }
#endif
#ifdef CORE_INT48_PIN
static ENCODER_ISR_ATTR void isr48(void) { update(interruptArgs[48]); }
#endif
#ifdef CORE_INT49_PIN
static ENCODER_ISR_ATTR void isr49(void) { update(interruptArgs[49]); }
#endif
#ifdef CORE_INT50_PIN
static ENCODER_ISR_ATTR void isr50(void) { update(interruptArgs[50]); }
#endif
#ifdef CORE_INT51_PIN
static ENCODER_ISR_ATTR void isr51(void) { update(interruptArgs[51]); }
#endif
#ifdef CORE_INT52_PIN
static ENCODER_ISR_ATTR void isr52(void) { update(interruptArgs[52]); }
#endif
#ifdef CORE_INT53_PIN
static ENCODER_ISR_ATTR void isr53(void) { update(interruptArgs[53]); }
#endif
#ifdef CORE_INT54_PIN
static ENCODER_ISR_ATTR void isr54(void) { update(interruptArgs[54]); }
#endif
#ifdef CORE_INT55_PIN
static ENCODER_ISR_ATTR void isr55(void) { update(interruptArgs[55]); }
#endif
#ifdef CORE_INT56_PIN
static ENCODER_ISR_ATTR void isr56(void) { update(interruptArgs[56]); }
#endif
#ifdef CORE_INT57_PIN
static ENCODER_ISR_ATTR void isr57(void) { update(interruptArgs[57]); }
#endif
#ifdef CORE_INT58_PIN
static ENCODER_ISR_ATTR void isr58(void) { update(interruptArgs[58]); }
#endif
#ifdef CORE_INT59_PIN
static ENCODER_ISR_ATTR void isr59(void) { update(interruptArgs[59]); }
#endif
#endif
};
#if defined(ENCODER_USE_INTERRUPTS) && defined(ENCODER_OPTIMIZE_INTERRUPTS)
#if defined(__AVR__)
#if defined(INT0_vect) && CORE_NUM_INTERRUPT > 0
ISR(INT0_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(0)]); }
#endif
#if defined(INT1_vect) && CORE_NUM_INTERRUPT > 1
ISR(INT1_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(1)]); }
#endif
#if defined(INT2_vect) && CORE_NUM_INTERRUPT > 2
ISR(INT2_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(2)]); }
#endif
#if defined(INT3_vect) && CORE_NUM_INTERRUPT > 3
ISR(INT3_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(3)]); }
#endif
#if defined(INT4_vect) && CORE_NUM_INTERRUPT > 4
ISR(INT4_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(4)]); }
#endif
#if defined(INT5_vect) && CORE_NUM_INTERRUPT > 5
ISR(INT5_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(5)]); }
#endif
#if defined(INT6_vect) && CORE_NUM_INTERRUPT > 6
ISR(INT6_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(6)]); }
#endif
#if defined(INT7_vect) && CORE_NUM_INTERRUPT > 7
ISR(INT7_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(7)]); }
#endif
#endif // AVR
#if defined(attachInterrupt)
// Don't intefere with other libraries or sketch use of attachInterrupt()
// https://github.com/PaulStoffregen/Encoder/issues/8
#undef attachInterrupt
#endif
#endif // ENCODER_OPTIMIZE_INTERRUPTS
#endif

View File

@ -0,0 +1,9 @@
# Encoder Library
Encoder counts pulses from quadrature encoded signals, which are commonly available from rotary knobs, motor or shaft sensors and other position sensors.
http://www.pjrc.com/teensy/td_libs_Encoder.html
http://www.youtube.com/watch?v=2puhIong-cs
![Encoder Knobs Demo](http://www.pjrc.com/teensy/td_libs_Encoder_1.jpg)

View File

@ -0,0 +1,64 @@
Please use this form only to report code defects or bugs.
For any question, even questions directly pertaining to this code, post your question on the forums related to the board you are using.
Arduino: forum.arduino.cc
Teensy: forum.pjrc.com
ESP8266: www.esp8266.com
ESP32: www.esp32.com
Adafruit Feather/Metro/Trinket: forums.adafruit.com
Particle Photon: community.particle.io
If you are experiencing trouble but not certain of the cause, or need help using this code, ask on the appropriate forum. This is not the place to ask for support or help, even directly related to this code. Only use this form you are certain you have discovered a defect in this code!
Please verify the problem occurs when using the very latest version, using the newest version of Arduino and any other related software.
----------------------------- Remove above -----------------------------
### Description
Describe your problem.
### Steps To Reproduce Problem
Please give detailed instructions needed for anyone to attempt to reproduce the problem.
### Hardware & Software
Board
Shields / modules used
Arduino IDE version
Teensyduino version (if using Teensy)
Version info & package name (from Tools > Boards > Board Manager)
Operating system & version
Any other software or hardware?
### Arduino Sketch
```cpp
// Change the code below by your sketch (please try to give the smallest code which demonstrates the problem)
#include <Arduino.h>
// libraries: give links/details so anyone can compile your code for the same result
void setup() {
}
void loop() {
}
```
### Errors or Incorrect Output
If you see any errors or incorrect output, please show it here. Please use copy & paste to give an exact copy of the message. Details matter, so please show (not merely describe) the actual message or error exactly as it appears.

View File

@ -0,0 +1,29 @@
/* Encoder Library - Basic Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
#include <Encoder.h>
// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder myEnc(5, 6);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
Serial.println("Basic Encoder Test:");
}
long oldPosition = -999;
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
}

View File

@ -0,0 +1,46 @@
/* Encoder Library - NoInterrupts Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
// If you define ENCODER_DO_NOT_USE_INTERRUPTS *before* including
// Encoder, the library will never use interrupts. This is mainly
// useful to reduce the size of the library when you are using it
// with pins that do not support interrupts. Without interrupts,
// your program must call the read() function rapidly, or risk
// missing changes in position.
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include <Encoder.h>
// Beware of Serial.print() speed. Without interrupts, if you
// transmit too much data with Serial.print() it can slow your
// reading from Encoder. Arduino 1.0 has improved transmit code.
// Using the fastest baud rate also helps. Teensy has USB packet
// buffering. But all boards can experience problems if you print
// too much and fill up buffers.
// Change these two numbers to the pins connected to your encoder.
// With ENCODER_DO_NOT_USE_INTERRUPTS, no interrupts are ever
// used, even if the pin has interrupt capability
Encoder myEnc(5, 6);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
Serial.println("Basic NoInterrupts Test:");
}
long position = -999;
void loop() {
long newPos = myEnc.read();
if (newPos != position) {
position = newPos;
Serial.println(position);
}
// With any substantial delay added, Encoder can only track
// very slow motion. You may uncomment this line to see
// how badly a delay affects your encoder.
//delay(50);
}

View File

@ -0,0 +1,113 @@
/* Encoder Library - SpeedTest - for measuring maximum Encoder speed
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
// This SpeedTest example provides a simple way to verify how much
// CPU time Encoder is consuming. Connect a DC voltmeter to the
// output pin and measure the voltage while the encoder is stopped
// or running at a very slow speed. Even though the pin is rapidly
// pulsing, a DC voltmeter will show the average voltage. Due to
// software timing, it will read a number much less than a steady
// logic high, but this number will give you a baseline reading
// for output with minimal interrupt overhead. Then increase the
// encoder speed. The voltage will decrease as the processor spends
// more time in Encoder's interrupt routines counting the pulses
// and less time pulsing the output pin. When the voltage is
// close to zero and will not decrease any farther, you have reached
// the absolute speed limit. Or, if using a mechanical system where
// you reach a speed limit imposed by your motors or other hardware,
// the amount this voltage has decreased, compared to the baseline,
// should give you a good approximation of the portion of available
// CPU time Encoder is consuming at your maximum speed.
// Encoder requires low latency interrupt response. Available CPU
// time does NOT necessarily prove or guarantee correct performance.
// If another library, like NewSoftSerial, is disabling interrupts
// for lengthy periods of time, Encoder can be prevented from
// properly counting the intput signals while interrupt are disabled.
// This optional setting causes Encoder to use more optimized code,
// but the downside is a conflict if any other part of your sketch
// or any other library you're using requires attachInterrupt().
// It must be defined before Encoder.h is included.
//#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
#include "pins_arduino.h"
// Change these two numbers to the pins connected to your encoder
// or shift register circuit which emulates a quadrature encoder
// case 1: both pins are interrupts
// case 2: only first pin used as interrupt
Encoder myEnc(5, 6);
// Connect a DC voltmeter to this pin.
const int outputPin = 12;
/* This simple circuit, using a Dual Flip-Flop chip, can emulate
quadrature encoder signals. The clock can come from a fancy
function generator or a cheap 555 timer chip. The clock
frequency can be measured with another board running FreqCount
http://www.pjrc.com/teensy/td_libs_FreqCount.html
+5V
| Quadrature Encoder Signal Emulator
Clock |
Input o----*-------------------------- ---------------------------o Output1
| |14 | |
| _______|_______ | | _______________
| | CD4013 | | | | CD4013 |
| 5 | | 1 | | 9 | | 13
---------| D Q |-----|----*----| D Q |------o Output2
| | | | | | |
| | 3 | | | 11 | |
| ----|> Clk | ---------|> Clk |
| | | | |
| 6 | | 8 | |
| ----| S | ----| S |
| | | | | | |
| | 4 | _ | 2 | 10 | _ | 12
| *----| R Q |--- *----| R Q |----
| | | | | | | |
| | |_______________| | |_______________| |
| | | | |
| | | 7 | |
| | | | |
--------------------------------------------------------------
| | |
| | |
----- ----- -----
--- --- ---
- - -
*/
void setup() {
pinMode(outputPin, OUTPUT);
}
#if defined(__AVR__) || defined(TEENSYDUINO)
#define REGTYPE unsigned char
#else
#define REGTYPE unsigned long
#endif
void loop() {
volatile int count = 0;
volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));
REGTYPE mask = digitalPinToBitMask(outputPin);
while (1) {
myEnc.read(); // Read the encoder while interrupts are enabled.
noInterrupts();
*reg |= mask; // Pulse the pin high, while interrupts are disabled.
count = count + 1;
*reg &= ~mask;
interrupts();
}
}

View File

@ -0,0 +1,46 @@
/* Encoder Library - TwoKnobs Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
#include <Encoder.h>
// Change these pin numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder knobLeft(5, 6);
Encoder knobRight(7, 8);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
Serial.println("TwoKnobs Encoder Test:");
}
long positionLeft = -999;
long positionRight = -999;
void loop() {
long newLeft, newRight;
newLeft = knobLeft.read();
newRight = knobRight.read();
if (newLeft != positionLeft || newRight != positionRight) {
Serial.print("Left = ");
Serial.print(newLeft);
Serial.print(", Right = ");
Serial.print(newRight);
Serial.println();
positionLeft = newLeft;
positionRight = newRight;
}
// if a character is sent from the serial monitor,
// reset both back to zero.
if (Serial.available()) {
Serial.read();
Serial.println("Reset both knobs to zero");
knobLeft.write(0);
knobRight.write(0);
}
}

View File

@ -0,0 +1,4 @@
ENCODER_USE_INTERRUPTS LITERAL1
ENCODER_OPTIMIZE_INTERRUPTS LITERAL1
ENCODER_DO_NOT_USE_INTERRUPTS LITERAL1
Encoder KEYWORD1

View File

@ -0,0 +1,10 @@
name=Encoder
version=1.4.4
author=Paul Stoffregen
maintainer=Paul Stoffregen
sentence=Counts quadrature pulses from rotary & linear position encoders.
paragraph=Encoder counts pulses from quadrature encoded signals, which are commonly available from rotary knobs, motor or shaft sensors and other position sensors.
category=Signal Input/Output
url=http://www.pjrc.com/teensy/td_libs_Encoder.html
architectures=*

View File

@ -0,0 +1,116 @@
#ifndef direct_pin_read_h_
#define direct_pin_read_h_
#if defined(__AVR__)
#define IO_REG_TYPE uint8_t
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL))
#define IO_REG_TYPE uint8_t
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(__SAM3X8E__) // || defined(ESP8266)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(__PIC32MX__)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0)
/* ESP8266 v2.0.0 Arduino workaround for bug https://github.com/esp8266/Arduino/issues/1110 */
#elif defined(ESP8266)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)(0x60000000+(0x318)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
/* ESP32 Arduino (https://github.com/espressif/arduino-esp32) */
#elif defined(ESP32)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(__SAMD21G18A__) || defined(__SAMD21E18A__)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0)
#elif defined(__SAMD51__)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) portInputRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#elif defined(RBL_NRF51822)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define DIRECT_PIN_READ(base, pin) nrf_gpio_pin_read(pin)
#elif defined(ARDUINO_ARCH_NRF52840)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) digitalPinToPinName(pin)
#define DIRECT_PIN_READ(base, pin) nrf_gpio_pin_read(pin)
#elif defined(ARDUINO_NANO_RP2040_CONNECT)
#define IO_REG_TYPE pin_size_t
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) pin
#define DIRECT_PIN_READ(base, pin) digitalRead(pin)
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
#include "scss_registers.h"
#include "portable.h"
#include "avr/pgmspace.h"
#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId)
#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType)
#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase)
#define EXT_PORT_OFFSET_SS 0x0A
#define EXT_PORT_OFFSET_SOC 0x50
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase)
#define PIN_TO_BITMASK(pin) pin
#define IO_REG_TYPE uint32_t
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
IO_REG_TYPE ret;
if (SS_GPIO == GPIO_TYPE(pin)) {
ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS));
} else {
ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC);
}
return ((ret >> GPIO_ID(pin)) & 0x01);
}
#define DIRECT_PIN_READ(base, pin) directRead(base, pin)
#endif
#endif

View File

@ -0,0 +1,87 @@
#if defined(__AVR__)
#include <avr/io.h>
#include <avr/interrupt.h>
#define attachInterrupt(num, func, mode) enableInterrupt(num)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define SCRAMBLE_INT_ORDER(num) ((num < 4) ? num + 2 : ((num < 6) ? num - 4 : num))
#define DESCRAMBLE_INT_ORDER(num) ((num < 2) ? num + 4 : ((num < 6) ? num - 2 : num))
#else
#define SCRAMBLE_INT_ORDER(num) (num)
#define DESCRAMBLE_INT_ORDER(num) (num)
#endif
static void enableInterrupt(uint8_t num)
{
switch (DESCRAMBLE_INT_ORDER(num)) {
#if defined(EICRA) && defined(EIMSK)
case 0:
EICRA = (EICRA & 0xFC) | 0x01;
EIMSK |= 0x01;
return;
case 1:
EICRA = (EICRA & 0xF3) | 0x04;
EIMSK |= 0x02;
return;
case 2:
EICRA = (EICRA & 0xCF) | 0x10;
EIMSK |= 0x04;
return;
case 3:
EICRA = (EICRA & 0x3F) | 0x40;
EIMSK |= 0x08;
return;
#elif defined(MCUCR) && defined(GICR)
case 0:
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GICR |= (1 << INT0);
return;
case 1:
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GICR |= (1 << INT1);
return;
#elif defined(MCUCR) && defined(GIMSK)
case 0:
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GIMSK |= (1 << INT0);
return;
case 1:
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GIMSK |= (1 << INT1);
return;
#endif
#if defined(EICRB) && defined(EIMSK)
case 4:
EICRB = (EICRB & 0xFC) | 0x01;
EIMSK |= 0x10;
return;
case 5:
EICRB = (EICRB & 0xF3) | 0x04;
EIMSK |= 0x20;
return;
case 6:
EICRB = (EICRB & 0xCF) | 0x10;
EIMSK |= 0x40;
return;
case 7:
EICRB = (EICRB & 0x3F) | 0x40;
EIMSK |= 0x80;
return;
#endif
}
}
#elif defined(__PIC32MX__)
#ifdef ENCODER_OPTIMIZE_INTERRUPTS
#undef ENCODER_OPTIMIZE_INTERRUPTS
#endif
#else
#ifdef ENCODER_OPTIMIZE_INTERRUPTS
#undef ENCODER_OPTIMIZE_INTERRUPTS
#endif
#endif

View File

@ -0,0 +1,396 @@
// interrupt pins for known boards
// Teensy (and maybe others) define these automatically
#if !defined(CORE_NUM_INTERRUPT)
// Wiring boards
#if defined(WIRING)
#define CORE_NUM_INTERRUPT NUM_EXTERNAL_INTERRUPTS
#if NUM_EXTERNAL_INTERRUPTS > 0
#define CORE_INT0_PIN EI0
#endif
#if NUM_EXTERNAL_INTERRUPTS > 1
#define CORE_INT1_PIN EI1
#endif
#if NUM_EXTERNAL_INTERRUPTS > 2
#define CORE_INT2_PIN EI2
#endif
#if NUM_EXTERNAL_INTERRUPTS > 3
#define CORE_INT3_PIN EI3
#endif
#if NUM_EXTERNAL_INTERRUPTS > 4
#define CORE_INT4_PIN EI4
#endif
#if NUM_EXTERNAL_INTERRUPTS > 5
#define CORE_INT5_PIN EI5
#endif
#if NUM_EXTERNAL_INTERRUPTS > 6
#define CORE_INT6_PIN EI6
#endif
#if NUM_EXTERNAL_INTERRUPTS > 7
#define CORE_INT7_PIN EI7
#endif
// Arduino Uno, Duemilanove, Diecimila, LilyPad, Mini, Fio, etc...
#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) ||defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__)
#define CORE_NUM_INTERRUPT 2
#define CORE_INT0_PIN 2
#define CORE_INT1_PIN 3
// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define CORE_NUM_INTERRUPT 6
#define CORE_INT0_PIN 2
#define CORE_INT1_PIN 3
#define CORE_INT2_PIN 21
#define CORE_INT3_PIN 20
#define CORE_INT4_PIN 19
#define CORE_INT5_PIN 18
// Arduino Nano Every, Uno R2 Wifi
#elif defined(__AVR_ATmega4809__)
#define CORE_NUM_INTERRUPT 22
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
#define CORE_INT20_PIN 20
#define CORE_INT21_PIN 21
// Arduino Leonardo (untested)
#elif defined(__AVR_ATmega32U4__) && !defined(CORE_TEENSY)
#define CORE_NUM_INTERRUPT 5
#define CORE_INT0_PIN 3
#define CORE_INT1_PIN 2
#define CORE_INT2_PIN 0
#define CORE_INT3_PIN 1
#define CORE_INT4_PIN 7
// Sanguino (untested) and ATmega1284P
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__)
#define CORE_NUM_INTERRUPT 3
#define CORE_INT0_PIN 10
#define CORE_INT1_PIN 11
#define CORE_INT2_PIN 2
// ATmega32u2 and ATmega32u16 based boards with HoodLoader2
#elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__)
#define CORE_NUM_INTERRUPT 8
#define CORE_INT0_PIN 8
#define CORE_INT1_PIN 17
#define CORE_INT2_PIN 13
#define CORE_INT3_PIN 14
#define CORE_INT4_PIN 15
#define CORE_INT5_PIN 16
#define CORE_INT6_PIN 19
#define CORE_INT7_PIN 20
// Chipkit Uno32 - attachInterrupt may not support CHANGE option
#elif defined(__PIC32MX__) && defined(_BOARD_UNO_)
#define CORE_NUM_INTERRUPT 5
#define CORE_INT0_PIN 38
#define CORE_INT1_PIN 2
#define CORE_INT2_PIN 7
#define CORE_INT3_PIN 8
#define CORE_INT4_PIN 35
// Chipkit Uno32 - attachInterrupt may not support CHANGE option
#elif defined(__PIC32MX__) && defined(_BOARD_MEGA_)
#define CORE_NUM_INTERRUPT 5
#define CORE_INT0_PIN 3
#define CORE_INT1_PIN 2
#define CORE_INT2_PIN 7
#define CORE_INT3_PIN 21
#define CORE_INT4_PIN 20
// http://hlt.media.mit.edu/?p=1229
#elif defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define CORE_NUM_INTERRUPT 1
#define CORE_INT0_PIN 2
// ATtiny44 ATtiny84
#elif defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#define CORE_NUM_INTERRUPT 1
#define CORE_INT0_PIN 8
// ATtiny441 ATtiny841
#elif defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__)
#define CORE_NUM_INTERRUPT 1
#define CORE_INT0_PIN 9
//https://github.com/SpenceKonde/ATTinyCore/blob/master/avr/extras/ATtiny_x313.md
#elif defined(__AVR_ATtinyX313__)
#define CORE_NUM_INTERRUPT 2
#define CORE_INT0_PIN 4
#define CORE_INT1_PIN 5
// Attiny167 same core as abobe
#elif defined(__AVR_ATtiny167__)
#define CORE_NUM_INTERRUPT 2
#define CORE_INT0_PIN 14
#define CORE_INT1_PIN 3
// Arduino Due
#elif defined(__SAM3X8E__)
#define CORE_NUM_INTERRUPT 54
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
#define CORE_INT20_PIN 20
#define CORE_INT21_PIN 21
#define CORE_INT22_PIN 22
#define CORE_INT23_PIN 23
#define CORE_INT24_PIN 24
#define CORE_INT25_PIN 25
#define CORE_INT26_PIN 26
#define CORE_INT27_PIN 27
#define CORE_INT28_PIN 28
#define CORE_INT29_PIN 29
#define CORE_INT30_PIN 30
#define CORE_INT31_PIN 31
#define CORE_INT32_PIN 32
#define CORE_INT33_PIN 33
#define CORE_INT34_PIN 34
#define CORE_INT35_PIN 35
#define CORE_INT36_PIN 36
#define CORE_INT37_PIN 37
#define CORE_INT38_PIN 38
#define CORE_INT39_PIN 39
#define CORE_INT40_PIN 40
#define CORE_INT41_PIN 41
#define CORE_INT42_PIN 42
#define CORE_INT43_PIN 43
#define CORE_INT44_PIN 44
#define CORE_INT45_PIN 45
#define CORE_INT46_PIN 46
#define CORE_INT47_PIN 47
#define CORE_INT48_PIN 48
#define CORE_INT49_PIN 49
#define CORE_INT50_PIN 50
#define CORE_INT51_PIN 51
#define CORE_INT52_PIN 52
#define CORE_INT53_PIN 53
// ESP8266 (https://github.com/esp8266/Arduino/)
#elif defined(ESP8266)
#define CORE_NUM_INTERRUPT EXTERNAL_NUM_INTERRUPTS
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
// GPIO6-GPIO11 are typically used to interface with the flash memory IC on
// most esp8266 modules, so we should avoid adding interrupts to these pins.
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
// ESP32 (https://github.com/espressif/arduino-esp32)
#elif defined(ESP32)
#define CORE_NUM_INTERRUPT 40
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
// GPIO6-GPIO11 are typically used to interface with the flash memory IC on
// esp32, so we should avoid adding interrupts to these pins.
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
#define CORE_INT21_PIN 21
#define CORE_INT22_PIN 22
#define CORE_INT23_PIN 23
#define CORE_INT25_PIN 25
#define CORE_INT26_PIN 26
#define CORE_INT27_PIN 27
#define CORE_INT32_PIN 32
#define CORE_INT33_PIN 33
#define CORE_INT34_PIN 34
#define CORE_INT35_PIN 35
#define CORE_INT36_PIN 36
#define CORE_INT39_PIN 39
// Arduino Zero - TODO: interrupts do not seem to work
// please help, contribute a fix!
#elif defined(__SAMD21G18A__) || defined(__SAMD21E18A__)
#define CORE_NUM_INTERRUPT 31
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
#define CORE_INT20_PIN 20
#define CORE_INT21_PIN 21
#define CORE_INT22_PIN 22
#define CORE_INT23_PIN 23
#define CORE_INT24_PIN 24
#define CORE_INT25_PIN 25
#define CORE_INT26_PIN 26
#define CORE_INT27_PIN 27
#define CORE_INT28_PIN 28
#define CORE_INT29_PIN 29
#define CORE_INT30_PIN 30
#elif defined(__SAMD51__)
#define CORE_NUM_INTERRUPT 26
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
#define CORE_INT20_PIN 20
#define CORE_INT21_PIN 21
#define CORE_INT22_PIN 22
#define CORE_INT23_PIN 23
#define CORE_INT24_PIN 24
#define CORE_INT25_PIN 25
// Arduino 101
#elif defined(__arc__)
#define CORE_NUM_INTERRUPT 14
#define CORE_INT2_PIN 2
#define CORE_INT5_PIN 5
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
// Arduino Nano 33 BLE
#elif defined(ARDUINO_ARCH_NRF52840)
#define CORE_NUM_INTERRUPT 22
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN A0
#define CORE_INT15_PIN A1
#define CORE_INT16_PIN A2
#define CORE_INT17_PIN A3
#define CORE_INT18_PIN A4
#define CORE_INT19_PIN A5
#define CORE_INT20_PIN A6
#define CORE_INT21_PIN A7
// Arduino Nano RP2040 Connect
#elif defined(ARDUINO_NANO_RP2040_CONNECT)
#define CORE_NUM_INTERRUPT 20
#define CORE_INT0_PIN 0
#define CORE_INT1_PIN 1
#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT16_PIN 16
#define CORE_INT17_PIN 17
#define CORE_INT18_PIN 18
#define CORE_INT19_PIN 19
// #define CORE_INT20_PIN A6
// #define CORE_INT21_PIN A7
#endif
#endif
#if !defined(CORE_NUM_INTERRUPT)
#error "Interrupts are unknown for this board, please add to this code"
#endif
#if CORE_NUM_INTERRUPT <= 0
#error "Encoder requires interrupt pins, but this board does not have any :("
#error "You could try defining ENCODER_DO_NOT_USE_INTERRUPTS as a kludge."
#endif

View File

@ -103,7 +103,7 @@
103, 103,
103, 103,
103, 103,
103 0
], ],
"custom_group_rules": [], "custom_group_rules": [],
"expanded_rows": [], "expanded_rows": [],