SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By noouch
I've run in to a bit of problem designing a MIDI controller with lots of knobs. There is code to forward incoming MIDI messages from other controllers to the MIDI Out in the main loop, and that should run as fast as possible. This means it's better to not poll all the knobs (there are about 40 of them) in the main loop unless it's absolutely necessary.

So what I'd like to do is get an interrupt signal from the multiplexer whenever a knob is changed and an update is necessary. Is there an elegant way of doing this, or perhaps even a multiplexer that provides such a function?
User avatar
By thebecwar
The short answer is no. That assumes you're using a standard style MUX like the CD74HC4067.

The longer answer is that the mega328 does have an ADC complete interrupt, so you could fake it by using the ADC conversion interrupt to switch to the next MUX channel and start a conversion. Between interrupts you still could (theoretically) do other things. You probably want to read section 23 from the mega328's datasheet before you go too much farther. Alternatively you could use a timer interrupt, to periodically loop through all the MUX channels. It all depends on how much lag you're willing to accept.
By noouch
thebecwar wrote:Alternatively you could use a timer interrupt, to periodically loop through all the MUX channels. It all depends on how much lag you're willing to accept.
The point is to have as close to zero lag and "zippering" for the controls as possible. High latency is still better than a low sampling frequency though.

Judging by the datasheet I could get away with an update every 3-5ms, which should be enough for starters. The overhead for transmitting a signal is about that much as well. I guess it would be easier to poll all the knobs in the main loop and set an interrupt for incoming MIDI signals.

Once a knob change is detected (by storing and updating an array to compare old and current values), the value still needs to be interpolated to 14 bits and then a MIDI library function is called according to a lookup table for assigning and mapping controllers.

Do you think that the ADC complete interrupt would leave enough air for other stuff to run if I utilize the full 15ksps that the ATmega offers?
User avatar
By thebecwar
The arduino runs at 16MHz. This means that the clock cycles every 0.0625 microseconds (us). (1/16,000,000th of a second)
15k samples per second gives you a sample approximately every 66.6 us. (1/15,000th of a second)

That means that in theory you have 1065 clock cycles in between ADC sample conversions. In reality it's slightly less because the calculation I did ignores conversion time, but the exact number isn't really important as we'll see in a second.

An interrupt vector takes a maximum of 4 clock cycles to begin, and 4 clock cycles to end. That means that if you are using the ADC complete interrupt, you have 8 clock cycles tied up every sample. That takes our total clock cycles down to 1057.

Even if you take 500 clock cycles to process the interrupt, you still have plenty of time left to accomplish other tasks before the next ADC complete interrupt fires (about 557 cycles).

I don't really see any way to reduce the 'zipper' effect without additional hardware complexity.