Is it possible to replace user input with a variable?

Hello everyone and thank you if you’ve decided to help. I’ll try and keep this short…Also, NOOB alert.

I’m trying to make a ‘bytebeat’ synth. It works fine as long as I’m compiling the equation. If I try and get user input, it fails horribly and I’m not savvy enough yet to know if I’m asking the right questions to even get the right answer.

Here’s a snippet of what I’m attempting in my ISR…

/******** Called every time TCNT2 = OCR2A ********/
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  OCR1AL = y;        // Update the PWM output index++
  if (Play_Flag != 1) {       // y kept at 0 so there's no sound and no reason to disable interrupts.
    y = 0;
  } else {
    y  = MyEqu;
  // y = (((t%(t>>16|t>>8))>>2)&t)-1; // These are just example equations
  // y = t*(t>>10&((t>>16)+1));
  }
  index++; // This indexes drawing the audio waveform on the lcd.
  t++;       // This t variable increments by one for each interrupt. It's what I need to be able to use in 
                // to replace the 't' in the user collected string and replace with this variable. 
  Flag = 0;  // Just a flag to allow the LCD to write a pixel on the screen to make a waveform.
}

If I un-comment one of those equations and comment out the ‘y = MyEqu;’ it works like a silly bytebeat synth should. Here’s how I declared the variable ‘MyEqu’.

volatile static char MyEqu;

Finally, here’s the code where I build the equation from user input…of course there’s 16 different ‘if’ statements depending on which button I push, but this one is what it ‘seemingly’ causing the problems.

      if (val > KeyPad[3][1] && val < KeyPad[3][2]) {  //This just catches that I pushed the button I 
        display.println("t");                                          //labeled 't' on a resistive keypad.
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7; // Just code for indexing the cursor.
        } else {
          X = X + 7;
        }
    MyEqu += t;      // <----------yeah, that's the problem...       
    display.setCursor(X, Y);
    delay(250);       // Delay because I haven't gotten around to de-bouncing the buttons yet.
      }

I want to type the equation using the keypad, hit the ‘play’ key, and have it run the equation using the timers and output to make sound. Obviously, having a simple equation like “t>>t” works fine at compile time if it’s already there at compile time, but every attempt I’ve made to make “t” from the user input equate to “t” the variable has failed. I hope I’m not wasting anyone’s time with this question. It may very well be that I need to study more. So far, my efforts to figure this out have been rather hopeless. Thanks for any help that can be offered!

volatile static char MyEqu;
MyEqu += t;      // <----------yeah, that's the problem..

Please explain what you are trying to do in the second snippet above, although I think that I know the answer… What is t ?

In the second snippet, t is just a variable that increments each time the ISR executes. The equations need to have that value of t. Because the equation is held in a byte, it adjusts the value to 0-255 and that’s output on pin 9 at an audible frequency. There’s a counter that indexes 256 times then overflows to 0. The values obtained from the equation determine the shape of the waveform. So far I’ve only been able to get predetermined equations to compute. No matter what I’ve tried, I can’t seem to get that value of t… that is user input, to represent the value t that is my variable. I’m also worried that if I spend too much time writing code in the ISR I could end up with other timing issues. I’m kind of wondering if the language even supports what I’m trying to do.

Here’s more of the code. Sorry if it’s poorly written, I’m still pretty new at this. It’s become a battle of attrition between my frustration for lack of skill and my wont to succeed.

  /******** Set timer1 for 8-bit fast PWM output ********/
  pinMode(9, OUTPUT);       // Make timer's PWM pin an output
  TCCR1B  = (1 << CS10);    // Set prescaler to full 16MHz
  TCCR1A |= (1 << COM1A1);  // PWM pin to go low when TCNT1=OCR1A
  TCCR1A |= (1 << WGM10);   // Put timer into 8-bit fast PWM mode
  TCCR1B |= (1 << WGM12); 

  /******** Set up timer 2 to call ISR ********/
  TCCR2A = 0;               // We need no options in control register A
  TCCR2B = (1 << CS21);     // Set prescaller to divide by 8
  TIMSK2 = (1 << OCIE2A);   // Set timer to call ISR when TCNT2 = OCRA2
  OCR2A = 114; // sets the frequency of the generated wave 32 is C3
  sei();
}

void loop() {
    int val;
    int analogPin = A7;
    val = analogRead(analogPin);

    if(val > 320 && val < 335) {  // the value of the button, bottom row, 2nd in, has a resistive val around 320-335 ohms (the play/stop button)
         display.clearDisplay(); // Clear display before the waveform starts
         delay(1);
         display.setTextSize(1);
         display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
         display.setCursor(100,57);
         display.println("Stop");
         display.display();
         delay(250);
         display.clearDisplay();
         Play_Flag = 0; //set play flag
         equWindow();
          }    


    
    if (Flag == 0) {  //Checks if an interrupt has occurred. If so, call drawing function and setflag
    audioWave(index, y);
    Flag = 1;
  }
}

/******** Called every time TCNT2 = OCR2A ********/
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  OCR1AL = y;        // Update the PWM output index++
  if (Play_Flag != 1) {
    y = 0;
  } else {
    y  = MyEqu;
  // y = (((t%(t>>16|t>>8))>>2)&t)-1;
  // y = t*(t>>10&((t>>16)+1));
  }
  index++;
  t++;
  Flag = 0;
}

    void equWindow(void) {
    int val = 0;
    int analogPin = A7; //Define analog pin A7
    delay(250);
    int X = 0;
    int Y = 0;
      display.clearDisplay();
      display.setTextSize(1);             // Normal 1:1 pixel scale
      display.setTextColor(SSD1306_WHITE); // Draw white text
      display.setCursor(100,57);
      display.println("Play");
      display.display();
      delay(250);
      display.setCursor(X,Y);
    while (Play_Flag != 1) {// while loop to stay here until the right button is pushed;
       val = analogRead(analogPin); //read value of analog pin

      if (val > KeyPad[0][1] && val < KeyPad[0][2]) { // Key 0,1 was pressed (1)
        display.println("1");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 1;
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[1][1] && val < KeyPad[1][2]) { 
        display.println("2");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 2;
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[2][1] && val < KeyPad[2][2]) { 
        display.println("3");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 3;    
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[3][1] && val < KeyPad[3][2]) { 
        display.println("t");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += t;        // <----------- That's what needs to be fixed... somehow.
    display.setCursor(X, Y);
    delay(250);
      }
      
      if (val > KeyPad[4][1] && val < KeyPad[4][2]) { 
        display.println("4");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 4;
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[5][1] && val < KeyPad[5][2]) { 
        display.println("5");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 5;        
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[6][1] && val < KeyPad[6][2]) { 
        display.println("6");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 6;
    display.setCursor(X, Y);
    delay(250);
      }

       if (val > KeyPad[7][1] && val < KeyPad[7][2]) { 
        display.println("(");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += '(';        
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[8][1] && val < KeyPad[8][2]) { 
        display.println("7");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 7;
    display.setCursor(X, Y);
    delay(250);
      }
            
    if (val > KeyPad[9][1] && val < KeyPad[9][2]) { 
        display.println("8");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 8;
    display.setCursor(X, Y);
    delay(250);
      }
     
      if (val > KeyPad[10][1] && val < KeyPad[10][2]) { 
        display.println("9");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 9;
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[11][1] && val < KeyPad[11][2]) { 
        display.println(">");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += ">";
    display.setCursor(X, Y);
    delay(250);
      }

      if (val > KeyPad[12][1] && val < KeyPad[12][2]) { 
        display.println("0");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += 0;
    display.setCursor(X, Y);
    delay(250);
      }

//Serial.println(MyEqu);
     
          if(val > 320 && val < 335) { 
            display.clearDisplay(); // Clear display before the waveform starts
            delay(1);
            display.setTextSize(1);
            display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
            display.setCursor(100,57);
            display.println("Play");
            display.display();
            delay(250);
            display.clearDisplay();
            Play_Flag = 1; //set play flag
            index = 0; // Set so the equation plays from the beginning
            t = 0;     // reset the timer
          }
    }

  }

In the second snippet, t is just a variable that increments each time the ISR executes.

Is t declared as volatile?

Where is the code which takes user input for a value of t?

cattledog:
Is t declared as volatile?

Yes, t is declared as volatile because I had read that it’s a good idea if the variable will be used inside a ISR. Declared as static because I figured it would be used in different places in the program as a global variable.

volatile static char MyEqu; <— that’s how I declared it in the beginning.

Where is the code which takes user input for a value of t?

      if (val > KeyPad[3][1] && val < KeyPad[3][2]) { 
        display.println("t");
        display.display();
        if ((X+7)>=128){
          X = 0;
          Y = Y + 7;
        } else {
          X = X + 7;
        }
    MyEqu += t;        // <----------- That's what needs to be fixed... somehow.
    display.setCursor(X, Y);
    delay(250);
      }

The idea is that each time I press a button on the resistive keypad, it would display it on the lcd and append the value to the equation. When I press the button that I’ve labeled ‘play’, it sets a flag in the ISR and the hope is that I can switch the variable to compute 'y = '. Here’s that code:

/******** Called every time TCNT2 = OCR2A ********/
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  OCR1AL = y;        // Update the PWM output index++
  if (Play_Flag != 1) {
    y = 0;
  } else {
    y  = MyEqu; // <---------- I need a way to enter an equation like I've written below (that's 
                       //                  commented out), so that it executes right here.

  // y = (((t%(t>>16|t>>8))>>2)&t)-1;
  // y = t*(t>>10&((t>>16)+1));
  }
  index++;
  t++;
  Flag = 0;
}

Thank you for taking the time to try and help me out.

I recommend that you reproduce the problem in an MCVE (minimal, complete, verifiable example) https://stackoverflow.com/help/minimal-reproducible-example

I would go with either user input or the timer ISR for changing t, but not both.

If you go for user input instead of the timer, I would use serial input/output from the monitor, rather than a keypad and oled display, as it will make it easier for people to run you code.

I've taken your advice and hopefully this clarifies what I'm trying to accomplish. If there's anything else I can do to attempt to make it clearer, I'll do my best. Thanks :)

unsigned long t;
byte y;

char MyEqu; // for incoming serial data

void setup() {
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}

void loop() {
  
  if (Serial.available() > 0) {
    MyEqu = Serial.read();
    My_ISR(MyEqu);
  }
}

void My_ISR(char x) {
  
  y = MyEqu; // I need the variable y to equal the result of the equation from the user's serial input. 
             // For example... input t*t into the serial monitor input. The variable y needs to have 
             // the calculated value in a byte. The var y takes whatever number results from the calculation and 
             // scales it into a byte. That byte feeds the waveform with a value to OCR1AL for my timer ISR.
             // I need to be able to calculate the value of t in the equation whereever
             // it is placed in the input variable MyEqu. The variable t has no static placement where I could substitute out a value
             // since the equation itself is user defined during runtime. 
  Serial.println(y);
  t++;
}

I need the variable y to equal the result of the equation from the user's serial input.

For example... input t*t into the serial monitor input.

Or more complex

(((t%(t>>16|t>>8))>>2)&t)-1 // These are just example equations
 t*(t>>10&((t>>16)+1))

I'm not certain that you can achieve what you are trying to do--enter a character string, user defined during run time, and have it evaluated as a mathematical function.

I have seen simple 4 function arithmetical parsers for a simple calculator but nothing more complex like the mathematical expression library (ExpTk) which would be suitable for an arduino.

I think the best you can do, is have a predefined array of functions as character strings and an equivalent array of the actual functions or function pointers. You enter the string and the parameters. Then, compare the entered characters with strcmp to the functions as characters, select the correct function, and then parse the parameters from the entry and use them in the actual functions.

See https://forum.arduino.cc/index.php?topic=109864.15

I'm not certain that you can achieve what you are trying to do--enter a character string, user defined during run time, and have it evaluated as a mathematical function.

After the hours trying to get it to work, I was afraid that's what the answer was. I made the same project on a Raspberry Pi zero and when I ran into the same problem, I chose to open a file and actually write the code into that open file with the user equation written in the code at the right spot. It was easy at that point to write a bash script to run the program that collected the user equation, wrote it into the code, then executed the newly written .py file. I chose python for that and it seemed to work well enough. I decided to go with it on the Arduino as a challenge and figured it was my lack of abilities that were the issue rather than the limitations of the code. Turns out it was both. lol Thank you very much for taking the time to respond. I can close this chapter and move onto something else.