MCP23017-RotaryEncoder-No-Interrupts
This example demonstrates the use of MCP23017 IĀ²C port expanders with rotary encoders that send relative Control Change messages.
- Boards: š
- AVR, AVR USB, Nano Every, Nano 33 IoT, Nano 33 BLE, UNO R4, Pi Pico, Due, Teensy 3.x, ESP8266, ESP32
Connections
- SDA: MCP23017 SDA
- SCL: MCP23017 SCL
- 12: MCP23017 INTA or INTB
Connect up to 8 encoders to the MCP23017's GPIO pins: the first encoder connects to GPIO A0 and A1, the second encoder connects to GPIO A2 and A3, ..., the eighth encoder connects to GPIO B6 and B7.
Connect the "common" pins of the encoders to ground.
The built-in pull-up resistors of the MCP23017 will be enabled.
Make sure that the reset and address pins are all configured correctly (reset to Vcc; A0, A1 and A2 to ground).
If you need more than one MCP23017 with encoders, you can connect their interrupt pins together. This does result in higher latency, because on average, half of the total number of MCP23017s have to be polled, which is relatively slow, and might lead to missed pulses when using a large number of encoders.
Behavior
When the position of one of the encoders changes, a relative Control Change message is sent.
Mapping
Map the Arduino as a Mackie Control Universal in your DAW. The encoders will control the pan (just like the V-Pots on an MCU).
Cautions
The interrupt pin of the MCP23017 doesn't trigger a hardware interrupt on the Arduino. It's used only to determine whether the Arduino should read the GPIO registers from the MCP23017.
If the update function isn't called often enough, you will miss encoder pulses, and the position will be incorrect.
It's very important to keep your main loop free from any code that blocks for more than a couple of hundreds of microseconds.
Keep in mind that reading analog inputs can be slow, so adding lots of potentiometers to Control Surface will interfere with the encoders.
Written by PieterP, 2020-04-06
https://github.com/tttapa/Arduino-Helpers
#include <Wire.h>
using WireType = decltype(Wire);
using EncoderPositionType = uint8_t;
using MCPEncoderType = MCP23017Encoders<WireType, EncoderPositionType>;
RelativeCCSender> {
CCMCPEncoder(MCPEncoderType::MCP23017Encoder enc,
MIDIAddress address,
int16_t multiplier = 1, uint8_t pulsesPerStep = 4)
pulsesPerStep, {}) {}
};
MCPEncoderType enc {Wire, 0x0, 12};
CCMCPEncoder ccencoders[] {
{
enc[0],
1,
4,
},
};
void setup() {
Wire.begin();
Wire.setClock(800000);
enc.begin();
}
void loop() {
}
The main header file that includes all Control-Surface header files.
Control_Surface_ & Control_Surface
A predefined instance of the Control Surface to use in the Arduino sketches.
bool update()
Read the analog input value, apply the mapping function, and update the average.
void begin()
Initialize the Control_Surface.
void loop()
Update all MIDI elements, send MIDI events and read MIDI input.
An abstract class for rotary encoders that send MIDI events.
GenericMIDIRotaryEncoder(Enc &&encoder, MIDIAddress address, int16_t speedMultiply, uint8_t pulsesPerStep, const Sender &sender)
Construct a new MIDIRotaryEncoder.
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
A class for debug MIDI interfaces sending and receiving human-readable MIDI messages over the USB CDC...
constexpr uint8_t V_POT_5
V-Pot 5 (Relative) (Out)
constexpr uint8_t V_POT_2
V-Pot 2 (Relative) (Out)
constexpr uint8_t V_POT_1
V-Pot 1 (Relative) (Out)
constexpr uint8_t V_POT_7
V-Pot 7 (Relative) (Out)
constexpr uint8_t V_POT_8
V-Pot 8 (Relative) (Out)
constexpr uint8_t V_POT_6
V-Pot 6 (Relative) (Out)
constexpr uint8_t V_POT_3
V-Pot 3 (Relative) (Out)
constexpr uint8_t V_POT_4
V-Pot 4 (Relative) (Out)