Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: analogRead from MIDI controller overwhelming synthesizer with messages

  1. #1
    Junior Member
    Join Date
    Feb 2019
    Posts
    10

    analogRead from MIDI controller overwhelming synthesizer with messages

    Hi forum! I built a MIDI controller with a Teensy 3.2 and everything is working great except the pitch bend controlled by a joystick.



    First some quick explanation: MIDI pitch bend is sent with values between 0-16383 (-8191 through +8192 on a Teensy) so you'll notice that all of these values are within the typical 0-1023 but multiplied by 16 and offset by -8191.

    "Center" on this joystick is -438 and drifts a bit so I created a "dead zone" from -450 through 0. In other words, If x < -450 pitch bend down, if x > 0 pitch bend up.

    I wired the joystick backwards so I reversed -8191 and 8192 in the map() function: map(x, 0, 1023, 8192, -8191).



    On to the main problem!

    Originally, I was getting overwhelming info sent by the Teensy because it was sending a readout after every loop. This was overwhelming my computer and the software synthesizer I was controlling. I wanted to reduce the info without slowing it down since a music interface needs realtime control so a delay() wouldn't help.

    I set it up so that it would only Serial.print and usbMIDI.sendPitchBend when the value changed. The analogRead value keeps drifting by 16 (by 1 in 0-1023 terms) so I wrote the code to only send messages when the value had changed from previous loops by 17 (i chose 17 instead of 16 because i was occasionally getting a drift of 17):

    if ((x < (prev_x - 17)) || (x > (prev_x + 17)))

    This works ok on the positive side but on the negative side, I'm still getting overwhelming messages. On the positive side of the joystick, the edge reads "x is 7905" (not quite 8192) and holds there until I move it which is good enough. I still receive alot of info returning to center but is less than it was and is working as expected. But on the negative side, serial monitor will read:
    13:53:44.069 -> x is -8110
    13:53:44.216 -> x is -8110
    13:53:44.216 -> x is -8110
    13:53:44.329 -> x is -8110
    13:53:44.329 -> x is -8110
    This info is overwhelming my synth and why is it even printing if this is not true: ((-8110 < (-8127)) || (-8110 > (-8093)))

    and

    Is there an easier way to accomplish what I'm trying to do?

    Thank you so much for reading!

    Code:
    #include <Bounce.h>
    
    const int channel = 1;
    int x = 0;
    int prev_x = 0;
    int y = 0;
    int prev_y = 0;
    int bounce_ms = 5;
    
    Bounce C = Bounce(0, bounce_ms);
    Bounce E = Bounce(1, bounce_ms);  
    Bounce G = Bounce(2, bounce_ms);  
    Bounce b = Bounce(3, bounce_ms);  
    Bounce B = Bounce(4, bounce_ms);
    Bounce Eb = Bounce(5, bounce_ms);  
    Bounce Gb = Bounce(6, bounce_ms);  
    Bounce Bb = Bounce(7, bounce_ms);  
    Bounce T2 = Bounce(8, bounce_ms);
    Bounce T1 = Bounce(9, bounce_ms);
    Bounce T3 = Bounce(10, bounce_ms);
    Bounce T4 = Bounce(11, bounce_ms);
    Bounce JB = Bounce(12, bounce_ms);
    Bounce b2 = Bounce(16, bounce_ms);
    Bounce Ab = Bounce(17, bounce_ms);
    Bounce E2 = Bounce(18, bounce_ms);
    Bounce Db = Bounce(19, bounce_ms);
    Bounce c = Bounce(20, bounce_ms);
    Bounce A = Bounce(21, bounce_ms);
    Bounce F = Bounce(22, bounce_ms);
    Bounce D = Bounce(23, bounce_ms);
    
    void setup() {
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      pinMode(4, INPUT_PULLUP);
      pinMode(5, INPUT_PULLUP);
      pinMode(6, INPUT_PULLUP);  
      pinMode(7, INPUT_PULLUP);
      pinMode(8, INPUT_PULLUP);
      pinMode(9, INPUT_PULLUP);
      pinMode(10, INPUT_PULLUP);
      pinMode(11, INPUT_PULLUP);
      pinMode(12, INPUT_PULLUP);  
      pinMode(16, INPUT_PULLUP);
      pinMode(17, INPUT_PULLUP);
      pinMode(18, INPUT_PULLUP);
      pinMode(19, INPUT_PULLUP);
      pinMode(20, INPUT_PULLUP); 
      pinMode(21, INPUT_PULLUP);
      pinMode(22, INPUT_PULLUP);
      pinMode(23, INPUT_PULLUP);
    }
    
    void loop() {
      C.update();
      E.update();
      G.update();
      b.update();
      B.update();
      Eb.update();
      Gb.update();
      Bb.update();
      T2.update();
      T1.update();
      T3.update();
      T4.update();
      JB.update();
      b2.update();
      Ab.update();
      E2.update();
      Db.update();
      c.update();
      A.update();
      F.update();
      D.update();
    
      if (B.fallingEdge()) {
        usbMIDI.sendNoteOn(59, 99, channel);  // 59 = B3
      }
      if (C.fallingEdge()) {
        usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
      }
      if (Db.fallingEdge()) {
        usbMIDI.sendNoteOn(61, 99, channel);  // 61 = Db4
      }
      if (D.fallingEdge()) {
        usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
      }
      if (Eb.fallingEdge()) {
        usbMIDI.sendNoteOn(63, 99, channel);  // 63 = Eb4
      }
      if (E.fallingEdge()) {
        usbMIDI.sendNoteOn(64, 99, channel);  // 64 = E4
      }
      if (E2.fallingEdge()) {
        usbMIDI.sendNoteOn(64, 99, channel);  // 64 = E4
      }
      if (F.fallingEdge()) {
        usbMIDI.sendNoteOn(65, 99, channel);  // 65 = F4
      }
      if (Gb.fallingEdge()) {
        usbMIDI.sendNoteOn(66, 99, channel);  // 66 = Gb4
      }
      if (G.fallingEdge()) {
        usbMIDI.sendNoteOn(67, 99, channel);  // 67 = G4
      }
      if (Ab.fallingEdge()) {
        usbMIDI.sendNoteOn(68, 99, channel);  // 68 = Ab4
      }
      if (A.fallingEdge()) {
        usbMIDI.sendNoteOn(69, 99, channel);  // 69 = A5
      }
      if (Bb.fallingEdge()) {
        usbMIDI.sendNoteOn(70, 99, channel);  // 70 = Bb5
      }
      if (b.fallingEdge()) {
        usbMIDI.sendNoteOn(71, 99, channel);  // 71 = B5
      }
      if (b2.fallingEdge()) {
        usbMIDI.sendNoteOn(71, 99, channel);  // 71 = B5
      }
      if (c.fallingEdge()) {
        usbMIDI.sendNoteOn(72, 99, channel);  // 72 = c
      }
      if (T1.fallingEdge()) {
        usbMIDI.sendControlChange(64, 127, channel);  // 64 = sustain
      }
      if (T2.fallingEdge()) {
        usbMIDI.sendPitchBend(-8191, channel);  
      }
      if (T3.fallingEdge()) {
        usbMIDI.sendPitchBend(8192, channel);  
      } 
      if (T4.fallingEdge()) {
        usbMIDI.sendControlChange(64, 127, channel);  // 66 = sostenuto
      }
      if (JB.fallingEdge()) {
        usbMIDI.sendControlChange(82, 127, channel);  
      }
      
      
      if (B.risingEdge()) {
        usbMIDI.sendNoteOff(59, 99, channel);  // 59 = B3
      }
      if (C.risingEdge()) {
        usbMIDI.sendNoteOff(60, 99, channel);  // 60 = C4
      }
      if (Db.risingEdge()) {
        usbMIDI.sendNoteOff(61, 99, channel);  // 61 = Db4
      }
      if (D.risingEdge()) {
        usbMIDI.sendNoteOff(62, 99, channel);  // 62 = D4
      }
      if (Eb.risingEdge()) {
        usbMIDI.sendNoteOff(63, 99, channel);  // 63 = Eb4
      }
      if (E.risingEdge()) {
        usbMIDI.sendNoteOff(64, 99, channel);  // 64 = E4
      }
      if (E2.risingEdge()) {
        usbMIDI.sendNoteOff(64, 99, channel);  // 64 = E4
      }
      if (F.risingEdge()) {
        usbMIDI.sendNoteOff(65, 99, channel);  // 65 = F4
      }
      if (Gb.risingEdge()) {
        usbMIDI.sendNoteOff(66, 99, channel);  // 66 = Gb4
      }
      if (G.risingEdge()) {
        usbMIDI.sendNoteOff(67, 99, channel);  // 67 = G4
      }
      if (Ab.risingEdge()) {
        usbMIDI.sendNoteOff(68, 99, channel);  // 68 = Ab4
      }
      if (A.risingEdge()) {
        usbMIDI.sendNoteOff(69, 99, channel);  // 69 = A5
      }
      if (Bb.risingEdge()) {
        usbMIDI.sendNoteOff(70, 99, channel);  // 70 = Bb5
      }
      if (b.risingEdge()) {
        usbMIDI.sendNoteOff(71, 99, channel);  // 71 = B5
      }
      if (b2.risingEdge()) {
        usbMIDI.sendNoteOff(71, 99, channel);  // 71 = B5
      }
      if (c.risingEdge()) {
        usbMIDI.sendNoteOff(72, 99, channel);  // 72 = c
      }
      if (T1.risingEdge()) {
        usbMIDI.sendControlChange(64, 0, channel);  // 64 = sustain
      }
      if (T2.risingEdge()) {
        usbMIDI.sendPitchBend(0, channel);  
      }
      if (T3.risingEdge()) {
        usbMIDI.sendPitchBend(0, channel); 
      }
      if (T4.risingEdge()) {
        usbMIDI.sendControlChange(64, 0, channel);  // 66 = sostenuto
      }
      /*if (JB.risingEdge()) {
        usbMIDI.sendNoteOff(71, 99, channel);  // 71 = B5
      }*/
    
      x = analogRead(0);
      x = map(x, 0, 1023, 8192, -8191);
      y = analogRead(1);
      y = map(y, 1023, 0, -126, 127);
    
    if ((x < (prev_x - 17)) || (x > (prev_x + 17))){
        Serial.print("x is ");
        Serial.println(x);
        if (x < -450 || x > 0)
        usbMIDI.sendPitchBend(x, channel);
        else usbMIDI.sendPitchBend(0, channel);
      }
      if ((y > -1) && (prev_y != y )){
        usbMIDI.sendControlChange(1, y, channel);
        //Serial.print("y_up is ");
        //Serial.println(y);
      } 
      if ((y < 0) && (prev_y != y)){
        usbMIDI.sendControlChange(11, y, channel);
        //Serial.print("y_down is ");
        //Serial.println(y);
      }
    //delay(2);
    prev_x = x;
    prev_y = y;
    }

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,277
    You seem to be stuck with the mathematics. The problem is that inequalities become reversed when the sign changes. For example 5 > 3 is true. But when I (which is a legal operation) multiply both sides by -1, I would get -5 > -3 which is not true. That's why changing the sign implies always reversing the inequality sense : -5 < -3.

    You could now distinguish more cases, depending on the sign of x and prev_x (and in a similar way y and prev_y) but that risks to complicate things. A simpler and cleaner approach is mathematically measuring the absolute distance between x and prev_x and compare it to an always positive value which gives correct sign-independent results :
    Code:
    if (abs(x - prev_x) > 17) {
      //do whatever stuff, serial.print, send pitchbend data, etc.
    }
    The next logical problem is that you always update prev_x from x at the end of each loop, independent of the fact if an update has been sent or not. Now, imagine the (highly improbable, I admit) case of a very, very slow movement, so that from one of the next ADC reading, x changes only by 10. So, starting at for example x = -7000, prev_x would follow up -6990, -6980... up to +7000 without a single pitchbend message sent ever. That's why I'd suggest to update prev_x only when a message has been sent.
    So, let's admit a first reading of -7000 => send and update,
    then -6990 => distance 10 => no send, no update,
    then -6981 => distance 9 which wouldn't trigger anything, but cumulated distance 19 => send and update

    Conclusion:
    Code:
    if (abs(x - prev_x) > 17) {
      //do whatever stuff, serial.print, send pitchbend data, etc.
      prev_x = x;
    }
    Last edited by Theremingenieur; 02-26-2019 at 10:58 PM.

  3. #3
    Junior Member
    Join Date
    Feb 2019
    Posts
    10
    Hi Theremingeniur, thanks for showing me the abs() function. That will definitely simplify things. Excellent. I'll use that from now on.

    While abs() certainly simplifies things, I still don't understand why ((-8110 < (-8127)) || (-8110 > (-8093))) would print numbers when it isnt true. Maybe there's something I'm just not understanding.

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,277
    Quote Originally Posted by heyjudemw View Post
    While abs() certainly simplifies things, I still don't understand why ((-8110 < (-8127)) || (-8110 > (-8093))) would print numbers when it isnt true. Maybe there's something I'm just not understanding.
    With updating prev_x from x at the and of each loop, you can't really know if the prev_x was -8110, too, so that you would truly compare against -8127 and -8093. It is probable that there have been a few loop runs in-between, where x (and thus prev_x) had slightly changed in the meantime without triggering a print, and thus without you being aware of these changes. I wouldn't scratch my head because of that, now that you have a simple working solution.

  5. #5
    Junior Member
    Join Date
    Feb 2019
    Posts
    10
    That sounds reasonable. I'll rewrite the code with the abs() function and see where it gets me. Thanks for the advice!!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •