1. 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.
    Dismiss Notice

Digital Clock(Big)... Using PIC

Discussion in 'Electronic Projects Design/Ideas/Reviews' started by Ayne, May 6, 2007.

  1. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    I think you may have misunderstood (or I wasn't clear). I was suggesting directly driving each display with some sort of latch with 25-ma/pin capability. No multiplexing at all. Of course there's no reason to throw 6 ICs at the solution (grin) and as you say it probably isn't a viable solution with "big displays".
     
    Last edited: May 9, 2007
  2. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    I believe you have a workable solution Sir. And it seems you've settled on Common Anode displays.

    Have fun. Mike
     
  3. Ayne

    Ayne New Member

    Joined:
    Apr 30, 2006
    Messages:
    415
    Likes:
    0
    Location:
    Multan, Pakistan.
    Where is GRAMO.
    GRAMO are u going to show basic code for the above project??

    Thanks
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. gramo

    gramo New Member

    Joined:
    Oct 2, 2006
    Messages:
    1,221
    Likes:
    23
    Location:
    Newcastle, Australia

    lol, I won't write the whole thing, but surely a push in the right direction will help.

    Personally, I would prefer to use 7 I/O's for the segment's, instead of adding the 4511. Now you have one less component, and the whole project is still very doable with a single 28 Pin PIC.

    From there, you need 'Shadow Registers' that contain the Hour/Minute/Second data. Multiplexing each buffer quickly would ensure the displays would not appear to flicker.

    The following was written with Swordfish, and the wiring diagram is just a piccy from my site, so you could use the same analogy, but with a different circuit;
    Note: This code displays how to use the ISRTimer library. Two timers are set up. One to increment a variable, the other to multiplex the displays

    Code (text):
    Device = 18F452
    Clock = 20

    #option _Segment_Port = PORTC                      // Define the 7-Segment PORT
    #option _Segment_TRIS = GetTRIS(_Segment_Port)     // Nice way to automatically get the TRIS
                                                       //  automatically from a selected port
                                                       
    Include "ISRTimer.bas"  
    Include "utils.bas"

    Dim Segment_1_TRIS As TRISD.1,                     // User must define what pins control
        Segment_2_TRIS As TRISD.0,                     //  each segment
        Segment_1 As PORTD.1,
        Segment_2 As PORTD.0            
    Dim Number As Byte,                                // Program variables that require no
        Segment_Data As _Segment_Port,                 //  user settings
        Segment_TRIS As _Segment_TRIS,
        Segment_1_Data As Byte,
        Segment_2_Data As Byte

    Const
        Timer1 = 0,
        Timer2 = 1
     
    // Update_Segments event, multiplex the segment data...
    Sub Update_Segments()

        If Segment_1 = 1 Then
            Segment_1 = 0
            Segment_Data = Segment_2_Data
            Segment_2 = 1
        Else
            Segment_2 = 0
            Segment_Data = Segment_1_Data
            Segment_1 = 1    
        EndIf

    End Sub

    Function Segment_Encode(Segment_Byte As Byte) As Byte  // Convert a byte into segment information
        Select Segment_Byte
                Case 0
                Result = %00111111
                Case 1         
                Result = %00000110
                Case 2         
                Result = %01011011
                Case 3         
                Result = %01001111
                Case 4         
                Result = %01100110
                Case 5         
                Result = %01101101
                Case 6         
                Result = %01111100
                Case 7         
                Result = %00000111
                Case 8         
                Result = %01111111
                Case 9         
                Result = %01100111       
            EndSelect
    End Function

    Sub EncodeSegmentData()                          // Encodes segment data

        Segment_1_Data = Digit(Number,1)             // Extract the first digit & convert it
        Segment_1_Data = Segment_Encode(Segment_1_Data)
        Segment_2_Data = Digit(Number,2)             // Extract the second digit & convert it
        Segment_2_Data = Segment_Encode(Segment_2_Data)

    End Sub

    // Increment_Number event will increment the register Number
    Sub Increment_Number()

        Inc(Number)
        If Number = 100 Then
            Number = 0
        EndIf
       
        EncodeSegmentData

    End Sub

    // Start Of Program...
    Timer.Initialize(2)                              // initialize the timer module...

    // initialise each timer
    Timer.Items(Timer1).Interval = 5                 // 5ms
    Timer.Items(Timer1).OnTimer = @Update_Segments   // timer1 event handler
    Timer.Items(Timer2).Interval = 500               // 500ms
    Timer.Items(Timer2).OnTimer = @Increment_Number  // timer2 event handler

    Number = 0                                       // Initialize variables
    EncodeSegmentData

    Segment_TRIS = %00000000                         // Make the segment data lines outputs
    Low(Segment_1_TRIS)
    Low(Segment_2_TRIS)

    Timer.Items(Timer1).Enabled = True               // enable the timers...
    Timer.Items(Timer2).Enabled = True
    Timer.Start                                      // start processing all timers...
     
    // main program loop...
    While True

    Wend
     
    [​IMG]
     
  6. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Driving segments directly from I/O pins is fine for a few displays but the I/O pins just can't meet the peak current demands when you lower the duty cycle with 4 or more displays.

    I'm pretty good at analyzing code but I'm lost with that example. Why not just use a 1-msec interrupt to "scan" the display and update the Clock variables once per second (once per 1000 interrupts)?

    I'm pretty proud of my High Performance PWM display design -- a single IC and six or seven transistors, and you don't need a 28 pin PIC
     
    Last edited: May 10, 2007
  7. gramo

    gramo New Member

    Joined:
    Oct 2, 2006
    Messages:
    1,221
    Likes:
    23
    Location:
    Newcastle, Australia

    The multiplexing is done every 5mS, this could be lowered too 1mS if you want, just a matter of changing this line;
    Code (text):
    Timer.Items(Timer1).Interval = 1                 // 1ms
    Timer.Items(Timer1).OnTimer = @Update_Segments   // timer1 event handler
    Now, every 1mS, the following Procedure will execute;
    Code (text):
    // Update_Segments event, multiplex the segment data...
    Sub Update_Segments()

        If Segment_1 = 1 Then
            Segment_1 = 0
            Segment_Data = Segment_2_Data
            Segment_2 = 1
        Else
            Segment_2 = 0
            Segment_Data = Segment_1_Data
            Segment_1 = 1    
        EndIf

    End Sub
    Of course you can add more displays if need be, but I would consider using a variable to track what segment is being displayed, and use a Select Case routine, like this;
    Code (text):
    Inc(Current_Display)                                 //
    If Current_Display = 6 Then Current_Display = 0      // Roll over to first display if required
    Select Current_Display                               // Find out what data to display
        Case 0
            // Display Seconds_0
        Case 1
            // Display Seconds_1
        Case 2
            // Display Minutes_0
        Case 3
            // Display Minutes_1
        Case 4
            // Display Hours_0
        Case 5
            // Display Hours_1
    EndSelect
    As for meeting the peak current demands, well the demands are met by the ULN2003 (upto 500mA per channel). It is driven by logic voltages (from the PIC)
     
    Last edited: May 10, 2007
  8. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    It seems you may not be familiar with duty cycle, average, and peak current.

    If you multiplex 8 displays you'll have a 12.5% duty cycle. The 20-ma or so peak current that an I/O pin can supply to an individual LED will have an "average" current of 2.5-ma and your display will be much dimmer.
     
    Last edited: May 11, 2007
  9. Ayne

    Ayne New Member

    Joined:
    Apr 30, 2006
    Messages:
    415
    Likes:
    0
    Location:
    Multan, Pakistan.
    I am making Main Board in Eagle.
    But there is a problem
    [​IMG]
    How to connect +5 Volts and ground to IC2(4028) and IC1(4511).

    (I will make it's PCB in Eagle)
    Thanks
     
  10. Ayne

    Ayne New Member

    Joined:
    Apr 30, 2006
    Messages:
    415
    Likes:
    0
    Location:
    Multan, Pakistan.
    My project is approx 80% completed.

    Power Supply And it's PCB.

    [​IMG]

    [​IMG]



    Display Board And it's PCB

    [​IMG]

    [​IMG]


    Main Board(Pcb under construction)

    [​IMG]


    I am enjoying this Project.
    I am writing it's code in MikroBasic.
    Code is approx completed but not tested yet...

    Soon i will post the Whole Project here.

    Thanks.
     
  11. gramo

    gramo New Member

    Joined:
    Oct 2, 2006
    Messages:
    1,221
    Likes:
    23
    Location:
    Newcastle, Australia
    Just a pointer: You can open the pictures in Paint and use the "Stretch/Skew" feature to make them smaller ;)

    Why not use Logic FET's? That way you could drive them without the transistor/resistors in place, saving 18 components!
     
  12. Hero999

    Hero999 Banned

    Joined:
    Apr 6, 2006
    Messages:
    14,902
    Likes:
    79
    Location:
    England
    What MOSFETs are you using?

    What current are you passing through them?

    The chances are you don't even need logic level MOSFETs as they will be alright at low currents with a low gate voltage. Check out the datasheet.
     
  13. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    :DThe last 10% of the project takes 90% of the total project time.
     
  14. demestav

    demestav Member

    Joined:
    Aug 15, 2003
    Messages:
    139
    Likes:
    0

    Excuse me if it is a stupid question, but with which software do you design these? They look REALLY nice...

    Thank you
     
  15. Ayne

    Ayne New Member

    Joined:
    Apr 30, 2006
    Messages:
    415
    Likes:
    0
    Location:
    Multan, Pakistan.
    I have changed the IDEA :D
    Now the Idea is:
    Using PIC16F877A.
    Clock will show the "Time And Date And Day And Temperature(later) also"

    Now i am working on Schamatic...

    I will post as it will complete.
     
  16. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Day-of-week may be difficult to display on 7-segment displays. I thought about using 7 discrete LEDs for one project (below).

    Temperature, or Outside Temp' and Inside Temp' display modes is a good idea. I thought about adding it to my 16F88 clock using one-wire DS18B20 temperature probes since I have 3 pins left over (grin).

    You need a 40 pin 16F877A?


    (drawings were done using drawing tools in Excel 2000)
    [​IMG]
     
    Last edited: May 18, 2007
  17. Ayne

    Ayne New Member

    Joined:
    Apr 30, 2006
    Messages:
    415
    Likes:
    0
    Location:
    Multan, Pakistan.
    I have Complete my Design.

    Now i am using PIC16F877A.
    20MHz Crystel.

    I am not enough expert in Assembly. I have write small program like blinking LEDs in Assembly but never do any big project with it but now i an going to program this project in Assembly.

    [​IMG]

    If there will be some problem in programming in Assembly i will ask u.. I mean it is only possiable with ur help.

    What u say,
    I should use Two seprate crystal, one for PIC clock Frequnecy and one for Clock TICK.

    OR

    Only one crystal For both Purpose..

    Plz give me a right Direction. (Which Timer I use for which purpose i mean For Scaning purpose which Timer or For Timer TIck Which Timer)

    I request to Administator.. "Plz delete all post from above this POST".. I was going to start a new Thread but i not started. I don't want to listen huge on my this request. Remain Focus on Project in this thread.

    Thanks
     
    Last edited: May 18, 2007
  18. mneary

    mneary New Member

    Joined:
    Feb 27, 2007
    Messages:
    4,502
    Likes:
    67
    Location:
    California USA
    The command to use is invoke.
     
  19. kybert

    kybert New Member

    Joined:
    May 15, 2004
    Messages:
    164
    Likes:
    0
    Location:
    Bristol, England
    Mike, how can this circuit have brightness control? Can you do a timeing diagram showing the PWM signal in relation to the update signals for setting the segment values?
     
  20. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    I use a 1 msec PWM period and I 'scan' the display columns using that 1 msec Timer 2 interrupt. The displays are blanked when the PWM signal is high at the beginning of each interrupt cycle and that's when I borrow the column driver lines RB1 and RB2 to load the MIC5821 shift register. One display column is turned on when the PWM signal goes low. Varying the PWM duty cycle between 2% and 100% provides full fade-to-black brightness control from 98% to 0%, respectively. The interrupt driver (listing below) uses 12 instruction words plus a few instructions later on to setup the SEGDAT and COLPOS variables for the next 'scan' interrupt cycle. You don't see anything in the driver code for brightness control because it's pretty much an invisible background process. Simply change the CCPR1 duty cycle register at any time in your Main program to adjust display brightness.

    The green area in the drawing below is the portion of the digit or column scan interval where the display is "on" (during the PWM "off time").

    [​IMG]

    Code (text):
    ;
    ;  The seven LED columns are 'scanned' one at a time at 1-msec
    ;  interrupt intervals for an overall 14.3% LED duty cycle and
    ;  142.85-Hz refresh rate...
    ;
    ;  A minimum PWM 'on' time of 2% guarantees a minimum window
    ;  of 20-usecs (80 instruction cycles) at the beginning of
    ;  each interrupt cycle where PWM drives the <OE> input high
    ;  (display off)...  This allows me to reuse the RB1 and RB2
    ;  column driver lines temporarily as '5821 <DAT> and <CLK>
    ;  lines to load the '5821 (without messing up the display)
    ;  before RB1 and RB2 resume their column driver duties when
    ;  PWM drives <OE> low (display on)...
    ;
    ;  The 2% minimum PWM 'on' time limits maximum brightness to
    ;  98% but the 2% loss of brightness is inperceivable
    ;
    ISR_LED
            movlw   d'8'            ;                                 |B0
            movwf   TEMP            ; serial bit count                |B0
    ISR_Load
            bcf     SERCLK          ; preset '5821 CLK line lo (RB1)  |B0
            bcf     SERDAT          ; preset '5821 DAT line lo (RB2)  |B0
            rlf     SEGDAT,F        ; shift data bit into Carry       |B0
            skpnc                   ; a '1' bit?                      |B0
            bsf     SERDAT          ; yes, set SERDAT line to 1       |B0
            bsf     SERCLK          ; clock data bit into the '5821   |B0
            decfsz  TEMP,F          ; all 8 bits sent/loaded?         |B0
            goto    ISR_Load        ; no, branch and do another       |B0
    ;
    ;  now setup Port B column drivers before PWM drives the '5821
    ;  <OE> pin low to turn on the segment driver outputs & display
    ;
    ;  COLPOS variable cycles through the following fixed values
    ;  one interrupt at a time to 'scan' the display and switches;
    ;
    ;  00000010, column 1, inverted 11111101
    ;  00000100, column 2, inverted 11111011
    ;  00001000, column 3, inverted 11110111
    ;  00010000, column 4, inverted 11101111
    ;  00100000, column 5, inverted 11011111
    ;  01000000, column 6, inverted 10111111
    ;  10000000, column 7, inverted 01111111
    ;
    ISR_Column
            comf    COLPOS,W        ; invert bits (only 1 bit low)    |B0
            movwf   PORTB           ; setup the column drivers        |B0
    ;
     
     

    Attached Files:

    Last edited: Dec 2, 2007
  21. kybert

    kybert New Member

    Joined:
    May 15, 2004
    Messages:
    164
    Likes:
    0
    Location:
    Bristol, England
    Ah i think i see what your doing:

    When the PWM goes high

    1. Set MIC5821 output to off (linked to PWM signal)
    2. Clock in the required 7-seg code into the MIC5821.
    3. Enable the next digit RBx line.

    When the PWM goes low, the digit is shown. All other digits are off.
    Repeat for each digit.

    This means that each display is lit up in turn, and is on for 1/7th of the total time required to show all 7 digits as they take it in turn.

    In that case, does the current to the display have to be 7 times greater than the normal If ? E.g. a 7-seg element may be rated at 25mA, so it should be driven at 175mA ?
     
    Last edited: Dec 2, 2007

Share This Page