;========================================================================= ;;CDI for model engines ;Based on "Bike Advance" 4.23 ;V1.0 09.14.2005 Jon-Magne Johansen ;========================================================================= ;========================================================================== Title "Zenoah Advance" ; http://www.modelbouw.gompy.net/cdi/cdi.htm ; 23 01 06 Version 1.00 for 16F84a GOMPY ; ------------------------------------------------------------------------- ; ; ; ;========================================================================== ; ; Ign advance starts at 1500 engine RPM ; ; Ign full advance is at 16000 engine RPM ; ; dwell time is fixed at 1mS, = 10 X 100uS loops ; ; After 1500 RPM, the ignition advance is calculated in 116 steps. ; This continues up until 16000 RPM is reached. ; ; ; At a engine speed of 1200 RPM; ; ; 1200 / 60 = 20 revs per second ; 1 / 20 = 50mS per rev ; 1 rev = 360 degrees ; ; 36 degrees at 1200 RPM = (36 / 360) X 50 = 5mS ; ; Therefore maximum retard at 1200 RPM = 0mS after the firing ; point is reached. This figure remains constant down to 0 RPM. ; ; At a engine speed of 16000 RPM, maximum advance will have been reached, ; and ignition is immediately after the firing point is reached. ; ; The intermediate values will be looked up in an advance table map ; and will correspond to engine speed from 1500 RPM to 16000 RPM. ; ; Map holds retard values in 100uS loops for every loop change ; in rpm rate. ; ; ; ;========================================================================== ; ; PIC 16F84 wiring ; ;========================================================================== ; ; RA2 1+--O--+18 RA1 ; pickup36°-----------> RA3 2| |17 RA0 ; test jumper---------> RA4 3| |16 Osc ------ 4MHz ; +5V--+----R---------> MCLR 4| |15 Osc ------ Quartz ; Ground--------------- Vss 5| |14 Vcc ------ +5Vdc ; Thyristor <------- RB0 6| |13 RB7 ------>PickupLED ; LEDrpmLimit <------- RB1 7| |12 RB6 ; ReverseOutput<------- RB2 8| |11 RB5 ; Strobe<-------------- RB3 9+-----+10 RB4 ;========================================================================== ; ; Versions ; ;========================================================================== ; Version 2.3: add a reverse output to coil, detect rotor __-__ ; Version 2.6: modif calculation, detect rotor --_-- ; Version 2.8: modif register ; Version 3.0: correction at low RPM, or big retard. ; Version 3.1: deboun=1ms, initial delay=18ms, detect rotor high __-__ ; Version 3.2: suppression extra pluses at low RPM ; Version 4.0: simplification, 4MHz cristal.trigger on decreasing edge ; Version 4.1: trigger on rising edge ; Version 4.2: map move at the end of the soft. max adv=0ms ; Version 4.3: range 1500-16000RPM (for 2strokes) ; ; ;========================================================================== ; ; Directives ; ;========================================================================== list p=16f84a ; processor type ; __config B'11111111110001' ; No code protect, PWRT on, no watchdog, Quartz 4to20Mhz ; ; Page 0: 0-FF page1: 100-1FF page2: 200-2FF page3: 300-3FF ;========================================================================== ; ; Register Definitions ; ;========================================================================== W EQU H'0000' F EQU H'0001' ;----- Register Files------------------------------------------------------ INDF EQU H'0000' TMR0 EQU H'0001' PCL EQU H'0002' STATUS EQU H'0003' FSR EQU H'0004' PORTA EQU H'0005' PORTB EQU H'0006' EEDATA EQU H'0008' EEADR EQU H'0009' PCLATH EQU H'000A' INTCON EQU H'000B' OPTION_REG EQU H'0081' TRISA EQU H'0085' TRISB EQU H'0086' EECON1 EQU H'0088' EECON2 EQU H'0089' ;----- STATUS Bits -------------------------------------------------------- IRP EQU H'0007' RP1 EQU H'0006' RP0 EQU H'0005' NOT_TO EQU H'0004' NOT_PD EQU H'0003' Z EQU H'0002' DC EQU H'0001' C EQU H'0000' ;----- INTCON Bits -------------------------------------------------------- GIE EQU H'0007' EEIE EQU H'0006' T0IE EQU H'0005' INTE EQU H'0004' RBIE EQU H'0003' T0IF EQU H'0002' INTF EQU H'0001' RBIF EQU H'0000' ;----- OPTION Bits -------------------------------------------------------- NOT_RBPU EQU H'0007' INTEDG EQU H'0006' T0CS EQU H'0005' T0SE EQU H'0004' PSA EQU H'0003' PS2 EQU H'0002' PS1 EQU H'0001' PS0 EQU H'0000' ;========================================================================== ; ; Define ; ;========================================================================== #DEFINE rotor PORTA,3 ; [pin2]= sensor input #DEFINE coil PORTB,0 ; [pin6]= output to coil #DEFINE revcoil PORTB,2 ; [pin8]= reverse output to coil #DEFINE rpmmax PORTB,1 ; [pin7]= Min and Max RPM led #DEFINE led PORTB,7 ; [pin13]= pickup led #DEFINE strobe PORTB,3 ; [pin9] = strobe light output #DEFINE test PORTA,4 ; [pin3] = test jumper input ;========================================================================== ; ; RAM Definition ; ;========================================================================== rpmhi equ 0Ch ; RPM counter register high rpmlo equ 0Dh ; RPM counter register low dwell equ 0Eh ; dwell time counter rtdset equ 0Fh ; retard value holding register math equ 11h ; calculation register coilflg equ 12h ; coil status spkflg equ 13h ; flag after one spark rotflg equ 14h ; rotor sense flag retard equ 15h ; new retard value d1 equ 16h ;Temp value for the testdelay routine d2 equ 17h ;Temp value for the testdelay routine ;========================================================================== ; ; Main Program ; ;========================================================================== org 0 ; start adress 0 start bsf STATUS,RP0 ; go to bank 1 movlw H'FF' ; set all portA.. movlw TRISA ; ..as inputs movlw H'00' ; set all portB.. movwf TRISB ; ..as outputs ; movlw b'11000001' ; no pull-up,rising edge int,internal timer,1:4 movwf OPTION_REG bcf STATUS,RP0 ; come back into bank 0 ; clrw ; clear all variables clrf PORTA ; clear variables clrf PORTB clrf math clrf rpmlo clrf coilflg movlw 0xff ; rpmhi = FF initially movwf rpmhi movwf spkflg ; no spark until pickup is high movwf rotflg ; and no spark loop if pickup stay up movwf retard ; retard value = 25ms initially ; ; ; 100uS loop time ; 4MHz clock / 4 = 1MHz instruction cycle ; cycle time = 1/1MHz = 100uS ; 100uS/100uS = 100 cycles ; prescaler set to divide by 4 ; preset TMR0 = 231, when = 0 = 100uS ; 231 to 255 = 25 x 4(prescaler) = 100 ; movlw .231 ;movlw .206 for a 8MHz clock movwf TMR0 ; ; btfss test ; if the test jumper is set (low) goto testdelay ; goes to testdelay routine mnloop movf TMR0,W btfss STATUS,Z ; is TMR0=0 ? goto mnloop ; no, main delay loop ; movlw .231 ; yes, re-preset TMR0 (240max) movwf TMR0 ; incf rpmlo,F ; increment rpmlo btfsc STATUS,Z ; is rpmlo = 0 ? incf rpmhi,F ; yes, increment rpmhi ; ; if rpm count > 1400h, 5120 x 100us=0.5 Secs, then it is assumed that the ; motor has stopped. Reinitialize system. movlw 0x14 subwf rpmhi,W btfsc STATUS,Z ; rpmhi - 14 = 0 ? goto start ; yes ; ;rotchk btfss rotor ; + is rotor high or low? rotchk btfsc rotor ; (- detect pickup low) (CH ignitions sensor) goto rnowlw ; low ; movf rotflg,W ; high, is it flagged high also? rotflg=FF? btfss STATUS,Z goto coilck ; yes ; movlw 0xff ; no movwf rotflg ; flag rotor as up bsf led ; turn ignition pickup led on clrf spkflg ; reset flag for one spark goto rpmcalc ; calculate RPM ; rnowlw movf rotflg,W ; is it flagged low already ? rotflg=0? btfsc STATUS,Z goto coilck ; yes, wasn't flagged high ; dolow bcf led ; no, turn ignition pickup led off clrf rotflg ; flag rotor as down goto mnloop ; decret decf retard,F ; no, decrement retard then wait goto mnloop ; coilck movf coilflg,W ; is coil flagged high? coilflg=FF? btfss STATUS,Z goto upcoil ; yes, then decrement dwell count movf retard,W ; is retard = 0 ? btfss STATUS,Z goto decret ; no, then decrement retard ; movf spkflg,W ; yes, a spark have been done? spkflg=FF? btfss STATUS,Z goto mnloop ; yes, no more spark ; bsf coil ; no, go on for the first spark bsf strobe ; same for strobe bcf revcoil movlw 0xff ; set flag for high coil movwf coilflg movwf spkflg ; set flag for one spark ; ****************** YOU CAN MODIFY THE DWELL VALUE BELLOW ******** movlw .1 ; 10 X 100uS = 1ms movwf dwell ; set dwell time ; goto mnloop ; upcoil ; if dwell # 0 then dwell - 1 ; if dwell now = 0, turn on coil ; decfsz dwell,F ; dwell = dwell - 1 goto mnloop ; dwell <> 0, wait bcf coil ; dwell = 0, turn coil off bcf strobe ; same with strobe bsf revcoil ; dwell = 0, turn revcoil on clrf coilflg ; set flag for low coil goto mnloop ; rpmcalc ; engine RPM <= 1500 at maximum retard, = 40ms ; ; 40mS = 400 X 100us loops, = 190h ; ( 1500RPM for a 1cyl - 4stroke with one spark loose ) ; ( 1500RPM for a 1cyl - 2stroke ) ; ( 750RPM for a 4cyl - 4stroke = 25Hz ) ; ; engine RPM >= 16000 at maximum advance, = 3.8mS ; 3.8mS = 38 X 100uS loops, = 26h ; ( 16000RPM for a 1cyl - 4stroke with one spark loose ) ; ( 16000RPM for a 1cyl - 2stroke ) ; ( 8000RPM for a 4cyl - 4stroke = 266Hz ) ; ; this routine determines whether the engine RPM ; value is below 38 loop counts - max advance, or above ; 400 loop counts - max retard, or some where in between. ; ; ; high RPM: ; > 16000RPM ; movf rpmhi,W btfss STATUS,Z ; is rpmhi = 0? goto bigfv ; no ; movf rpmlo,W xorlw 0x26 ; yes, is rpmlo = 26h ? btfsc STATUS,Z goto maxadv ; yes, do max advance ; movlw 0x26 subwf rpmlo,W ; no, is rpmlo < 26h ? btfss STATUS,C goto maxadv ; yes, do max advance ; ; medium RPM: goto caladv ; no, calculate new advance ; ; ; low RPM: ; < 1500RPM bigfv movf rpmhi,W xorlw .1 ; is rpmhi = 1 ? btfsc STATUS,Z goto resfv ; yes, see if rpmlo = 90h ; movlw .1 subwf rpmhi,W ; no, is high byte > 1 ? btfsc STATUS,C goto maxret ; yes, do max retard ; goto caladv ; no, calculate new advance ; resfv movf rpmlo,W xorlw 0x90 ; rpmhi = 1, does rpmlo = 90h ? btfsc STATUS,Z goto maxret ; yes, do max retard ; movlw 0x90 subwf rpmlo,W ; no, is rpmlo > 90h ? btfsc STATUS,C goto maxret ; yes, do max retard ; ; ; the formula to get the data stored in the map is as follows ; ; rpmhi/lo count - 37 ; 116 - --------------------------- ; 4 ; caladv movlw d'37' ; rpmhi/lo - 37 subwf rpmlo,F ; rpmlo = rpmlo - 37 btfss STATUS,C decf rpmhi,F ; ; divide result by 4 ; bcf STATUS,C rrf rpmhi,F rrf rpmlo,F ; / 2 ; bcf STATUS,C rrf rpmhi,F rrf rpmlo,F ; / 4 ; ;bcf STATUS,C ;rrf rpmhi,F ;rrf rpmlo,F ; / 8 ; movlw .116 ; 116 entries in map list movwf math ; movf rpmlo,W subwf math,W ; W = 116 - result ; bcf PCLATH,0 ; be sure to go h'200' bsf PCLATH,1 ; where is the map. call map ; read map movwf rtdset ; come back with new retard value ; rpmset clrf rpmhi ; clear RPM counters clrf rpmlo movf rtdset,W ; transfert advance value movwf retard goto mnloop ; (therefore minimum retard is 1 loop-100us) ; maxret movlw 0x0 movwf rtdset ; retard value = 32h (5ms) bcf rpmmax ; turn off maxrpm led goto rpmset ; maxadv clrf rtdset ; retard value = 5ms bsf rpmmax ; turn on maxrpm led goto rpmset ; map org h'200' ; store map at 200h addwf PCL,1 ; add W + PCL ; *********** INSERT YOUR OWN VALUES HERE ******************* retlw 0h ;0ms retlw 1h ;0,1ms 1503rpm retlw 1h ;0,1ms 1517rpm retlw 2h ;0,2ms 1531rpm retlw 3h ;0,3ms 1545rpm retlw 3h ;0,4ms 1559rpm retlw 4h ;0,4ms 1573rpm retlw 4h ;0,5ms 1587rpm retlw 5h ;0,5ms 1601rpm retlw 5h ;0,5ms 1616rpm retlw 5h ;0,6ms 1631rpm retlw 5h ;0,6ms 1646rpm 27Hz retlw 6h ;0,7ms 1661rpm retlw 6h ;0,7ms 1677rpm retlw 7h ;0,8ms 1692rpm retlw 7h ;0,8ms 1708rpm retlw 8h ;0,9ms 1724rpm retlw 8h ;0,9ms 1741rpm retlw 9h ;1ms 1758rpm retlw 0ah ;1ms 1775rpm retlw 0bh ;1,1ms 1792rpm retlw 0bh ;1,1ms 1809rpm retlw 0ch ;1,2ms 1827rpm retlw 0ch ;1,2ms 1846rpm retlw 0dh ;1,3ms 1864rpm retlw 0dh ;1,3ms 1883rpm retlw 0eh ;1,4ms 1902rpm retlw 0eh ;1,4ms 1922rpm retlw 0fh ;1,5ms 1942rpm retlw 0fh ;1,5ms 1962rpm retlw 10h ;1,6ms 1983rpm retlw 10h ;1,6ms 2004rpm retlw 11h ;1,7ms 2026rpm retlw 11h ;1,7ms 2048rpm retlw 12h ;1,8ms 2070rpm retlw 12h ;1,8ms 2093rpm 35Hz retlw 13h ;1,9ms 2116rpm retlw 13h ;1,9ms 2140rpm retlw 13h ;1,9ms 2165rpm retlw 14h ;2ms 2190rpm retlw 14h ;2ms 2215rpm retlw 15h ;2,1ms 2241rpm retlw 15h ;2,1ms 2268rpm retlw 16h ;2,2ms 2295rpm retlw 17h ;2,3ms 2323rpm retlw 18h ;2,4ms 2351rpm retlw 18h ;2,4ms 2381rpm retlw 19h ;2,5ms 2411rpm retlw 19h ;2,5ms 2441rpm retlw 1ah ;2,6ms 2473rpm 41Hz retlw 1ah ;2,6ms 2505rpm retlw 1ah ;2,6ms 2538rpm retlw 1bh ;2,7ms 2572rpm retlw 1bh ;2,7ms 2606rpm retlw 1ch ;2,8ms 2642rpm retlw 1ch ;2,8ms 2679rpm retlw 1dh ;2,9ms 2716rpm retlw 1dh ;2,9ms 2755rpm retlw 1dh ;2,9ms 2795rpm retlw 1dh ;2,9ms 2836rpm retlw 1eh ;3ms 2878rpm retlw 1eh ;3ms 2921rpm retlw 1eh ;3ms 2965rpm retlw 1fh ;3,1ms 3011rpm retlw 1fh ;3,1ms 3059rpm retlw 20h ;3,2ms 3107rpm retlw 20h ;3,2ms 3158rpm retlw 21h ;3,3ms 3210rpm retlw 21h ;3,3ms 3263rpm retlw 21h ;3,3ms 3319rpm retlw 22h ;3,4ms 3376rpm retlw 22h ;3,4ms 3435rpm retlw 23h ;3,4ms 3496rpm retlw 23h ;3,4ms 3560rpm retlw 24h ;3,5ms 3626rpm retlw 24h ;3,5ms 3694rpm retlw 25h ;3,6ms 3765rpm retlw 25h ;3,6ms 3838rpm retlw 25h ;3,6ms 3914rpm 65Hz retlw 26h ;3,7ms 3994rpm retlw 26h ;3,7ms 4077rpm retlw 27h ;3,8ms 4163rpm retlw 27h ;3,8ms 4252rpm retlw 28h ;4ms 4346rpm 72Hz retlw 28h ;4ms 4444rpm retlw 28h ;4ms 4546rpm retlw 28h ;4ms 4653rpm retlw 29h ;4,1ms 4765rpm retlw 29h ;4,1ms 4883rpm retlw 2ah ;4,2ms 5006rpm retlw 2ah ;4,2ms 5136rpm retlw 2ah ;4,2ms 5273rpm retlw 2bh ;4,3ms 5417rpm retlw 2bh ;4,3ms 5569rpm retlw 2ch ;4,4ms 5729rpm retlw 2ch ;0,4ms 5899rpm retlw 2dh ;4,5ms 6080rpm retlw 2dh ;4,5ms 6272rpm retlw 2dh ;4,5ms 6476rpm retlw 2eh ;4,6ms 6693rpm retlw 2eh ;4,6ms 6926rpm retlw 2fh ;4,7ms 7176rpm retlw 2fh ;4,7ms 7443rpm retlw 30h ;4,8ms 7732rpm retlw 30h ;4,8ms 8044rpm 134Hz retlw 30h ;4,8ms 8381rpm retlw 31h ;4,9ms 8748rpm retlw 31h ;4,9ms 9149rpm retlw 32h ;5ms 9587rpm retlw 32h ;5ms 10070rpm retlw 32h ;5ms 10604rpm 168Hz retlw 32h ;5ms 11196rpm retlw 32h ;5ms 11859rpm retlw 32h ;5ms 12605rpm 1ms retlw 32h ;5ms 13451rpm retlw 32h ;5ms 14418rpm 240Hz retlw 32h ;5ms 15534rpm ; *********** END OF YOUR OWN VALUES ****************************** retlw 8h ; in case of overlap ; line544 ; ; reset vector ; ; org 300h ; if the program is loose, ; ; ; goto start ; It goes back home. ; ; ;===================JMJ================================ ;Test routine, sends ignition pulses to the thyristor at 4hz/140hz, ;selectable by rotor input. testdelay ; btfss test ; checks the jumper to disconnect test mode ; goto start bsf rpmmax bcf led btfss rotor ; checks hall device. slow test if low, fast test if high goto slowtest goto fasttest slowtest bsf led ; Delay = 0.005 seconds ; Clock frequency = 4 MHz ;4998 cycles movlw 0xE7 movwf d1 movlw 0x04 movwf d2 Delay_0 decfsz d1, f goto $+2 decfsz d2, f goto Delay_0 goto $+1 goto trigger ; triggers the thyristor goto testdelay fasttest bsf led ; Delay = 0.3 seconds ; Clock frequency = 4 MHz ;299998 cycles movlw 0x5F movwf d1 movlw 0xEB movwf d2 Delay_1 decfsz d1, f goto $+2 decfsz d2, f goto Delay_1 goto $+1 goto trigger ; triggers the thyristor goto testdelay trigger bsf coil ; set output bcf revcoil ; set reverse output ; Delay = 0.002 seconds ; Clock frequency = 4 MHz movlw 0x8F movwf d1 movlw 0x02 movwf d2 Delay_3 decfsz d1, f goto $+2 decfsz d2, f goto Delay_3 ;2 cycles goto $+1 bcf coil bsf revcoil goto testdelay ; ;=============================End JMJ============================= end