MIDI instrument - controlling Neopixels (ws2812) with softpots - only 2 out of 3 softpots are controlling pixels as expected

Thanks for that. There is clearly a problem with that fret data with the first 8 frets all showing the maximum value. Not too sure at the moment if this is a hardware or software problem. So we need to test which it is.
This is best done by continuously reading the ribbon pots (one to start with) and printing out both the raw value and the processed value. Given your difficulties in being able to do the simple addition of the printing out of the EEPROM contents, I have written some code for you to try. I don't have your hardware so it is just the code I have written, that is compiled but not tested.

/*
  Arduino Ribbon Synth MIDI test code for ribbon sensors
   ------------------------------------
*/
#include <EEPROM.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define N_STR     3
#define N_FRET    21
#define PIN_BUTTON_STICK 3
#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
int softPotVals[] = {
  0, 0, 0
};
int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

//--------- Setup ----------------//
void setup() {

    //begin at MIDI spec baud rate
  Serial.begin(9600);
  delay(800);
  Serial.println("Starting test");
  //Serial.begin(31250);
  
  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
      for (int j = 1; j < 21; j++) {
         fretDefs[i][j] = EEPROM.read(j + (21 * i));
      }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  pinMode(PIN_BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_LEFT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_UP, INPUT_PULLUP);
  pinMode(PIN_BUTTON_DOWN, INPUT_PULLUP);
  pinMode(PIN_BUTTON_STICK, INPUT_PULLUP);
}

//----------Main Loop---------------//
void loop() {
  readSensors();
}

void readSensors() { // just read the ribbon pot
    softPotVals[0] = analogRead(softPotPins[0]);
    Serial.print("Raw read "); Serial.println(softPotVals[0]);
    softPotVals[0] = map(softPotVals[0], calibrationMin[0], calibrationMax[0], 0, 255);
    Serial.print("Maped value "); Serial.println(softPotVals[0]);
    softPotVals[0] = constrain(softPotVals[0], 0, 255);
    Serial.print("Maped value "); Serial.println(softPotVals[0]);
    delay(1000);
  }

This will print out every second, so move your finger along the soft pot from top to bottom and see what the readings are.

I did notice when writing this code that the analogue inputs reading the ribbon pots had their internal pull up pin enabled. That coupled with your pull down resistor is not a good thing to do.

1 Like

Ok, after uploading your test sketch I get the below results for Softpot A0 when slowly moving from the high fret end to the low fret end. The 'Maped value' readings alternating between 242 and 255 at the end happen when I release my finger from the softpot altogether.

Starting test
Raw read 2
Maped value 229
Maped value 229
Raw read 9
Maped value 140
Maped value 140
Raw read 37
Maped value -216
Maped value 0
Raw read 61
Maped value -522
Maped value 0
Raw read 83
Maped value -803
Maped value 0
Raw read 142
Maped value -1555
Maped value 0
Raw read 175
Maped value -1976
Maped value 0
Raw read 197
Maped value -2256
Maped value 0
Raw read 226
Maped value -2626
Maped value 0
Raw read 261
Maped value -3072
Maped value 0
Raw read 304
Maped value -3621
Maped value 0
Raw read 331
Maped value -3965
Maped value 0
Raw read 370
Maped value -4462
Maped value 0
Raw read 418
Maped value -5074
Maped value 0
Raw read 458
Maped value -5584
Maped value 0
Raw read 492
Maped value -6018
Maped value 0
Raw read 529
Maped value -6489
Maped value 0
Raw read 566
Maped value -6961
Maped value 0
Raw read 607
Maped value -7484
Maped value 0
Raw read 640
Maped value -7905
Maped value 0
Raw read 672
Maped value -8313
Maped value 0
Raw read 708
Maped value -8772
Maped value 0
Raw read 753
Maped value -9345
Maped value 0
Raw read 793
Maped value -9855
Maped value 0
Raw read 832
Maped value -10353
Maped value 0
Raw read 870
Maped value -10837
Maped value 0
Raw read 919
Maped value -11462
Maped value 0
Raw read 972
Maped value -12138
Maped value 0
Raw read 1009
Maped value -12609
Maped value 0
Raw read 22
Maped value -25
Maped value 0
Raw read 0
Maped value 255
Maped value 255
Raw read 0
Maped value 255
Maped value 255
Raw read 0
Maped value 255
Maped value 255
Raw read 1
Maped value 242
Maped value 242
Raw read 1
Maped value 242
Maped value 242

OK Thanks, very interesting. There is no way that the mapped values should be coming out as negative because they are only going to be constrained to zero.

Can you do another experiment for me please.
Can you move those 100K pull down resistors to be pull up resistors.
The take your code from reply #33 and comment out these lines

Then run the calibration again and repeat that last code I gave you.
Then we might get somewhere with this calculation which looks like it is getting something wrong.

Yes that is strange, as the only non-negative mapped values I get are on the first 1/2 centimeter or so of the very high end/terminal side of the softpot

Sure, after moving the 100k resistors on the wipers of all 3 softpots from ground to the positive rail, reloading/calibrating the sketch from post #33 with the specified lines commented out - I get the following results when running the test sketch:

  • The last several results starting with -28560 occur after releasing my finger from the softpot, and it repeats -28560 (and -28531 every so often)
Starting test
Raw read 5
Maped value 113
Maped value 113
Raw read 48
Maped value -1105
Maped value 0
Raw read 80
Maped value -2011
Maped value 0
Raw read 130
Maped value -3428
Maped value 0
Raw read 163
Maped value -4363
Maped value 0
Raw read 221
Maped value -6006
Maped value 0
Raw read 288
Maped value -7905
Maped value 0
Raw read 331
Maped value -9123
Maped value 0
Raw read 372
Maped value -10285
Maped value 0
Raw read 408
Maped value -11305
Maped value 0
Raw read 445
Maped value -12353
Maped value 0
Raw read 469
Maped value -13033
Maped value 0
Raw read 502
Maped value -13968
Maped value 0
Raw read 540
Maped value -15045
Maped value 0
Raw read 572
Maped value -15951
Maped value 0
Raw read 607
Maped value -16943
Maped value 0
Raw read 639
Maped value -17850
Maped value 0
Raw read 680
Maped value -19011
Maped value 0
Raw read 723
Maped value -20230
Maped value 0
Raw read 757
Maped value -21193
Maped value 0
Raw read 797
Maped value -22326
Maped value 0
Raw read 828
Maped value -23205
Maped value 0
Raw read 856
Maped value -23998
Maped value 0
Raw read 882
Maped value -24735
Maped value 0
Raw read 918
Maped value -25755
Maped value 0
Raw read 954
Maped value -26775
Maped value 0
Raw read 990
Maped value -27795
Maped value 0
Raw read 1011
Maped value -28390
Maped value 0
Raw read 1011
Maped value -28390
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1016
Maped value -28531
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0
Raw read 1017
Maped value -28560
Maped value 0

I say:
there is something badly wrong.
the documentation of the function map:

Syntax

map(value, fromLow, fromHigh, toLow, toHigh)

Parameters

value: the number to map.
fromLow: the lower bound of the value’s current range.
fromHigh: the upper bound of the value’s current range.
toLow: the lower bound of the value’s target range.
toHigh: the upper bound of the value’s target range.

This means the last two parameters are the min and the max-value of the value that is returned

The code posted in post

#41

this line of code does the mapping

  softPotVals[0] = map(softPotVals[0], calibrationMin[0], calibrationMax[0], 0, 255);

the last two parameters are 0 and 255 this means all values printed by
the line

  Serial.print("Maped value "); Serial.println(softPotVals[0]);

must be in the range between 0 and 255

negative values impossible !

So where the heck do the negative values come from??
Is this is a variable-type-problem?
Does the map-function need all parameters of the same type?

The testcode uses the variable

softPotVals[0]

for everything.
It is just a testcode but maybe this is too lazy to do it that way

this variable is defined as int. which is a signed variable that can contain negative values

int softPotVals[] = {
  0, 0, 0
};

could this be a problem of out-of-bound-writing?
or is it a variable-type-problem?

best regards Stefan

1 Like

Thanks for your insight Stefan! Maybe I should try either using byte or unsigned char variable types instead of int, since they limit between 0 and 255.

I will continue to try to figure out ways to test out both theories; please let me know if you have any thoughts on other ways to test. Thanks again!

Neither unsigned char nor the byte variable types changed the results much. I got the below results when following the procedure as instructed in post #43 - after changing the softPotVals and softPotValsOld variables to the unsigned char variable type:

  • The only positive mapped values are at the end when I released my finger from the softpot
Starting test
Raw read 18
Maped value -400
Maped value 0
Raw read 20
Maped value -473
Maped value 0
Raw read 50
Maped value -1566
Maped value 0
Raw read 101
Maped value -3424
Maped value 0
Raw read 159
Maped value -5537
Maped value 0
Raw read 198
Maped value -6957
Maped value 0
Raw read 247
Maped value -8742
Maped value 0
Raw read 354
Maped value -12640
Maped value 0
Raw read 388
Maped value -13879
Maped value 0
Raw read 429
Maped value -15372
Maped value 0
Raw read 512
Maped value -18396
Maped value 0
Raw read 561
Maped value -20181
Maped value 0
Raw read 573
Maped value -20618
Maped value 0
Raw read 624
Maped value -22476
Maped value 0
Raw read 680
Maped value -24516
Maped value 0
Raw read 722
Maped value -26046
Maped value 0
Raw read 749
Maped value -27030
Maped value 0
Raw read 779
Maped value -28122
Maped value 0
Raw read 807
Maped value -29142
Maped value 0
Raw read 836
Maped value -30199
Maped value 0
Raw read 864
Maped value -31219
Maped value 0
Raw read 896
Maped value -32385
Maped value 0
Raw read 908
Maped value 32714
Maped value 255
Raw read 954
Maped value 31039
Maped value 255
Raw read 984
Maped value 29946
Maped value 255
Raw read 993
Maped value 29618
Maped value 255
Raw read 997
Maped value 29472
Maped value 255
Raw read 996
Maped value 29509
Maped value 255

You should always post your actual code.

nobody here as a glas-sphere that is able to show your code while holding this glas-sphere in front of the screen showing the serial output you have posted.

here is a modified version of the testcode that uses different variables

/*
  Arduino Ribbon Synth MIDI test code for ribbon sensors
   ------------------------------------
*/
#include <EEPROM.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define N_STR     3
#define N_FRET    21
#define PIN_BUTTON_STICK 3
#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
int softPotVals[] = {
  0, 0, 0
};
int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

unsigned long dummy1;
unsigned long dummy2;
unsigned long dummy3;
unsigned long dummy4;
unsigned long raw;
unsigned long mappedValue;
unsigned long constrained;
//--------- Setup ----------------//
void setup() {

    //begin at MIDI spec baud rate
  Serial.begin(9600);
  delay(800);
  Serial.println("Starting test");
  //Serial.begin(31250);
  
  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
      for (int j = 1; j < 21; j++) {
         fretDefs[i][j] = EEPROM.read(j + (21 * i));
      }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  pinMode(PIN_BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_LEFT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_UP, INPUT_PULLUP);
  pinMode(PIN_BUTTON_DOWN, INPUT_PULLUP);
  pinMode(PIN_BUTTON_STICK, INPUT_PULLUP);
}

//----------Main Loop---------------//
void loop() {
  readSensors();
}

void readSensors() { // just read the ribbon pot
    raw = analogRead(softPotPins[0]);
    Serial.print("Raw read "); 
    Serial.println(raw);

    mappedValue = map(raw, calibrationMin[0], calibrationMax[0], 0, 255);
    Serial.print("Maped value  "); 
    Serial.println(mappedValue);

    constrained = constrain(mappedValue, 0, 255);
    Serial.print("constrained value "); 
    Serial.println(constrained);
    delay(1000);
  }

try this code. And even if you did not change a single character
post the complete codeversion that you have compiled
together with the serial output
best regards Stefan

1 Like

If a program does not work as expected reduce the possible bugs by reducing variety.

In the testcode

Your variable

int calibrationMax[] = {
  0, 0, 0
};

is initialised with zero and gets never assigned any other value
variable

    calibrationMin[i] = EEPROM.read(21 + (21 * i));

gets assigned values
This means you call the function map with
... map(value,10,0...)
Where the second parameter should be a min-value compared to max-value (the third parameter)

So if you change the map-function to use hardcoded numbers
and test again. WHat values do you get?
Ad if these values are correct, change one single hardcoded value back to the variable and check again etc.

best regards Stefan

1 Like

Ok thanks. Below is the full code I first uploaded to the Arduino for calibration (still configured as Mike requested in post #43 with pull-up resistors and the 3 lines of code commented out):

[code]
/*
  Arduino Ribbon Synth MIDI controller
   ------------------------------------
   ©2014 Dean Miller
*/

#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <QuickStats.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define PIEZO_THRESHOLD_ON 12

#define PIN_LED 13
#define NEO_PIN   21
#define N_PIXELS  21      //# of LEDS

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
#define PIN_PIEZO_1 A3
#define PIN_PIEZO_2 A4
#define PIN_PIEZO_3 A5
#define PIN_POT_1 8
#define PIN_POT_2 6

#define PIN_BUTTON_STICK 3

#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

//Joystick
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
#define STICK 4

#define PIEZO_SAMPLES 400
#define PADDING 2

#define THRESH    200
#define N_STR     3
#define N_FRET    21


//#define MOD_THRESHOLD 30  //Modulation is not send under this value

long noteDebounceTime = 0;
int noteDebounceDelay = 25;

long lastDebounceTime = 0;
int debounceDelay = 200;


long ledDebounceTime = 0;
int ledDebounceDelay = 20;

int mod_final;

//bool isPitchBend = false;
unsigned int pitchBendLight = 0;
//bool dim = false;


//------Note Class---------//
/*
  A note class that stores some info about each note played is necessary
   to ensure that open strings are held for the specified amount of time.
   That is a problem with using the piezos as triggers instead of FSRs, they
   only register momentary impact or vibration, creating a problem for open strings.
*/

class Note {
    int _number;
    int _velocity;
    int _startTime;
    int _fretted;

  public:
    void init(int number, int velocity, int startTime, int fretted) {
      _number = number;
      _velocity = velocity;
      _startTime = startTime;
      _fretted = fretted;
    }

    int number() {
      return _number;
    }

    int velocity() {
      return _velocity;
    }

    int fretted() {
      return _fretted;
    }

    int timeActive() {
      return millis() - _startTime;
    }
};

//------ Global Variables ---------//

/*
  fret defs stored in EEPROM for calibration purposes.
  Lower output voltages from USB ports result in different values read from
  SoftPots and wonky fret definitions.*/

int F0 = 250;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];
//short fretDefs[N_STR][N_FRET];

int piezoVals[] = {
  0, 0, 0
};
int piezoPins[] = {
  PIN_PIEZO_1, PIN_PIEZO_2, PIN_PIEZO_3
};

int softPotVals[] = {
  0, 0, 0
};
int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

int potVal1Old = -1;
int potVal2Old = -1;
int softPotValsOld[] = {
  0, 0, 0
};

int fretTouched[N_STR];
int noteFretted[N_STR];

int stringActive[] = {
  false, false, false
};
int stringPlucked[] = {
  false, false, false
};

Note *activeNotes[N_STR];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

//true for low strings, false for high strings
int stringSetLow = true;
int octave = 3;


//E A D
int offsets_low[] = {16, 21, 26};

//G B E
int offsets_high[] = {19, 23, 28};

//default offsets
int offsets[] = {52, 57, 62};

//states of control buttons
int buttonStates[] = {
  false, false, false, false, false
};
int stickActive = false;
int stickZeroX = 0;
int stickZeroY = 0;
int stickState = false;

int altControlSet = false;
int stickXY = false;
int fullLegatoMode = false;

int minDurationOpen = 75;
int minVelocity = 75;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_PIXELS, NEO_PIN, NEO_GRB + NEO_KHZ800);
int led_number[3] = {0, 0, 0};
int led_color;
int led;
int prev_led;

unsigned long last_read;

QuickStats stats;

//--------- Setup ----------------//
void setup() {

  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
    for (int j = 1; j < 22; j++) {
      fretDefs[i][j] = EEPROM.read(j + (21 * i));
      Serial.println(j + (21 * i)); Serial.print(" - ");  Serial.println(fretDefs[i][j]);
    }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
    Serial.println(21 + (21 * i)); Serial.print(" - ");  Serial.println(calibrationMin[i]);
  }

  //For Calibration, use 9600
  Serial.begin(9600);
  //Serial.println("START");

  //Use 31250 MIDI spec baud rate during normal use
  Serial1.begin(31250);
  
  pinMode(PIN_SOFTPOT_1, INPUT);
  pinMode(PIN_SOFTPOT_2, INPUT);
  pinMode(PIN_SOFTPOT_3, INPUT);
  pinMode(PIN_PIEZO_1, INPUT);
  pinMode(PIN_PIEZO_2, INPUT);
  pinMode(PIN_PIEZO_3, INPUT);
  /*
  digitalWrite(PIN_SOFTPOT_1, HIGH);
  digitalWrite(PIN_SOFTPOT_2, HIGH);
  digitalWrite(PIN_SOFTPOT_3, HIGH);
  */
  pinMode(PIN_BUTTON_RIGHT, INPUT);
  digitalWrite(PIN_BUTTON_RIGHT, HIGH);

  pinMode(PIN_BUTTON_LEFT, INPUT);
  digitalWrite(PIN_BUTTON_LEFT, HIGH);

  pinMode(PIN_BUTTON_UP, INPUT);
  digitalWrite(PIN_BUTTON_UP, HIGH);

  pinMode(PIN_BUTTON_DOWN, INPUT);
  digitalWrite(PIN_BUTTON_DOWN, HIGH);

  pinMode(PIN_BUTTON_STICK, INPUT);
  digitalWrite(PIN_BUTTON_STICK, HIGH);

  pixels.Color(0, 0, 0);
  pinMode(PIN_LED, OUTPUT);

  pixels.begin();
  pixels.setBrightness(50);
  pixels.show();
  
  while (millis() < 500) {
    for (int i = 0; i < N_STR; i++) {
      int val = analogRead(softPotPins[i]);
      if (val > calibrationMax[i]) calibrationMax[i] = val;
    }

    //calibrate joystick
    stickZeroX = analogRead(PIN_JOYSTICK_X);
    stickZeroY = analogRead(PIN_JOYSTICK_Y);
  }
}

//----------Main Loop---------------//
void loop() {
  //reset
  for (int i = 0; i < N_STR; i++) {
    stringPlucked[i] = false;
    piezoVals[i] = false;
  }

  //read values of all sensors
  readSensors();

  determineFrets();

  //if we are in full legato mode, run the function
  if (fullLegatoMode) {
    fullLegato();
  }

  //otherwise just do the regular thing
  else {
    //test for legato action
    legatoTest();
   // onLED(N_PIXELS, 0, 0, 0);
    //use this info to determine which notes to pluck
    pickNotes();
    onLED(N_PIXELS, 0, 0, 0);
  }

  //send not off messages and reset necessary things
  cleanUp();

  //check for control changes
  readControls();
}

void readSensors() {
  for (int i = 0; i < N_STR; i++) {

    //read piezo vals
    int piezoVal = analogRead(piezoPins[i]);
    

    //if the value breaks the threshold read for max amplitude
    /* TODO: this is less than ideal. Have it determine which piezos were triggered and
       then sample them all at once for better support for polyphonic stuff.
    */

    if (piezoVal > PIEZO_THRESHOLD_ON) {
      int v_new = piezoVal;
      for (int sample = 0; sample < PIEZO_SAMPLES; sample++) {
        piezoVal = analogRead(piezoPins[i]);
        if (piezoVal > v_new) {
          v_new = piezoVal;
        }
      }
      piezoVals[i] = v_new;
      piezoVals[i] = map(piezoVals[i], 0, 500, 0, 127);
      piezoVals[i] = constrain(piezoVals[i], minVelocity, 127);
    }

    //read the value of all the softPots
    softPotVals[i] = analogRead(softPotPins[i]);
    softPotVals[i] = map(softPotVals[i], calibrationMin[i], calibrationMax[i], 0, 255);
    softPotVals[i] = constrain(softPotVals[i], 0, 255);
  }
}

void determineFrets () {
  static int count = 0;

  //---------Get Fret Numbers------
  for (int i = 0; i < N_STR; i++) {
  
    int softPotVal = softPotVals[i];

    //check for open strings
    if (softPotVal >= F0) {
      softPotValsOld[i] = softPotVal;
      fretTouched[i] = 0;
      led_number[i] = fretTouched[i];
    }

    //loop through the array of fret definitions
    for (int j = 1; j < N_FRET; j++) {

      int k = j - 1;
      if (softPotVal <= fretDefs[i][k] &&
          softPotVal > fretDefs[i][j] &&
          abs(softPotVal - softPotValsOld[i]) > PADDING) {

        softPotValsOld[i] = softPotVal;
        fretTouched[i] = j-2;
        led_number[i] = fretTouched[i];
        // Serial.print("string= ");  Serial.print(i);  Serial.print("  FretTouched= ");  Serial.print(j); Serial.print("  softpotval = ");  Serial.println(softPotVal);  //count=0;}
      }
    }
    if (softPotVal <= fretDefs[i][20]) {
      softPotValsOld[i] = softPotVal;
      fretTouched[i] = N_FRET;
      led_number[i] = fretTouched[i];
    }
  }
}

void pickNotes() {
  for (int i = 0; i < N_STR; i++) {

    //if the piezo was hit, play the fretted note
    if (piezoVals[i]) {
      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      if (stringActive[i]) {

        //turn off the currently active note on that string
        noteOff(0x80 + i, activeNotes[i]->number(), 0);
        free(activeNotes[i]);
      }

      if (!stringActive[i]) {

        //mark string as active
        stringActive[i] = true;
      }
      //register with active notes
      activeNotes[i] = (Note *) malloc(sizeof(Note));

      if (fretTouched[i] > 0) activeNotes[i]->init(noteFretted[i], piezoVals[i], millis(), true);

      else activeNotes[i]->init(noteFretted[i], piezoVals[i], millis(), false);

      //turn on fretted note
      noteOn(0x90 + i, activeNotes[i]->number(), activeNotes[i]->velocity());

      //mark that the string was plucked
      stringPlucked[i] = true;
    }
  }
}

void legatoTest() {
  for (int i = 0; i < N_STR; i++) {
    if (stringActive[i]) {
      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      if (noteFretted[i] != activeNotes[i]->number() && fretTouched[i]) {
        //turn on new note
        int vel = activeNotes[i]->velocity();
        noteOn(0x90 + i, noteFretted[i], vel);

        //turn off old note
        noteOff(0x80 + i, activeNotes[i]->number(), 0);
        free(activeNotes[i]);

        //register new note as the active one
        activeNotes[i] = (Note *) malloc(sizeof(Note));
        activeNotes[i]->init(noteFretted[i], vel, millis(), true);
      }
    }
  }
}
/*


*/
void fullLegato() {
  for (int i = 0; i < N_STR; i++) {
    if (fretTouched[i]) {

      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      int vel = 127;

      if (!stringActive[i]) {
        noteOn(0x90 + i, noteFretted[i], vel);

        //register new note as the active one
        activeNotes[i] = (Note *) malloc(sizeof(Note));
        activeNotes[i]->init(noteFretted[i], vel, millis(), true);
        stringActive[i] = true;
      }
      else {

        if (noteFretted[i] != activeNotes[i]->number()) {
          int vel = 80;
          noteOn(0x90 + i, noteFretted[i], vel);

          //turn off old note
          noteOff(0x80 + i, activeNotes[i]->number(), 0);
          free(activeNotes[i]);

          //register new note as the active one
          activeNotes[i] = (Note *) malloc(sizeof(Note));
          activeNotes[i]->init(noteFretted[i], vel, millis(), true);
        }
      }
    }
  }
}

 
void cleanUp() {
  for (int i = 0; i < N_STR; i++) {

    //no fret is touched and the string is marked active
    if (!fretTouched[i] && stringActive[i]) {

      //if open string
      if (!activeNotes[i]->fretted()) {
        if (activeNotes[i]->timeActive() > minDurationOpen) {
          //turn off the active note
          noteOff(0x80 + i, activeNotes[i]->number(), 0);

          //mark as inactive
          stringActive[i] = false;
          free(activeNotes[i]);
        }
      }
      else {
        //turn off the active note
        noteOff(0x80 + i, activeNotes[i]->number(), 0);

        //mark as inactive
        stringActive[i] = false;
        free(activeNotes[i]);
      }
    }
  }
}

void readControls() {

  if (altControlSet) {
    minDurationOpen = analogRead(PIN_POT_1);
    minDurationOpen = map(minDurationOpen, 0, 1023, 0, 255 );

    minVelocity = analogRead(PIN_POT_2);
    minVelocity = map(minVelocity, 0, 1023, 0, 127);
  }

  //Potentiometers set the values for controllers 69 and 7
  else {
    int potVal1New = analogRead(PIN_POT_1);
    int potVal2New = analogRead(PIN_POT_2);

    if (abs(potVal1New - potVal1Old) > 30 || potVal1New == 0 || potVal1New == 1023 ) {
      if ((potVal1New - potVal1Old) != 0) {
        //Send MIDI control change message
        int val = map(potVal1New, 0, 1023, 0, 127);
        val = constrain(val, 0, 127);
        controllerChange(69, val);
        potVal1Old = potVal1New;
      }
    }

    if (abs(potVal2New - potVal2Old) > 30 || potVal2New == 0 || potVal2New == 1023) {
      if ((potVal2New - potVal2Old) != 0) {
        //Send MIDI control change message
        int val = map(potVal2New, 0, 1023, 0, 127);
        val = constrain(val, 0, 127);
        controllerChange(7, val);
        potVal2Old = potVal2New;
      }
    }
  }

  //-----ENGAGE FULL LEGATO MODE-----
  //removes the need for triggering with piezo for fretted notes
  if (digitalRead(PIN_BUTTON_LEFT) == LOW && !buttonStates[LEFT]) {
    fullLegatoMode = true;
    buttonStates[LEFT] = true;
  }
  if (digitalRead(PIN_BUTTON_LEFT) == HIGH && buttonStates[LEFT]) {
    fullLegatoMode = false;
    buttonStates[LEFT] = false;
  }

  led = max(led_number[0],led_number[1]);
  Serial.println(led_number[0]);
   //Serial.println(led_number[1]);
  if (led == -1){
    led = 0;
    onLED(N_PIXELS,0,0,0);
  }
    
  else{
    led = led + 1;
    led = map(led,0,N_FRET - 1,0,N_PIXELS);
    led_color = map(led,0,30,0,255);
    //Serial.println(led_number);
    if((millis() - ledDebounceTime ) > ledDebounceDelay){
      for(int i=0;i<led;i++){
        //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
        pixels.setPixelColor(i, Wheel(led_color));
      }
      if(prev_led > led)
        for(int i=led;i<N_PIXELS;i++){
          //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
          pixels.setPixelColor(i, (pixels.Color(0, 0, 0)));
        }
        pixels.show();
        ledDebounceTime = millis(); 
        prev_led = led ;
    }
  }



  //switch to alt control set
  if (digitalRead(PIN_BUTTON_LEFT) == LOW && !buttonStates[LEFT]) {
    altControlSet = !altControlSet;
    buttonStates[LEFT] = true;
  }
  if (digitalRead(PIN_BUTTON_LEFT) == HIGH && buttonStates[LEFT]) buttonStates[LEFT] = false;


  //Right button triggers calibration
  if (digitalRead(PIN_BUTTON_RIGHT) == LOW && !buttonStates[RIGHT]) {
    buttonStates[RIGHT] = true;
    calibrate();
  }



  //---- CHANGING THE OCTAVE -------//
  //UP and down buttons used to change offset/octave. Cycles through EAD and GBE like an infinite guitar neck.

  //---- UP BUTTON ----
  if (digitalRead(PIN_BUTTON_UP) == LOW) {
    //change the set of strings
    if (!buttonStates[UP]) {

      octave = octave - 1;

      stringSetLow = !stringSetLow;

      for (int i = 0; i < N_STR; i++) {
        //if low
        if (stringSetLow) {
          offsets[i] = offsets_low[i] + (12 * octave);
        }
        //if high
        if (!stringSetLow) {
          offsets[i] = offsets_high[i] + (12 * octave);
        }
      }
    }

    buttonStates[UP] = true;
  }
  //reset state once button is no longer being pressed
  if (digitalRead(PIN_BUTTON_UP) == HIGH && buttonStates[UP]) buttonStates[UP] = false;

  //----DOWN BUTTON----
  if (digitalRead(PIN_BUTTON_DOWN) == LOW) {
    //change the set of strings
    if (!buttonStates[DOWN]) {

      octave = octave + 1;

      stringSetLow = !stringSetLow;

      for (int i = 0; i < N_STR; i++) {
        //if low
        if (stringSetLow) {
          offsets[i] = offsets_low[i] + (12 * octave);
        }
        //if high
        if (!stringSetLow) {
          offsets[i] = offsets_high[i] + (12 * octave);
        }
      }
    }

    buttonStates[DOWN] = true;
  }
  //reset state once button is no longer being pressed
  if (digitalRead(PIN_BUTTON_DOWN) == HIGH && buttonStates[DOWN]) buttonStates[DOWN] = false;

  //switch stick to xy mode
  if (digitalRead(PIN_BUTTON_RIGHT) == LOW && !buttonStates[RIGHT]) {
    stickXY = !stickXY;
    buttonStates[RIGHT] = true;
  }
  if (digitalRead(PIN_BUTTON_RIGHT) == HIGH && buttonStates[RIGHT]) buttonStates[RIGHT] = false;

  //--------JOYSTICK-------//
  /* Click down the joystick to activate it. In regular mode it will read absolute position from the
     center in any direction (sends to modwheel, MIDI controller 1), and in XY mode the x axis
     sends to controller 2 (breath) and the y axis sends to controller 4 (foot).  */

  if (digitalRead(PIN_BUTTON_STICK) == LOW) {
    //activate joystick
    if (!buttonStates[STICK]) {
      //make sure modwheel value is set to 0 when stick is off
      if (stickActive) controllerChange(1, 0);
      stickActive = !stickActive;
    }
    buttonStates[STICK] = true;
  }
  //reset once stick is no longer being pressed
  if (digitalRead(PIN_BUTTON_STICK) == HIGH && buttonStates[STICK]) buttonStates[STICK] = false;

  if (stickActive) {
    //read positions from center
    float xPos = map(analogRead(PIN_JOYSTICK_X), stickZeroX, 1023, 0, 127);
    float yPos = map(analogRead(PIN_JOYSTICK_Y), stickZeroY, 1023, 0, 127);

    //get absolute position from center
    float z = sqrt(sq(xPos) + sq(yPos));
    int stickVal = (int)constrain(z, 0, 127);

    if (stickVal > 0) {
      stickState = true;
      if (stickXY) {
        controllerChange(2, abs(xPos));
        controllerChange(4, abs(yPos));
      }
      else controllerChange(1, stickVal);
    }
    else if (stickState && stickVal == 0) {
      stickState = false;
      if (stickXY) {
        controllerChange(2, 0);
        controllerChange(4, 0);
      }
      else controllerChange(1, 0);
    }
  }
}

//----CALIBRATION----//
/* Likely will only have to calibrate once. This is done by activating calibration mode and
   "plucking" each note on each string starting with the upper bound (after the 21st fret) and descending down
   to just after the 1st fret. Starts with the low E string, then the A string and then the D string.
   fret definitions are stored in EEPROM. Once it is calibrated for the voltage put out by the MIDI --> USB board
   you can just have the calibration button do something else because you probably won't need it again.
*/
void unset(int i){
  //this function doesn't even do anything!!
}

void calibrate() {
  
  Serial.println("calibrating...");
  
  for (int i = 0; i < N_STR; i++) {
    //Flash the LED too indicate calibration
    /*
      digitalWrite(PIN_LED, HIGH);
      delay(100);
      digitalWrite(PIN_LED, LOW);
      delay(100);
      digitalWrite(PIN_LED, HIGH);
      delay(100);
      digitalWrite(PIN_LED, LOW);
      delay(100);
      digitalWrite(PIN_LED, HIGH);
    */
    //Flash the LED too indicate calibration
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();
  
    int sensorMax = 0;
    int sensorMin = 1023;
    int val;

    //loop through the array of fret definitions
    for (int j = N_FRET; j > 0; j--) {

      int response = false;
      //wait for response
      Serial.println("waiting");
      //wait for response
      while (!response) {

        //read piezo val
        int piezoVal = analogRead(piezoPins[i]);

        //get the sensor min value (highest fret) on the first round
        if (j == N_FRET) {
          int fretVal = analogRead(softPotPins[i]);
          if (fretVal > sensorMax) (sensorMax = fretVal);
           clrLED();
          //if the piezo is hit, register this as the definition for this fret
          if (piezoVal > PIEZO_THRESHOLD_ON) {
            int fretVal = analogRead(softPotPins[i]);
            sensorMin = fretVal;
            val = fretVal;
            response = true;
            clrLED();
       /*   int addr = j * sizeof(short) + (N_FRET*i*sizeof(short));
          Serial.print("Writing ");
          Serial.print(val);
          Serial.print(" to address: ");
          Serial.println(addr);
          EEPROM.write(addr, val); */
          }
        }

        else {
          //get the rest of the fret definitions
          //if the piezo is hit, register this as the definition for this fret
          if (piezoVal > PIEZO_THRESHOLD_ON) {
            int fretVal = analogRead(softPotPins[i]);
            fretVal = map(fretVal, sensorMin, sensorMax, 0, 255);
            fretVal = constrain(fretVal, 0, 255);
            val = fretVal;
            response = true;
            clrLED();
          }
        }
      }

      //write to memory
      digitalWrite(PIN_LED, LOW);
      EEPROM.write(j + (N_FRET * i), val);
      Serial.println(val);
      delay(100);
      onLED(10, 250, 0, 0);
//      delay(100);
      digitalWrite(PIN_LED, HIGH);
    }


    //update global definitions
    calibrationMin[i] = EEPROM.read(N_FRET + (N_FRET * i));
   // Serial.println(N_FRET + (N_FRET * i)); Serial.print(" - ");  Serial.println(calibrationMin[i]);
    for (int j = 1; j < 22; j++) {
      fretDefs[i][j] = EEPROM.read(j + (i * N_FRET));
      Serial.println(j + (i * N_FRET)); Serial.print(" - ");  Serial.println(fretDefs[i][j]);
    }
    clrLED();
  }
  delay(100);
  onLED(10, 250, 0, 0);
  buttonStates[RIGHT] = false;
  digitalWrite(PIN_LED, LOW);
}
void onLED(int led, int red, int green, int blue) {
  for (int i = 0; i < N_STR; i++) {
  
    //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(red, green, blue));
  }
  pixels.show();
}

void clrLED() {
  for (int i = 0; i < N_PIXELS; i++){
    pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // turn off
  }
  pixels.show();
}
//-------------MIDI functions-----------------

//note-on message
void noteOn(int cmd, int pitch, int velocity) {

  Serial1.write(byte(cmd));
  Serial1.write(byte(pitch));
  Serial1.write(byte(velocity));
  digitalWrite(PIN_LED, HIGH);
}
//note-off message
void noteOff(int cmd, int pitch, int velocity) {

  Serial1.write(byte(cmd));
  Serial1.write(byte(pitch));
  Serial1.write(byte(0));
  digitalWrite(PIN_LED, LOW);
}

//Sends controller change to the specified controller
void controllerChange(int controller, int value) {
  Serial1.write(byte(0xb0));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));

  Serial1.write(byte(0xb1));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));

  Serial1.write(byte(0xb2));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3 + pitchBendLight, 0, WheelPos * 3 + pitchBendLight);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3 + pitchBendLight , 255 - WheelPos * 3 + pitchBendLight);
  }
  else{
    WheelPos -= 170;
    return pixels.Color(WheelPos * 3 + pitchBendLight , 255 - WheelPos * 3 + pitchBendLight , 0 );
  }
  if(mod_final> 50){
  }
}
[/code]

After calibration of the softpots using the above code, I uploaded the below updated test sketch to the Arduino:

[code]
/*
  Arduino Ribbon Synth MIDI test code for ribbon sensors
   ------------------------------------
*/
#include <EEPROM.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define N_STR     3
#define N_FRET    21
#define PIN_BUTTON_STICK 3
#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
int softPotVals[] = {
  0, 0, 0
};
int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

unsigned long dummy1;
unsigned long dummy2;
unsigned long dummy3;
unsigned long dummy4;
unsigned long raw;
unsigned long mappedValue;
unsigned long constrained;
//--------- Setup ----------------//
void setup() {

    //begin at MIDI spec baud rate
  Serial.begin(9600);
  delay(800);
  Serial.println("Starting test");
  //Serial.begin(31250);
  
  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
      for (int j = 1; j < 21; j++) {
         fretDefs[i][j] = EEPROM.read(j + (21 * i));
      }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  pinMode(PIN_BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_LEFT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_UP, INPUT_PULLUP);
  pinMode(PIN_BUTTON_DOWN, INPUT_PULLUP);
  pinMode(PIN_BUTTON_STICK, INPUT_PULLUP);
}

//----------Main Loop---------------//
void loop() {
  readSensors();
}

void readSensors() { // just read the ribbon pot
    raw = analogRead(softPotPins[0]);
    Serial.print("Raw read "); 
    Serial.println(raw);

    mappedValue = map(raw, calibrationMin[0], calibrationMax[0], 0, 255);
    Serial.print("Maped value  "); 
    Serial.println(mappedValue);

    constrained = constrain(mappedValue, 0, 255);
    Serial.print("constrained value "); 
    Serial.println(constrained);
    delay(1000);
  }
[/code]

