For my final I decided to do a few different things. I really wanted to combine what I’ve learned with both digital and analog, so I set about building a Voltage Controlled Oscillator (VCO) and a sequencer to control said VCO. Because this is a class on digital electronics, I’m going to brush a bit over some of the analog side, but it’s still important to cover.

VCO

For my VCO, I went with the classic LM13700 OTA because it can be built into a rather versatile square/triangle oscillator nearly out of the box. It only requires a few common components.

The main thing I changed here was the capacitor. I used one rated 10nF. The only thing I really needed after this on the analog side was a simple current source to make the control voltage control the VCO properly. This is just because while this schematic is referred to as a VCO, it actually responds to current due to the propertied of OTAs. Anyway, that’s enough analog for today.

The Sequencer and CV Generator

The issue with only having a VCO is having nothing to give it a voltage. Fortunately, the Teensy that we have been using in class is perfect for this job. It includes two DACs, which allow me to send a decent range of voltages to the VCO. All I had to do was use the analogWrite() function with the right pin number and a value between 0 and 255. To get a usable range of numbers that would correlate to usable notes on the VCO, I just had to find two values an octave apart and then space eleven values relatively evenly between those two values (one of those values would be the root note of the chromatic scale, so it would add up to twelve tones and a doubled octave of the root). I didn’t bother for the sake of this project to tune these values to any standard note tuning because it would add complexity outside the scope of this class.

Once I had all thirteen values, I could simply put them in an array. This allows scale degrees to be used by the rest of the program instead of having to have multiple places where the same values are defined. This has the added benefit of making retuning the whole system rather easy.

Once I had the tuning taken care of, I decided to make a more capable sequencer than we had built in class. I upgraded the monophonic step sequencer to have a more practical eight steps. This allowed the little synthesizer to have much more melodic variety, and the combination of this with the direction switch allows for a whole lot of melody writing for such a simple instrument.

Demo

Honestly a really versatile little instrument.

Code

int inputPins[9] = { A16, A17, A18, A19, A20, A21, A12, A13, 33 };

int delayLength = 200;
int noteSet[13] = { 100, 108, 116, 124, 132, 140, 149, 158, 166, 174, 182, 191, 200 };
int notes[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
int LEDPins[8] = { 3, 4, 5, 6, 7, 8, 9, 10 };

int CVPin = A22;

int currentStep = 0;
unsigned long lastStepTime;

void setup() {

  Serial.begin(9600);
  
  for (int i = 0; i<sizeof(inputPins);i++) {

    pinMode(inputPins[i], INPUT);
    
  }

  for (int i = 0; i<sizeof(LEDPins);i++) {

    pinMode(LEDPins[i], OUTPUT);
    
  }

}

void loop() {

  for (int i = 0; i < 8; i++) {

    notes[i] = map(analogRead(inputPins[i]), 0, 1023, 0, 12); //Allows values between 0 and 12
    
  }

  stepSequence();
  
}

void stepSequence() {

  if (millis() > lastStepTime + delayLength) {

    lastStepTime = millis();
    
    digitalWrite(LEDPins[currentStep], LOW);

    if (digitalRead(33) == HIGH) {
      currentStep++;
      if (currentStep >= 8) {
        currentStep = 0;
      }
    } else {

      currentStep--;
      if (currentStep < 0) {
        currentStep = 7;
      }
      
    }
    

    digitalWrite(LEDPins[currentStep], HIGH);

    analogWrite(CVPin, noteSet[notes[currentStep]]);
    
  }

}



0 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.