Doué Pt. 3: Monitoring Frequency

OLYMPUS DIGITAL CAMERA

This is Pt.3 of my serie about modding a Monotron Duo to add Midi and other features.

PLS1 & Interrupts

As we’ve seen in our previous episode, the monotron duo has a few pad points revealing the different stages of the vco core. We saw that one of them -PLS1- is running at twice the frequency of the output oscillator SQR1 and looks like a short pulse from 0->5V. The pulse with is not modulatable.

Capture d'écran 2014-11-15 12.08.23We could think about using it as an oscillator but it’s going to be quite busy/high-passy and most likely not very interesting.

However, we can combine it with an interesting feature of our Teensy: it can trigger interrupts on digital input pins. This means that if a digital input pins changes from ‘high’ to ‘low’ (or vice-versa), we can trigger some code to be executed. By feeding PLS1 to a digital input pin, the pin will be set to ‘low’ then ‘high’ repetitively and – very interestingly- sync’d on the VCO core of oscillator 1. If we succeed in measuring the interval of time between these spikes, we end up with a measure of the oscillator’s period – and therefore frequency.

Because tuning is always tricky to achieve properly, we could benefit of some degree of feedback and evaluate the difference between the frequency we’re expecting to have for a given note and the one actually produced by the monotron.

Midi Note > Expected Frequency > PitchCV > PLS1 > Real Frequency

Making it for real

Let’s see what are the step required to make it work.

The first thing is that you can’t directly wire the PLS1 pad to the teensy’s input pin because it’s going to alter the voltage inside the VCO core and make everything go wrong. So we need to isolate the two using a buffer. This is a simple operation for an opamp and we’ll use again a TLV2472 since it can operate in the 0->5v range rail to rail. The configuration is a standard inverting voltage follower:

opamp6

I’ve used 56K resistors for R. And rather than connecting the non-inverting input to the ground, it is connected it to VBias – i.e. 2.5v – so that the signal is inverted across the middle of its range. The output of the buffer now looks like this:

Capture d'écran 2014-11-15 12.08.01

And we can safely connect it to the teensy’s pin without introducing any perturbations inside the monotron.

In the teensy. We need now to generate an interrupt each time the pulse rises.

 static const uint8_t PLS1_FEEDBACK_PIN = 23;
 pinMode(PLS1_FEEDBACK_PIN, INPUT);
 attachInterrupt(PLS1_FEEDBACK_PIN, onPls1Raised, RISING);

This turns the pin 23 to be an input pin and then wires the onPls1Raised() method to be called everytime the pin goes from low state to high state.

Next, we need to evaluate the time between two succeeding pulse. The teensy library provides a micros() method returning the number of microseconds elapsed. This is an integer and you have to take care that it can wrap around after a certain times. I’ve come up with this:

static unsigned int lastMicros;
void SInitIntervalEvaluator()
{
  lastMicros = micros();

}
unsigned int SIntervalInMicroSecs()
{
unsigned int micro = micros();

  unsigned int mDelta = micro - lastMicros;

  if (lastMicros > micro)

{

    mDelta = 429497296 - lastMicros + micro;

  }

  lastMicros = micro;

  return mDelta;

}

You call SInitIntervalEvaluator() at startup and everytime you call SIntervalInMicroSecs() you get the number of micro seconds elapsed since the last call.

Now we can use this value in our interrupt and get the number of microseconds elapsed since the last pulse and compute the resulting pulse frequency (remember this pulse goes twice faster than the actual VCO output wave)

void onPls1Raised()
{
  cli();
  usigned int microsecs = SIntervalInMicroSecs();
  float frequency = 500000.f /microsecs;
  sei();
}

Since it might change a tad from pulse to pulse, it is probably a good idea to average the results. Just remember you should not do too much code in an interrupt since it might prevent other tasks (like audio, envelopes, midi) to be done in timely manner. Here’s the sketch running, compared to measurement done from the audio output:

OLYMPUS DIGITAL CAMERA

If you fancy digging deeper, you can find all the code related to this part on github: E02_FrequencyFeedback.

Next time, we’ll use the frequency measurement to implement auto-tuning of the midi input. See ya.

Leave a Reply

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