Then I got the below results from the serial monitor:

Starting test
Raw read 4
Maped value  85
constrained value 85
Raw read 13
Maped value  4294966999
constrained value 255
Raw read 48
Maped value  4294965511
constrained value 255
Raw read 101
Maped value  4294963259
constrained value 255
Raw read 152
Maped value  4294961091
constrained value 255
Raw read 210
Maped value  4294958626
constrained value 255
Raw read 282
Maped value  4294955566
constrained value 255
Raw read 344
Maped value  4294952931
constrained value 255
Raw read 404
Maped value  4294950381
constrained value 255
Raw read 453
Maped value  4294948299
constrained value 255
Raw read 494
Maped value  4294946556
constrained value 255
Raw read 541
Maped value  4294944559
constrained value 255
Raw read 593
Maped value  4294942349
constrained value 255
Raw read 639
Maped value  4294940394
constrained value 255
Raw read 673
Maped value  4294938949
constrained value 255
Raw read 714
Maped value  4294937206
constrained value 255
Raw read 769
Maped value  4294934869
constrained value 255
Raw read 808
Maped value  4294933211
constrained value 255
Raw read 858
Maped value  4294931086
constrained value 255
Raw read 898
Maped value  4294929386
constrained value 255
Raw read 942
Maped value  4294927516
constrained value 255
Raw read 960
Maped value  4294926751
constrained value 255
Raw read 1013
Maped value  4294924499
constrained value 255
Raw read 1012
Maped value  4294924541
constrained value 255
Raw read 1015
Maped value  4294924414
constrained value 255
Raw read 1015

I'm not sure if I'm following you correctly, but I changed the map-function 2nd and 3rd parameters (min and max values) to the hardcoded numbers 0 and 255 as shown in the full code below:

[code]
/*
  Arduino Ribbon Synth MIDI test code for ribbon sensors
   ------------------------------------
*/
#include <EEPROM.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define N_STR     3
#define N_FRET    21
#define PIN_BUTTON_STICK 3
#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
int softPotVals[] = {
  0, 0, 0
};
int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

unsigned long dummy1;
unsigned long dummy2;
unsigned long dummy3;
unsigned long dummy4;
unsigned long raw;
unsigned long mappedValue;
unsigned long constrained;
//--------- Setup ----------------//
void setup() {

  //begin at MIDI spec baud rate
  Serial.begin(9600);
  delay(800);
  Serial.println("Starting test");
  //Serial.begin(31250);

  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
    for (int j = 1; j < 21; j++) {
      fretDefs[i][j] = EEPROM.read(j + (21 * i));
    }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  pinMode(PIN_BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_LEFT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_UP, INPUT_PULLUP);
  pinMode(PIN_BUTTON_DOWN, INPUT_PULLUP);
  pinMode(PIN_BUTTON_STICK, INPUT_PULLUP);
}

//----------Main Loop---------------//
void loop() {
  readSensors();
}

void readSensors() { // just read the ribbon pot
  raw = analogRead(softPotPins[0]);
  Serial.print("Raw read ");
  Serial.println(raw);

  //mappedValue = map(raw, calibrationMin[0], calibrationMax[0], 0, 255);
  mappedValue = map(raw, 0, 255, 0, 255);
  Serial.print("Maped value  ");
  Serial.println(mappedValue);

  constrained = constrain(mappedValue, 0, 255);
  Serial.print("constrained value ");
  Serial.println(constrained);
  delay(1000);
}
[/code]

Then I got the below results in the serial monitor. This seems closer to me, but still not quite right. The Raw read value of 1010 at the end is after I released my finger from the softpot.


Starting test
Raw read 8
Maped value  8
constrained value 8
Raw read 8
Maped value  8
constrained value 8
Raw read 21
Maped value  21
constrained value 21
Raw read 46
Maped value  46
constrained value 46
Raw read 133
Maped value  133
constrained value 133
Raw read 235
Maped value  235
constrained value 235
Raw read 286
Maped value  286
constrained value 255
Raw read 319
Maped value  319
constrained value 255
Raw read 358
Maped value  358
constrained value 255
Raw read 396
Maped value  396
constrained value 255
Raw read 431
Maped value  431
constrained value 255
Raw read 480
Maped value  480
constrained value 255
Raw read 504
Maped value  504
constrained value 255
Raw read 557
Maped value  557
constrained value 255
Raw read 586
Maped value  586
constrained value 255
Raw read 621
Maped value  621
constrained value 255
Raw read 658
Maped value  658
constrained value 255
Raw read 691
Maped value  691
constrained value 255
Raw read 724
Maped value  724
constrained value 255
Raw read 772
Maped value  772
constrained value 255
Raw read 846
Maped value  846
constrained value 255
Raw read 889
Maped value  889
constrained value 255
Raw read 926
Maped value  926
constrained value 255
Raw read 934
Maped value  934
constrained value 255
Raw read 962
Maped value  962
constrained value 255
Raw read 995
Maped value  995
constrained value 255
Raw read 1006
Maped value  1006
constrained value 255
Raw read 1010
Maped value  1010
constrained value 255

That looks about right. An analogRead will give values between 0 and 1023. So with nothing being pressed and a pull up resistor you should get 1023 as a raw value.

That is wrong see this for how the map function works map function
This says:-
map(value, fromLow, fromHigh, toLow, toHigh)
So you need at the very least to use
mappedValue = map(raw, 0, 1023, 0, 255);
which is exactly the same as dividing the raw value by 4 or shifting the number 2 places to the right so either of these two lines would do the same thing
`mappedValue = raw / 8;

// or
mappedValue = raw >> 2;
`
By putting a number that is greater than the range fromLow, fromHigh, into a map screws up the results as you have found.

What is odd is why on earth would you want to map the raw data into that range in the first place? Perhaps the writer wanted a single byte value to put into the EEPROM rather than a double byte value. I did say the code was not very good.

1 Like

I was not sure if this is the reason for the negative values. Now everything makes sense.
@The Arduino-Team: You should add this under "notes & warnings" in the reference.

I think that we have only two options here.

  1. Rewrite all the code, which will mean me having to make one myself. Three 500mm ribbon pots costs more than I would like to spend on this. I can't find 300 or 400 mm pots for sale in the UK, so I would have to make it with 200mm pots.

  2. Patch the mess we have to simply fix the problems of not being able to light the LEDs from the third ribbon. To that end I think I have found the problem here.

The line:-
led = max(led_number[ 0 ], led_number[ 1 ]);

Does not consider led_number[ 2 ] which is derived from the the third ribbon connector. As the max function can only take in two arguments you can't simply add the third ribbon cable. So I would try getting this number in two stages. First find if the biggest value is led_number[ 0 ], or led_number[ 1 ], and then see if that is bigger than led_number[ 2 ].

Here are the changes to the code originally posted in the first post here in context

  //-----ENGAGE FULL LEGATO MODE-----
  //removes the need for triggering with piezo for fretted notes
  if (digitalRead(PIN_BUTTON_LEFT) == LOW && !buttonStates[LEFT]) {
    fullLegatoMode = true;
    buttonStates[LEFT] = true;
  }
  if (digitalRead(PIN_BUTTON_LEFT) == HIGH && buttonStates[LEFT]) {
    fullLegatoMode = false;
    buttonStates[LEFT] = false;
  }

  led = max(led_number[0], led_number[1]);
  if( led_number[2] > led ) led =  led_number[2] ; 
  //Serial.println(led_number[0]);
   //Serial.println(led_number[1]);
1 Like

In my view it does not screw anything up

map(value, fromLow, fromHigh, toLow, toHigh)

map creates a linear function (representing a line) going through 2 points : (x fromLow , y toLow ) and (x fromHigh, y toHigh )

if you enter values that are outside [x fromLow , x fromHigh] you' ll get the corresponding Y value on the line

map would calculate the function f which goes through A and B
then if you look for x = C then the corresponding Y is D and is within range but if you look at the Y coordinate for point E then it's out of range because E was not in the initial interval.

the doc is clear about it as it states:

Does not constrain values to within the range, because out-of-range values are sometimes intended and useful. The constrain() function may be used either before or after this function, if limits to the ranges are desired.

1 Like

Something was clearly being screwed up because the OP was getting negative values after a map operation, with no negative values possible. It is not his code and the code is very badly written. I am aware that under some conditions you can use values outside the ranges given with a map function but on this occasion something was badly wrong.

OK

this might be due to the unsigned value.

I would advise against doing map() with unsigned integers as the C++ rules says that everything gets promoted to unsigned in the math

I guess setting up the max-value as zero and the min-value as positive
because it was initialised with zero and then never assigned a different value

created a map-function with negative slope and this negative slope - I guess - has created the negative value

So this is something that could be explained in the reference
examples for

  • map(value, 0, +100,...)
  • map(value, +100, 0,...)
  • map(value, -100, 0,...)
  • map(value, -100, +100,...)
    including pictures similar to what J-M-L posted

best regards Stefan

The order of min and max does not matter as long as they are matching pairs. If you call

map(v, x1,x2,y1,y2);

You get an affine function (first order y = ax + b) that draws the line between (x1,y1) and (x2,y2). That’s what defines the slope of the line.

If you submit a value v that is not in between x1 and x2 then you can’t expect a value between y1 and y2 (with the rounding to the integral part - so it’s not technically an affine function really - there is a discontinuity and you have actually a set of horizontal lines like stairs)

Here is the code of the function where you can see that


long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

The catch is that the maths within the function is done using signed long integer so you have possible side effects there in case of overflow during the multiplication, truncation in the division and obviously a possible division by 0 if the integral parts Of in_max == in_min (vertical line)

