USB MIDI to Serial and CV/GATE
This project uses my Arduino Pro Mini MIDI USB CV PCB for a USB MIDI to Serial MIDI and CV/GATE device that has a CV/GATE that is compatible with my Korg Volca Modular.
It takes MIDI NoteOn/NoteOff and translates them into CV that can be used to set the pitch of a CV/GATE synth.
IMPORTANT: I strongly recommend that you do not connect this to your Volcas. I am not an electronics person but have accepted the risk of causing a possibly expensive problem. I will not be held responsible if you end up doing the same.
https://makertube.net/w/puRwMGeELa5zq3YhMrMC4h
https://makertube.net/w/cPjFeqigcrBHgMMPLjPNPb
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
If you are new to Arduino, see the Getting Started pages.
The Circuit
This is an application for my completed Arduino Pro Mini MIDI USB CV PCB.
The Code
The board was designed to require a PWM output on D3. With hindsight, D9 might have been more useful as D9 is a “Timer 1” timer on the ATMega328, but D3 is a “Timer 2” timer. The former are 16-bit timer/counters. The latter are only 8-bit.
No matter. I still have 255 levels of PWM to play with.
The initial PWM criteria I wanted were:
- No prescalar – run at full CPU speed. In the case of a 3V3 Pro Mini this is 8MHz.
- Use FastPWM mode – this will count up and then reset to zero.
- Use a TOP value of 255 – the maximum.
- Use the OC2B output, which is connected to D3. OC2A is not used.
- Use the mode where OC2B is cleared on compare match; set at 0 (BOTTOM).
- The PWM value is therefore written into OCR2B.
At some point the code will have to translate from MIDI note number over to a PWM value. My previous project mapped MIDI note C2 (36) onto 0V and went up from there for 5 octaves to C7 (96). This is a range of 60 steps, so actually, revisiting the PWM code, if we change the mode to use an alternative TOP Value of 239, that means each MIDI note corresponds to a specific step of 4. That would be pretty useful!
So the updated PWM criteria is now as follows:
- No prescalar – still run at full CPU speed. In the case of a 3V3 Pro Mini this is 8MHz.
- Use FastPWM mode – this will count up and then reset to zero.
- Use a TOP value of OCR2A, which will be set to 239.
- Use the OC2B output, which is connected to D3. OC2A is not used.
- Use the mode where OC2B is cleared on compare match; set at 0 (BOTTOM).
- The PWM value is therefore written into OCR2B.
The PWM operating frequency is given by a formula in the datasheet, but is basically the time it takes for the counter to count from 0 to 239 and reset, whilst running at 8MHZ. So the PWM frequency = 8000000 / 240 = 33.3kHz.
At such a frequency the (now updated) PWM filter components chosen give a pretty smooth output between 0V and 3.3V, which are them amplified using the OpAmp for a 0V to 5V range.
Note: No interrupts are required for the operating of PWM in this manner. We can just update the PWM value whenever is useful during the operation of the code.
The complete PWM code is thus as follows
void initPwm() {
pinMode(3, OUTPUT);
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20);
OCR2A = 239;
}
void setPwm (uint8_t pwmval) {
OCR2B = pwmval;
}
The value used for PWM will only be active for 0-239. Any value of 240 or higher will just be considered “always on”.
This all means that converting from MIDI to PWM value is now pretty trivial:
#define MIDI_LOWEST_NOTE 36 // C2
#define MIDI_HIGHEST_NOTE 95 // C7
uint8_t midi2pwm (uint8_t note) {
if (note < MIDI_LOWEST_NOTE) note = MIDI_LOWEST_NOTE;
if (note > MIDI_HIGHEST_NOTE) note = MIDI_HIGHEST_NOTE;
return (note - MIDI_LOWEST_NOTE) * 4;
}
Logging the average voltage for each MIDI note (pre and post amplification) gives me the following:
C20.080.08C30.721.06C41.352.03C52.023.01C62.653.95C73.284.90Plotting these on a graph looks like this:
That is a pretty good linear response, but is slightly under in terms of the top-end output. At 1V/oct a semitone is around 83mV, so dropping 0.1V at the top ought to be dropping a semitone.
But jumping through the octaves it sounds all right to me. It’s definitely not dropping a semitone anyway, so I’m not sure what is going on. I might need to come back to this one!
The rest of the code is fairly straightforward MIDI reception and processing that I’ve done several times before now. There are a few design notes:
- Automatic MIDI THRU is turned off or both serial and USB MIDI.
- When a note that is not on the required channel or is out of the C2-C7 range is received, it is ignored.
- Anything received over USB is automatically sent to the serial OUT and anything received over serial is automatically sent to the USB OUT.
- NoteOff is only processed if received for the currently playing note.
- Consecutive NoteOn messages update the CV and replace the previously playing note.
- There is an option for a GATE type operation:
- GATE goes HIGH on NoteOn.
- GATE goes LOW on NoteOff.
- Or for a TRIGGER pulse type operation:
- GATE goes HIGH on NoteOn.
- GATE remains HIGH for a defined time (e.g. 10mS) then automatically goes off.
- On reception of NoteOff there are several possible options for what to do with the CV:
- Leave it and do nothing. This allows any envelopes to complete on removal of the GATE signal with no change of CV. But the CV will remain at the last level until a new note is received.
- Set it to the NoteOff pitch received. Although in reality this is probably going to be the same as “do nothing”.
- Set the CV to 0. This means there is no “dangling” CV voltage, but the synth will probably respond to the changing CV.
- I’ve left in a compile-time PWMTEST mode that just plays the different Cs for measuring voltages, and so on.
Closing Thoughts
This actually seems to work surprisingly well. I did wonder if the apparent inaccuracies of the output might cause an issue, but it doesn’t seem to.
The PWM filter issue was annoying, but on the one hand, it was a lot easier to build and debug with a PCB in hand; but of course on the other hand, if I’d done it first on solderless breadboard, the problem would have almost certainly be spotted and the design would probably have been right.
This has only looked at a pitch CV. It would be interesting at some point to do some kind of MIDI CC to CV control device.
Kevin
#arduinoProMini #cv #define #korg #midi #midi2cv #usbMidi #volca