Friday, 17 March 2017

Cassette Player Hack! CV Pitch Control




A little while back I decided to have a play experimenting with cassette recorders; making tape loops etc, and I got on ebay looking for a cheap player (having junked all the ones I owned years ago). I got quite lucky finding a job lot of FOUR identical Panasonic players for just over £20 for the lot!

Not only that but I found there is a service manual online complete with schematics and all kinds of lovely technical info


For my first experiment I wanted to add a pitch control, and it actually turned out to be easier than I expected!


In this player, when one of the buttons on the player is pressed, a switch supplies power at 6V to the motor. There doesn't seem to be any electronic speed control of the motor, and I think the faster FF/Rewind speed is implemented via gearing and mechanical ratio selection. Therefore all I needed to do was find some way to slow down the motor!

Doing this by reducing the motor voltage or current directly is a bit tricky - for example putting a potentiometer in series with the motor would not be a good approach as the pot would need to dissipate a lot of power and would likely get hot and the carbon track would soon burn out. 

Instead, the usual way of doing this type of speed control is to use Pulse Width Modulation (PWM) and some kind of electronic switch (e.g. a transistor). If you know synths, chances are you are familiar with PWM as a means of modulating a square wave to get a phasing kind of effect. What PWM does to a waveform is change the width of the "peaks" of a square wave relative to the "troughs" while keeping the frequency the same. As well as changing the audio character of the wave, PWM allows you to change the overall time a the square wave is "ON" vs "OFF" and therefore how much power the wave transfers averaged over time.

So lets say we feed the PWM'd square wave into a motor, the motor will spin faster as the proportion of time the power is ON vs OFF is increased. Therefore by controlling the PWM "duty cycle" (as this ratio is called) we can control the motor speed.

There are various ways to make a PWM signal, and the first thing I used was a circuit using a 555 timer chip (rather like this http://www.instructables.com/id/Simple-and-dirty-Pulse-Width-Modulation-PWM-Wi/). To actually drive the motor I didn't feed the oscillator output directly into the motor but instead fed it into the base of a TIP115 transistor (PNP Darlington Type), which was placed in series to the cassette motor positive wire (high side). This means the oscillator activates the transistor which then does the switching (as this is a PNP transistor, the switch is actually ON when the oscillator output is LOW)

This worked nicely and let me work the tape speed using a potentiometer to control the oscillator duty cycle. The frequency of the PWM carrier needed to be quite low for the motor to rotate rather than just whining). I went for about 70Hz.

Rather than a pot, what I really wanted was to be able to control the speed using a 5V CV (control voltage) signal which I can generate from a music sequencer. When I put +5V to the CV input I want the motor to run at normal speed. 0V should stop the motor. +2.5V should run at half speed (ideally). You get the picture...!

I could have done this with a 555 but it seemed like it might be hard to get a suitable circuit that would work right at the extremes (i.e. support 100% and 0% duty), plus I had a load of PIC12F1822 microcontrollers and know them really well (and they are same size as the 555) 

So I ended up with the following circuit (click to see full schematic)

The motor wires are shown at the right. The transistor (actually TIP115) is placed in series with the motor. 

The two diodes on the top right are 1N4001's and are there to drop off some of the 6V motor power voltage so that it is below the 5.5V limit of the PIC supply. The circuit is powered from the motor power supply so it powered only when a key is pressed on the player.

The diodes on the left are 1N4148 and clamp the incoming CV to the PIC power rails. 

R2 limits clamped CV current and I used 1k but it could be higher (e,g. 4k7). I soldered R2 directly to the socket, so it is not on the stripboard. 

I used a 100k Linear pot for the manual control with a 3.5mm jack that breaks the connection to the pot and overrides with external CV input. JP1 is a programming header.

The box in the middle is the PIC12F1822 microcontroller (DIP-8). Of course this a microcontroller based project, which is nothing without firmware! I'll include the firmware source below. 

