Wacky MIDI readings from a 4067 multiplexer, until a delay is applied.

Status
Not open for further replies.

Hitachii

Active member
Hello,

Currently using an HP4067 on a breakout board with 16 pots connected to a 4.1, sending MIDI over serial UART to another device, which allows me to see the MIDI readings on the computer.

Using a modified version of the code I found, the reading from my pots look fine in the serial monitor, but when looking at the readings on the computer (in MIDI form), they're all over the place. The values skip around, turning one knob won't work, but a whole other value will begin to turn, some don't work at all. However, if I apply a delay of at least 3 milliseconds, all of the values read perfectly fine. If there's a delay of one or two milliseconds, the skipping returns.

All of the pins are in order on the board and in the code. Digital pins S0 - S3 are on pins 2 - 5. The analog pin is connected to pin 38. If this is significant, the TX I'm using is right next door at pin 2, and pin 1 RX is not in use. There is no accidental contact between any of the pins.

Before getting the multiplexer, the pots were connected to the board itself. There were no issues with how they behaved. Using the same computer program, they never skipped around like they are after hooking them up to the multiplexer. Should I debounce the digital pins? It's not a long enough delay for it to make a very discernible difference, but I'm not sure if the delay there will cause me a headache further down in the code. Thanks!

Code:
#include <MIDI.h>
#define muxIn 38      

#define muxPin0 2  
#define muxPin1 3  
#define muxPin2 4  
#define muxPin3 5  

int CCChan[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
int potVal[16]; 

int initPot[16];
int lastInitPot[16];

MIDI_CREATE_DEFAULT_INSTANCE(); 
 
void setup()
{

  pinMode(muxPin0, OUTPUT);
  pinMode(muxPin1, OUTPUT);
  pinMode(muxPin2, OUTPUT);
  pinMode(muxPin3, OUTPUT);
MIDI.begin();
//Serial.begin(9600);     //optional for viewing print lines below
}
 
void loop()
{
  for(int i = 0; i < 16; i++)  {
  byte channel = (i);
  digitalWrite(muxPin0, bitRead(channel, 0));
  digitalWrite(muxPin1, bitRead(channel, 1));
  digitalWrite(muxPin2, bitRead(channel, 2));
  digitalWrite(muxPin3, bitRead(channel, 3));
 
   initPot[i] = (map(analogRead(muxIn), 0, 1023, 0, 127));
   if(initPot[i] != lastInitPot[i]){
    lastInitPot[i] = initPot[i];
    potVal[i] = initPot[i];
    delay(3);
      MIDI.sendControlChange(CCChan[i], potVal[i], 1);
   }
   
/*  Serial.print("Channel: ");   // left this in, in case it comes in handy.
  Serial.println(CCChan[i]);
  Serial.println(" ");
  Serial.print("Pot Value: ");
  Serial.println(potVal[i]);
  Serial.println(" ");
  
  delay(300);//*/
  }
}

Unrelated bonus question: Is it necessary to mount the Teensy Audio Board directly on the pins of the Teensy, or is it possible instead to use similar available pins and mount it elsewhere?
 
Could be so simple that 16 CC messages without any pause overflows the serial out buffer.
 
Could be so simple that 16 CC messages without any pause overflows the serial out buffer.

Thanks again. Is there a better method than using a delay the way that I have? Your explanation might explain other problems I'm having sending MIDI too.
 
well midi serial is 32,5 kbaud, about 3200 bytes per second, and a midi message usually 3 bytes so about 1000 messages per second. Now this is more than most midi receivers can handle.

So how to make sure the output doesnt overflow, some possible strategies:
* Keep the delays even if delays are ugle and wasteful of processor resources.
* Only send the CC if the new value is at least 2 (3 .. ) counts different from the previous
* Set a timer/timeout (with elapsedMillis) for every control channel so it is silent for say 10ms after any previous change, you can well read and debounce inputs during this time but dont send it and flood the output and the receiver
 
That's very helpful, thank you. Looks like I'll have to get creative with loading values from EEPROM since only 12 of my 20 parameters seem to send MIDI messages when the 'load' button is hit. It's set so that all the addresses read from an array and send MIDI messages... all too quickly from what I gather here.

* Set a timer/timeout (with elapsedMillis) for every control channel so it is silent for say 10ms after any previous change, you can well read and debounce inputs during this time but dont send it and flood the output and the receiver

This looks like the solution to that issue?

p.s. I've successfully used the equation you helped me with to expand my preset system to have hundreds of presets to scroll through. Even more after my expanded memory arrives :D.
 
While it’s possible you may be sending too much data for the MIDI buffer, you state that it worked fine without the multiplexer and that’s likely still the case. Of note is that when you add a multiplexer chip into the mix you do have to add a delay, but not in the place that you have it and it’s usually in microseconds or even nanoseconds depending on the chip used. The delay has to come after you switch channels on the multiplexer and before reading from the pin or else problems will arise with the values not being correct. For more information consider reading the relevant section on multiplexers on the USBMIDI page: https://www.pjrc.com/teensy/td_midi.html
 
Thank you very much. Thank you for the link, it couldn't be any more direct than this snippet from the USBmidi page.

Code:
  // select 74HC4051 channel 5 (of 0 to 7)
  digitalWrite(1, HIGH);
  digitalWrite(2, LOW);
  digitalWrite(3, HIGH);
  
  // allow 50 us for signals to stablize
  delayMicroseconds(50);
  
  // read the signals routed to pins 10, 19, 20
  // through channel 5 of each 74HC4051 chip
  buttonPin10channel5.update();
  knobPin19channel5 = analogRead(19);
  knobPin20channel5 = analogRead(20);
 
Status
Not open for further replies.
Back
Top