Remembering and retrieving potentiometer values in arrays

I’ve built a project which multiplexed 20 odd pots through a Teensy and into Pure Data on my mac, to use with guitar processing effects. Now i’m trying to add virtual pots by using a joystick to select a virtual pot position on x axis and increase/decrease the value on Y axis.

I’ve gotten the code setup to remember the value of the pot once the joystick goes back to neutral, and to appropriately advance to the next virtual pot or backwards to previous pot. The selected virtual pot sets the array index for the array that stores the Y axis pot values.

I have the code working to remember the Y axis values when the joystick returns to neutral and to print the value to serial when it changes. The problem I’m having is that when I attempt to store the last value in the array, and then re-read it the next time I come back to that position with the x-axis selector, there is some bleed through happening.

You can see in the image attached that I scroll up to position 4, change the Y value up to 170, then scroll back down to position 0. On the way, it changes position 3 value to 170. When I scroll again past position 4 it begins writing value 170 into the array at positions 6,7,8, etc… Eventually if I scroll through the X-axis positions enough it really starts jumbling up the values or dropping them to zero.

I figured I was trying to read/write to the array too quickly, and added the 30ms delay which actually seems to have resolved the jumbling and now the code behaves how it should. Of course, now going from value of 0 up to 1024 on the Y axis takes much longer.

// Use a joystick on X axis to select incremental position by one's. 
// Each toggle will advance the position count whichever direction it is moved (+ or -). 
// Y axis will then read pot value and store value in an array.
// The array position and value will be transmitted via serial.

int selectPosition = 0;   // The position selector will go from 0 to 29, for 30 total control options in pure data
int lastPosition = 0;  // save the last position
const int selectMax = 29; // last position
const int selectMin = 0; // first position
const int selectMove = 1; // Increase in selectPosition with each step

const int Xjoystick = A0;   // center pin of joystick X connected here
int XpotValue = 0; // starts at zero
const int XpotCenter = 512; // adjust to suit your joystick
const int XpotDeadRange = 150; // movements by this much either side of centre are ignored

const int Yjoystick = A1;  // center pin of joystick Y connected here
int YpotValue = 0; //starts at zero
const int YpotCenter = 512;
const int YpotDeadRange = 50;

int lastValue = 0; // last Y value for concept trial only, won't work with the array setup in the final
const int valueMax = 1024; //max Y potentiometer value
const int valueMin = 0; //min Y potentiometer value
const int valueMove = 5; //Increase selected array value by this number

unsigned long curMillisX;
unsigned long readIntervalMillisX = 150; //time between reads of X joystick position. 
unsigned long lastReadMillisX;

unsigned long curMillisY;
unsigned long readIntervalMillisY = 20; //time between reads of Y joystick position. 
unsigned long lastReadMillisY;

int valueArray[30]; //store the Y joystick value in each selected X position (from 0-29)
int arrayIndex = 0; //to be mated to selectPosition to advance the array.

void setup() {
  Serial.begin(9600);
}

void loop() {
  curMillisX = millis();
  curMillisY = millis();
  readXJoystick();
  readYJoystick();
}

void readXJoystick() {
      // check the time
  if (curMillisX - lastReadMillisX >= readIntervalMillisX) {
    lastReadMillisX += readIntervalMillisX;  //update lastRead time
    XpotValue = analogRead(Xjoystick); // read the Xjoystick
    
      // figure if a move is required
    if (XpotValue > XpotCenter + XpotDeadRange) {
      selectPosition += selectMove;
    }
    
    if (XpotValue < XpotCenter - XpotDeadRange) {
      selectPosition -= selectMove;
    }
    
      // check that the values are within limits
    if (selectPosition > selectMax) {
      selectPosition = selectMax;
    }
    if (selectPosition < selectMin) {
      selectPosition = selectMin;
    }
  }
  
  if (selectPosition != lastPosition) { //check if the position has changed and print the result to serial if so
       Serial.print("Position");
       Serial.println(selectPosition);
       arrayIndex = selectPosition;  // the position advances the array index accordingly
       lastPosition = selectPosition; // save the position
  }
}


void readYJoystick() {  //read from Y stick and advance/subtract the value when the stick is out of the deadzone
      // check the time
  if (curMillisY - lastReadMillisY >= readIntervalMillisY) {
    lastReadMillisY += readIntervalMillisY;
    
      // read the Yjoystick
    YpotValue = analogRead(Yjoystick);
    lastValue = valueArray[arrayIndex]; //set last value to the previous saved value in the array at position determined by X joystick
     
     // figure if a move is required by reading the last value of the valueArray based on the index position from X joystick.
    if (YpotValue > YpotCenter + YpotDeadRange) { //If > than the dead range ++
      lastValue += valueMove;
    }
    
    if (YpotValue < YpotCenter - YpotDeadRange) { //If < than dead range --
      lastValue -= valueMove;
    }
    
      // check that the values are within limits
    if (valueArray[arrayIndex] > valueMax) {
      lastValue = valueMax; // if higher than limit set to max
    }
    if (valueArray[arrayIndex] < valueMin) {
      lastValue = valueMin;  // if lower than limit set to min
    }
  }
  
  if (lastValue != valueArray[arrayIndex]) { //if value changed, print new value to serial
      Serial.print("value position ");
      Serial.print(arrayIndex);
      Serial.print("-");
      Serial.println(lastValue);
      valueArray[arrayIndex] = lastValue;   // the selected position in the array is now written with the new value from the Y joystick.
  }
  delay(30);
}

Is there a more efficient way or error-proof way to store and retrieve the values while maintaining the maximum speed?

Thank you for any recommendations or corrections! Always looking to learn and appreciate all the helpful topics here

Your joystick has two pots (normal construction) You are using the x values derived from these posts to index an array and storing the analog y value in the array at that index x. You are getting inconsistent results. Is that about correct?
How is it being made visible to the end user which X value has been selected.?
Deriving an index from a pot value often requires some hysteresis treatment. See

You are getting inconsistent results. Is that about correct?

Yep that's it.

I will look into adding some hysteresis treatment but I'm not sure that's entirely what's going on. I'll be at a certain index selected by X-axis. I adjust the Y-joystick and set a value for the index. The Y joystick value returns to neutral (512) and is at rest, and if I wait seconds and advance the index position with the x-joystick there is occasional advancing of the Y value in the array even though the Y pot is not moving. So the Y pot is back at neutral at rest, and the array is still being written to with the last value from the last time the Y pot changed.

I don't think I'm reading an actual value from the Y-pot, I think its' just being carried over from the last array index into the next one. Again this seems to disappear and no longer be a problem when I add either a delay of at least 40ms or increase the readIntervalMillisY to at least 40 (basically doing the same thing). I'm hoping to get rid of the delay to make the whole process as fast as possible, provided there is no bleed through/crossover of the Y value.

Ultimately I will print the results of index and value over the serial port. In Pure Data the serial data will be sorted and I will have an array of control number boxes which receive each index and value and then are sent on to whatever function they control in the patch.

OK. I'm still just trying to build up a picture of what you are attempting to do, especially from the point of view of the user of the system.

It looks like the user can use the joy stick in the horizontal direction (X axis) to select one on 30 positions (0 to 29).
When he has selected one he can then start moving the joystick in one Y direction from the middle index position (which has analog value 512). When he has held a steady position for a number of milliseconds, that analog reading from the Y potentiometer is stored in an array.

How does the user know which X position (0 to 29) he has selected ?
How does the user know how long a reading must be held steady on the Y potentiometer before it is accepted as valid, and that he can move on to the next X setting ?
What prevents a user accidentally moving, when the potentiometer is set for a specific Y value, in the X direction one or two increments back or forward, and having the Y value stored at the wrong location ?

Yes, you're right on everything about how i'm trying to use the joystick.

I'm still thinking about how I want to do the display portion, but for now in Pure Data the values will be printed across the serial line. Each time a new index is selected it prints "position" followed by the index. PD will route the index to the correct output each time the word "position" is read. I'll then have a visual indicator color change to highlight the selected control. This index position will open up the selected input to then receive the Y value as it is printed. The visual control (either number box or slider graph) will change with Y value.

In the end i'll probably attach a screen to my raspberry Pi to visualize the controls, or try and do it with an LCD from the Teensy. I guess for that I'll have to figure out how to save the array values and load them up the next time I power up the circuit.