-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add README, get color wheel working, code cleanup.
- Loading branch information
Showing
3 changed files
with
129 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
The Whueel | ||
========== | ||
|
||
The _Hue Wheel_: a MIDI controller for controlling the hue of lights. | ||
|
||
Currently uses MIDI channel 7 and control change 111. | ||
|
||
Built from: | ||
* [Teensy 2.0](https://www.pjrc.com/store/teensy.html) | ||
* [Bourns EAW Absolute Rotary Encoder](https://www.bourns.com/products/encoders/contacting-encoders/product/EAW) | ||
* [12X WS8212 RGB LED Ring](http://www.diymalls.com/OLED?product_id=345) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,99 +1,129 @@ | ||
// #define STR_PRODUCT L"The Whueel MIDI" | ||
#include "ACE128.h" // Absolute Contact Encoder | ||
#include <ACE128map12345678.h> // mapping for pin order 12345678 | ||
#include <Wire.h> // I2C bus communication library - required to support ACE128 | ||
// FIXME: Attempt to change USB device name! | ||
#define STR_PRODUCT L"The Whueel MIDI" | ||
|
||
#if !defined(__AVR_ATmega32U4__) || !defined(CORE_TEENSY) | ||
#error "Only designed to run on Teensy 2.0!" | ||
#endif | ||
|
||
#if !defined(USB_MIDI) | ||
#error "USB Type should be set to MIDI!" | ||
#endif | ||
|
||
#include "ACE128.h" | ||
#include <ACE128map12345678.h> | ||
#include <Adafruit_NeoPixel.h> | ||
|
||
// Create an ACE128 instance called myACE | ||
ACE128 myACE(10,9,8,7,11,14,13,12, (uint8_t*)encoderMap_12345678); | ||
|
||
uint8_t pinPos = 0; // pin values | ||
uint8_t oldPos = 255; | ||
uint8_t old_upos = 255; | ||
uint8_t upos = 0; | ||
uint8_t seen = 0; | ||
elapsedMillis msec = 0; | ||
|
||
|
||
// Which pin on the Arduino is connected to the NeoPixels? | ||
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1 | ||
|
||
// How many NeoPixels are attached to the Arduino? | ||
#define NUMPIXELS 12 // Popular NeoPixel ring size | ||
|
||
// When setting up the NeoPixel library, we tell it how many pixels, | ||
// and which pin to use to send signals. Note that for older NeoPixel | ||
// strips you might need to change the third parameter -- see the | ||
// strandtest example for more information on possible values. | ||
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); | ||
|
||
void setup() { | ||
int error = 1; | ||
myACE.begin(); // this is required for each instance, initializes the pins | ||
pinPos = myACE.acePins(); // get IO expander pins | ||
oldPos = pinPos; // remember where we are | ||
Serial.begin(9600); | ||
Serial.println(myACE.acePins()); | ||
pixels.begin(); | ||
#define MIDI_CHANNEL 7 | ||
#define MIDI_CC_NUM 111 | ||
|
||
#define ACE_PIN1 10 | ||
#define ACE_PIN2 9 | ||
#define ACE_PIN3 8 | ||
#define ACE_PIN4 7 | ||
#define ACE_PIN5 11 | ||
#define ACE_PIN6 14 | ||
#define ACE_PIN7 13 | ||
#define ACE_PIN8 12 | ||
|
||
#define PIXEL_COUNT 12 | ||
#define PIXEL_OFFSET 8 | ||
#define PIXEL_PIN 6 | ||
|
||
// ACE128 instance with pin mapping. | ||
ACE128 encoder(ACE_PIN1, ACE_PIN2, ACE_PIN3, ACE_PIN4, ACE_PIN5, ACE_PIN6, ACE_PIN7, ACE_PIN8, (uint8_t*)encoderMap_12345678); | ||
|
||
// NeoPixel ring (12 LED). | ||
Adafruit_NeoPixel pixels(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); | ||
|
||
void setup() | ||
{ | ||
encoder.begin(); | ||
encoder.setZero(0); | ||
pixels.begin(); | ||
Serial.begin(9600); | ||
Serial.println(encoder.acePins()); | ||
} | ||
|
||
static void check_pins(uint8_t pins) | ||
{ | ||
static uint8_t seen_pins = 0; | ||
static uint8_t old_pins = 255; | ||
|
||
void loop() { | ||
|
||
pinPos = myACE.acePins(); // get IO expander pins | ||
upos = myACE.upos(); // get logical position - unsigned | ||
if (pins == old_pins) { | ||
return; | ||
} | ||
|
||
if (pinPos != oldPos) { // did we move? | ||
seen |= pinPos ^ oldPos; // what changed? | ||
oldPos = pinPos; // remember where we are | ||
if (seen < 255) { | ||
Serial.print("looking for pins: "); | ||
for (uint8_t i = 0; i <= 7; i++) { | ||
if (! (seen & 1 << i)) { | ||
Serial.print(i, DEC); | ||
seen_pins |= pins ^ old_pins; | ||
old_pins = pins; | ||
if (seen_pins < 255) { | ||
Serial.print("looking for pins: "); | ||
for (uint8_t i = 0; i <= 7; i++) { | ||
if (! (seen_pins & 1 << i)) { | ||
Serial.print(i, DEC); | ||
} | ||
} | ||
} | ||
Serial.println(""); | ||
} else { | ||
Serial.print(" upos "); | ||
Serial.println(upos, DEC); | ||
Serial.println(""); | ||
} | ||
else { | ||
Serial.print("pins = "); | ||
Serial.println(pins, DEC); | ||
} | ||
} | ||
|
||
static void update_midi(uint8_t upos) | ||
{ | ||
static uint8_t old_upos = 255; | ||
static elapsedMillis msec = 0; | ||
|
||
// Send MIDI updates at most 50x/sec and only if input changed. | ||
if (msec >= 20 && upos != old_upos) { | ||
msec = 0; | ||
old_upos = upos; | ||
usbMIDI.sendControlChange(MIDI_CC_NUM, upos, MIDI_CHANNEL); | ||
} | ||
} | ||
|
||
// only check the analog inputs 50 times per second, | ||
// to prevent a flood of MIDI messages | ||
pixels.setBrightness(0x10); | ||
if (msec >= 20) { | ||
msec = 0; | ||
// only transmit MIDI messages if analog input changed | ||
if (upos != old_upos) { | ||
usbMIDI.sendControlChange(111, upos, 7); | ||
old_upos = upos; | ||
pixels.setPixelColor(4, (upos >= 123 || upos < 6) ? 0xff0000 : 0x400000); | ||
pixels.setPixelColor(5, (upos >= 6 && upos < 17) ? 0xbf3f00 : 0x301000); | ||
pixels.setPixelColor(6, (upos >= 17 && upos < 27) ? 0x7f7f00 : 0x202000); | ||
pixels.setPixelColor(7, (upos >= 27 && upos < 38) ? 0x3fbf00 : 0x103000); | ||
pixels.setPixelColor(8, (upos >= 38 && upos < 49) ? 0x00ff00 : 0x004000); | ||
pixels.setPixelColor(9, (upos >= 49 && upos < 59) ? 0x00bf3f : 0x003010); | ||
pixels.setPixelColor(10, (upos >= 59 && upos < 70) ? 0x007f7f : 0x002020); | ||
pixels.setPixelColor(11, (upos >= 70 && upos < 81) ? 0x003fbf : 0x001030); | ||
pixels.setPixelColor(0, (upos >= 81 && upos < 91) ? 0x0000ff: 0x000040); | ||
pixels.setPixelColor(1, (upos >= 91 && upos < 102) ? 0x3f00bf : 0x100030); | ||
pixels.setPixelColor(2, (upos >= 102 && upos < 113) ? 0x7f007f: 0x200020); | ||
pixels.setPixelColor(3, (upos >= 113 && upos < 123) ? 0xbf003f: 0x300010); | ||
|
||
//for (int i=0; i < pixels.numPixels(); i++) { | ||
// pixels.setPixelColor(i, () << 16 | ||
//pixels.setPixelColor(i, upos); | ||
//} | ||
pixels.show(); | ||
|
||
// MIDI Controllers should discard incoming MIDI messages. | ||
// http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash | ||
while (usbMIDI.read()) { | ||
// ignore incoming messages | ||
} | ||
} | ||
} | ||
|
||
static void update_leds(uint8_t upos) | ||
{ | ||
static uint8_t old_upos = 255; | ||
|
||
if (upos == old_upos) { | ||
return; | ||
} | ||
|
||
old_upos = upos; | ||
pixels.setBrightness(255); | ||
|
||
for (uint16_t p = 0; p < pixels.numPixels(); p++) { | ||
uint16_t pIndex = (p + PIXEL_OFFSET) % pixels.numPixels(); | ||
uint16_t pPos = pIndex * 128 / pixels.numPixels(); | ||
uint16_t pDiff = abs((int16_t)pPos - (int16_t)upos); | ||
if (pDiff > 64) { | ||
pDiff = 128 - pDiff; | ||
} | ||
uint8_t pVal = 15; | ||
if (pDiff <= (128 / pixels.numPixels())) { | ||
pVal = 255 - pDiff * 288 / pixels.numPixels(); | ||
} | ||
uint32_t pColor = pixels.ColorHSV(pIndex * (65535 / pixels.numPixels()), 255, pVal); | ||
pixels.setPixelColor(p, pColor); | ||
} | ||
|
||
pixels.show(); | ||
} | ||
|
||
// MIDI Controllers should discard incoming MIDI messages. | ||
// http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash | ||
while (usbMIDI.read()) { | ||
// ignore incoming messages | ||
} | ||
void loop() | ||
{ | ||
uint8_t pins = encoder.acePins(); | ||
uint8_t upos = encoder.upos(); | ||
|
||
check_pins(pins); | ||
update_midi(upos); | ||
update_leds(upos); | ||
} |