There is no more beautiful electronic instrument than the iconic Vox Continental organ. I had one in the late 70s/early 80s. However, they are all now over 50 years old. Their electrolytics are shot, their germanium transistors are on the blink and pretty much everything else is unreliable. As a lockdown project, I wanted to create a modern playable, maintainable Vox Continental retaining the original appearance but using Midi and a VST instrument - the excellent ComboV free plugin from Martinic.
Rather than hack up an existing Continental I started from a set of bits - the case and lid from a Vox Jaguar, outer lid and legs from a Continental, keyboard from a dual-manual continental. I found all these parts on online auctions and specialist groups, built and covered the organ itself (that's a whole other story) and developed the electronics and programs. It works - I've played it to crowds - and it looks the biz. Plus, I have included some extras to make it a playable synth using Eurorack.
2. Basic ConceptIt is possible to multiplex or matrix keyboard inputs but for this 49-key board I realised I could simply use an Arduino – either an Mega or Mega ADK (which have 54 digital input pins and 16 analogue pins), or a Due (which has 54 digital input pins and 12 analogue pins). The Due is a higher powered machine, but it runs at 3.3V which adds a bit of complexity.
To generate audio live, I could have run the generated Midi into an external hardware module or PC, but I wanted to use an embedded PC running "headless". The Lattepanda is a tiny quad-core Windows 10 SBC, with a built-in Arduino Leonardo (not essential for this project). There is a version of the BIOS which allows it to boot immediately on 5V power supply. If optimised for audio the Lattepanda is capable of playing a VST instrument. Brad Robinson's book Glitch-Free explains in detail how to tune Windows for live audio performance. I have set it up to run Brad Robinson's Cantabile VST host program on startup. There is a free version, but for this project I need the Solo (paid) version because I use "bindings" to shut down Cantabile and Windows cleanly on the Lattepanda.
The Arduino program has to do three basic things:
1 – Sense the state of the 49 keys and transmit MIDI Note On and Note Off messages;
2 – Sense the state of the vibrato switch and transmit MIDI Control Change messages; and
3 – Read the 6 drawbars and transmit MIDI Control Change messages.
These functions are well documented and basically easy enough to implement, particularly since the device only needs to transmit MIDI not receive it.
I also used the extra power of the Due to:
4 - Generate square wave and gate outputs for use in analogue synthesis (You could additionally or alternately use an ADC output to generate a control voltage (CV) instead of the square wave).
The Due program uploaded here is the one I'm running, but I have run both uploaded Mega programs on a clone Mega, and they ought to work too.
4. Live Music Issues 1 - LatencySome special issues arise when playing live music.
Firstly, the latency (i.e. delay between pressing a key and hearing the sound play) needs to be short. Of course, delays always exist in the real world – every metre of air adds 3mS – but those which affect all instruments together (via the PA for example) are less disturbing than those which put different instruments out of time with each other.
Ideally, the latency should be less than 10mS, and if it is over 20mS it definitely is likely to be quite noticeable. Unfortunately, using Windows for audio can often result in long latency, as discussed below, so it is important to add as little as possible within the keyboard.
Sending serial MIDI itself incurs some delay. Each note message (and each control change message) uses 3 bytes plus start and stop bits – 30 bits total – and at 31, 250 bits per second serial transmission that takes up about 1ms; a ten note chord is therefore going to take about 10mS just to send.
USB is potentially faster, but the delay depends on how Windows handles incoming MIDI which is unpredictable and uncontrollable. Avoiding delay while reading notes and sending MIDI is therefore important.
Several excellent Arduino code libraries exist for handling MIDI via serial and USB ports (though if all you're doing is sending MIDI via serial it is in fact so simple that a library is overkill). USB is available on the Due using the “Native USB Port”. It can also be implemented on a genuine Arduino Mega by reprogramming the serial communications chip with HIDUINO or equivalents. This isn't possible on cheap Mega clone boards, but they can be used to transmit MIDI over USB, in conjunction with the Hairless MIDI and LoopMIDI programs running on the host computer – these can run at up to 115,200 baud, which is faster than conventional serial MIDI.
5. Live Music Issues 2 - message overloadAnother problem is that simplistically generating MIDI can result in a flood of messages. Unfortunately, switches (including keyboards) “bounce” after being switched ON or OFF, and this can generate multiple on/off messages during the following 20mS or so. Analogue potentiometers such as drawbars “jitter” – there is often electrical noise, particularly when playing live – resulting in sending erroneous messages even when nothing is being done by the player. The flood of messages can tie up the computer unnecessarily and run the risk of losing a message – if this is a Note Off message, the result is a hanging note, which can be very disturbing.
To deal with these issues, I adopted the following principles:
1. Keys need to be read and acted on ASAP. Bounce only happens after an initial transition, so only the first detected transition should be acted on. After this, real keyboard players cannot physically press the key ON again in less than about 80ms. So locking out any further transitions for, say, 20mS after the initial transition ought to eliminate bounce safely, without causing the kind of delay sometimes resulting from conventional debounce software routines.
2. All other controls are MUCH less latency-sensitive. Delays of 100mS or so are likely to be acceptable for drawbars or switches (probably a little less for a volume pedal, but still less than for a note press). So these should not be allowed to take priority over reading keys.
3. Drawbar changes are typically few and far between, typically in between songs.
4. Drawbars and other controls (except pedals) can only be operated when one hand is not playing notes. So, if more than 5 notes are held down there is no need to read drawbars or other manual controls.
5. On the Arduino Mega (and many other devices which use charging a capacitor to perform analogue reads) analogue potentiometer reads are MUCH slower than digital reads – reading multiple pots takes closer to milliseconds than microseconds. There are ways to speed this up, but at a cost in programming complexity and, sometimes, accuracy. So in each reading cycle it’s best to read only ONE of the potentiometers, and do the next one next time round. (This isn’t necessary on the Due, which is much faster, but I left the code in anyway).
6. Traditional drawbars as used in the Vox Continental are a ladder of resistors, having 10 stops. Thus, the resolution is pretty coarse. You can represent 10 stops in 4 bits, whereas analogue to digital convertors on the Arduino processors default to at least 10 bit readings. There is no point in sending updated readings where the change is less than about 10% of the range. Although this is not strictly true of the swell pedal, this too is a blunt instrument – playing live, I think you can get away with only updating where changes are more than about 5% of the range.
I attempted to use these principles in the code to minimise latency for note messages, and the total number of messages sent. One other thing. My program detects when all keys have been switched off, and sends in response an "All Notes Off" Midi command on all channels. That makes sure there are no hanging notes.
6. Polyphonic Midi OutputMy main program loop allocates a digital input pin to each note. A state-reading input loop checks each digital input pin in turn and stores the state in an array. That way, the state of all pins is captured at the same instant. A note reading loop then compares these states with the previous readings on the same pin. If the state of a pin changed within the last 20mS any further changes are ignored. Where there are changes in note state the note state array is updated, and a flag is set for that note to indicate a change in state. Counts are kept of the number of notes ON and the number of note state changes.
These arrays are then read to generate NOTE ON and NOTE OFF messages for those that have changed state.
Having generated the messages they are sent either:
1. Via the native USB port of a Due, and
2. Via the serial port and a Midi breakout board;
3. Or if using a cheap Mega clone, as serial over USB – this can run at up to 115,000 baud, but requires a serial-to-MIDI arrangement (such as Hairless MIDI and LoopMIDI) at the other end.
7. Monophonic Midi OutputMono synths are either low-note priority or high-note priority. I implemented functions to determine both the lowest and highest notes being played, and send MIDI note messages on different channels, so that you can run a mono synth (high-note or low-note priority) in parallel.
Arduinos have programmable timers, which makes it easy to create a square wave DC output without using much CPU time. The Mega (and most other Arduinos) have a built-in tone() function which starts a square wave on a specified pin at a specified frequency, and a noTone() function to turn it off again. By coupling this through a DC-blocking capacitor you can generate square wave mono AC audio with an amplitude of +/-2.5V for the Mega and +/-1.65V for the Due (I used 1uF polyester cap which retained a nice square shape, but a smaller capacitance would probably be OK).
On its own this just makes a continual buzzing sound, but I generate a gate signal on another pin, which is HIGH whenever a note is being played. Running the gate into an ADSR or other function allows you to play with the envelope of the square wave. Gate signals work in different ways. A gate signal stays on whilst a note is played, whereas a trigger signal sends a short pulse when a note is first pressed. Some synths re-trigger – that is, send a new gate every time a new note is played. It would be fairly easy to program any of these behaviours. Gates are usually at 5V, which is easy for a Mega – the Due only generates 3.3V but I used a level convertor PCB to change that to +5V. I put an LED across the gate line, to give visual feedback that the Arduino is working properly by lighting up whilst a note is being played.
8. Problems Using Arduino DueGenerally, I found that the Due could simply be swapped with the Mega. The 3.3V gate and square wave signals seem to work fine (and could easily be amplified in the Eurorack environment anyway). The MIDI DIN interface board I used has a link which can be soldered over to swap into 3.3V mode. Everything else doesn’t care about the voltage, and the current draws don’t seem to be a problem.
Unfortunately, the Due is a less popular board, and therefore less well supported. There were three specific issues that caused me difficulties.
Firstly, the standard Arduino MIDIUSB library does not always work reliably with the Due – a known but unfixed issue. (There are alternative libraries but I didn’t try them). In my program, multiple messages per cycle are generated because of the Mono() function switching one on and one off every time there is a note change, and the SwitchAllNotesOff() function sending three CCs. I found that some messages were skipped, where they were sent back-to-back in the same cycle.
This could be cured by adding a delay between sending messages. Anything above 20uS provides some improvement, but longer delays are better. I found that a 50uS delay between messages worked pretty well.
However, a cleaner solution is to decouple generating and sending MIDI messages. I have not timed my main program loop but the Due operates at over 25 MIPS, so the loop runs pretty quick when no notes are pressed and no analog readings are taken. Humans work much slower than computers, so in most program cycles no notes are pressed and no controls are operated. These empty cycles can be used to send MIDI messages.
To decouple the message sending I created queues – you could do it with one, but using 3 allowed me to allocate different priorities to different messages. The sending function checks whether 50uS have elapsed since the last message was sent, and if so, sends any queued MIDI notes on the polyphonic MIDI channel, before sending queued notes on the mono channels, and (with lowest priority) control change messages. That way, stray control channel messages cannot create latency on note messages. This seems to work without issues.
Secondly, the Arduino IDE for the Due does not have tone() and noTone() functions like those for the Mega, but using some excellent information from the Internet and a bit of head-scratching I managed to program equivalents to these – rather better, in fact, since they can provide variable pulse duty cycles.
The third issue is the most annoying because it is the least expected and hence the hardest to detect. Unlike most Arduinos, some versions of the Due do not automatically start running your program when switched on – they have to be reset every time. This problem is not confined to cheap clones – some genuine Arduino Dues are affected too.
Solutions on the web included adding a capacitor and/or resistor, or re-flashing the firmware for the Atmel ATmega16U2 UART processor, but these are both too fiddly for me. I wondered about doing a software reset on startup, but since the program restarts at the beginning you might get stuck in an endless loop of resets that way. Behaviour on startup is a tricky problem – it’s possible to brick the board if you get it wrong.
So rather than waste time I wasted money instead - I bought a clone (£16) that advertised that it had solved the problem by using a cheaper CH340G UART. That worked fine straight out of the package (I already had the UART driver installed on the PC I used for programming). It is worth checking for this problem before spending too much money on a Due, however!
Briefly, here's what I did to set up the Lattepanda to run headless:
1. Configure Windows 10 for audio (see Glitch-Free) including:
- Setting power mode to “performance”;
- Preventing Windows from powering down the USBhubs;
- Giving priority to background tasks;
- Disabling all network adaptors, Bluetooth etc.
2. Remove the password requirement (usingPowershell).
3. Set the computer BIOS to boot automatically when powered up (described in the Lattepanda online documentation).
4. Connect and install USB audio interface if using one (I used a Digidesign MBox2 Micro).
5. Download VST plugins of choice – I use the free Martinic ComboV (widely available online) for the Vox sounds.
6. Install Cantabile (or other VST host of choice) plus jBridge if you want to use 32-bit plugins in a 64-bit VST host.
7. Configure Windows to run Cantabile (or VST host of choice) on startup.
8. Configure Cantabile to route the incoming MIDI notes and controls to the plugins.
9. Write a batch file which will close Cantabile, and then shut down Windows and power down the computer.
10. Configure a Cantabile binding to call the batch file on receipt of a particular MIDI message.
One thing to note is that the Lattepanda's Intel Cherry Trail CPU is inclined to throttle itself back if it gets hot, and it can get hot quite easily especially if you put it in a casing to protect it. I installed a little heatsink with fan (DFRobot FIT0504) on the metal shield covering the CPU, and that cooled it right down and had the CPUs running at full speed.
A Vox Continental, like many other combo organs, has a bussed keyboard design. Each key has a switch contact (several actually but that doesn't matter) which normally rest against a copper bus bar. Each key is connected to a tone generator. There are separate tone generators for each note, which are always running. When no notes are played the outputs of all tone generators therefore run to the earth bus bar. When a key is pressed, the contact leaves the earth bus bar and contacts the output bus bar. The generated tones for the notes played are taken off the output bus bar.
To connect these up digitally, I connected the output bus bar to +3.3V from the Arduino and the earth bus bar to the Arduino Ground. I connected each key to a digital input pin of the Arduino and sensed the output from each key. Simple.
The only tricky bit is getting a good, reliable connection but one which allows disassembly for maintenance. After trying unsuccessfully with soldered and screwed connections I bought a crimp connector and connected all the wires to Dupont pin blocks, which I connected in turn to a Mega connection shield. That way the connections are firm and vibration-proof, but the Arduino board can easily be uncoupled and replaced. I mounted them using long bolts running upwards from a metal mounting plate, up through the Due and the shield so that I could bolt the two together to the mounting plate which in turn is screwed to the organ body. It's important to use rubber nuts (or insulating washers) in contact with the shield - a metal nut will short out some connections (a very hard bug to detect).
It is really easy to connect the wrong wires to the wrong pins, so I indirected the the array of pins in the Arduino program to allow me to change the sequence after everything was wired up.
I mounted the Midi breakout board to the top of the shield - it fits neatly onto two of the bolts through the Arduino mounting holes.
Vox and other early organs had drawbars consisting of a slider running along a ladder of resistors.
I didn't have an original Vox drawbar set, but I was lucky enough to find drawbars from a later Vox 300 organ in an auction, which look the same but are in fact normal linear potentiometers - easier to connect up. If you can't find Vox ones, drawbars from later Hammonds are similar. Spares can still be bought. Kit organs like Wersi are also possibilities, with a bit of hacking up (there are usually a few on eBay).
The original drawbars work just like a quantised potentiometer, and you can wire them the same way. Originally the audio signals flowed through the drawbar circuits. Again, we are reversing that so we put +3.3V over each and sense the signal coming off the drawbar slider.
So basically, each drawbar slider wiper contact is connected to an analog input pin of the Due, and the two sides of each drawbar pot are commonly connected to bars running to the +3.3V and GND lines.
The problem, I found, is noise. I adopted software solutions, but as a belt-and-braces I added a 1uF polyester capacitor across the +3.3V and GND bars, and a 100pF cap between each wiper contact and the GND bar. It would have been better to do it at the Arduino end but I didn't have the space there. With the caps and software filtering it worked nice and smoothly.
There was still plenty of space inside the organ so just for fun, I plugged in a Eurorack frame and a couple of modules, specifically a Patchblocks Eurorack programmable module, an ADSR, a filter and a ring modulator. I fed the capacitor-decoupled square wave and gate lines from the Due to sockets on a panel I made up.
I got a NOS Protek PUP55-31-Q11 external PSU from eBay (there seem to be plenty there). That generates +/12V and +5V which are suitable for the Arduino, Eurorack and Lattepanda. The Lattepanda needs at least 3A, and this PSU generates 5A.
14. Inputs and OutputsThe Vox Continental has a pretty small rear panel for mains input and audio output sockets. I made up a replacement with a panel-mount USB type-B socket wired to a micro-USB plug suitable to couple to the Arduino. To save space I used a right-angle plug. A one-meter micro-USB to Type A USB cable allowed connection to the Lattepanda. I also added a 5-pin DIN socket for serial MIDI out from the MIDI breakout board, and a jack socket wired to a minijack plug for connection to the audio interface (or directly to the Lattepanda headphone socket, or the Eurorack output).
15. Control PanelThe Vox control panel features an ON switch, a VIBRATO switch and a power neon indicator. Exact replicas are now unobtainable, but I managed to knock up something similar. I ran the +5V through a rocker switch with an LED-driven panel indicator to emulate the Vox Continental control panel. I connected the vibrato switch across GND and +3.3V from the Arduino, and the wiper into a digital input pin.
Comments
Please log in or sign up to comment.