Tuesday, January 28, 2014


I have now mounted all components on the MIDI2VC PCB. It pretty much works as expected. I had done a couple of errors on the DIN5 footprint and generally the MIDI in circuitry. This has now been fixed by patching and using chassis mount DIN5 connector. A problem persists, however, and that is symbols being dropped in the opto coupler. I've checked and rechecked the circuitry and the data sheets but cannot find any errors. It is difficult to trouble shoot this with an analog scope, so I may have to hunt this one down with a digital scope, if I can only borrow one.. I can always take a trip to work I guess .. :)

MIDI2VC, bottom, patched MIDI connector to the left.
MIDI2VC, component side.

Thursday, January 23, 2014

VCA's and PCB's


The PCB's from Osh Park came yesterday. They look like this:
PCB's from  Osh Park
 I haven't started mounting them yet, but I immediately saw that the MIDI contact didn't fit. This wasn't so surprising, I didn't have the part when I made footprint, and the schematic of the part was a bit strange (I'm not that good at mechanical drawings).


 I need a voltage controlled amplifier for the synthesizer. This is to be used for generating the envelope. I looked at a few ways of doing this, but using the LM13700 seemed the most reasonable. Remember that I burnt an LM13700 not long ago? I realised that I probably burned just one of the channels. So I wired up a VCA circuit i found in the data sheet (page 10, fig 23):
VCA from LM13700 data sheet
The circuit, and it's output, looks like this:
Input to VCA is the sine, output is the clipped sine.

VCA from LM13700
The VCA looks to be working fine, but I might tweak some resistor values after testing it with the Attack and Release envelope generator I intend to build soon.

Broken Power Supply

When I was fiddling with the VCA the power supply to the gain control was overpowered. This surprised me, since it can drive 3A, and I calculated max current to 1.5mA. Seems like there is something wrong with the current measurement in the old power supply. It can, however, give up to 1.2mA, which is just fine right now. So I'll need to fix it, but first I've got some more interesting things to do...

Sunday, January 19, 2014

MIDI2VC code update, addition of "MIDI Key Bucket"

I've added some functionality to the MIDI2VC code. The problem that needed fixing was when multiple MIDI keys where pressed simultaneously, this could confuse the system. What I've added now is a priority system, where the lowest key pressed is the one the generates an output voltage. This is similar to what is used in the Mini Moog. In the future, I might implement a function for choosing one of several priority systems, but I'll need a PIC with more IO's to do that.
I can't test this functionality very well right now, since MIDI Ox only let's me play two simultaneous keys, and I haven't gotten my real MIDI keyboard to work with the MIDI2VC yet. I have tried sending manual MIDI keys, using UART, and that works as expected.
 Here are the updated functions.

 //**************Function processUARTBuffer*******************  
 //Interprets UARTBuffer, toggles LED and sends appropiate  
 //I2C data to DAC  
 void processUARTBuffer(int UARTBufferF[])  
   extern int i2cData[];  
   extern int MIDISimKeysPressed;  
   const int DACLookupTable[127] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x017, 0x072, 0x0C2, 0x116, 0x169, 0x1B9, 0x20C, 0x25F, 0x2B0, 0x305, 0x356, 0x3A9, 0x3FC, 0x44D, 0x4A2, 0x4F5, 0x547, 0x5C7, 0x5EF, 0x63E, 0x691, 0x6E7, 0x739, 0x78E};  
   int DACValue;  
   int DACValue;  
   //If UART symbol is MIDI "Note on", light LED and  
   //send lowest data in MIDI key bucket to DAC  
   if (((UARTBufferF[0] & 0xF0) == 0x90) && (UARTBufferF[2] != 0x00))  
     //Keeps track of number of keys simultaneously pressed  
     DACValue = DACLookupTable[isLowestInMIDISimKeysBucket()];  
     i2cData[1] = (DACValue & 0xFF);  
     i2cData[0] = ((DACValue & 0x0F00) >> 8);  
     i2cDataToBeSent = 1;  
     //If UART symbol is MIDI "Note off", check if there are  
     //other notes in bucket and send their lowest data to DAC, otherwise  
     //turn off LED and send zeros to DAC  
   else if (((UARTBufferF[0] & 0xF0) == 0x80) || (UARTBufferF[2] == 0x00))  
     if (MIDISimKeysPressed == 0)  
       i2cData[0] = 0x00;  
       i2cData[1] = 0x00;  
       i2cDataToBeSent = 1;  
     else if (MIDISimKeysPressed > 0)  
       DACValue = DACLookupTable[isLowestInMIDISimKeysBucket()];  
       i2cData[1] = (DACValue & 0xFF);  
       i2cData[0] = ((DACValue & 0x0F00) >> 8);  
       i2cDataToBeSent = 1;  
 //**************Function pushMIDISimKeysBucket***************  
 //Function for pushing a MIDI key int into the MIDI bucket.  
 //The MIDI bucket is a data sctructure that holds a number  
 //of ints. The pushed int is placed in the first available  
 //empty array slot, in no other order. Empty slots are valued  
 //-1, since 0 is a valid key value.  
 //Each value in the bucket (except -1) is unique, if not, there  
 //is something wrong. No error checking for this is implemented.  
 void pushMIDISimKeysBucket(int midiKey)  
   extern int MIDISimKeysBucket[];  
   //place MIDI key value in first -1 (empty) instance  
   int i = 0;  
   while (i < MIDISimKeysBucketSize)  
     if (MIDISimKeysBucket[i] == -1)  
       MIDISimKeysBucket[i] = midiKey;  
       i = MIDISimKeysBucketSize;  
 //**************Function popMIDISimKeysBucket***************  
 //Function for removing value from bucket.  
 void popMIDISimKeysBucket(int midiKey)  
   extern int MIDISimKeysBucket[];  
   //Find value in array and replace with -1  
   //If no value is found, do nothing  
   int i = 0;  
   while (i < MIDISimKeysBucketSize)  
     if (MIDISimKeysBucket[i] == midiKey)  
       MIDISimKeysBucket[i] = -1;  
       i = MIDISimKeysBucketSize;  
 //**************Function isLowestInMIDISimKeysBucket*********  
 //Returns the lowest value in the bucket  
 int isLowestInMIDISimKeysBucket()  
   extern int MIDISimKeysBucket[];  
   int lowestKey = 0x7f; //Highest legal MIDI key  
   //Finds lowest key, that isn't -1, in bucket  
   int i = 0;  
   while (i < MIDISimKeysBucketSize)  
     if ((MIDISimKeysBucket[i] < lowestKey) && (MIDISimKeysBucket[i] > -1))  
       lowestKey = MIDISimKeysBucket[i];  
   return lowestKey;  

