February 2010 Archives
Sat Feb 13 17:23:47 CET 2010
Set time of Nixie clock
To set the time of my Nixie clock, I have added a button to my schematic and updated the software.
Yes, the schematic is ugly, ....
Click for larger picture
... the source code is ugly, ....
Yes, the schematic is ugly, ....
Click for larger picture
... the source code is ugly, ....
LIST p=PIC16F648A INCLUDE "p16f648a.inc" errorlevel -302 __CONFIG _CP_OFF&_DATA_CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF&_INTOSC_OSC_NOCLKOUT cblock h'20' menu ; 0 = display clock ; 1 = menu HH ; 2 = menu HL ; 3 = menu MH ; 4 = menu ML submenu HZ50counter button ; count how long button is pressed tmp DL DH S H M ML MH HL HH tens_and_ones bin hundreds TENS ONES DisplayCounter endc org h'0000' init: bsf STATUS, RP0 ; select bank 1 ; bcf PCON, OSCF ; CLK=48Khz movlw b'11111000' ; 1 = input 0 = output movwf TRISA ; set input/output PORTA clrf TRISB ; PORTB = output bcf STATUS, RP0 ; select bank 0 movlw h'07' ; turn comparators off movwf CMCON main: movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clrf H clrf M clrf S clrf menu clrf submenu clrf button clrf DisplayCounter incf DisplayCounter, F Loop: btfsc PORTA, D'3' goto released incf button, F movlw D'2' subwf button, w btfss STATUS, Z goto cont1 pressed: ; pressed for longer then 1Sec clrf button ; reset counter movf submenu, w btfsc STATUS, Z goto INCmenu ; if pressed and no submenu then INC menu movlw D'1' subwf menu, w btfss STATUS, Z goto XH movlw D'10' addwf H, F XH: movlw D'2' subwf menu, w btfsc STATUS, Z incf H, F movlw D'3' subwf menu, w btfss STATUS, Z goto XM movlw D'10' addwf M, F XM: movlw D'4' subwf menu, w btfsc STATUS, Z incf M, F ; Convert Hour:Minutes to HH,HL:MH,ML ; ---------------------------------------------------- movf M, w call Convert movf TENS, w movwf MH ; Minutes High Digit movf ONES, w movwf ML ; Minutes Low Digit movf H, w call Convert movf TENS, w movwf HH ; Hour High Digit movf ONES, w movwf HL ; Hour Low Digit ; --------------------------------------------------- goto cont1 INCmenu: incf menu, F goto cont1 released: clrf button movf submenu, w btfsc STATUS, Z goto Enter_Submenu clrf menu clrf submenu goto cont1 Enter_Submenu: clrf submenu incf submenu, F cont1: movlw D'5' subwf menu, w btfsc STATUS, Z clrf menu ; if menu = 5 then menu = 0 movf menu, W btfsc STATUS, Z goto clock1 ; if menu = 0 then display normal clock movf submenu, w btfsc STATUS, Z goto DISPmenu ; Display :menu movlw D'1' subwf menu, w btfss STATUS, Z goto x1 movf HH, w call number_to_digit x1: movlw D'2' subwf menu, w btfss STATUS, Z goto x2 movf HL, w call number_to_digit x2: movlw D'3' subwf menu, w btfss STATUS, Z goto x3 movf MH, w call number_to_digit x3: movlw D'4' subwf menu, w btfss STATUS, Z goto x4 movf ML, w call number_to_digit x4: goto DC1 DISPmenu: movf menu, W call number_to_digit bsf PORTA, D'2' goto DC1 clock1: clrf submenu ; Display Nothing and update HH,HL:MH,ML movlw d'1' subwf DisplayCounter, w btfss STATUS, Z goto clock2 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA ; Convert Hour:Minutes to HH,HL:MH,ML ; ---------------------------------------------------- movf M, w call Convert movf TENS, w movwf MH ; Minutes High Digit movf ONES, w movwf ML ; Minutes Low Digit movf H, w call Convert movf TENS, w movwf HH ; Hour High Digit movf ONES, w movwf HL ; Hour Low Digit ; --------------------------------------------------- clock2: ; Display HH movlw d'2' subwf DisplayCounter, w btfss STATUS, Z goto clock3 movf HH, w call number_to_digit clock3: ; Display Nothing movlw d'3' subwf DisplayCounter, w btfss STATUS, Z goto clock4 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clock4: ; Display HL movlw d'4' subwf DisplayCounter, w btfss STATUS, Z goto clock5 movf HL, w call number_to_digit clock5: ; Display Nothing movlw d'5' subwf DisplayCounter, w btfss STATUS, Z goto clock6 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clock6: ; Display : movlw d'6' subwf DisplayCounter, w btfss STATUS, Z goto clock7 movlw b'00000000' movwf PORTB movlw b'00000100' movwf PORTA clock7: ; Display Nothing movlw d'7' subwf DisplayCounter, w btfss STATUS, Z goto clock8 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clock8: ; Display MH movlw d'8' subwf DisplayCounter, w btfss STATUS, Z goto clock9 movf MH, w call number_to_digit clock9: ; Display Nothing movlw d'9' subwf DisplayCounter, w btfss STATUS, Z goto clock10 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clock10: ; Display ML movlw d'10' subwf DisplayCounter, w btfss STATUS, Z goto clock11 movf ML, w call number_to_digit clock11: ; Display Nothing, and reset DisplayCounter movlw d'11' subwf DisplayCounter, w btfss STATUS, Z goto DCup movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA DC1: clrf DisplayCounter DCup: incf DisplayCounter, F clrf HZ50counter HZ50islow: btfss PORTA, d'4' goto HZ50islow HZ50ishigh: btfsc PORTA, d'4' goto HZ50ishigh incf HZ50counter, F ; Do every 1/50 sec. : 50HZcounter++ movlw d'50' subwf HZ50counter, w ; 50 * 1/50 seconds -> 1 second btfss STATUS, Z goto HZ50islow second: incf S, F ; Do every second : S = S + 1 movlw d'60' subwf S, w btfsc STATUS, Z ; If S = 60 then goto minute goto minute goto M1 minute: clrf S ; S was 60, so we do M = M + 1 and S = 0 ; OK, it's time to update the clock by 1 minute ; --------------------------------------------- incf M, F movlw d'60' subwf M, w btfss STATUS, Z goto M1 movwf M incf H, F movlw d'24' subwf H, w btfss STATUS, Z goto M1 movwf H M1: goto Loop ; ---------------------------------------------------------------------------- ; Subroutines ; ---------------------------------------------------------------------------- number_to_digit: movwf tmp BTFSC STATUS, Z ; if tmp = 0 then tmp = 10 movlw D'10' movwf tmp movlw b'00000001' movwf DL clrf DH ; DH:DL = 0000000000000001 dountilzero: decfsz tmp, F goto isnotzero movf DL, w movwf PORTB movf DH, w movwf PORTA return isnotzero: BCF STATUS, C rlf DL, F rlf DH, F goto dountilzero ;----------------------------------------------------------------------; ; Change binary nbr in bin to BCD ; ;----------------------------------------------------------------------; binary_to_bcd: ; by Scott Dattalo clrf hundreds swapf bin, W addwf bin, W andlw B'00001111' skpndc addlw 0x16 skpndc addlw 0x06 addlw 0x06 skpdc addlw -0x06 btfsc bin,4 addlw 0x16 - 1 + 0x6 skpdc addlw -0x06 btfsc bin,5 addlw 0x30 btfsc bin, 6 addlw 0x60 btfsc bin,7 addlw 0x20 addlw 0x60 rlf hundreds, f btfss hundreds, 0 addlw -0x60 movwf tens_and_ones btfsc bin,7 incf hundreds, f return ;----------------------------------------------------------------------; ; Display binary value in W in decimal ; ;----------------------------------------------------------------------; Convert: movwf bin call binary_to_bcd ; movf hundreds, W ; I don't use numbers > 99 ; movwf ... swapf tens_and_ones, W andlw H'F' movwf TENS movf tens_and_ones, W andlw H'F' movwf ONES return ; ---------------------------------------------------------------------------- end ; ----------------------------------------------------------------------------.... there are bugs, for example it's possible to set the clock's time to 67:89, but it does work
Sat Feb 6 20:28:50 CET 2010
Nixie clock with PIC16f648a
After driving a nixie tube with a PIC16f648a it's time to do something more usefull with it, for example a clock.
Because the PIC16f648a is running with it's internal oscillator, and the circuit is powered by 230V 50Hz, I decided to synchronize the clock with the 50Hz mains frequency (look at RA4 in the schematic drawing) which will be more accurate.
Click for larger picture
And I have updated the PIC program so it displays a clock and uses the RA4 input to synchronize the clock with with the 50Hz mains frequency.
Click on the photo above to see the Nixie clock in action
or
click here to see it on youtube
(warning: low quality movie)
ToDo:
Because the PIC16f648a is running with it's internal oscillator, and the circuit is powered by 230V 50Hz, I decided to synchronize the clock with the 50Hz mains frequency (look at RA4 in the schematic drawing) which will be more accurate.
Click for larger picture
And I have updated the PIC program so it displays a clock and uses the RA4 input to synchronize the clock with with the 50Hz mains frequency.
LIST p=PIC16F648A INCLUDE "p16f648a.inc" errorlevel -302 __CONFIG _CP_OFF&_DATA_CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF&_INTOSC_OSC_NOCLKOUT cblock h'20' HZ50counter tmp DL DH S H M ML MH HL HH tens_and_ones bin hundreds TENS ONES DisplayCounter endc org h'0000' init: bsf STATUS, RP0 ; select bank 1 ; bcf PCON, OSCF ; CLK=48Khz movlw b'11111000' ; 1 = input 0 = output movwf TRISA ; set input/output PORTA clrf TRISB ; PORTB = output bcf STATUS, RP0 ; select bank 0 movlw h'07' ; turn comparators off movwf CMCON main: movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clrf H clrf M clrf S clrf DisplayCounter incf DisplayCounter, F Loop: ; Convert Hour:Minutes to HH,HL:MH,ML ; ----------------------------------- movf M, w call Convert movf TENS, w movwf MH ; Minutes High Digit movf ONES, w movwf ML ; Minutes Low Digit movf H, w call Convert movf TENS, w movwf HH ; Hour High Digit movf ONES, w movwf HL ; Hour Low Digit test1: ; Display Nothing movlw d'1' subwf DisplayCounter, w btfss STATUS, Z goto test2 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA test2: ; Display HH movlw d'2' subwf DisplayCounter, w btfss STATUS, Z goto test3 movf HH, w call number_to_digit test3: ; Display Nothing movlw d'3' subwf DisplayCounter, w btfss STATUS, Z goto test4 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA test4: ; Display HL movlw d'4' subwf DisplayCounter, w btfss STATUS, Z goto test5 movf HL, w call number_to_digit test5: ; Display Nothing movlw d'5' subwf DisplayCounter, w btfss STATUS, Z goto test6 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA test6: ; Display : movlw d'6' subwf DisplayCounter, w btfss STATUS, Z goto test7 movlw b'00000000' movwf PORTB movlw b'00000100' movwf PORTA test7: ; Display Nothing movlw d'7' subwf DisplayCounter, w btfss STATUS, Z goto test8 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA test8: ; Display MH movlw d'8' subwf DisplayCounter, w btfss STATUS, Z goto test9 movf MH, w call number_to_digit test9: ; Display Nothing movlw d'9' subwf DisplayCounter, w btfss STATUS, Z goto test10 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA test10: ; Display ML movlw d'10' subwf DisplayCounter, w btfss STATUS, Z goto test11 movf ML, w call number_to_digit test11: ; Display Nothing and reset DisplayCounter movlw d'11' subwf DisplayCounter, w btfss STATUS, Z goto test12 movlw b'00000000' movwf PORTB movlw b'00000000' movwf PORTA clrf DisplayCounter test12: incf DisplayCounter, F clrf HZ50counter HZ50islow: btfss PORTA, d'4' goto HZ50islow HZ50ishigh: btfsc PORTA, d'4' goto HZ50ishigh incf HZ50counter, F ; Do every 1/50 sec. : 50HZcounter++ movlw d'50' subwf HZ50counter, w ; 50 * 1/50 seconds -> 1 second btfss STATUS, Z goto HZ50islow second: incf S, F ; Do every second : S = S + 1 movlw d'60' subwf S, w btfsc STATUS, Z ; If S = 60 then goto minute goto minute goto M1 minute: clrf S ; S was 60, so we do M = M + 1 and S = 0 ; OK, it's time to update the clock by 1 minute ; --------------------------------------------- incf M, F movlw d'60' subwf M, w btfss STATUS, Z goto M1 movwf M incf H, F movlw d'24' subwf H, w btfss STATUS, Z goto M1 movwf H M1: goto Loop ; ---------------------------------------------------------------------------- ; Subroutines ; ---------------------------------------------------------------------------- number_to_digit: movwf tmp BTFSC STATUS, Z ; if tmp = 0 then tmp = 10 movlw D'10' movwf tmp movlw b'00000001' movwf DL clrf DH ; DH:DL = 0000000000000001 dountilzero: decfsz tmp, F goto isnotzero movf DL, w movwf PORTB movf DH, w movwf PORTA return isnotzero: BCF STATUS, C rlf DL, F rlf DH, F goto dountilzero ;----------------------------------------------------------------------; ; Change binary nbr in bin to BCD ; ;----------------------------------------------------------------------; binary_to_bcd: ; by Scott Dattalo clrf hundreds swapf bin, W addwf bin, W andlw B'00001111' skpndc addlw 0x16 skpndc addlw 0x06 addlw 0x06 skpdc addlw -0x06 btfsc bin,4 addlw 0x16 - 1 + 0x6 skpdc addlw -0x06 btfsc bin,5 addlw 0x30 btfsc bin, 6 addlw 0x60 btfsc bin,7 addlw 0x20 addlw 0x60 rlf hundreds, f btfss hundreds, 0 addlw -0x60 movwf tens_and_ones btfsc bin,7 incf hundreds, f return ;----------------------------------------------------------------------; ; Display binary value in W in decimal ; ;----------------------------------------------------------------------; Convert: movwf bin call binary_to_bcd ; movf hundreds, W ; I don't use numbers > 99 ; movwf ... swapf tens_and_ones, W andlw H'F' movwf TENS movf tens_and_ones, W andlw H'F' movwf ONES return ; ---------------------------------------------------------------------------- end ; ----------------------------------------------------------------------------
Click on the photo above to see the Nixie clock in action
or
click here to see it on youtube
(warning: low quality movie)
ToDo:
- Make a better looking schematic drawing
- Add a switch or something to set the time of the clock, so I don't have to wait at 00:00 to power the circuit
- Solder the floating electronic components on the circuit board
Mon Feb 1 22:54:13 CET 2010
Drive Nixie tube digits with a PIC16f648a
After making a power supply to drive a nixie tube and adding 11 BUZ80 SIPMOS Power Transistors it was time to add a PIC to the circuit.
Click for larger picture
To test if everything works as expected, I have written a little test program (asm) to display all the digits ( 1 2 3 4 5 6 7 8 9 0 : ) in a loop.
Click on the photo above to see the Nixie clock in action
or
click here to see it on youtube
(warning: low quality movie)
ToDo:
Click for larger picture
To test if everything works as expected, I have written a little test program (asm) to display all the digits ( 1 2 3 4 5 6 7 8 9 0 : ) in a loop.
LIST p=PIC16F648A INCLUDE "p16f648a.inc" errorlevel -302 __CONFIG _CP_OFF&_DATA_CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF&_INTOSC_OSC_NOCLKOUT cblock h'20' delay1 delay2 delay3 endc org h'0000' init: bsf STATUS, RP0 ; select bank 1 ; bcf PCON, OSCF ; CLK=48Khz movlw b'11111000' ; 1 = input 0 = output movwf TRISA ; set input/output PORTA clrf TRISB ; PORTB = output bcf STATUS, RP0 ; select bank 0 movlw h'07' ; turn comparators off movwf CMCON main: movlw b'00000001' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00000010' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00000100' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00001000' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00010000' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00100000' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'01000000' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'10000000' movwf PORTB movlw b'00000000' movwf PORTA call Delay movlw b'00000000' movwf PORTB movlw b'00000001' movwf PORTA call Delay movlw b'00000000' movwf PORTB movlw b'00000010' movwf PORTA call Delay movlw b'00000000' movwf PORTB movlw b'00000100' movwf PORTA call Delay goto main ; ---------------------------------------------------------------------------- ; Subroutines ; ---------------------------------------------------------------------------- ; Delay = 1 seconds ; Clock frequency = 4 MHz ; Actual delay = 1 seconds = 1000000 cycles ; Error = 0 % Delay ;999990 cycles movlw 0x07 movwf delay1 movlw 0x2F movwf delay2 movlw 0x03 movwf delay3 Delay_0 decfsz delay1, f goto $+2 decfsz delay2, f goto $+2 decfsz delay3, f goto Delay_0 ;6 cycles goto $+1 goto $+1 goto $+1 ;4 cycles (including call) return ; Generated by http://www.piclist.com/cgi-bin/delay.exe (December 7, 2005 version) ; Sat Jan 30 23:37:02 2010 GMT ; See also various delay routines at http://www.piclist.com/techref/microchip/delays.htm ; ---------------------------------------------------------------------------- end ; ----------------------------------------------------------------------------
Click on the photo above to see the Nixie clock in action
or
click here to see it on youtube
(warning: low quality movie)
ToDo:
- Make a better looking schematic drawing
- Do something useful with it, instead of just counting numbers