The firmware works by having a loop in code actually do the PWM cycle (since I only want it to run at 70Hz there is no need to use the specialised PWM peripherals on the PIC). While the PWM cycle runs, the PIC's analog to digital converter (ADC) gets a 10 bit value from the CV input. I simply take the top 8 bits of the ADC reading and put them into my duty cycle variable.

On each PWM cycle the transistor is ON when the cycle starts and goes OFF when the duty counter (controlled by CV) is reached. So a lower CV will mean a shorter duty cycle.

Since the motor is switched on the high side, I need a PNP transistor. To turn the transistor ON I need to draw current from the transistor base (I think of the 'P' in PNP as 'pulling' a current out of it to switch it on - hmm yeah I know there's a 'P' in NPN too - shut up! :) 
So to turn on the transistor the PIC output PIN is set to a LOW output voltage so it can sink current from the transistor based. However since the PIC output pin will have a HIGH voltage lower than the transistor emitter (since PIC is powered at < 5.5V) that wont cut off the transistor. Therefore I switch the transistor during the PWM cycle by alternating the pin between output mode (with LOW state) and input mode (High impedence) where no current is sunk by the pin.

Conclusion : This is the only cassette player I've modded so far, but I am pretty sure that the same principle should be applicable to other players. One key fact with this one is that the low side of the motor is grounded, so I can power my circuit using the voltage difference between the motor supply and ground. I needed to make sure the motor voltage would not damage the circuit - in this player it is 6V so a couple of silicon diodes in series can drop this down into a safe voltage for the PIC (each diode drops off something like 0.4V)

Something else I did was to remove the erase head - this is because I want to use loops of tape and be able to record and overdub loops on the same player. An erase head will always leave a sound gap in a loop (corresponding to the physical gap between the erase and record/playback heads) and will prevent overdubs. In this player the erase head was a simple permanent magnet on a plastic arm which can simply be unclipped without damaging it (great if I need to erase anything later)

The tape I used is an answering machine outgoing message loop - works well but is quite long (30 seconds at normal speed). I might try making my own loops so they can be a bit shorter

This approach can only slow a tape down, not speed it up. I think you can only speed the tape up (at least using the same motor) by increasing the voltage, which might have consequences for other parts of the player circuitry. I think I prefer the effect of slowing playback right down to flappy graininess than speeding it up, but there is always the option of recording at slow speed to allow playback at faster speed.

First look inside

Simple 6V DC motor with grounded low side - nice!

Adding the wires to transistor and ground wire

The control circuit (will eventually be fitted inside player case)



The firmware source code - I am using SOURCEBOOST C but I think it should be fairly easy to port to other compilers or microcontrollers

#include

#pragma DATA _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF &_CLKOUTEN_OFF
#pragma DATA _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_19 & _LVP_OFF
#pragma CLOCK_FREQ 16000000
typedef unsigned char byte;

void main()
{
        // osc control / 16MHz / internal
        osccon = 0b01111010;
        
        // configure analog input AN3 enabled
ansela = 0b00010000;
        // turn on the ADC
        // ADC clock is Fosc/32
        // Result left justified (8 bit value in adresh register)
        // Voltage reference is power supply (VDD)
        adcon1=0b00100000; //fOSC/32
        adcon0=0b00001101; // Left justify / Vdd / AD on // AN3

byte count = 0;
byte duty = 0;
delay_ms(250); // delay to allow settling of power supply before starting to drive motor
        for(;;) {
if(count == duty) { // end of duty cycle (or start of zero duty cycle)
trisa.2 = 1;    // set drive pin as input (high impedence, floating)
}
else if(!count) { // start of duty cycle when 8 bit count rolls over
lata.2=0; // drive output pin LOW to sink current 
trisa.2 = 0;    // and enable pin output mode
}
if(!count) { // at start of duty cycle we store the previous ADC result and 
// kick off a new ADC reading
duty = adresh;
adcon0.1=1;
}
++count; // duty cycle count (just allow 8 bit value to roll over to 0)
delay_us(50); // delay gives ~50-70Hz carrier
        }        
}




No comments:

Post a Comment