Ringer circuit fitted in a phone |
This ringer circuit produces a 50V square wave and pulses the existing solenoids which activate the hammer on the two bell. I have decided that it is too big for the phone so another solution is needed so that I can still use the bells in the GPO phone.
Whilst retaining the bells, I have got rid of the 2 solenoids altogether as they are also quite big. So in order to ring the two bells in the phone I have decided that I need a bicycle bell. Well sort of, the mechanism an old fashioned cycle bell uses to spin round and hit the internal sides of the bell itself. This will be replicated using an electric motor, which will spin the 'dingers' against the sides of the 2 bells.
For this purpose I bought a stepper motor as this can be controlled easily with the outputs from a PIC micro controller, which I will be using anyway to decode the dialled number from the rotary.
I built a circuit using the PICKit2 demo board - which has a 16f690 installed in it - to send the required pulses to the stepper motor controller.
Once I'd found the PIC16F690 datasheet I decided to program the very simple logic using the native assembly language, this initially proved to be quite tricky. (I spent a few years writing assembly for flight control software as a job, but this was nearly 20 years ago!). After searching for tutorials and rereading the datasheet, I had a "light bulb" moment and it all became fairly straight forward.
Using MPLAB 8, I wrote a simple program that sends a pulse-train to the 4 inputs of the stepper motor, the speed of the pulses and hence the stepper is controlled by the POT on the demo board.
Basically the program does the following:
; Wire 1 2 3 4 5 6 7 8 Port
; ORG x x x C0
; YEL x x x C1
; PIK x x x C2
; BLU x x x C3
This is the pulses that have to be sent to the stepper, so orange, then orange + yellow, then yellow etc. this is the half drive for the stepper.
The ports are the ports on the PIC used for output of the pulse.
Here's the source:
;
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF)
; Registers for use with the variable delay loop.
UDATA
dc1 res 1 ; Reserve 1 byte of data memory and call it dc1
dc2 res 1 ; Reserve 1 byte of data memory and call it dc2
dc3 res 1 ; Reserve 1 byte of data memory and call it dc3
org 0 ; start vector
Start
BSF STATUS,RP0 ; set bit at RP0 in register STATUS to select bank 1
movlw 0h ; 00000000 - makes ports C0 & C1 as outputs
movwf TRISC ; moves the 00000000 to TRISC
BCF STATUS,RP0 ; clear bit at RP0 in register STATUS to reselect bank 0
; Setup the ADC
; NOTE: you can set these bits individually using "bsf register,bit"
movlw b'001' ; set the sample rate to /8
movwf ADCON1 ; move to ADCON1
; The below 2 statements are the same as the 3rd
; movlw b'00000001' ; switch A2D on
; movwf ADCON0
bsf ADCON0,ADON ; Sets the ADON bit in ADCON0
Loop
call A2D
bsf PORTC,RC0 ; C0 - using bsf does not alter content of w so means the A2D is detected
call A2D
; bsf PORTC,RC0
; bsf PORTC,RC1
movlw b'00000011' ; C0 & C1 - could set ports like this, but done for the above reason.
movwf PORTC
call A2D
bsf PORTC,RC1 ; C2
call A2D
movlw b'00000110' ; C0 & C1 - could set ports like this, but done for the above reason.
movwf PORTC
call A2D
bsf PORTC,RC2 ; C3
call A2D
movlw b'00001100' ; C0 & C1 - could set ports like this, but done for the above reason.
movwf PORTC
call A2D
bsf PORTC,RC3 ; C3
call A2D
movlw b'00001001' ; C0 & C1 - could set ports like this, but done for the above reason.
movwf PORTC
GOTO Loop ; go to Loop label
; 10 millisecond delay loop - altered to speed it up
; setting W to 1 will be a
delay10
movwf dc3 ; move value in w to memory location dc3
dly2
movlw .1 ; Repeat inner loop 1 times (was 13) - this speeds it up for stepper motor
movwf dc2 ; move .13 to memory location dc2
clrf dc1 ; clear dc1
dly1
decfsz dc1,f ; decrement value at dc1 to 0 then jump
goto dly1
decfsz dc2,f ; decrement value at dc2 to 0 then jump
goto dly1
decfsz dc3,f ; decrement value at dc3 to 0 then jump
goto dly2
return
A2D:
bsf ADCON0,GO ; start conversion
btfss ADCON0,GO
; if ADCON0 == 0 then jump (this bit will change to zero when the conversion is complete)
goto $-1 ; goto previous line
movf ADRESH,w ; Copy the value to the w register
ADDLW 1 ; Add 1 so that the minimum value is always > 1
call delay10 ; calls the delay script once the value has been read from the POT
return