MIDI control for the Monotron using a Teensy 3.0

IMG_0002

IMG_0002

Edit: This is just the first part of my monotron mod. For more information and links about what it’s all about, you can jump here.. otherwise, continue in this meaty post.

This is a description of how you can easily add MIDI to a Korg Monotron using a Teensy 3.0.

The objective here is twofold: First to provide an easy way to control the Monotron’s pitch and filter cut-off via MIDI, then provide an easy open-source extension framework to the Monotron’s capabilities using the Teensy as main MCU.

Since I’m relatively new to this topic, I’ll also try to add extensive information on the process so that it can hopefully help people in the same situation.

I’m extremely grateful to the people that directly – or indirectly – helped me to achieve this through thorough documentation of their projects or by answering my noobish question. Olivier Gillet (Mutable Instrument), Paul Maddox (Vaco Loco) and Tony Hardie-Bick and Collin Cunningham – A huge thanks to all of you.

If you know Teensy/Arduino and basic electronics, you should directly grab the schematics and the teensy code over here.

Introduction

Surprisingly, although the schematics for the monotron have been out for a long time, most of the monotron ‘hacks’ I could find are pretty limited. Either they are intended to CV control which – not having any modular – didn’t appeal to me much or provide a simple, direct midi control of pitch. On top of that, all MIDI kits are closed source so people can’t start building on the existing expertise.

After trying to dissect the ways the shruti-1 worked, it seemed obvious that when driven from an MCU, controlling an analog oscillator/filter could go a lot further than a simple one to one MIDI mapping and I decided to explore the possibilities this cheap unit could deliver.

Out of the box

The first thing to do is to allow some connection to the soldering points Korg gently left for us to use as external control.  The easiest way to do that is to solder a series of cable to some kind of breakout box that will allow us to plug or unplug the controlling MCU at will.

This is an extremely well documented video from Collin Cunningham explaining how to do this, so I won’t re-explain it all. After doing this, you will have four wires coming out of the monotron, allowing you to connect an external circuit to pitch control, cut-off control, gate and ground. Even better, this is completely non-destructive – the monotron will continue to work exactly like before.

Choosing the MCU

When selecting the unit that will drive the monotron, I wanted to have something as simple as possible. There are tons of them out there but I wanted something that I could program easily and bootstrap quickly in order to concentrate on the task itself. The arduino could have been a choice but the Teensy 3.0 looked even more appealing. Extremely small form factor, cheap, runs up to 96Mhz and, most importantly, has a build in usb class compliant MIDI mode that provides direct MIDI compatibility without having to do any work.

Generating signals

To control the monotron, we need to generate 3 different signals: one for the Gate (that lets the oscillator signal feed the filter), one for the pitch of the oscillator, and one for the filter cut-off frequency. All those signal are within the range of 0v-5v which is precisely the type of voltage the teensy can deal with.

The gate is the easiest one. It expects 5v to open the gate and 0v to close it, which is exactly what the Teensy’s digital pin will do.

For the pitch and filter cut-off signals, we need to generate a DC signal that varies somewhere between 0v and 5v – depending on how high we want the pitch/filter frequency to be. To do so, we have two alternative: either use the onboard PWM of the teensy (see here for a description on how PWM works) or use an additional DAC. The onboard PWM is an easy option, but it is restricted to a range of 255 values. This is somehow fine for the filter cut-off but won’t be very precise for pitch tracking. One can then decide to either use a reduced octave range and use PWM or use a higher precision DAC.

Not knowing upfront how much tweaking would be needed to ensure correct pitch tracking, I decided to use a 12-bit DAC. More so, since I was going to have a DAC, I decided to use  a mcp4822 that provides 2 seprate 12-bit dac in one chip. That way I can use the second channel to generate digital audio from the Teensy itself and add extra digital oscillators to the monotron using the same setup.

Making the connections

1. The Gate:

As we saw already, connecting the gate a as simple as connecting one digital pin of the teensy to the gate input in our monotron breakout-box. In our case, we’ll choose the teensy’s pin 5 to control.

Monotron Gate Control

2. The Filter cut-off

Since we decided to control the cut-off using PWM, we need to take care of the fact that we will generate a high frequency variable pulse signal that we want to somehow ‘average’ to a constant DC value using a low-pass filter.

It is usual to use a fairly high carrier frequency for the PWM (in this case I’m using 31250 Hz on the teensy’s Pin 3) and apply changes to it at a much lower frequency (we’ll use 800Hz) so that the high frequencies of the carrier can be attenuated enough through a simple passive RC filter. Looking at the schematics, this is achieved by the R3 and C1, which give us a low pass with a cut-off frequency of about 723Hz.

Also, the monotron doesn’t use the full 0v-5v range for CV control of the cut-off but a lower range. Since the Teensy can only generate either 0v or 5v, we’ll need to lower that voltage using a voltage divider. This is achieved by R1/R2 which will divide by a factor of two the voltage generated by the Teensy.

Finally, we’ll need somehow to accomodate the monotron’s expectation in terms of impedance. Looking at its schematics, the voltage we’ll apply is taking an equivalent path as the LFO cut-off control and since that one is regulated through mR44 (I’m using the m prefix here because I’m referring to the monotron’s schematics), we’ll mimic this behavior and add a 10K (R4) resistor too.

monotron_cutoff

Pitch

Since we decided to control the Pitch using a DAC, we won’t have PWM components in it but we still might have some high frequency noise liked to the DAC’s operating frequency (44.1Khz). To be sure we have a clean signal, we will filter the DAC’s output pretty much the same way as the filter cut-off,provide a stable output voltage using R5/C2. Since the pitch is also fed to the monotron the same way as the internal LFO is and we’ll need to provide a resistor equivalent to mR4, which in our case is R6.

Pitch control

Rough Control

At this point, we have pretty much all of our schematics ready. All we need is to add the SPI connection between the teensy and the mcp4822 (so we can control it) and add the various ground and 5V connection.

schematics_1024

 

Calibrating

We can now start programming the Teensy to send values to the monotron’s pitch and cut-off. However, unless you are extremely lucky, it is most likely going to be out of tune since you don’t know what value you need to set the DAC to in order to have  the monotron to produce semi-tones. We end up with something that reacts to not but isn’t properly tuned like this:

So we need a way to calibrate our DAC output.

The easiest way I found was to use Live 9 and comparing the monotron’s output with an instance of Operator using 4 sine one octave apart each, playing a single constant C note. This would lead to a nice identifiable spectrum location

Operator Spectrum

Since I can use MIDI to control the monotron, I generated C notes octave apart and used the pitch bend to calibrate the note frequencies until the spectrums matched nicely

Screen shot 2013-03-21 at 09.39.04

This method has the double advantage of providing a direct ‘rough’ visual cue of where the peaks are located but also generate beats between the monotron’s oscillator and Operator’s when the frequency gets closer providing a more precise cue as how close the frequencies are.

After calibrating the DAC’s output that way, we end up with a nice tuned range across 4 octaves (C0-C4)

The good news is that the voltage control needed by the monotron is nicely linear and there’s no real need to start correcting the pitch inside the teensy. Note also that since the pitch and cut-off knob of the monotron are still active, the result is going to be dependent of those. I end up setting the VCO pitch pot somewhere around 9 o’clock and the cut-off at 12 o’clock.

In the end, we have a nicely controllable unit that is completely sequencable from within any MIDI sequencer.

Code and schematics

I’ve made an archive containing both the schematics and the teensy code. The teensy code is separated in two different file. One – hardware.ino – containing the code dealing with the hardware setup and Pin/DAC/PWM control. The other – monotron_control.ino – hooks up the midi received by the teensy’s usb port to the hardware control. Hopefully it’s simple enough to be understood but if needed, I might go more in detail in a later post.

You can grab a zip file over at github.

Extension

From here, you got software control over pitch and cut-off. It’s easy to add more code to provide various LFO’s, envelopes or use the first DAC channel to generate additional oscillators fed to the monotron through the aux input….

Enjoy !

48 comments

  1. Hi Marc,

    it doesn’t work:

    i installed arduino 1.0.4 and teensyduino, downloaded your monotron_control files
    connected teensy to my mac. launched arduino and opened monotron_control.ino.

    i get the following error msg on verification:
    monotron_control.ino:2:27: fatal error: IntervalTimer.h: No such file or directory
    compilation terminated.

    what to do?

    please help.

    thanks.

      1. Hi Marc,

        thanks for your quick response 😉

        ok, installed IntervallTimer.h !

        Verification still gives:

        monotron_control.ino: In function ‘void setup()’:
        monotron_control.ino:87:3: error: ‘usbMIDI’ was not declared in this scope
        monotron_control.ino: In function ‘void loop()’:
        monotron_control.ino:98:3: error: ‘usbMIDI’ was not declared in this scope

        My Configuration – in the Tools menu:
        Board: Teensy 3.0 (of course)
        Serial Port: /dev/tty.usbmodem12341
        USB Type: Serial
        CPU Speed: 48 Mhz
        Keyboard Layout: US English

        My Hardware:
        MacBook Pro 13″
        Arduino 1.0.4 with Teensyduino

        Teensy 3.0 blinks periodically (Bootloader)

        ???

          1. Hi marc,

            already tried the MIDI USB Type – gives:

            monotron_control.cpp.o: In function `setup’:
            /Applications/monotron_control.ino:83: undefined reference to `Hardware::SInstance()’
            /Applications/monotron_control.ino:83: undefined reference to `Hardware::Init(Hardware::Configuration const&)’
            collect2: error: ld returned 1 exit status

            Maybe i should put the Hardware folder (including the Hardware.h file) in my Arduino libraries directory ?

  2. in theory if all the files are in the same folder they should be correctly found by the ide. It’s strange, I’ve never seen this. I’m running 1.0.3 but I don’t see what it would be an issue.

    I find the path strange too (/Applications/monotron_control.ino). Normally the arduino environment forces you to set the sketches in a folder with the same name as the main .ino file.

    1. Hi Marc,

      finally i got it working !
      Moving the monotron_control folder from my downloads folder into the documents directory was the solution.

      Thanks for your help and your work !

  3. Hi,
    Just wondering if you think there is a possible way to use regular MIDI rather than USB MIDI? Maybe using MCU inputs to scan a MIDI socket?

      1. I dont have any background in modding this but I want some of the functionality you mention. Is it possible for me to send you my monotron and you do it for me for a fee?

        1. I could think of that. The only specific point right now is that I have no real solution for casing yet.

          So if you are happy with some trashy exposed circuit-bended look like this on this page:

          http://www.marc-nostromo.com/?p=242

          I could try to do you one.

          Note also that this mod currently only works with the original monotron: the delay isn’t interesting – at least not from my experiments because of the relationship between the filter and the delay – and the duo is a complete different beast with respect to controlling pitch.

          Does that fit your needs ?

      2. Hi Marc,

        It’s not clear to me from your scheamics and description: do I need to build Collins breakoutbox with all those resistros and potentiometers, or I can just simple wiring out the CV points from the Monotron’s PCB?

        Thanks,
        G.t.

        1. You don’t need to build the breakout-box, the schematics are made so you can wire directly the connections to the CV points.

  4. Hi Marc,
    sorry to disturb you, i am trying to compile your code for teensy 3.1 and I don’t seem to be able to trigger the

    void onParamUpdate(Hardware::Parameters& parameters)

    Note On and Note Off are properly recognized (i used a pin to have a LED going on or off), but if I use the code to blink a LED from onParamUpdate nothing happens…..

    Do I need to do anything special to compile the Monotron_control.c and the Hardware.c files? I am currently compiling Monotron_control in the arduino IDE.

    Thank you in advance,
    Alessandro

  5. Marc,
    I found out what was my problem.

    I needed to define IntervalTimer(s) globally, it does not work if I define them inside the Hardware::Init() .

    Not sure if this is necessary because I am using Teensy 3.1 (Arduino 1.0.5, Teensyduino 1.18-rc1) …
    (Hopefully this will help somebody else)

    Thank you for being such a great inspiration !

    Cheers,
    Alessandro

    1. Cool. Thanks for the information. I haven’t got a teensy 3.1 yet although the extra audio dac and power upgrade looks really tempting.

      Glad you enjoy the starting point. Let me know what you end up with !

  6. Hi Marc,

    First off I wanted to say thanks for this article. It has really inspired me to take the leap, buy a Teensy and start poking around with the Monotron schematic test points. I have to say that I have had no compile errors, but I simply can not get the output pins to even “wiggle” based on the code you put in that zip.

    After looking through your code for a bit, I think I’m going to start my own implementation of your concept from scratch. The difference being that at least for the first prototype I’m going to cheap out and ignore the DAC and do pitch via PWM. This project will still use the same concepts you outlined here, but I figure it will give me an excuse to start my own development process, going through checks for the MIDI note recognition of the teensy to how the math translates the pitch/cutoff into a proper voltage level.

    I’m going to try to outline my development efforts at my own blog (citing your project as a starting point of course), kind of making a “lab notebook” series of posts as I work on it. Maybe at some point I’ll go back and see if there is any clear reason that your code didn’t work for me, and I hope at the end of my efforts we can compare notes.

    Thanks again for the inspiration,

    Jake

    1. fantastic. The main advantage of the dac vs PWM is resolution. You will probably end up with something that is not enough precise to get correct pitches. But hack away and have fun, that’s the point ! Share a link here of your blog so people can also dive there if needed.

  7. I’m a bit confused. I thought the teensy 3 is a 3.3 volt system, not a 5 volt system. You can’t get 5 volts out from the PWM pins, can you?

      1. True. Measuring is always the best. The reason I ask is I want to drive a Moog Minitaur through CV, and it takes 0-5.

        Did some more searching. Output of Teensy’s 3.1 DAC is 0-3.3v, so I guess I need to pull up that range with an op amp or something to get 0-5v?

        The Teensy pulls down the 5v you are feeding it to 3.3v to prevent all the magic blue smoke from leaving the device.

        http://goo.gl/bkCff5

        On the other hand, you CAN run the Teensy 2.0 at 5v. I’m tempted to alternate the output of the PWM (maybe with a lowpass filter to smooth it out?) between values to try to get accurate notes. No idea how well that would work out.

  8. Hi,

    I’ve followed this great tutorial with a teensy 3.1 and a DAC mcp4822.
    There is no problem with the code, I think, as I haven’t got no error messages, but there is no sound at all…

    In ableton, I ‘ve set the “midi to” to teensy midi / channel 1
    My construction of the schematic seems to be good too…

    Could someone help me please, I’m a newbie and I’m really confused.

    Teensy 3.1 / arduino 1.0.5-r2 / teensy loader 1.18

    1. To debug this, the easiest is to strip most of the code slowly until it works.
      First write a constant value to the mcp4822 and see if you receive the expected voltage on the pin. Try a few values that way.

      Then try to recieve a MIDI message in the teensy.

      Then hook both of them together. Etc..
      Good luck !

    2. I think I had the same issue at first, and found out that I needed to define IntervalTimer(s) globally, so you need to make a few changes to Marc’s code.
      Something may have changed between teensy 3.0 and 3.1.

      1. Hi Allessandro & Marc

        I’m a complete newbie to this too, and I think I must be having the same problem. Can I ask what exactly you mean by needing to define Interval Timer(s) globally? I know your (Alessandro) project was for the Duo, but what changes would I have to make to Marc’s code to get it running for a regular Monotron on teensy 3.1?

        Many thanks!

        1. Hi Frank,

          I don’t have a teensy 3.1 yet but I assumed the correction from Allessandro’s mail. To make things easier, I’ve decided to host the code with modifications on GitHub.

          So try the version of the code hosted at

          https://github.com/Mdashdotdashn/nostromotron

          Allessandro, if you are passing by, can you check the modifications are correct from what you’ve done ?

    1. I don’t think you will be able to drive the teensy from the monotron’s battery pack. In the final board (see this picture) I’m using the usb port of the teensy to both power the teensy and the monotron.

  9. Hi Marc,

    First of all, thanks for making this tutorial and making it so easily understandable to guys like me.

    I’ve got basic electronics knowledge and no experience modding synths/wtv.

    Anyway, could you help me on the following?

    I wired up the teensy to the monotron as stated – the only difference being at the time that I do not have the 22.2 K resistors, instead I came up in a way to pull 22.4K out of 5 resistors combined in series/parallel – and after compiling your source and launching live to serve as a midi output to the teensy, the monotron does not respond to it.

    I have fiddled around and checked all the wirings, all looks correct.

    Do you have any idea of what it can be?

    (By the way, I noticed something odd when no headphones are connected to the monotron – the LFO rate reacts to the AUX feed, do you also have any idea of what causes this?)

    Thanks in advance!

    João

    1. When a whole system doesn’t work, the best is to take it into smaller, manageable parts.

      Try measuring the output voltage from the dac and gate to see if you are getting what is expected. If you do, look at the monotron side. Debugging this kind of circuit takes a while but it also makes you gain understanding of what happens.

  10. Marc,
    I completed the MIDI-fy project of my Monotron Duo, and wanted to thank you again for your inspiration.
    As you may remember, I was using the TeensyDuino rev. 3.1
    I was hoping to do everything with just its internal DAC, but I had to add another DAC because the range of Vrib covers only a bit more than an octave. So I used the other DAC to control the pitch over about 4 octaves total. (I used a MCP 4922, so I still have one DAC available, I may use it for an envelope generator …).
    In my implementation, I used 2 digital potentiometers (AD8402) to control frequency and resonance of the low-pass filter: I am very happy with the results.
    I learned that for the Monotron Duo we don’t have to generate the Gate signal: the Gate is generated by the TI onboard processor.
    So basically Vrib covers the 18 half-tones of the ribbon from ~0.1V to 3.3V
    I’d be happy to share with you and with your blogs the schematics and the code (it is derived from yours – it was a great jump-start…..).
    After the breadboarding phase i went ahead and procure 5 boards – so I still have 4 available if anybody is interested.
    Youtube video is here:
    https://www.youtube.com/watch?v=4ZYha-b2i_g&feature=youtu.be

    1. Hey Alessandro.

      That’s greeat news. I meant to try the duo for a while but never got round to do it. There’s actually quite a few people that wanted this but nobody ever posted a schematic for it.

      I’d be really happy to share the schematics over here so people can find the information easily.

      Cheers,
      Marc.

  11. Hello,

    I happen to have a teensy 2.0 lying around, and I was wondering if this setup was possible with the 2.0 instead of the 3.0? Thanks

  12. Hi there,

    I own a Monotron Duo and I would like Just to control the pitch by an external keyboard, not an Ipad so trought a standard midi, is this possible? i don’t really catch the schematics you did to make this thing work

    tks

    kind regrads

    1. Hi,

      Do you mean you would like to control it via midi or directly with some other means. Adding a real midi port is doable but isn’t part of this mod. I’m planning on adding this to the version 2 mod I’m currently doing (which is a duo btw). Follow the blog and hopefully you’ll get it in not too long.

  13. Marc,
    Thank you for sharing this project, I am currently working on converting a Monotron Delay and have had some success using the MidiVox schematics and an Uno board. However, when I came upon your project I realized it was more in line with what I wanted to accomplish (more than just simple MIDI to CV and direct USB MIDI). That being said; I am not very skilled on the programming end of things and I am trying to use an MCP4921 for pitch control to no avail (gate and cutoff are showing on my scope). Obviously the 4921 is a single output DAC and I think this is confusing things for me. Any insight would be appreciated. Thanks again for your work.

    Doug Keener

    1. Hi Doug.
      Sorry I missed your comment. The single dac situation should really be close to the dual one I’m using… except that you need to poke just one output. The easiest it to try to send a square wave to it and see whether it shows on a scope too. Do you have anything I could look at ?

      Good luck !

  14. Marc,
    thanks for the schematic and the tutorial. For info, I have used this setup and code to be able to build a Midi In from DIN and output to CV. It was very straightforward, and so now I have a Midi DIN to CV converter. There are just few small changes to your code to allow the midi signal from serial1 (Rx = pin0) to be read by Midi.read(). The sketch uses the standard Midi library, and the setup looks like this:

    void setup()
    {
    // Initialise hardware
    MIDI.begin(MIDI_CHANNEL_OMNI);
    Hardware::Configuration configuration;

    configuration.audioRate_ = 57600;//44100;
    configuration.paramRate_ = 1000;//800;

    configuration.audioCB_ = onSampleUpdate;
    configuration.paramCB_ = onParamUpdate;

    bool status = Hardware::SInstance().Init(configuration);

    // Initialise midi input callbacks
    MIDI.setHandleNoteOff(SOnNoteOff);
    MIDI.setHandleNoteOn(SOnNoteOn) ;
    MIDI.setHandleControlChange(SOnControlChange) ;
    MIDI.setHandlePitchBend(SOnPitchChange);
    }
    The midi in uses an optoisolator as you would normally use.
    all the best
    m

  15. Hi Marc,

    First off, I would like to say a massive thank you for writing this great guide, it has really instilled a passion for electronics in me.

    I have followed your guide and everything works, however my monotron isn’t producing coherent semitones. To help me troubleshoot, I was wondering whether you could please answer a few questions that I have?

    Do I need to program the DAC via the Arduino code in some way? Or do I need to simply just hook up the circuit as shown in the schematic, load the code, tune the pitch knob on the monotron and then everything should work? Secondly, when I’m attaching the VOutA, AVss and LDAC to the ground, which ground should I use? The Teensy ground, the Monotron ground, both or even neither?

    I tune my monotron to be accurate to C when I trigger it, via pressing a C key on my keyboard, however when I press D I get a note that is a few cents flatter, and then when I send an E note, I get an E note that is even flatter than the D (and so on). On pure gut feeling I feel as though it could be an issue with how I have grounded my circuit, but it could be anything, a few more pointers on how you calibrated your monotron pitch (either via the code, or via calibrating the DAC) would be greatly appreciated.

    Until then, keep the great articles coming and again a massive thank you!

    Jonny

  16. Hi Marc.
    Thanks so much for this tutorial. I’ve been having a problem trying to get it to work. When I try to upload the sketch onto my Teensy I get this error:

    monotron_control.ino: In function ‘void setup()’:
    monotron_control.ino:83:8: warning: unused variable ‘status’ [-Wunused-variable]
    Hardware.ino: In member function ‘void Hardware::SetDACValue(uint8_t, uint16_t, uint8_t)’:
    Hardware.ino:49:33: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
    Hardware.ino: In member function ‘void Hardware::onAudioUpdate()’:
    Hardware.ino:65:17: warning: unused variable ‘MCP4822_HIGH_GAIN’ [-Wunused-variable]
    Hardware.ino: In member function ‘bool Hardware::Init(const Hardware::Configuration&)’:
    Hardware.ino:121:1: warning: no return statement in function returning non-void [-Wreturn-type]

    Sketch uses 18,056 bytes (6%) of program storage space. Maximum is 262,144 bytes.
    Global variables use 4,116 bytes (6%) of dynamic memory, leaving 61,420 bytes for local variables. Maximum is 65,536 bytes.

    My Monotron clicks when I trigger MIDI notes but it does not produce a tone. I have triple checked my wiring and I think that it is somehow related the IDE (I am using 1.6.5 and I see that this was originally created for 1.0.4). I tried to use an earlier version but I could not get the Teensyduino installer to recognize older versions. Any ideas would be greatly appreciated. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *