Hi Im working on a midi controller I'm using the Teensy 4.1 with a mpc23s17 I currently have 8 encoders wired up to the mcp. When I turn the encoders I have to turn them almost a full rotation to get it to move one or two increments on the serial monitor. Anybody have any tips? Thanks in advance.
Here is the code I'm using
#include <Adafruit_MCP23X17.h>
#include <MIDI.h>
Adafruit_MCP23X17 mcp;
MIDI_CREATE_DEFAULT_INSTANCE();
const int MCP_CS_PIN = 10; // Chip select for SPI
const int NUM_ENCODERS = 8;
// Encoder state storage
uint8_t lastState[NUM_ENCODERS];
int encoderValues[NUM_ENCODERS] = {0};
// MIDI CC numbers for each encoder
const uint8_t midiCCs[NUM_ENCODERS] = {20, 21, 22, 23, 24, 25, 26, 27};
void setup() {
Serial.begin(115200);
MIDI.begin(MIDI_CHANNEL_OMNI);
if (!mcp.begin_SPI(MCP_CS_PIN)) {
Serial.println("Failed to initialize MCP23S17");
while (1);
}
// Setup encoder pins
for (int i = 0; i < NUM_ENCODERS; i++) {
int pinA = i * 2;
int pinB = i * 2 + 1;
mcp.pinMode(pinA, INPUT);
mcp.pinMode(pinB, INPUT);
mcp.digitalWrite(pinA, HIGH); // enable pull-ups
mcp.digitalWrite(pinB, HIGH);
// Read initial state
uint8_t a = mcp.digitalRead(pinA);
uint8_t b = mcp.digitalRead(pinB);
lastState = (a << 1) | b;
}
}
void loop() {
for (int i = 0; i < NUM_ENCODERS; i++) {
int pinA = i * 2;
int pinB = i * 2 + 1;
uint8_t a = mcp.digitalRead(pinA);
uint8_t b = mcp.digitalRead(pinB);
uint8_t state = (a << 1) | b;
if (state != lastState) {
int delta = getEncoderDelta(lastState, state);
if (delta != 0) {
encoderValues = constrain(encoderValues + delta, 0, 127);
MIDI.sendControlChange(midiCCs, encoderValues, 1);
Serial.print("Encoder ");
Serial.print(i);
Serial.print(": ");
Serial.println(encoderValues);
}
lastState = state;
}
}
}
int getEncoderDelta(uint8_t last, uint8_t current) {
// Basic gray-code to direction mapping
if ((last == 0b00 && current == 0b01) ||
(last == 0b01 && current == 0b11) ||
(last == 0b11 && current == 0b10) ||
(last == 0b10 && current == 0b00)) {
return 1;
}
if ((last == 0b00 && current == 0b10) ||
(last == 0b10 && current == 0b11) ||
(last == 0b11 && current == 0b01) ||
(last == 0b01 && current == 0b00)) {
return -1;
}
return 0;
}
Here is the code I'm using
#include <Adafruit_MCP23X17.h>
#include <MIDI.h>
Adafruit_MCP23X17 mcp;
MIDI_CREATE_DEFAULT_INSTANCE();
const int MCP_CS_PIN = 10; // Chip select for SPI
const int NUM_ENCODERS = 8;
// Encoder state storage
uint8_t lastState[NUM_ENCODERS];
int encoderValues[NUM_ENCODERS] = {0};
// MIDI CC numbers for each encoder
const uint8_t midiCCs[NUM_ENCODERS] = {20, 21, 22, 23, 24, 25, 26, 27};
void setup() {
Serial.begin(115200);
MIDI.begin(MIDI_CHANNEL_OMNI);
if (!mcp.begin_SPI(MCP_CS_PIN)) {
Serial.println("Failed to initialize MCP23S17");
while (1);
}
// Setup encoder pins
for (int i = 0; i < NUM_ENCODERS; i++) {
int pinA = i * 2;
int pinB = i * 2 + 1;
mcp.pinMode(pinA, INPUT);
mcp.pinMode(pinB, INPUT);
mcp.digitalWrite(pinA, HIGH); // enable pull-ups
mcp.digitalWrite(pinB, HIGH);
// Read initial state
uint8_t a = mcp.digitalRead(pinA);
uint8_t b = mcp.digitalRead(pinB);
lastState = (a << 1) | b;
}
}
void loop() {
for (int i = 0; i < NUM_ENCODERS; i++) {
int pinA = i * 2;
int pinB = i * 2 + 1;
uint8_t a = mcp.digitalRead(pinA);
uint8_t b = mcp.digitalRead(pinB);
uint8_t state = (a << 1) | b;
if (state != lastState) {
int delta = getEncoderDelta(lastState, state);
if (delta != 0) {
encoderValues = constrain(encoderValues + delta, 0, 127);
MIDI.sendControlChange(midiCCs, encoderValues, 1);
Serial.print("Encoder ");
Serial.print(i);
Serial.print(": ");
Serial.println(encoderValues);
}
lastState = state;
}
}
}
int getEncoderDelta(uint8_t last, uint8_t current) {
// Basic gray-code to direction mapping
if ((last == 0b00 && current == 0b01) ||
(last == 0b01 && current == 0b11) ||
(last == 0b11 && current == 0b10) ||
(last == 0b10 && current == 0b00)) {
return 1;
}
if ((last == 0b00 && current == 0b10) ||
(last == 0b10 && current == 0b11) ||
(last == 0b11 && current == 0b01) ||
(last == 0b01 && current == 0b00)) {
return -1;
}
return 0;
}