woensdag 13 december 2023

PICmicro PWM VCO

Many of the 8-bit PICmicro microcontrollers have a PWM built in, which usually is used to do D/A conversion by changing the pulse width and adding a low pass filter (see other posts on this blog). I was curious whether instead of doing this, it might be possible to use the actual PWM output as the waveform, turning this into a VCO.

I used the 16F690, mostly because I am familiar with it and because I have a number of them in a drawer. It has analog inputs that can be used to convert the input voltage, and a single PWM. To get the PWM frequencies in the audible range I changed the clock frequency of the microcontroller to 125 kHz. Fortunately this is easy. I then computed which notes it could play, from C1 to D#6 and determined the appropriate values. I decided that I'd accept an input voltage from 0V for C1 to 5.33V for D#6. Since the PICmicro can only accept voltages up to 5V this meant I had to have a voltage divider. I decided to use two OPAMP for this: one that allowed adding and subtracting -6V to 6V to the input voltage, and the other to divide the voltage and invert it back to the normal range. This worked fine.

For the PWM input I used a default of 5V which was fed through an attenuator, so if the cable is not plugged in it had a range from 0-5V, and if the cable was plugged in the incoming voltage could be attentuated. That was fed to the second analog channel. Since the PWM range changes with each note I had to build a clever piece of code that checked each bit of the incoming data and add various divisions of the maximum range.

Finally, since the output only moves between 0V and 5V, I added a transistor inverter with CV input, so I got a free VCA. The output of this I pushed through a high pass filter to remove the DC component and will be multiplying by two so I get 10 Vpp (I didn't make this currently, but it just means adding two 47k resistors to the OPAMP). I will add schematics later, but I wanted to at least publish the current source code.

I needed to use assembly because at 125 kHz the processor is quite slow, and I do need to do the A/D conversion and output fast enough to not have issues with latency between notes.