Wednesday, January 15, 2014

Chip burning, but success in the end

LM13700 bias input

After thinking about it for a while, I realised that the bias current input of the LM13700 isn't referenced to ground, but to the negative rail. That explains the doubled amplitude of the VCO waveforms. Looking in the data sheet you can see that the bias input sits a current mirror over the negative rail. It seems like there should be two diode drops over V-. But since I'm there messing around and changing the current setting resistor, I may as well measure it properly. So, voltage between positive and negative rail is measured to V+-V-=18.034V. The resistor is 38.33kΩ and the current IA=0.4371mA, so: 18.034V-0.4371mA·38.33kΩ=1.28V, which we, with confidence, can say is two diode drops.
 Changing the current controlling resistor for IA, I made a calculation error, and since I stopped thinking for a little while, I used a too small resistor and killed the chip with 3mA on the current bias input. This is about 1 mA over the maximum current. I did get a new chip today (they are quite expensive) and wired everything up again, and now it actually works like it should...

Completing the VCO

By wiring the log converter to the VCO and connecting the input of the log converter to the VCO, I now can play some music... By connecting the MIDI2VC output to the log converter and the VCO output to a speaker, I can now play using Midi Ox as MIDI source. The VCO needs some tuning, so I added a tuning pot that adds or subtracts some voltage from the input stage inverter in the log converter. Here are some pictures:
Playable system. MIDI2VC to the right. Log converter and VCO on the upper left. To the lower left is a mixer mentioned in earlier posts.
And here's a video where you can hear some random notes from the system (sorry about low sound volume):

Logarithmic VCO, final schematic

Saturday, January 11, 2014

Current controlled oscillator, LM13700 transconductance amplifier


There is a neat device for building a voltage, or rather current, controlled oscillator. It's a transconductance amplifier called LM13700. It has a positive and negative voltage input, but a current output. It also has a current bias input. The output current is proportional to the differential input times the current bias input. The LM13700 has a lot of applications such as voltage controlled -amplifier, -resistor and -filter and multiplier.
 In the data sheet, page 16, there is a simple VCO, which works very similar to the VCO i built in an earlier blog post.
I did my own schematic of the VCO with pin numbers of the device:
Voltage (or rather current-) controlled oscillator taken from the LM13700 datasheet.

I want my oscillator to play between C2, 65.4064Hz, and C6, 1046.50Hz. The frequency of the VCO is: fOSC=IC2/(4CfIARA). The current for the lowest key, VC = 1V, was measured to 64μA, and current for the highest, VC = 5V, was 1.02mA. That means we have 4Cf IA RA = IC2fOSC, with the two values IC2fOSC = 64μA·65.4064Hz =979nC and IC2fOSC =  1.02·mA1046.50Hz = 975nC, which has a mean of 977nC. Our target will therefore be 4CfIARA = 977nC.
 We also have that the output amplitudes of the oscillator is A=IARA, so that's a good place to start deciding our component values. If we go by the data sheet and set RA= 4.7kΩ (closest E12 resistor to  5.1kΩ) and we want 1V amplitude, we get IA=1V/4.7kΩ = 213μA. With a 39kΩ resistor connected to positive rail we get  IA=231μA, close enough. We now only have to decide the value of Cf.
Cf = IC2fOSC /(4IARA)=977nC/(4·231μA·4.7kΩ) = 225nF. I found two 120nF caps in my junk box, so I'll use them in parallel to get 240nF.

Circuit build

The LM13700 is hid under the decoupling cap. The black alligator clip is the current source.

The two waveforms at VC = 3V. 
We can see that the waveforms have a nice shape, but the amplitude is twice of what I calculated. The frequency is a bit on the lower side. I'll hook the VCO up to the log converter and the MIDI2VC, and see how parameters can be calibrated. It would be interesting to figure out why the VCO differs in function from the calculations, but right now I'm more eager to test out the MIDI2VC...

Logarithmic Converter, Control Voltage to Logarithmic Current, Part 2, Implementation

Here's an image of the logarithmic converter built on a copper plane.
Logarithmic converter
The measurement cables measures IC2, from converter to ground. The two PNP transistors are glued together for better thermal stability. The IC is a dual op amp, LM358P.
The following table shows IC2 as a function of VC.

VC(V) Simulated IC2 (mA) Measured IC2 (mA)
0 0.027 0.031
1 0.055 0.064
2 0.110 0.130
3 0.220 0.268
4 0.443 0.551
5 0.871 1.02
I think simulated and measured data compares pretty good, considering that simulation is done using general op amp model, and not the right transistors. IC2 doubles pretty well with every voltage step. We really don't need exact values, since a calibration pot will be added as soon as the VCO is up and running. The next post will be about building the VCO.

Thursday, January 9, 2014

Logarithmic Converter, Control Voltage to Logarithmic Current, Part 1, theory

One standard of analogue synthesizer control is 1V/octave. This is what I'm implementing in the MIDI2VC, and now I need to build a simple logarithmic converter to place between the MIDI2VC and the VCO. In fact, I will actually build a new, really simple VCO from a LM13700.
 The logarithmic converter is thoroughly explained in Electronotes S-019. The one described on page 2 is one that sinks current, and the LM13700 VCO needs a current source. In Electronotes 129 there is a big VCO schematic that has a log converter with a current source. A combination of the two schematics is seen here:
Current source logarithmic converter
The relationship between the currents is:
\[ I_{C2 } = I_{C1} e^{-V_{IN}\cdot  \ 26  \text{mV} } \]
Ignoring the small base currents in the transistors, we also have
\[ I_{O } = I_{C1}+I_{C2} \]
We will want to limit  $I_{C2}$ to protect the LM13700. It can receive a current of 2mA, but let's set max current to 1mA to be on the safe side. We can combine the two current equations to:
\[ I_{O } = I_{C2} ( 1 +  e^{V_{IN} / 26  \text{mV} } )  \]
$A_2$ is an inverting attenuator that converts positive control voltage to negative in voltage:
\[ V_{IN} = V_C \cdot 18 \text{mV}   \]
$V_O$ will swing all the way to the positive rail (or close at least). $V_e$ is always close to 0.6mV (diode drop). We want the converter to work up to 5 Volts (max output of the MIDI2VC). This means we should set
\[ R_L \le \frac{9-0.6 \mathrm{V}}{1\mathrm{mA} (1+e^{-5 \cdot 18/26} ) } =  8144 \Omega \]
In fact, we need to go a bit lower on $R_L$, due to the approximations in the calculation. I settled fro $R_L = 6.8$k\Omega.
We now set:
\[ I_{C1} \le  1\mathrm{mA} e^{-5 \cdot 18/26} \]
We can get this current by connecting 330k\Omega to the negative rail.
An LTSPICE simulation of this circuit can give us a plot like this:
Output current as function of voltage. Note that the current doubles between each 1V increment up to the current limitation. Simulation done in LTSPICE.

Friday, January 3, 2014

Playing the MIDI2VC with a MIDI device

A lot is working right now. I've made a look up table that translates MIDI keys to DAC programming values. I can now connect my computers USB2MIDI cable and play tunes using MIDIOX and the computer keyboard (not in tune though, I'll get back to that issue further down).  I had to modify two functions in the code to get this to work. One addition to the code is that "Note off", can be triggered with "Velocity" equals 0. I found that my MIDI keyboard signals note off that way, and MIDIOX does it with "0x80". So the code needs to support both ways. The modified code can be seen below:

1:  //***********************************************************  
2:  //**************Function processUARTSymbol*******************  
3:  //Checks to see if received UART symbol is 0x8X or 0x9X, or  
4:  //a symbol that follows one of those symbols  
5:  //The function puts 0x8X (or 0x9X) and it's following symbol  
6:  //in a two symbol buffer and then sends that buffer to  
7:  //function processUARTBuffer  
8:  //***********************************************************  
10:  void processUARTSymbol(int UARTSymbol) {  
11:    extern int UARTBufferCounter;  
12:    extern int UARTBuffer[];  
14:    //If symbol is MIDI "Note On"(0x9X) or MIDI "Note Off"(0x80),  
15:    //place symbol and it's following symbol in UART buffer  
16:    if (((UARTSymbol & 0xF0) == 0x80) || ((UARTSymbol & 0xF0) == 0x90)) {  
17:      UARTBufferCounter = 1;  
18:      UARTBuffer[0] = UARTSymbol;  
19:    } else if (UARTBufferCounter == 1) {  
20:      UARTBufferCounter = 2;  
21:      UARTBuffer[1] = UARTSymbol;  
22:    } else if (UARTBufferCounter == 2) {  
23:      UARTBufferCounter = -1;  
24:      UARTBuffer[2] = UARTSymbol;  
25:      processUARTBuffer(UARTBuffer);  
26:    }  
28:    return;  
29:  }  
32:  //***********************************************************  
33:  //**************Function processUARTBuffer*******************  
34:  //Interprets UARTBuffer, toggles LED and sends appropiate  
35:  //I2C data to DAC  
36:  //***********************************************************  
38:  void processUARTBuffer(int UARTBufferF[]) {  
39:    extern int i2cData[];  
40:    const int DACLookupTable[127] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x017,0x072,0x0C2,0x116,0x169,0x1B9,0x20C,0x25F,0x2B0,0x305,0x356,0x3A9,0x3FC,0x44D,0x4A2,0x4F5,0x547,0x5C7,0x5EF,0x63E,0x691,0x6E7,0x739,0x78E};  int DACValue;  
41:    int DACValue;  
43:    //If UART symbol is MIDI "Note on", light LED and  
44:    //send data to DAC  
45:    if (((UARTBufferF[0] & 0xF0) == 0x90) && (UARTBufferF[2] != 0x00) ) {  
47:      DACValue = DACLookupTable[UARTBufferF[1]];  
48:      i2cData[1] = (DACValue & 0xFF);  
49:      i2cData[0] = ((DACValue & 0x0F00)>>8);  
51:      lightLED();  
52:      i2cDataToBeSent = 1;  
53:    }//If UART symbol is MIDI "Note off", turn off LED and  
54:      //send zeros to DAC  
55:    else if (((UARTBufferF[0] & 0xF0) == 0x80) || (UARTBufferF[2] == 0x00)) {  
56:      i2cData[0] = 0x00;  
57:      i2cData[1] = 0x00;  
59:      unlightLED();  
60:      i2cDataToBeSent = 1;  
62:    }  
64:    return;  
65:  }  

I am having problems when I connect my MIDI keyboard. Some of the MIDI packets from the keyboard are lost in transfer. I don't lose anything when connecting it to the computer and receiving with MIDIOX, so there has to be something bad with my optocoupler. I looked at the data sheet, but I can't find anything that should rule out the optocoupler I use. I have not found anyone online using it in a MIDI project though, so there may be something with it that is not good. It is pin compatible with the recommended device, PC 900V0NSZX. So a switch will be easily done. The Sharp device costs about the double though. 


Playing the MIDI2VC using my current, very simple, VCO, is not possible to do in tune. The VCO has a linear voltage control and the MIDI2VC is now programmed to give a 1V/octave  control voltage. So my next step will be modifying the VCO to get logarithmic control voltage input. I'll get back on that in my next post.