UberNewbie can't set his clock...


Closed Thread
Results 1 to 20 of 20
  1. #1
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323

    Default UberNewbie can't set his clock...

    Greetings all,

    Well... another total PIC newbie here...

    I've dabbled in electronics for a few decades and can generally navigate my way around hardware pretty well.
    But I'm *totally* new to PIC's and programming in general, so please be gentle with me...

    I'm attempting to build a project that requires an RTC with battery backup and an LCD display that displays (among other things).. the real time.
    The problem I'm having is setting the clock.

    I'm using a 16F690, a DS1302, and a standard 16x2 LCD (in 4-bit mode). Compiler is PICBASIC PRO and programmer is a PICkit2.
    I've got the DS1302 and LCD up and running just fine. The clock keeps (and displays) time just fine. I also have no trouble detecting the set buttons.

    The problem is SETTING the clock. I think I'm either math challenged and/or just generally clueless here.

    The sample program I started with sets the initial time manually when you load the PIC, but what I need of course is to set it with buttons. That's where my troubles begin.

    Here's some snippets of my code, so you've got an idea where I'm at: (just the relevant bits I think)

    Code:
    	' Allocate variables
    	rtcyear var      byte
    	rtcday  var      byte
    	rtcmonth var     byte
    	rtcdate var      byte
    	rtchr   var      byte
    	rtcmin  var      byte
    	rtcsec  var      byte
    	rtccontrol  var  byte
    '**This is what I want to do away with and replace with buttons:
    Code:
            ' Set initial time 
            rtcyear = $09   'Set Year
            rtcday = $05    'Set Day
            rtcmonth = $1  'Set Month
            rtcdate = $1   'Set Date of month
            rtchr = $21     'Set Hour
            rtcmin = $03    'Set Minutes
            rtcsec = $20    'Set Seconds
            Gosub settime   ' DO IT! - Set the time

    '**This is the main goods:
    Code:
       ' Subroutine to write time to RTC
    settime:
            RST = 1         ' Ready for transfer
    
            Shiftout IO, SCLK, LSBFIRST, [$8e, 0]  ' Enable write
    
            RST = 0         ' Reset RTC
    
            RST = 1         ' Ready for transfer
    
            ' Write all 8 RTC registers in burst mode
            Shiftout IO, SCLK, LSBFIRST, [$be, rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, 0]
    
            RST = 0         ' Reset RTC
            
    
            Return       
            
    
        ' Subroutine to read time from RTC               
    gettime:
            RST = 1         ' Ready for transfer
    
            ' Read all 8 RTC registers in burst mode
            Shiftout IO, SCLK, LSBFIRST, [$bf]      
            Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol]
    
            RST = 0         ' Reset RTC
            Return
    
        ' Main program loop - updates the LCD with the time
    mainloop:         
            Gosub gettime   ' Read the time from the RTC
            
            ' Display time on LCD
            Lcdout $fe, 1, $fe, 2, hex2 rtchr, ":", Hex2 rtcmin, ":", Hex2 rtcsec,_
            $fe,$C0, "        ", Hex2 rtcmonth, "/", Hex2 rtcdate, "/" , Hex2 rtcyear
                  
    
            Pause 100       ' slow things down a bit to keep the LCD from freaking out
            
            gosub checkbuttons
    
            Goto mainloop   ' repeat until nauseated...

    When a button is detected I call a subroutine that's supposed to increment the minutes (or hours) to set the clock. This is where I'm tOO sTOoPid:

    Code:
    increminute:
            rtcmin= rtcmin + 1
            if rtcmin >= 60 then
            rtcmin = 0
            endif
            
            gosub settime
                
            return
    ---------

    Even that part works... to a degree. It does set the time on the clock. THE PROBLEM is that it sets the minutes on the LCD in HEX!

    if I start at 03 minutes (as shown on the LCD) and increment with the set button, it works fine until I get past 09... then it goes to 0A, OB, OE, etc. instead of continuing at 10, 11, 12, etc.
    Clearly, this will not do!

    Can someone please help me out of the darkness here? Or at least give me a shove in the right direction? I've searched about a million websites and forum posts, but....

    Thanks very much,
    Steve

  2. #2
    sinoteq's Avatar
    sinoteq Guest


    Did you find this post helpful? Yes | No

    Default To Hex or not :)

    Hi
    You have made this problem yourself and you will soon see it but do not worry we have all made something similar.

    First,
    In Set initial time you load the variables, this is good. But you load them in HEX form, that is bad. Example "rtchr = $21" will not load 21 in hours but 33. That are way too many hours for an earth clock "rtchr = 21 " will put 21 in hours so delete all the $ signs to use decimal numbers for the init.

    Secondly,
    Main loop Do not use the LCD command with HEX2 because this will make PBP to use HEX on the display and that is you main problem. Change the HEX2 to DEC2 and you will see a difference.

    Good luck.

  3. #3
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Thank you sinoteq !

    I tried the code without the $ in front of the variables, and using DEC2 instead of HEX2 in the LCDOUT command as you suggested, and now the button to set the time works fine. BUT, the time no longer displays correctly.

    Now it skips certain numbers (groups of 6 it seems) as it goes from 0 to 60, and it counts to 90 instead of 60 before it increments the minute and resets seconds to 0...

    So now the time "increment minutes" button goes from 0 to 60 then resets as is desired, but the time displayed from the RTC goes to 90 seconds and skips numbers.

    I'm open for more suggestions!

    Thanks,
    Steve

  4. #4
    sinoteq's Avatar
    sinoteq Guest


    Did you find this post helpful? Yes | No

    Default Ds1302

    If you look at the datasheet for the DS you will se that you have to do some formating of the DS result before you can display it. The DS does not store each SEC MIN HOUR and so on as a byte, it is stored in a mixed byte (I bet Melanie knows the correct word for it)

    Example:
    The register for seconds is 8 bits wide but is split into a 10 SEC part and a SEC part. So you have to look at the DS data as (n*10SEC)+SEC.
    You have to move this into a byte before you can display it. I have never used DS1302 but I have used the DS1307 and the idea is similar.

    Please look at http://pdfserv.maxim-ic.com/en/ds/DS1302.pdf Table 3 page 9

  5. #5
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    (I bet Melanie knows the correct word for it)

    Melanie has all kinds of words for all kinds of situations... but in this instance I'll chose to use BCD (Binary Coded Decimal)...

  6. #6
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Thanks folks,

    Yes, BCD is what it is I guess. And that explains why it works to use HEX2 to send to the LCD and why DEC2 doesn't work right.

    It also explains why when manually loading the time..

    Code:
    rtcmin = $11    'Set Minutes
    ..it works to say the numbers are HEX when you're really entering DEC info. For numbers from 0 to 9 it works, AND it puts the digits in the right place for BCD.

    If I want to set the minutes to 11, it works to say "rtcmin = $11"
    But if I try to enter it as "11" with out the $..
    Code:
    rtcmin = 11    'Set Minutes
    ..when it loads into the clock as BCD, it ends up as "1A" on the display.

    I can picture what's going on (although I don't think I've put it in words well)
    but I don't know how to solve the problem...

    After I increment my variable "rtcmin" by 1, is there a way to "fool" things into thinking it's hex again? (without actually to converting hex. I want "12 = $12", not "12 = 0C")

    Am I totally lost?

  7. #7
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    Can you figure the code behind this?...

    Code:
    	BCDByte=DecimalByte DIG 1
    	BCDByte=BCDByte<<4
    	BCDByte=BCDByte+DecimalByte DIG 0
    When DecimalByte=12, then BCDByte=$12

    or put another way...

    Code:
    	BCDByte=((DecimalByte DIG 1)<<4)+DecimalByte DIG 0

  8. #8
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Ahhh, thank you Melanie!
    A first glance tells me that is exactly what I'm looking for !

    I think the Shift Left Operator (<<) may be just what I'm after!

    I got sidetracked today...
    Code:
    GOSUB DoWifeChores
     DoWifeChores:
                        finish building new kitchen cabinet
    
      RETURN
    Tomorrow morning I'll see what I can do with that left shift operator and I'll report back.
    Thanks very much!

    Steve

  9. #9
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Ha Ha Ha ! Sorry, but it just struck me as funny . . .
    Code:
    If DoWifeChores = 1 THEN
    goto WifeHappy
    ELSE
    IF DoWifeChores = 0 THEN
    GOTO OnMyOWN
    endif
    
    OnMyOwn:
    Cook 
    Laundry
    Sleep Cold ' In all it's many possible meanings
    Look for apartment
    
    WifeHappy:
    Wife cooks
    Does Laundry
    Keeps you warm
    Let's you stay
    You have time to PIC :D
    finish building new kitchen cabinet
    Revenge for all those New Yankee Workshop videos she had to endure
    Last edited by Archangel; - 4th January 2009 at 07:37.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  10. #10
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Thanks to everyone that responded!

    Melanie, I still couldn't that snippet of code you supplied to work right. Using Dig 0 and Dig 1 to pick the 1's and 10's digits out of the BCD didn't give the desired results...

    What finally DID work for me was to split the minutes data apart using bitwise AND (&) like so:

    Code:
       BCDByteH = rtcmin & %11110000 'get the high nibble
       BCDByteL = rtcmin & %00001111 'get the low nibble
    That got my upper and lower 4 bits separated out OK so I can increment/decrement them with the pushbuttons.
    When I'm done I put them back together into rtcmin with bitwise OR (|)


    Code:
      rtcmin = BCDByteH | BCDByteL 
          
        gosub settime
    That seems to be working so far. More testing still to make sure...

    Anyway, thanks to all!

    (Oh, and Joe S., you MUST be a married man. You seem to know the code for it pretty well.

    Steve

  11. #11
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Byte_Butcher View Post
    (Oh, and Joe S., you MUST be a married man. You seem to know the code for it pretty well.

    Steve
    HE HE HE, YOU GOT IT ! I got a list of honey do's longer than a road across Texas, AND I got another list of Sonny Do's from my mother. Keeps me outta trouble.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  12. #12
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    Just for the record, the examples I posted are valid, tried and tested...

    Not knowing how you are manipulating your code and Buttons behind the scenes doesn't help... but, if your Seconds Button for example incremented the Seconds every time you pressed or held it...

    Code:
    	While SecondsButton=0
    		Seconds=Seconds+1
    		If Seconds>59 then Seconds=0
    		Pause 250
    		Wend
    That will give you a variable 'Seconds' which will contain a (Decimal) value in the range 0-59.

    Running it through either if the routines I posted previously you get...

    DecimalByte Decimal (HEX) = BCDByte Decimal (HEX)

    0-9 ($00-$09) = 0-9 ($00-$09)
    10-19 ($0A-$13) = 16-25 ($10-$19)
    20-29 ($14-$1D) = 32-41 ($20-$29)
    30-39 ($1E-$27) = 48-57 ($30-$39)
    40-49 ($28-$31) = 64-73 ($40-$49)
    50-59 ($32-$3B) = 80-89 ($50-$59)

    ...which then can be used for the Seconds Register for the timer chip.

    Now those routines are only valid for the range 0-99 giving a BCD of $00-$99, which is fine if you are setting clocks as you're only interested in 0-59 worst-case anyway.

    The way you've implimented things seems kinda hard work, if individually you are incrementing units seperately from the tens.

    Melanie, I still couldn't that snippet of code you supplied to work right. Using Dig 0 and Dig 1 to pick the 1's and 10's digits out of the BCD didn't give the desired results...
    Of course it didn't... that routine pulls the units and tens digits out a DECIMAL number to construct (encode) the BCD - not to decode the BCD... you weren't asking for that in your original post! To construct DECIMAL from BCD, you can do something simple like...
    Code:
    	DecimalByte=(BCDByte>>4)*10+(BCDByte & $0F)

  13. #13
    sinoteq's Avatar
    sinoteq Guest


    Did you find this post helpful? Yes | No

    Default little of topic but...

    Melanie and her "one line wonders" of code made me curious. In what order does PBP actually calculate and do things?
    Let's use her latest code as an example:

    Code:
    DecimalByte=(BCDByte>>4)*10+(BCDByte & $0F)
    Obviously the BCDByte is shifted right by 4 and the top 4 bits are made to 0. After the >>4 the data in BCDByte is "broken" and only the 4 low bits are valid.

    Will
    Code:
    DecimalByte=(BCDByte & $0F)+((BCDByte>>4)*10)
    give the same results?

    When does the shift command actually change the data in BCDByte?

  14. #14
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by sinoteq View Post
    When does the shift command actually change the data in BCDByte?
    It is my understanding that the shift command in a case like this will not change the data.
    It only tells what part of the value to use in the calculation.
    Dave
    Always wear safety glasses while programming.

  15. #15
    Join Date
    Jul 2003
    Posts
    2,358


    Did you find this post helpful? Yes | No

    Default

    OK, lets break this down...

    DecimalByte=(BCDByte>>4)*10+(BCDByte & $0F)

    The calculations in the brackets will be perfomed first, and the results stored in a PICBasic variable behind the scenes. BCDByte is unchanged - just as well because we refer to it twice, once to access the top four bits, and once to access the bottom four bits.

    Thereafter, PBP follows mathematical rules of priority... ie Multiplication and Division are performed before addition ans subtraction. Because items in brackets are always calculated from the centre out, and each set of brackets is it's own self-contained world, the result of the formula below, will be the same as that above.

    DecimalByte=(BCDByte & $0F)+((BCDByte>>4)*10)

    However, you do have an extra set of brackets there... but PBP actually resolved the formula without any additional penalty. Might not be so lucky on another occasion.

  16. #16
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Thanks again Melanie,
    Hmmm, I think I almost understand what's going on with that code. I must actually be learning something.

    I ended up with this, from the code you supplied and it works excellent.

    Code:
    increminute: 
    
            rtcmathtemp =(rtcmin>>4)*10+(rtcmin & $0F)  'convert BCD minutes into Decimal minutes
            
            rtcmathtemp=rtcmathtemp+1   'increment by 1
            If rtcmathtemp>59 then      'If minutes exceeds 59
            rtcmathtemp=0               'reset to 0
            endif
      
            rtcmin=((rtcmathtemp DIG 1)<<4)+rtcmathtemp DIG 0 'convert Decimal back to BCD
    
            gosub settime
           
            return

  17. #17
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default Sure would like to turn the trickle charger on...

    Sigh, well I seem to have a new problem. Although I'm obviously able to read/write to the DS1302 in "burst" mode, I seem to be having a problem addressing individual registers.

    For instance, I need to turn the trickle charger on...
    I *thought* it was as simple this:
    Code:
            rst = 1
    
            'Set Battery charger on and set to "1 diode, 2Kohm"
            Shiftout IO, SCLK, LSBFIRST, [$90, $A5]  ' Set charger   [$90, $A5] 
     
            RST = 0
    But that doesn't seem to do it for me.

    Anyone got the patience to help me along a little further....

    p-p-p-please?

    Thanks!

    Steve

  18. #18
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Hi Steve, check uot pages5/ 6 of this data sheet, it says: DS 1302 powers up with trickle charger disabled and only a pattern of 1010 will enable charger. http://forums.parallax.com/forums/attach.aspx?a=26594 HTH
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  19. #19
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Thanks Joe,
    You can't imagine how many times I've read the data sheet.... (it's been open on my desktop for days now)
    I'm clearly not quite understanding yet.

    Yes, a pattern of 1010 turns on the charger, and the other 4 bits of the byte set the charge rate.

    So what ( I think) I want to send is 10100101 which should tun on the charger and set it to "1 diode, 2Kohm" operation. In HEX, that's $A5, right?

    So I've sent $90, which should be the register address for the charger, and $A5, which should be the code to turn it on and set it to my chosen charge mode. I even tried sending the data in binary, like so:
    Code:
            rst = 1
    
            'Set Battery charger on and set to "1 diode, 2Kohm"
            Shiftout IO, SCLK, LSBFIRST, [$90, %10100101]  ' Set charger   [$90, $A5] 
     
            RST = 0
    but with the same (no) result.

    What am I doing wrong? (please!)

    Thanks,
    Steve

  20. #20
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Ahh, never mind, I figured it out...

    Setting up the trickle charger is the first task task I ask of the DS1302, and I just needed to pull the reset line LOW first, before I yank it high and move the data.
    All I was missing was "rst = 0" up front:

    Code:
     
           rst = 0
           rst = 1
    
            'Set Battery charger on and set to "1 diode, 2Kohm"
            Shiftout IO, SCLK, LSBFIRST, [$90, %10100101]  ' Set charger   [$90, $A5] 
     
            RST = 0
    Thanks again to everyone!

    Steve

Similar Threads

  1. Interruptus Frustratus
    By Byte_Butcher in forum General
    Replies: 16
    Last Post: - 17th April 2009, 20:36
  2. 16F628A - Stops if release power switch.
    By dene12 in forum General
    Replies: 16
    Last Post: - 14th February 2009, 07:57
  3. Help with sound command in 2 programs
    By hyperboarder in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 5th July 2007, 20:36
  4. error on compiling
    By parker in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 16th June 2005, 14:31
  5. How to set external clock source in PBP
    By TurboLS in forum mel PIC BASIC Pro
    Replies: 28
    Last Post: - 19th February 2005, 15:56

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts