PCB's and Schematics


Voltage Controlled Oscillator

Test of VCO first Revision

 

 


DIY-VCO by MinartAnalog

So this release is in beta status, working :-) and with non commercial backround. The expo converter and VCO is based on the publication from Robin Mitchell with additional waveformer for Sine, *PWM and *Saw. The PCB is made for the eurorack format.

If you need support or if you see any improvement, please contact me over mail minarterfurt@yahoo.de

 

Thanks

 

*twofold frequency as TRI & Sine

Complete VCO building instruction as download

Download
Minart Analog VCO Rev010 DIY manual .pdf
Adobe Acrobat Dokument 745.1 KB

VCO frontpanel made with toner transfer

Download
Scull VCO Frontplatte official.pdf
Adobe Acrobat Dokument 195.7 KB

PCB's, made with toner transfer

Some years I made my PCB's with UV lamp and etching, but this was every time a nightmare. 

I found an easy process, thanks to youtube ;-), calls "toner transfer method". 

The only tree things you need are a laser printer, heat transfer paper (standard paper also working) and a hot iron. 

Below you will find the full process wich will work very well.

 

1. print out your layout on the toner transfer paper and cut out the copper PCB 

2. Carefully position the PCB with your layout on toner transfer paper.

 

Place kitchen paper under and over all and go over with the iron for about 2min (full temperature).

3. afterwards lie the PCB with the paper in water for about 2min, then you can easy peel off the paper.

Nice ;-)

4. etch with sodium persulfate.

Done, it looks really nice. The toner you can remove with petrol.


DIY Sound Visualizer (Arduino based) by MinartAnalog

Simple nice to have module to visualize your sounds like an oscilloscope. Patch your synth output directly to the input of the sound visualizer and adjust the voltage level with the amplitude potentiometer. 

Schematic Probe

Front Panel

Download
sound visualizer.pdf
Adobe Acrobat Dokument 21.1 KB

Arduino Code

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

 

// Display-Definition

#define SCREEN_WIDTH 128  // OLED Display Breite

#define SCREEN_HEIGHT 64  // OLED Display Höhe

#define OLED_RESET -1     // Reset-Pin (nicht verwendet bei I2C)

#define SSD1306_ADDRESS 0x3C // I2C-Adresse des Displays

 

// Display-Objekt erstellen

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

 

// 'Minart Modular final', 128x64px

const unsigned char image [] PROGMEM = {

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 

            0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x10, 0x88, 0x80, 0x08, 0xc4, 0x13, 

            0x00, 0xff, 0xfc, 0xff, 0xef, 0xfe, 0xff, 0xff, 0xf7, 0xbc, 0xff, 0xf9, 0xbf, 0xff, 0x9f, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 

            0x01, 0xc3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc7, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x01, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x02, 0x00, 0x20, 0x07, 0x00, 

            0x02, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x63, 0xe9, 0x14, 0x40, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0x83, 0x83, 0xfe, 0xfe, 0xc0, 0x00, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00, 

            0x01, 0xc0, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3b, 0x07, 0x00, 

            0x00, 0xc0, 0x3f, 0x04, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x03, 0x07, 0x00, 

            0x00, 0xc0, 0xfd, 0xde, 0x3f, 0x00, 0x03, 0x0e, 0x01, 0xf8, 0x07, 0x08, 0x3f, 0xfe, 0x05, 0x00, 

            0x00, 0xc1, 0x87, 0xff, 0xff, 0x87, 0x0f, 0xff, 0x83, 0xff, 0x1f, 0xbe, 0x7f, 0xf8, 0x07, 0x00, 

            0x00, 0xc1, 0xf3, 0xc7, 0xc7, 0x9f, 0x87, 0xef, 0xc7, 0x3f, 0x87, 0xde, 0x1e, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0xe3, 0xc7, 0xc7, 0x87, 0x87, 0xc3, 0xc0, 0x07, 0x87, 0x80, 0x0e, 0x00, 0x03, 0x00, 

            0x00, 0xc0, 0x03, 0xc7, 0xc7, 0x87, 0x87, 0xc7, 0xc0, 0x07, 0x87, 0xc0, 0x1f, 0x00, 0x07, 0x00, 

            0x01, 0xc0, 0x02, 0xc7, 0xc7, 0x87, 0x87, 0xc3, 0xc1, 0xfd, 0x87, 0xc0, 0x1f, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x03, 0xc7, 0xc7, 0x87, 0x83, 0xc3, 0xc7, 0x87, 0x87, 0x80, 0x1f, 0x00, 0x07, 0x00, 

            0x01, 0xc0, 0x03, 0xc7, 0xc7, 0x87, 0x83, 0xc7, 0xcf, 0x07, 0x87, 0x80, 0x0f, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x03, 0x47, 0xc7, 0x87, 0x87, 0xc3, 0xcf, 0x87, 0x87, 0x80, 0x1e, 0x30, 0x07, 0x00, 

            0x00, 0xc0, 0x07, 0xe7, 0xce, 0xcf, 0xc7, 0xc7, 0xef, 0xff, 0xe7, 0xc0, 0x3f, 0xe0, 0x06, 0x00, 

            0x00, 0x00, 0x03, 0xc3, 0x07, 0x87, 0xc7, 0xc3, 0xc1, 0xe3, 0xc3, 0xc0, 0x0f, 0x80, 0x42, 0x00, 

            0x01, 0x00, 0x00, 0x80, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x01, 0xc0, 0x00, 0x31, 0x8e, 0x01, 0x01, 0x60, 0x00, 0x06, 0x02, 0x03, 0x10, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0xff, 0xff, 0x87, 0xc7, 0xfc, 0xe3, 0x8e, 0x0f, 0xc7, 0xfc, 0x00, 0x07, 0x00, 

            0x00, 0xe0, 0x00, 0x39, 0xc7, 0x39, 0xe3, 0x9c, 0xf3, 0x87, 0x19, 0xe3, 0x98, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x39, 0xe7, 0x30, 0xe3, 0x9c, 0x73, 0x87, 0x00, 0xe3, 0x80, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x00, 0x39, 0xe7, 0x38, 0xe3, 0x9c, 0x73, 0x8e, 0x07, 0xe3, 0x80, 0x00, 0x07, 0x01, 

            0x00, 0xc0, 0x00, 0x39, 0xe7, 0x38, 0xe3, 0x9c, 0x73, 0x8e, 0x38, 0xe3, 0x80, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x39, 0xe7, 0x3c, 0xe3, 0x9c, 0x7f, 0x8e, 0x38, 0xe3, 0x80, 0x00, 0x06, 0x00, 

            0x00, 0x80, 0x00, 0x7d, 0xef, 0x9f, 0x8e, 0xf3, 0xff, 0xff, 0xbf, 0xf7, 0xe0, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x10, 0x01, 0x00, 0x00, 0x80, 0x20, 0x82, 0x08, 0x41, 0x80, 0x00, 0x06, 0x00, 

            0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc7, 0xc7, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 

            0x08, 0xc3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc7, 0x00, 

            0x00, 0xc3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x87, 0x00, 

            0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 

            0x02, 0xfc, 0x48, 0x71, 0xb7, 0xfd, 0x42, 0x3d, 0x56, 0xa2, 0x9e, 0x5a, 0x9f, 0x87, 0xcf, 0x00, 

            0x00, 0x7f, 0xff, 0xff, 0xfa, 0xff, 0xfe, 0xff, 0xff, 0x9b, 0xff, 0xff, 0xff, 0x9f, 0xfe, 0x00, 

            0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20

};

 

 

// Analog Pins

int channelAI = A0;      // Probe

int delayAI = A1;        // Delay Potentiometer

float delayVariable = 1; // Verzögerungsvariable

float scale = 0;

int xCounter = 0;

int yPosition = 0;

int readings[128];

 

void setup() {

  // Serielle Kommunikation starten

  Serial.begin(9600);

 

  // Display initialisieren

  if (!display.begin(SSD1306_ADDRESS, 0x3C)) {

    Serial.println(F("SSD1306 Initialisierung fehlgeschlagen"));

    for (;;)

      ; // Endlosschleife bei Fehler

  }

 

  // Display löschen

  display.clearDisplay();

 

  // 1. Bild anzeigen

  display.drawBitmap(0, 0, image, 128, 64, WHITE);

  display.display();

  delay(2000);

 

  // Sinuswelle animieren

  animateSineWave(1); // Sinuswelle für 2 Sekunden anzeigen

 

  // Display löschen

  display.clearDisplay();

}

 

void loop() {

 

  // Messwerte visualisieren

  plotAnalogSignalWithScaling();

}

 

// Funktion zur Sinuswellen-Animation

void animateSineWave(int durationInSeconds) {

  unsigned long startTime = millis();

  const int amplitude = 20;  // Amplitude der Sinuswelle

  const int midpoint = SCREEN_HEIGHT / 2; // Mittellinie

 

  while (millis() - startTime < durationInSeconds * 1000) {

    display.clearDisplay();

 

    for (int x = 0; x < SCREEN_WIDTH; x++) {

      float angle = 2.0 * PI * x / SCREEN_WIDTH; // Berechnung des Winkels

      int y = midpoint + amplitude * sin(angle); // Sinuswert berechnen

      display.drawPixel(x, y, WHITE);            // Pixel für die Welle setzen

    }

 

    display.display();

    delay(50); // Animation verlangsamen

  }

}

 

void plotAnalogSignalWithScaling() {

  // Zeitbasis in Millisekunden pro Division

  float timebase = 10.0; // 10 ms pro Division

  int pixelsPerDivision = 16; // 8 Divisionen (128 / 16)

  float delayPerPixel = timebase / pixelsPerDivision; // Verzögerung pro Pixel

 

  const int displayHeight = 50;  // Höhe des Bereichs für das Signal

  const int midpoint = SCREEN_HEIGHT / 2;  // Fixierter Nullpunkt in der Mitte des Displays

  const int triggerThreshold = 30; // Schwellwert für Triggerung

  const int baseline = 500; // Standard 512 / Baseline für kein Signal (ADC-Mittelwert)

 

  float scaleFactor = 0.6; // Skalierungsfaktor (1.0 = volle Höhe, <1.0 = kleiner, >1.0 = größer)

 

  int readings[128];

  bool signalDetected = false;

 

  // Messwerte aufzeichnen

  for (xCounter = 0; xCounter < SCREEN_WIDTH; xCounter++) {

    int rawValue = analogRead(channelAI);

 

    // Trigger prüfen: Signal nur darstellen, wenn über Threshold

    if (abs(rawValue - baseline) > triggerThreshold) {

      signalDetected = true; // Signal erkannt

    }

 

    // Wenn kein Signal erkannt, baseline anzeigen

    if (!signalDetected) {

      readings[xCounter] = baseline;

    } else {

      readings[xCounter] = rawValue;

    }

 

    delay(delayPerPixel); // Zeitbasis

  }

 

  // Signal-Darstellung vorbereiten

  int minValue = baseline - (displayHeight / 2) / scaleFactor; // Untere Grenze

  int maxValue = baseline + (displayHeight / 2) / scaleFactor; // Obere Grenze

 

  // Signal zeichnen

  display.clearDisplay();

  for (xCounter = 1; xCounter < SCREEN_WIDTH; xCounter++) {

    int y1 = midpoint - map(readings[xCounter - 1], minValue, maxValue, -displayHeight / 2, displayHeight / 2) * scaleFactor;

    int y2 = midpoint - map(readings[xCounter], minValue, maxValue, -displayHeight / 2, displayHeight / 2) * scaleFactor;

 

    // Nur Werte innerhalb des darstellbaren Bereichs zeichnen

    if (y1 >= 0 && y1 < SCREEN_HEIGHT && y2 >= 0 && y2 < SCREEN_HEIGHT) {

      display.drawLine(xCounter - 1, y1, xCounter, y2, WHITE);

    }

  }

 

  display.display();

}