so the theoretical curve is the dotted blue line (function f) but the output of the map() function is the red "steps" (function g)

1 Like

This seems to work pretty great and the pixel strips are now being triggered with the 3rd softpot!

The problem with the stuck pixels when using more than 16 pixels out of the 24 pixel strand (mentioned in post #33) is still there - in addition to the issue with random MIDI notes/events being generated when using pull up or down resistors on the softpots, with or without the 3 lines code you last asked me to comment out.

Currently, the best I can get it to work is still with no resistors attached to the softpots, with the below code. Notice I did try changing the int softPotVals to unsigned long as well as using hard numbers for the fromLow and fromHigh parameters around line 329. I'm guessing I did not make all the necessary changes because I did not notice a drastic improvement.

The 16 LEDs used in the sketch respond fairly well with all 3 softpots now, but frets 18 through 21 still seem to be missing on all 3 softpots. For example the highest 2 frets on softpot A0 skip from A#3 to C#4 - and fret 1 is still very short (about a centimeter of the low end of the ribbon pot does not trigger any notes as shown in post #23)

[code]
/*
  Arduino Ribbon Synth MIDI controller
   ------------------------------------
   ©2014 Dean Miller
*/

#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <QuickStats.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define PIEZO_THRESHOLD_ON 12

#define PIN_LED 13
#define NEO_PIN   21
#define N_PIXELS  16      //# of LEDS

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
#define PIN_PIEZO_1 A3
#define PIN_PIEZO_2 A4
#define PIN_PIEZO_3 A5
#define PIN_POT_1 8
#define PIN_POT_2 6

#define PIN_BUTTON_STICK 3

#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

//Joystick
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3
#define STICK 4

#define PIEZO_SAMPLES 400
#define PADDING 2

#define THRESH    200
#define N_STR     3
#define N_FRET    21


//#define MOD_THRESHOLD 30  //Modulation is not send under this value

long noteDebounceTime = 0;
int noteDebounceDelay = 25;

long lastDebounceTime = 0;
int debounceDelay = 200;


long ledDebounceTime = 0;
int ledDebounceDelay = 20;

int mod_final;

//bool isPitchBend = false;
unsigned int pitchBendLight = 0;
//bool dim = false;


//------Note Class---------//
/*
  A note class that stores some info about each note played is necessary
   to ensure that open strings are held for the specified amount of time.
   That is a problem with using the piezos as triggers instead of FSRs, they
   only register momentary impact or vibration, creating a problem for open strings.
*/

class Note {
    int _number;
    int _velocity;
    int _startTime;
    int _fretted;

  public:
    void init(int number, int velocity, int startTime, int fretted) {
      _number = number;
      _velocity = velocity;
      _startTime = startTime;
      _fretted = fretted;
    }

    int number() {
      return _number;
    }

    int velocity() {
      return _velocity;
    }

    int fretted() {
      return _fretted;
    }

    int timeActive() {
      return millis() - _startTime;
    }
};

//------ Global Variables ---------//

/*
  fret defs stored in EEPROM for calibration purposes.
  Lower output voltages from USB ports result in different values read from
  SoftPots and wonky fret definitions.*/

int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];
//short fretDefs[N_STR][N_FRET];

int piezoVals[] = {
  0, 0, 0
};
int piezoPins[] = {
  PIN_PIEZO_1, PIN_PIEZO_2, PIN_PIEZO_3
};

unsigned long softPotVals[] = {
  0, 0, 0
};
int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

int potVal1Old = -1;
int potVal2Old = -1;
int softPotValsOld[] = {
  0, 0, 0
};

int fretTouched[N_STR];
int noteFretted[N_STR];

int stringActive[] = {
  false, false, false
};
int stringPlucked[] = {
  false, false, false
};

Note *activeNotes[N_STR];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

//true for low strings, false for high strings
int stringSetLow = true;
int octave = 3;


//E A D
int offsets_low[] = {16, 21, 26};

//G B E
int offsets_high[] = {19, 23, 28};

//default offsets
int offsets[] = {52, 57, 62};

//states of control buttons
int buttonStates[] = {
  false, false, false, false, false
};
int stickActive = false;
int stickZeroX = 0;
int stickZeroY = 0;
int stickState = false;

int altControlSet = false;
int stickXY = false;
int fullLegatoMode = false;

int minDurationOpen = 75;
int minVelocity = 75;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_PIXELS, NEO_PIN, NEO_GRB + NEO_KHZ800);
int led_number[3] = {0, 1, 2};
int led_color;
int led;
int prev_led;

unsigned long last_read;

QuickStats stats;

//--------- Setup ----------------//
void setup() {

  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
    for (int j = 1; j < 22; j++) {
      fretDefs[i][j] = EEPROM.read(j + (21 * i));
    }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  //begin at MIDI spec baud rate
  Serial.begin(9600);
  //Serial.println("START");
  Serial1.begin(31250);
  pinMode(PIN_SOFTPOT_1, INPUT);
  pinMode(PIN_SOFTPOT_2, INPUT);
  pinMode(PIN_SOFTPOT_3, INPUT);
  pinMode(PIN_PIEZO_1, INPUT);
  pinMode(PIN_PIEZO_2, INPUT);
  pinMode(PIN_PIEZO_3, INPUT);

  digitalWrite(PIN_SOFTPOT_1, HIGH);
  digitalWrite(PIN_SOFTPOT_2, HIGH);
  digitalWrite(PIN_SOFTPOT_3, HIGH);

  pinMode(PIN_BUTTON_RIGHT, INPUT);
  digitalWrite(PIN_BUTTON_RIGHT, HIGH);

  pinMode(PIN_BUTTON_LEFT, INPUT);
  digitalWrite(PIN_BUTTON_LEFT, HIGH);

  pinMode(PIN_BUTTON_UP, INPUT);
  digitalWrite(PIN_BUTTON_UP, HIGH);

  pinMode(PIN_BUTTON_DOWN, INPUT);
  digitalWrite(PIN_BUTTON_DOWN, HIGH);

  pinMode(PIN_BUTTON_STICK, INPUT);
  digitalWrite(PIN_BUTTON_STICK, HIGH);


  pinMode(PIN_LED, OUTPUT);

  pixels.begin();
  pixels.setBrightness(50);
  pixels.show();

  while (millis() < 500) {
    for (int i = 0; i < N_STR; i++) {
      int val = analogRead(softPotPins[i]);
      if (val > calibrationMax[i]) calibrationMax[i] = val;
    }

    //calibrate joystick
    stickZeroX = analogRead(PIN_JOYSTICK_X);
    stickZeroY = analogRead(PIN_JOYSTICK_Y);
  }
}

//----------Main Loop---------------//
void loop() {
  //reset
  for (int i = 0; i < N_STR; i++) {
    stringPlucked[i] = false;
    piezoVals[i] = false;
  }

  //read values of all sensors
  readSensors();

  determineFrets();

  //if we are in full legato mode, run the function
  if (fullLegatoMode) {
    fullLegato();
  }

  //otherwise just do the regular thing
  else {
    //test for legato action
    legatoTest();
    // onLED(N_PIXELS, 0, 0, 0);
    //use this info to determine which notes to pluck
    pickNotes();
    onLED(N_PIXELS, 0, 0, 0);
  }

  //send not off messages and reset necessary things
  cleanUp();

  //check for control changes
  readControls();
}

void readSensors() {
  for (int i = 0; i < N_STR; i++) {

    //read piezo vals
    int piezoVal = analogRead(piezoPins[i]);


    //if the value breaks the threshold read for max amplitude
    /* TODO: this is less than ideal. Have it determine which piezos were triggered and
       then sample them all at once for better support for polyphonic stuff.
    */

    if (piezoVal > PIEZO_THRESHOLD_ON) {
      int v_new = piezoVal;
      for (int sample = 0; sample < PIEZO_SAMPLES; sample++) {
        piezoVal = analogRead(piezoPins[i]);
        if (piezoVal > v_new) {
          v_new = piezoVal;
        }
      }
      piezoVals[i] = v_new;
      piezoVals[i] = map(piezoVals[i], 0, 500, 0, 127);
      piezoVals[i] = constrain(piezoVals[i], minVelocity, 127);
    }

    //read the value of all the softPots
    softPotVals[i] = analogRead(softPotPins[i]);
    softPotVals[i] = map(softPotVals[i], 0, 1023, 0, 255);
    softPotVals[i] = constrain(softPotVals[i], 0, 255);
  }
}

void determineFrets () {
  static int count = 0;

  //---------Get Fret Numbers------
  for (int i = 0; i < N_STR; i++) {

    int softPotVal = softPotVals[i];

    //check for open strings
    if (softPotVal >= F0) {
      softPotValsOld[i] = softPotVal;
      fretTouched[i] = 0;
      led_number[i] = fretTouched[i];
    }

    //loop through the array of fret definitions
    for (int j = 1; j < N_FRET; j++) {

      int k = j - 1;
      if (softPotVal <= fretDefs[i][k] &&
          softPotVal > fretDefs[i][j] &&
          abs(softPotVal - softPotValsOld[i]) > PADDING) {

        softPotValsOld[i] = softPotVal;
        fretTouched[i] = j - 2;
        led_number[i] = fretTouched[i];
        // Serial.print("string= ");  Serial.print(i);  Serial.print("  FretTouched= ");  Serial.print(j); Serial.print("  softpotval = ");  Serial.println(softPotVal);  //count=0;}
      }
    }
    if (softPotVal <= fretDefs[i][20]) {
      softPotValsOld[i] = softPotVal;
      fretTouched[i] = N_FRET;
      led_number[i] = fretTouched[i];
    }
  }
}

void pickNotes() {
  for (int i = 0; i < N_STR; i++) {

    //if the piezo was hit, play the fretted note
    if (piezoVals[i]) {
      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      if (stringActive[i]) {

        //turn off the currently active note on that string
        noteOff(0x80 + i, activeNotes[i]->number(), 0);
        free(activeNotes[i]);
      }

      if (!stringActive[i]) {

        //mark string as active
        stringActive[i] = true;
      }
      //register with active notes
      activeNotes[i] = (Note *) malloc(sizeof(Note));

      if (fretTouched[i] > 0) activeNotes[i]->init(noteFretted[i], piezoVals[i], millis(), true);

      else activeNotes[i]->init(noteFretted[i], piezoVals[i], millis(), false);

      //turn on fretted note
      noteOn(0x90 + i, activeNotes[i]->number(), activeNotes[i]->velocity());

      //mark that the string was plucked
      stringPlucked[i] = true;
    }
  }
}

void legatoTest() {
  for (int i = 0; i < N_STR; i++) {
    if (stringActive[i]) {
      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      if (noteFretted[i] != activeNotes[i]->number() && fretTouched[i]) {
        //turn on new note
        int vel = activeNotes[i]->velocity();
        noteOn(0x90 + i, noteFretted[i], vel);

        //turn off old note
        noteOff(0x80 + i, activeNotes[i]->number(), 0);
        free(activeNotes[i]);

        //register new note as the active one
        activeNotes[i] = (Note *) malloc(sizeof(Note));
        activeNotes[i]->init(noteFretted[i], vel, millis(), true);
      }
    }
  }
}
/*


*/
void fullLegato() {
  for (int i = 0; i < N_STR; i++) {
    if (fretTouched[i]) {

      switch (i) {
        case 0:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 1:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
        case 2:
          noteFretted[i] = fretTouched[i] + offsets[i];
          break;
      }

      int vel = 127;

      if (!stringActive[i]) {
        noteOn(0x90 + i, noteFretted[i], vel);

        //register new note as the active one
        activeNotes[i] = (Note *) malloc(sizeof(Note));
        activeNotes[i]->init(noteFretted[i], vel, millis(), true);
        stringActive[i] = true;
      }
      else {

        if (noteFretted[i] != activeNotes[i]->number()) {
          int vel = 80;
          noteOn(0x90 + i, noteFretted[i], vel);

          //turn off old note
          noteOff(0x80 + i, activeNotes[i]->number(), 0);
          free(activeNotes[i]);

          //register new note as the active one
          activeNotes[i] = (Note *) malloc(sizeof(Note));
          activeNotes[i]->init(noteFretted[i], vel, millis(), true);
        }
      }
    }
  }
}


void cleanUp() {
  for (int i = 0; i < N_STR; i++) {

    //no fret is touched and the string is marked active
    if (!fretTouched[i] && stringActive[i]) {

      //if open string
      if (!activeNotes[i]->fretted()) {
        if (activeNotes[i]->timeActive() > minDurationOpen) {
          //turn off the active note
          noteOff(0x80 + i, activeNotes[i]->number(), 0);

          //mark as inactive
          stringActive[i] = false;
          free(activeNotes[i]);
        }
      }
      else {
        //turn off the active note
        noteOff(0x80 + i, activeNotes[i]->number(), 0);

        //mark as inactive
        stringActive[i] = false;
        free(activeNotes[i]);
      }
    }
  }
}

void readControls() {

  if (altControlSet) {
    minDurationOpen = analogRead(PIN_POT_1);
    minDurationOpen = map(minDurationOpen, 0, 1023, 0, 255 );

    minVelocity = analogRead(PIN_POT_2);
    minVelocity = map(minVelocity, 0, 1023, 0, 127);
  }

  //Potentiometers set the values for controllers 69 and 7
  else {
    int potVal1New = analogRead(PIN_POT_1);
    int potVal2New = analogRead(PIN_POT_2);

    if (abs(potVal1New - potVal1Old) > 30 || potVal1New == 0 || potVal1New == 1023 ) {
      if ((potVal1New - potVal1Old) != 0) {
        //Send MIDI control change message
        int val = map(potVal1New, 0, 1023, 0, 127);
        val = constrain(val, 0, 127);
        controllerChange(69, val);
        potVal1Old = potVal1New;
      }
    }

    if (abs(potVal2New - potVal2Old) > 30 || potVal2New == 0 || potVal2New == 1023) {
      if ((potVal2New - potVal2Old) != 0) {
        //Send MIDI control change message
        int val = map(potVal2New, 0, 1023, 0, 127);
        val = constrain(val, 0, 127);
        controllerChange(7, val);
        potVal2Old = potVal2New;
      }
    }
  }

  //-----ENGAGE FULL LEGATO MODE-----
  //removes the need for triggering with piezo for fretted notes
  if (digitalRead(PIN_BUTTON_LEFT) == LOW && !buttonStates[LEFT]) {
    fullLegatoMode = true;
    buttonStates[LEFT] = true;
  }
  if (digitalRead(PIN_BUTTON_LEFT) == HIGH && buttonStates[LEFT]) {
    fullLegatoMode = false;
    buttonStates[LEFT] = false;
  }

  led = max(led_number[0], led_number[1]);
  if ( led_number[2] > led ) led =  led_number[2] ;
  //Serial.println(led_number[0]);
  //Serial.println(led_number[1]);
  if (led == -1) {
    led = 0;
    onLED(N_PIXELS, 0, 0, 0);
  }

  else {
    led = led + 1;
    led = map(led, 0, N_FRET - 1, 0, N_PIXELS);
    led_color = map(led, 0, 30, 0, 255);
    //Serial.println(led_number);
    if ((millis() - ledDebounceTime ) > ledDebounceDelay) {
      for (int i = 0; i < led; i++) {
        //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
        pixels.setPixelColor(i, Wheel(led_color));
      }
      if (prev_led > led)
        for (int i = led; i < N_PIXELS; i++) {
          //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
          pixels.setPixelColor(i, (pixels.Color(0, 0, 0)));
        }
      pixels.show();
      ledDebounceTime = millis();
      prev_led = led ;
    }
  }

  /*

    //switch to alt control set
    if (digitalRead(PIN_BUTTON_LEFT) == LOW && !buttonStates[LEFT]) {
      altControlSet = !altControlSet;
      buttonStates[LEFT] = true;
    }
    if (digitalRead(PIN_BUTTON_LEFT) == HIGH && buttonStates[LEFT]) buttonStates[LEFT] = false;


    //Right button triggers calibration
    if (digitalRead(PIN_BUTTON_RIGHT) == LOW && !buttonStates[RIGHT]) {
      buttonStates[RIGHT] = true;
      calibrate();
    }

  */

  //---- CHANGING THE OCTAVE -------//
  //UP and down buttons used to change offset/octave. Cycles through EAD and GBE like an infinite guitar neck.

  //---- UP BUTTON ----
  if (digitalRead(PIN_BUTTON_UP) == LOW) {
    //change the set of strings
    if (!buttonStates[UP]) {

      octave = octave - 1;

      stringSetLow = !stringSetLow;

      for (int i = 0; i < N_STR; i++) {
        //if low
        if (stringSetLow) {
          offsets[i] = offsets_low[i] + (12 * octave);
        }
        //if high
        if (!stringSetLow) {
          offsets[i] = offsets_high[i] + (12 * octave);
        }
      }
    }

    buttonStates[UP] = true;
  }
  //reset state once button is no longer being pressed
  if (digitalRead(PIN_BUTTON_UP) == HIGH && buttonStates[UP]) buttonStates[UP] = false;

  //----DOWN BUTTON----
  if (digitalRead(PIN_BUTTON_DOWN) == LOW) {
    //change the set of strings
    if (!buttonStates[DOWN]) {

      octave = octave + 1;

      stringSetLow = !stringSetLow;

      for (int i = 0; i < N_STR; i++) {
        //if low
        if (stringSetLow) {
          offsets[i] = offsets_low[i] + (12 * octave);
        }
        //if high
        if (!stringSetLow) {
          offsets[i] = offsets_high[i] + (12 * octave);
        }
      }
    }

    buttonStates[DOWN] = true;
  }
  //reset state once button is no longer being pressed
  if (digitalRead(PIN_BUTTON_DOWN) == HIGH && buttonStates[DOWN]) buttonStates[DOWN] = false;

  //switch stick to xy mode
  if (digitalRead(PIN_BUTTON_RIGHT) == LOW && !buttonStates[RIGHT]) {
    stickXY = !stickXY;
    buttonStates[RIGHT] = true;
  }
  if (digitalRead(PIN_BUTTON_RIGHT) == HIGH && buttonStates[RIGHT]) buttonStates[RIGHT] = false;

  //--------JOYSTICK-------//
  /* Click down the joystick to activate it. In regular mode it will read absolute position from the
     center in any direction (sends to modwheel, MIDI controller 1), and in XY mode the x axis
     sends to controller 2 (breath) and the y axis sends to controller 4 (foot).  */

  if (digitalRead(PIN_BUTTON_STICK) == LOW) {
    //activate joystick
    if (!buttonStates[STICK]) {
      //make sure modwheel value is set to 0 when stick is off
      if (stickActive) controllerChange(1, 0);
      stickActive = !stickActive;
    }
    buttonStates[STICK] = true;
  }
  //reset once stick is no longer being pressed
  if (digitalRead(PIN_BUTTON_STICK) == HIGH && buttonStates[STICK]) buttonStates[STICK] = false;

  if (stickActive) {
    //read positions from center
    float xPos = map(analogRead(PIN_JOYSTICK_X), stickZeroX, 1023, 0, 127);
    float yPos = map(analogRead(PIN_JOYSTICK_Y), stickZeroY, 1023, 0, 127);

    //get absolute position from center
    float z = sqrt(sq(xPos) + sq(yPos));
    int stickVal = (int)constrain(z, 0, 127);

    if (stickVal > 0) {
      stickState = true;
      if (stickXY) {
        controllerChange(2, abs(xPos));
        controllerChange(4, abs(yPos));
      }
      else controllerChange(1, stickVal);
    }
    else if (stickState && stickVal == 0) {
      stickState = false;
      if (stickXY) {
        controllerChange(2, 0);
        controllerChange(4, 0);
      }
      else controllerChange(1, 0);
    }
  }
}

//----CALIBRATION----//
/* Likely will only have to calibrate once. This is done by activating calibration mode and
   "plucking" each note on each string starting with the upper bound (after the 21st fret) and descending down
   to just after the 1st fret. Starts with the low E string, then the A string and then the D string.
   fret definitions are stored in EEPROM. Once it is calibrated for the voltage put out by the MIDI --> USB board
   you can just have the calibration button do something else because you probably won't need it again.
*/
void unset(int i) {
  //this function doesn't even do anything!!
}

void calibrate() {
  Serial.println("calibrating...");
  for (int i = 0; i < N_STR; i++) {
    //Flash the LED too indicate calibration
    /*
      digitalWrite(PIN_LED, HIGH);
      delay(100);
      digitalWrite(PIN_LED, LOW);
      delay(100);
      digitalWrite(PIN_LED, HIGH);
      delay(100);
      digitalWrite(PIN_LED, LOW);
      delay(100);
      digitalWrite(PIN_LED, HIGH);
    */
    //Flash the LED too indicate calibration
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();
    onLED(10, 250, 0, 0);
    delay(100);
    clrLED();

    int sensorMax = 1023;
    int sensorMin = 0;
    int val;

    //loop through the array of fret definitions
    for (int j = N_FRET; j > 0; j--) {

      int response = false;
      Serial.println("waiting");
      //wait for response
      while (!response) {

        //read piezo val
        int piezoVal = analogRead(piezoPins[i]);

        //get the sensor min value (highest fret) on the first round
        if (j == N_FRET) {
          int fretVal = analogRead(softPotPins[i]);
          if (fretVal > sensorMax) (sensorMax = fretVal);
          clrLED();
          //if the piezo is hit, register this as the definition for this fret
          if (piezoVal > PIEZO_THRESHOLD_ON) {
            int fretVal = analogRead(softPotPins[i]);
            sensorMin = fretVal;
            val = fretVal;
            response = true;
            clrLED();
          }
        }

        else {
          //get the rest of the fret definitions
          //if the piezo is hit, register this as the definition for this fret
          if (piezoVal > PIEZO_THRESHOLD_ON) {
            int fretVal = analogRead(softPotPins[i]);
            fretVal = map(fretVal, sensorMin, sensorMax, 0, 255);
            fretVal = constrain(fretVal, 0, 255);
            val = fretVal;
            response = true;
            clrLED();
          }
        }
      }

      //write to memory
      digitalWrite(PIN_LED, LOW);
      EEPROM.write(j + (N_FRET * i), val);
      Serial.println(val);
      delay(100);
      onLED(10, 250, 0, 0);
      //      delay(100);
      digitalWrite(PIN_LED, HIGH);
    }


    //update global definitions
    calibrationMin[i] = EEPROM.read(N_FRET + (N_FRET * i));
    Serial.print(N_FRET + (N_FRET * i)); Serial.print(" -cal- ");  Serial.println(calibrationMin[i]);

    for (int j = 1; j < 22; j++) {
      fretDefs[i][j] = EEPROM.read(j + (i * N_FRET));
      Serial.print("EEPROM.read(");
      Serial.print(j);
      Serial.print(" + (21 * ");
      Serial.print(i);
      Serial.print("))");
      Serial.print(" EEPROM.read(");
      Serial.print(j + (21 * i));
      Serial.print(")");

      Serial.print(" -fret- ");
      Serial.print("fretDefs[");
      Serial.print(i);
      Serial.print("][");
      Serial.print(j);
      Serial.print("]=");
      Serial.println(fretDefs[i][j]);
    }
    clrLED();
  }
  buttonStates[RIGHT] = false;
  digitalWrite(PIN_LED, LOW);
}
void onLED(int led, int red, int green, int blue) {
  for (int i = 0; i < N_STR; i++) {

    //pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(red, green, blue));
  }
  pixels.show();
}

void clrLED() {
  for (int i = 0; i < N_PIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // turn off
  }
  pixels.show();
}
//-------------MIDI functions-----------------

//note-on message
void noteOn(int cmd, int pitch, int velocity) {

  Serial1.write(byte(cmd));
  Serial1.write(byte(pitch));
  Serial1.write(byte(velocity));
  digitalWrite(PIN_LED, HIGH);
}
//note-off message
void noteOff(int cmd, int pitch, int velocity) {

  Serial1.write(byte(cmd));
  Serial1.write(byte(pitch));
  Serial1.write(byte(0));
  digitalWrite(PIN_LED, LOW);
}

//Sends controller change to the specified controller
void controllerChange(int controller, int value) {
  Serial1.write(byte(0xb0));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));

  Serial1.write(byte(0xb1));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));

  Serial1.write(byte(0xb2));
  Serial1.write(byte(controller));
  Serial1.write(byte(value));
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3 + pitchBendLight, 0, WheelPos * 3 + pitchBendLight);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3 + pitchBendLight , 255 - WheelPos * 3 + pitchBendLight);
  }
  else {
    WheelPos -= 170;
    return pixels.Color(WheelPos * 3 + pitchBendLight , 255 - WheelPos * 3 + pitchBendLight , 0 );
  }
  if (mod_final > 50) {
  }
}
[/code]

After calibrating with the above code, I ran the test sketch below and got the serial monitor results below that:

[code]
/*
  Arduino Ribbon Synth MIDI test code for ribbon sensors
   ------------------------------------
*/
#include <EEPROM.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

//------- Constants -------//
#define N_STR     3
#define N_FRET    21
#define PIN_BUTTON_STICK 3
#define PIN_BUTTON_RIGHT 11
#define PIN_BUTTON_UP 5
#define PIN_BUTTON_DOWN 2
#define PIN_BUTTON_LEFT 7

//Joystick
#define PIN_JOYSTICK_X 9
#define PIN_JOYSTICK_Y 10

#define PIN_SOFTPOT_1 A0
#define PIN_SOFTPOT_2 A1
#define PIN_SOFTPOT_3 A2
int softPotVals[] = {
  0, 0, 0
};
int F0 = 248;  // all bigger softpot values will be treated as open string
int F21 = 0;

int fretDefs[N_STR][N_FRET];

int calibrationMax[] = {
  0, 0, 0
};
int calibrationMin[N_STR];

int softPotPins[] = {
  PIN_SOFTPOT_1, PIN_SOFTPOT_2, PIN_SOFTPOT_3
};

unsigned long dummy1;
unsigned long dummy2;
unsigned long dummy3;
unsigned long dummy4;
unsigned long raw;
unsigned long mappedValue;
unsigned long constrained;
//--------- Setup ----------------//
void setup() {

  //begin at MIDI spec baud rate
  Serial.begin(9600);
  delay(800);
  Serial.println("Starting test");
  //Serial.begin(31250);

  //read fret definitions from EEPROM
  for (int i = 0; i < N_STR; i++) {
    fretDefs[i][0] = F0;
    for (int j = 1; j < 21; j++) {
      fretDefs[i][j] = EEPROM.read(j + (21 * i));
    }
    fretDefs[i][N_FRET] = 0;
    calibrationMin[i] = EEPROM.read(21 + (21 * i));
  }

  pinMode(PIN_BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_LEFT, INPUT_PULLUP);
  pinMode(PIN_BUTTON_UP, INPUT_PULLUP);
  pinMode(PIN_BUTTON_DOWN, INPUT_PULLUP);
  pinMode(PIN_BUTTON_STICK, INPUT_PULLUP);
}

//----------Main Loop---------------//
void loop() {
  readSensors();
}

void readSensors() { // just read the ribbon pot
  raw = analogRead(softPotPins[0]);
  Serial.print("Raw read ");
  Serial.println(raw);

  //mappedValue = map(raw, calibrationMin[0], calibrationMax[0], 0, 255);
  mappedValue = map(raw, 0, 1023, 0, 255);
  Serial.print("Maped value  ");
  Serial.println(mappedValue);

  constrained = constrain(mappedValue, 0, 255);
  Serial.print("constrained value ");
  Serial.println(constrained);
  delay(1000);
}
[/code]


Starting test
Raw read 1
Maped value  0
constrained value 0
Raw read 59
Maped value  14
constrained value 14
Raw read 137
Maped value  34
constrained value 34
Raw read 222
Maped value  55
constrained value 55
Raw read 326
Maped value  81
constrained value 81
Raw read 436
Maped value  108
constrained value 108
Raw read 513
Maped value  127
constrained value 127
Raw read 591
Maped value  147
constrained value 147
Raw read 668
Maped value  166
constrained value 166
Raw read 703
Maped value  175
constrained value 175
Raw read 767
Maped value  191
constrained value 191
Raw read 818
Maped value  203
constrained value 203
Raw read 869
Maped value  216
constrained value 216
Raw read 912
Maped value  227
constrained value 227
Raw read 944
Maped value  235
constrained value 235
Raw read 971
Maped value  242
constrained value 242
Raw read 999
Maped value  249
constrained value 249