// https://wokwi.com/projects/386139924464331777
// https://forum.arduino.cc/t/fader-pickup-catch-mode/1206227
// temporarily 0..31 disaplyed on 16 LEDs.
# define MAXX 32 // 128
# define OSCALE 2 // 8 so 16 LEDs are 0..127
# define ENCODER_CLK 2
# define ENCODER_DT 3
# define slideFaderPin A0
bool rotaryCCW;
bool rotaryCW;
# define testSnapZero A1
# define testSnapMAXX A2
# include <Adafruit_NeoPixel.h>
# define N_REAL 16
# define PIN 8
Adafruit_NeoPixel led(N_REAL, PIN, NEO_GRB + NEO_KHZ800);
# define faderPrime 6
# define rotaryPrime 5
# define catchMode 4
int rotaryValue = 16;
int slideFaderValue;
void setup()
{
Serial.begin(115200); Serial.println("first things first");
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);
pinMode(faderPrime, OUTPUT);
pinMode(rotaryPrime, OUTPUT);
pinMode(catchMode, OUTPUT);
// test buttons for very rapid slide fading LOW equals rapid movement to value
pinMode(testSnapZero, INPUT_PULLUP);
pinMode(testSnapMAXX, INPUT_PULLUP);
led.begin();
led.setPixelColor(1, 0xff0000);
led.show();
delay(777);
}
bool trackA = true;
enum {ROT = 0, FADE, FADE_LOW, FADE_HIGH, FADE_EQUAL};
char *stateTags[] = {"ROT", "FADE", "FADE_LOW", "FADE_HIGH", "FADE_EQUAL"};
unsigned char state = FADE;
void loop()
{
static int lastSlideFaderValue;
static int output;
// INPUT
bool slideFaderInput = false;
int faderReading;
faderReading = analogRead(slideFaderPin);
// these are so we can easily yank the fader to an extreme. still goes through mapping &c.
if (!digitalRead(testSnapZero)) faderReading = 0;
if (!digitalRead(testSnapMAXX)) faderReading = 1023;
int slideFaderValue = map(faderReading, 0, 1023, 0, MAXX);
if (slideFaderValue >= MAXX) slideFaderValue = MAXX - 1; // argh! map!
if (slideFaderValue != lastSlideFaderValue) {
slideFaderInput = true;
// lastSlideFaderValue = slideFaderValue; don't update this until it has informed any change of state
}
bool rotaryInput = rotaryCW || rotaryCCW;
/*
Serial.print(" slideFader at ");
Serial.print(valA);
Serial.print(" rotary accumulated value ");
Serial.print(rotaryValue);
Serial.println("");
*/
// PROCESS
if (rotaryInput) {
if (state == FADE) {
rotaryValue = slideFaderValue; // coming from fader, we grab the current value
}
state = ROT; // always
if (rotaryCW) {
rotaryValue++;
rotaryCW = false;
rotaryInput = true;
}
if (rotaryCCW) {
rotaryValue--;
rotaryCCW = false;
rotaryInput = true;
}
if (rotaryValue < 0) rotaryValue = 0;
if (rotaryValue >= MAXX) rotaryValue = MAXX - 1;
}
// just to report new state
static unsigned lastState = 0xff; // no state
if (state != lastState) {
Serial.print("state = "); Serial.println(stateTags[state]);
lastState = state;
}
switch (state) {
case ROT : // the rotary encoder is (still) in charge
output = rotaryValue;
if (slideFaderInput) {
if (lastSlideFaderValue < rotaryValue) state = FADE_LOW;
else if (lastSlideFaderValue > rotaryValue) state = FADE_HIGH;
else { // slideFaderValue == rotaryValue... it could happen
Serial.println("does this hapen? How do we deal with it?");
output = slideFaderValue;
state = FADE;
}
}
break;
case FADE_LOW : // rotary constant, slide fader activity, wait it may exceed and capture
if (slideFaderValue >= rotaryValue) {
Serial.println(" pickup catch from below!");
state = FADE;
output = slideFaderValue;
}
break;
case FADE_HIGH : // rotary constant, slide fader activity, it may subceed and capture
if (slideFaderValue <= rotaryValue) {
Serial.println(" pickup catch from above!");
state = FADE;
output = slideFaderValue;
}
break;
// case FADE_EQUAL : // silde fader good to just take over - it already did, nevermind
// break;
case FADE :
// rotaryValue = slideFaderValue;
output = slideFaderValue;
break;
default :
Serial.println("impossible"); while (1);
}
// now
lastSlideFaderValue = slideFaderValue;
// OUTPUT
// Serial.println(output);
setLAMPS(); // status indicators
led.clear();
led.setPixelColor(slideFaderValue / OSCALE, 0xd00000);
led.setPixelColor(output / OSCALE, 0xff40c0);
led.show();
}
void readEncoder() {
int dtValue = digitalRead(ENCODER_DT);
if (dtValue == HIGH) {
// Serial.println("Rotated clockwise >>");
rotaryCW = true;
}
if (dtValue == LOW) {
// Serial.println("Rotated counterclockwise <<");
rotaryCCW = true;
}
}
void setLAMPS()
{
switch (state) {
case ROT :
digitalWrite(rotaryPrime, HIGH);
digitalWrite(faderPrime, LOW);
digitalWrite(catchMode, LOW);
break;
case FADE_LOW :
case FADE_HIGH :
digitalWrite(rotaryPrime, HIGH);
digitalWrite(faderPrime, LOW);
digitalWrite(catchMode, HIGH);
break;
case FADE :
digitalWrite(faderPrime, HIGH);
digitalWrite(rotaryPrime, LOW);
digitalWrite(catchMode, LOW);
break;
default :
Serial.println("impossible"); while (1);
}
}
zero
maxx
instant
MAXX
instant
ZERO