Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Binary Clock Pic16F54

Status
Not open for further replies.

Talcum

New Member
Hello,

I just wondered if anybody could help me? I am trying to make a binary clock for my brother as a Christmas present but I have run into a few problems. I have started by using the text "The PIC Microcontroller" by John Morton which appears a lot on this forum.

The good news is that it kind of works :p, the code I have (which is written in .ASM) does count up the seconds to the right timing, and the so does the minutes and hours, but I have tried to be clever and use portb as the output for seconds, minutes and hours and porta is used to drive a transistor so that the correct LED bank (sec, min & hour) illuminate when called upon. This feature is referred to as strobing in the text and minimises the required number of I/O.

I currently have this project on a breadboard and I am using the pic16f54, and my connections for my pic are as follows

1 - Connected to Base of transistor 3 (drives hour LED bank) via a 68ohm resistor
2 - Not connected (NC)
3 - NC
4 - Connected to +4.5V supply via a 1.5k resistor
5 - +4.5V supply
6 - LED bank 1 ,2 & 3 (Bit 0 - LSB)
7 - LED bank 1 ,2 & 3 (Bit 1)
8 - LED bank 1 ,2 & 3 (Bit 2)
9 - LED bank 1 ,2 & 3 (Bit 3)
10 - LED bank 1 ,2 & 3 (Bit 4)
11 - LED bank 1 ,2 & 3 (Bit 5 - MSB)
12 - NC
13 - NC
14 - NC
15 - NC
16 - Connected to a 2MHz Crystal Oscilator
17 - Connected to Base of transistor 1 (drives seconds LED bank) via a 68ohm resistor
18 - Connected to Base of transistor 2 (drives minutes LED bank) via a 68ohm resistor

The Oscillator is set to XT
WDT = OFF
Code Protect = OFF

I have attached my code (BCLKv7).

Now when I power up this circuit the following happens

1) Seconds LED bank functions correctly
2) The minutes LED bank appears to be an amalgamation of the seconds and minutes timer
3) What should be the hours LED bank functions as the minutes LED bank perfectly without the amalgamation.

Now obviously if I swap pins 18 and 1 on the PIC it half solves the problem, but this isnt the answer. I have played around with the porta assignment in case I have shorted tracks on my breadboard and this doesn't appear to be the problem. Does anyone have any ideas?

Im sorry this is my first post. I know its a bit long, but I though it best to include everything.

P.S. I wanted to add a schematic with this post, what's the best way to do this? Do you simply use a particular program and upload it as an attachment?

P.S.S. I know at this time their is know way of setting the clock, but im just talking one step at a time as im quite new to this :)

Thanks Guys,

Talcum
 
Last edited:
I cannot open your attachments.
From what you say your mixed up with the multiplex o/ps.
Sounds like either the anodes or cathodes of all the dipslay leds for secs/mins and hours are commoned up and selected probably by a transistor, like a bc547 or the like.
Did you connect up the commons to a transistor or have you just connected them to ground or +v, this would explain whats happening.
Please try again to post the schematic.
 
Thanks Dr Pepper.

I will try and upload my schematic and a photo of my bread board. Just ignore the bottom right hand corner.. it was something else I was tinkering with :)

View attachment 68837

With regard to your message, each cathode is connected to the collector of a transistor (there is a transistor for each LED bank). I dont think there is a short between them, I cant see one unless my bread board is faulty... ill get the multimeter out. Secondly im not sure it is that because if I reassign the bits of porta, the problem moves to different LED banks.

P.S. Could you let me know if the link isn't working? I have tried to post the schematic, photo and my code.

Thanks,
 
looking at your schem I'd say your suffering from the old favorite rmw failure (read-modify-write), unless the code has been written to prevent it.

Beause you have really low value resistors on the bases of the trannys when the micro writes a '1' to one of them the tranny will pull so much current that the micro o/p wont be able to reach a logic '1', the internal current limit of the micro will come into effect and keep the voltage down.
This means the micro would read back a '0' after writing a '1', this would totally mess up the multiplex routine.

You dont really need that low a value 68 ohm, try replacing those with 1k ohm and see what happens, wouldnt surprise me if it fired into life.
 
Last edited:
Thanks for the suggestions Dr Pepper & blueroom electronics.

I have exchanged the 68ohm resistors connected to each of base of the transistors. I have tried 680 ohm, 1.2K and 4.7K. Im afraid we have still got the same problem.

I have also added a 22uf cap between pin 14 and 0V.

Are we sure it isn't my code? I cant see any errors in it. Just to confirm the problems we have are

1) Seconds LED bank functions correctly
2) The minutes LED bank appears to be an amalgamation of the seconds and minutes timer
3) What should be the hours LED bank functions as the minutes LED bank perfectly without the amalgamation.

I think I am more concerned that the hours LED bank is behaving as the minutes bank. Could there be timing issues? My code and hardware could have holes in them as I have designed all this from scratch.

Thanks for your help guys!
 
Hi Talcum,

Please take a closer look at your 'display' routine. You may have a 'ghosting' problem.

Code:
display
        movlw   b'0001'         ; bit mask for RA0
        movwf   porta           ; turn on 'secs' column
        movfw   sec             ; wreg = 'secs', 0..59
        movwf   portb           ; display 'secs'

        movlw   b'0010'         ; bit mask for RA1
        movwf   porta           ; turn on 'mins' column
        movfw   min             ; wreg = 'mins', 0..59
        movwf   portb           ; display 'mins'

        movlw   b'0100'         ; bit mask for RA2
        movwf   porta           ; turn on 'hour' column
        movfw   hour            ; wreg = 'hour', 0..23
        movwf   portb           ; display 'hour'

        retlw   0

The first thing I noticed is that you're not blanking the display before changing columns. When you set PORTA to b'0001' to turn on the RA0 (sec) column, you'll display 'hour' data still present on PORTB on the RA0 (sec) column for 4 microseconds before PORTB is updated with 'sec' data. The RA0 column will then display the correct 'sec' data for 4 microseconds before you set PORTA to b'0010' to turn on the RA1 (min) column. At this point you'll be displaying 'sec' data for 4 microseconds on the RA1 (min) column before updating PORTB with the correct 'min' data. The correct 'min' data is displayed on the RA1 (min) column for 4 microseconds. Then, when you set PORTA to b'0100' to turn on the RA2 (hour) display, you display the 'min' data still present on PORTB on the RA2 (hour) column for 4 microseconds before loading PORTB with the correct 'hour' data. Finally, you exit the "display" routine and the 'hour' column will be lighted for a whopping ~15 milliseconds before you come back to refresh the display again.

Would you like some suggestions or would you rather work this out yourself?

Happy Holidays and cheerful regards, Mike
 
Last edited:
Yes with high brightness led's you'll be able to see the crossover.

I'd alter the code so that all common cathodes are first turned off, then new led display data loaded then the correct cathode on.
 
Yes with high brightness led's you'll be able to see the crossover.

I'd alter the code so that all common cathodes are first turned off, then new led display data loaded then the correct cathode on.

Could you show us an example of what you mean, please?
 
Nope.
It just happens that I have a clock project that suffers from ghosting, I video'd it for your benefit, but you cant see the ghosting in the slightest, I only have a 'phone to take video's and a poxy one at that.
What happens is the wrong data is displayed for a very short period, meaning that the wrong data (eg hours data rather than mins) can be seen dimly.
The idea is to blank the display completely before switching the cathode transistors.
 
Last edited:

I'm sorry. I meant a code example, not a video example.

May I ask if you know assembly language and if you've looked at Talcum's program? If so, do you have any other recommendations, perhaps concerning the very short display time during each ~15-mS interval? I was thinking that if he used a shorter loop interval, perhaps something like ~5-Ms, that he could modify the display routine to display one new column during each consecutive ~5-mS interval. What do you think of something like this with only 6-uS of blanking between column refresh cycles?

Code:
;
;  refresh one new column each 5 mS interval (isochronous) for
;  an effective ~66.6 Hz display refresh rate
;
        clrc                    ; advance column select bit
        rrf     colsel,F        ; was that last column (RA0)?
        skpnc                   ; no, skip, else
        bsf     colsel,2        ; reset to first column (RA2)
        movf    hour,W          ; wreg = hour, 0..23
        btfsc   colsel,1        ; mins? no, skip, else
        movf    min,W           ; wreg = mins, 0..59
        btfsc   colsel,0        ; secs? no, skip, else
        movf    sec,W           ; wreg = secs, 0..59
        clrf    PORTA           ; blank the display
        movwf   PORTB           ; setup new column bits
        movf    colsel,W        ; active hi column select bit
        movwf   PORTA           ; display new column
 
Last edited:
Ok I see.
I think 15ms would work, 5ms might give less flicker.
That code looks very efficient, you could maybe puit a couple of nops after clearing porta to make sure the leds go out, but I dont think thats really necessary leds (unlike nixies) are very quick.
colsel needs to be cleared at startup so you dont get any flickers at switch on.
The leds being connected to portb without resistors would cause rmw issues if the software doesnt allow for it, an easy test for this if you have it breadboarded is to put 1k resistors from the collectors of the cathode select transistors to the cathodes of the leds.
Another thing you can do, I see you have a 2meg osc, you could replace that with a 555 circuit so you can wind the speed right down and see whats going on if you dont have mplab.
At this point I'd be getting out the pickit and running the program a line at a time and watching the leds and the appropriate registers.

Mike: Heres a snippet of code I did for a led clock, I gave up writing efficient code pics have plenty of memory these days, I find it better to write code I can follow easy, note I never bothered with a display blank time, it still works fine in fact I write data for a com cathode display first then correct it for a com anode, I did everything wrong and the clock still works fine:

;
;-------------------------------------7 segment display driver----------------------------------
;
dscan incf disel,f ;scan each of the 4 7 segs in turn
movf disel,w
sublw d'5'
btfsc status,z
clrf disel
;
movf disel,w ;update ones
btfsc status,z
goto ones
;
movf disel,w ;update tens
sublw d'1'
btfsc status,z
goto tens
;
movf disel,w ;update hunds
sublw d'2'
btfsc status,z
goto hund
;
movf disel,w ;update thou's
sublw d'3'
btfsc status,z
goto thou
;
goto symb ;update display symbols
;
;--------------------------
;
ones movlw b'00010001'
movwf portb ;address anode for lsd
movf mins,w ;then display mins ones
call seg7
movwf porta
comf porta,f ;due to the display being com anode, invert all the bits
return
;
tens movlw b'00000010'
movwf portb ;address tens digit
movf mins1,w ;then display mins tens
call seg7
movwf porta
comf porta,f
return
;
hund movlw b'00000100'
movwf portb ;address hunds digit
movf hours,w ;then display hours ones
call seg7
movwf porta
comf porta,f
return
;
thou movlw b'00011000'
movwf temp ;address msd
movf hours1,w ;then display tens of hours
call seg7
movwf porta
comf porta,f
;
btfsc porta,5
goto rfon1
bsf temp,5
movf temp,w
movwf portb
return
;
rfon1 bcf temp,5
movf temp,w
movwf portb
return
;
symb movlw b'00100000' ;address symb com anode
movwf portb
btfss flags2,3 ;when msf ok is set turn on clock symbol
goto clkoff
clkon movlw b'00010000'
movwf porta
comf porta,f
return
clkoff clrw ;when msf not ok turn clk symbol off
movwf porta
comf porta,f
;
return
;
 
Last edited:
Thanks for the comments and the code example.

Perhaps Talcum will update us on his progress when he checks back in.

Happy Holidays. Mike
 
Last edited:
Not holidays for me, I'm in the uk I work 6 days a week.
 
Hey guys,

Thanks again for the help. After reading your posts, I must say I didn't understand the code you posted, however I did understand the theory that Mike K8LH had left with regards to ghosting. What I have done is change my display subroutine to the following

Code:
display		movfw	sec
			movwf	portb
			movlw 	b'0001'
			movwf	porta
			clrf 	 porta	

			movfw	min
			movwf	portb
			movlw 	b'0010'
			movwf	porta
			clrf 	porta

			movfw	hour
			movwf	portb
			movlw 	b'0100'
			movwf	porta
			clrf 	porta

			retlw	0

This I thought was the easiest way to do what you said. So anyway the good news is that we now have seconds, minutes and hours working!

Now I didn't mention this before, but the LED's are really quite dim also as the clock counts up more LED's come on, the more LED's that are on the less bright they illuminate (obviously there is more current draw).

I have added a Darlington Pair to each transistor to amplify the current, but its still not quite enough. I realised that strobing the LED's would loose light intensity as the LEDs are not on all of the time. To fix this I thought that I could call up the display subroutine more often to increase the intensity, however in doing so I thought the clock itself will be less and less accurate. What do you think is my best option to increase the light intensity?

BTW I tried adding a 1.2K ohm resistor to the cathode, and this just stopped the LED's illuminating altogether.

Thanks guys, good learning learning curve for me there. Im quite chuffed for a beginner tbh :)
 
Well, you're only lighting each column for 2 microseconds each ~15 millisecond interval. That's not very much "average" current per LED.

Would you mind trying the following program and tell us if the LEDs are any brighter? You'll have to change the file suffix from 'txt' to 'hex'.

Regards, Mike
 
Last edited:
Hi Mike,

Im afraid I cant try this at the moment as im just about to go away with work for a few weeks. I promise ill do this when I get back.

Thanks
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top