Clock and Dual Termometer


Closed Thread
Results 1 to 25 of 25

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Great - as long as it works for your needs.

    But you can't get away from the fact that you're interrupting at 61.035Hz while it ideally should be 61Hz. That little difference WILL make it run fast.

    Let's see.... For a duration of 100.000 interrupts a time of 100,000/61.035=1638.40 seconds have passed. Your code, because it divides by 61, will "display" 1639.34 seconds (the clock runs fast).

    Here's an idea... If you keep a second WORD sized tick counter incrementing in your ISR and when it hits 1754 you reset it to zero and skip updating your normal Ticks variable for that interrupt only. This way, in 100,000 interrupts you'll only increment your Ticks variable 100,000 - (100,000/1754) = 99943 times, resulting in "time" of 99943/61 = 1638.40 seconds - pretty darn close to ideal. The clock will zig-zag a little bit but the period is only about 28 seconds so I don't think you'll notice.

    It's still early here, I may have made some terrible misstake in the math (doesn't have to be early for that). Anyway, it's an idea you may want to look into.

    /Henrik.

  2. #2
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    582


    Did you find this post helpful? Yes | No

    Default If You see one crazy man, it's me !

    I re-re-re-read all the topics on this forum (searching for "timer") and I found one code (Josepino's code) for HIGH-accuracy clock.
    I try to compile them, but I have errors. What I do wrong ?
    Code:
    DEFINE NO_CLRWDT
    Define	OSC	4
    
    DEFINE  LCD_DREG        PORTB      ' LCD Data Port
    DEFINE  LCD_DBIT        4      ' Starting Data Bit
    DEFINE  LCD_RSREG       PORTA      ' Register Select Port
    DEFINE  LCD_RSBIT       1      ' Register Select Bit
    DEFINE  LCD_EREG        PORTA      ' Enable Port
    DEFINE  LCD_EBIT        0      ' Enable Bit
    DEFINE  LCD_BITS      4      ' Data Bus Size
    DEFINE  LCD_LINES      2      ' Number of Lines on LCD
    
    DEFINE LCD_COMMANDUS 2000
    DEFINE LCD_DATAUS 50
    
    
    
    TRISA= %11111000                    ' RA0..3=Outputs RA4=Input
    TRISB= %00001111                 	' RB0..RB2=Inputs, RB3..RB7=Outputs
    
    CMCON = 7        
    
    pushButton1 var portb.0 'switch
    pushButton2 var portb.1 
    pushButton3 Var portb.2
    pushButton4 Var portb.3
    
    pressed con 0   		;value of button pressed
    notPressed con 1 		;value of button not pressed
    
    dhour   var     byte    ' Define display hour variable
    
    i       var     byte    ' Debounce loop variable
    
    ticks   var     byte    ' Define pieces of seconds variable
    Seconds  var byte
    Minutes  var byte
    Hours    var byte
    Days     var byte
    Months   var BYTE 
    
    TempC           var     word
    Float           var     word
    Sign            var     bit           ' +/- sign
    DQ              var     PORTA.4       ' One-wire data pin
    TempC2          var     word
    Float2          var     word
    Sign2           var     bit           ' +/- sign
    DQ2             var     PORTA.3       ' One-wire data pin
    semn            var     word
    semn2           var     word
    DS18B20_1 CON %01011111         
    DS18B20_2 CON %01011111         
         
    
    ;DS18B20_9bit  CON %00011111         ; 93.75ms, 0.5°C
    ;DS18B20_10bit CON %00111111         ; 187.5ms, 0.25°C 
    ;DS18B20_11bit CON %01011111         ; 375ms,   0.125°C
      
    SecondsChanged   var bit
    MinutesChanged   var bit
    HoursChanged     var bit
    DaysChanged      var bit
    SecondsChanged = 1
    MinutesChanged = 1
        
            
        Seconds = 0
        Minutes = 0
        Hours = 12
        Days = 1
        Months = 1
        SecondsChanged = 1
        MinutesChanged = 1
        HoursChanged = 1
        DaysChanged = 1
    
    
    
    include "timp.pbp.txt"
    
    Pause 200                          ' Wait for LCD to Initialize
    
    ' Init Sensor 1
    OWOUT DQ, 1, [$CC, $4E, 0, 0, DS18B20_1]
    OWOut DQ, 1, [$CC, $48]             
    OWOut DQ, 1, [$CC, $B8]
    OWOut DQ, 1, [$CC, $BE]
    Pause 50
    OWIn DQ, 2, [TempC.byte0, TempC.byte1]
    Pause 50
    ' Init Sensor 2
    OWOUT DQ2, 1, [$CC, $4E, 0, 0, DS18B20_2]
    OWOut DQ2, 1, [$CC, $48]             
    OWOut DQ2, 1, [$CC, $B8]
    OWOut DQ2, 1, [$CC, $BE]
    Pause 50
    OWIn DQ2, 2, [TempC2.byte0, TempC2.byte1]
    Pause 50
    
    
    mainloop:
    if tick.0=1 then
    tick.0=0
    Seconds = Seconds + 1
           SecondsChanged = 1
           if Seconds = 60 then
              Minutes = Minutes + 1
              MinutesChanged = 1
              Seconds = 0
           endif
           if Minutes = 60 then
              Hours = Hours + 1
              HoursChanged = 1
              Minutes = 0
           endif
           if Hours = 24 then
              Days = Days + 1
              DaysChanged = 1
              Hours = 0
           endif
           if Days = 32 then
              Months = Months + 1
              Days = 1
           endif
           if months = 13 then
           months = 1
           endif
    endif
    
    
        ' Check button pressed to set time
        if pushbutton1 = pressed Then
        gosub set_minutes
        endif
        if pushbutton2 = pressed then
        gosub set_hours
        endif
        if pushbutton4 = pressed then
        gosub set_days
        endif
        if pushbutton3 = pressed then
        gosub set_Months
        endif    
            ' Check for time to update screen
        
        If SecondsChanged = 1  Then
            SecondsChanged = 0  ' Display time as hh:mm:ss
    LCDout $FE, $80, dec2 Hours,":",dec2 Minutes,":",dec2 Seconds,"   ",DEC2 Days,"/",DEC2 Months
    LCDOUT $FE, $C0, semn,DEC ABS TempC/100,".", DEC1 ABS TempC/10, 223,"C ", $FE, $C0 + 9, semn2,DEC ABS TempC2/100,".", DEC1 ABS TempC2/10, 223,"C   " 
    '                pauseus 1386
        Endif
    
    Goto mainloop   ' Do it all forever
            
              
            
    set_minutes:
    Minutes = Minutes + 1
    if Minutes = 60 then
    Minutes = 0
    endif
    gosub debounce
    return
    
    set_hours:
    Hours = Hours + 1
    if Hours = 24 then
    Hours = 0
    endif
    gosub debounce
    return
    
    set_days:
    Days = Days + 1
    if Days = 32 then
    Days = 1
    endif
    gosub debounce
    return
    
    set_months:
    Months = Months +1
    if Months = 13 then
    Months = 1
    endif
    gosub debounce
    return
    debounce:
    For i = 1 To 100	' Debounce and delay for 100ms
    	Pause 1	' 1ms at a time so no interrupts are lost
    	Next i
    SecondsChanged = 1
    return
    
    ;===================================================
    Read_Temp:
        ' Skip ROM search & do temp conversion
        OWOut DQ, 1, [$CC, $BE]
        OWIn  DQ, 2, [TempC.byte0, TempC.byte1]
    
        Sign = TempC.15
        TempC = ABS(TempC)
        TempC = ((TempC >> 4)*100) + ((TempC & $F)*100 >> 4)
        IF Sign THEN TempC = -TempC
    IF TempC.15 THEN
    Semn="-"
    else
    Semn="+"
    endif
        OWOut DQ2, 1, [$CC, $BE]
        OWIn  DQ2, 2, [TempC2.byte0, TempC2.byte1]         
    
        Sign2 = TempC2.15
        TempC2 = ABS(TempC2)
        TempC2 = ((TempC2 >> 4)*100) + ((TempC2 & $F)*100 >> 4)
        IF Sign2 THEN TempC2 = -TempC2
    IF TempC2.15 THEN
    Semn2="-"
    else
    Semn2="+"
    endif
    Return
    ;===================================================
       End

    and timp.pbp.txt
    Code:
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR0_INT,   int_handler,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    
        INT_ENABLE  TMR0_INT     ; Enable Timer 1 Interrupts  
    ENDASM
            OPTION_REG = %00001000	' Set TMR0 configuration
           INTCON = %10100000	' Enable TMR0 interrupts
    
    
    		bres_hi	VAR	BYTE bank0 system		' hi byte of our 24bit variable
    		bres_mid	VAR	BYTE bank0 system	'	; mid byte
    		bres_lo	VAR	BYTE bank0 system		'; lo byte
    						'; (we only need 3 bytes for this system)
    bres_hi = $0F
    bres_mid= $42
    bres_lo= $40
    		tick	VAR	BYTE bank0 system
    
    ASM
    ;******************************************************************************
    ;  INTERRUPT HANDLER     (runs this code each timer0 interrupt)
    ;******************************************************************************
    ;
    ;------------------
    int_handler				;
    ;------------------
    
    	;-------------------------------------------------
    
    
    
    	;-------------------------------------------------
    	; Note! we get here every 256 instructions, we
    	; can now do our special one second timing system.				
    
    	; This consists of three main steps;
    	; * subtract 256 counts from our 24bit variable
    	; * test if we reached the setpoint
    	; * if so, add 1,000,000 counts to 24bit variable and generate event.
    	;-------------------------------------------------
    						; * optimised 24 bit subtract here 
    						; This is done with the minimum instructions.
    						; We subtract 256 from the 24bit variable
    						; by just decrementing the mid byte.
    
    	tstf bres_mid			; first test for mid==0
    	skpnz				; nz = no underflow needed
    	decf bres_hi,f			; z, so is underflow, so dec the msb
    
    	decfsz bres_mid,f		; dec the mid byte (subtract 256)
    
    						; now the full 24bit optimised subtract is done!
    						; this is about 4 times faster than a "proper"
    						; 24bit subtract.
    
    	goto int_exit			; nz, so definitely not one second yet.
    						; in most cases the entire 'fake" int takes
    						; only 9 instructions.
    	;------------------------
    						; * test if we have reached one second.
    						; only gets here when mid==0, it MAY be one second.
    						; only gets to here 1 in every 256 times.
    						; (this is our best optimised test)
    						; it gets here when bres_mid ==0.
    
    	tstf bres_hi			; test hi for zero too
    	skpz					; z = both hi and mid are zero, is one second!
    	goto int_exit			; nz, so not one second yet.
    
    	;-------------------------------------------------
    	; Only gets to here if we have reached one second.
    
    	; now we can generate our one second event, like add
    	; one second to our clock or whatever.
    	; (in this example we toggle a led)
    
    	; The other thing we need to do is add 1,000,000 counts
    	; to our 24bit variable and start all over again.
    	;-------------------------------------------------
    						; Add the 1,000,000 counts first.
    						; One second = 1,000,000 = 0F 42 40 (in hex)
    
    						; As we know hi==0 and mid==0 this makes it very fast.
    						; This is an optimised 24bit add, because we can
    						; just load the top two bytes and only need to do
    						; a real add on the bottom byte. This is much quicker
    						; than a "proper" 24bit add.
    
    	movlw 0x0F			; get msb value 
    	movwf bres_hi			; load in msb
    
    	movlw 0x42			; get mid value
    	movwf bres_mid			; load in mid
    
    	movlw 0x40			; lsb value to add
    	addwf bres_lo,f		; add it to the remainder already in lsb
    	skpnc				; nc = no overflow, so mid is still ok
    
    	incf bres_mid,f		; c, so lsb overflowed, so inc mid
    						; this is optimised and relies on mid being known
    						; and that mid won't overflow from one inc.
    
    						; that's it! Our optimised 24bit add is done,
    						; this is roughly twice as quick as a "proper"
    						; 24bit add.
    	;-------------------------
    						; now we do the "event" that we do every one second.
    
    						; Note! for this example we toggle a led, which
    						; will give a flashing led which is on for a second
    						; and off for a second.
    						; Add your own code here for your one second event.
    
    						; Note! My led is on porta,3
    						; your led may be on a different pin.
      movlw b'00000001'		; mask for bit 3
      xorwf tick,f			; toggle PORTA,bit3 (toggle the led)
    						
    	;-------------------------------------------------
    	; now our one second event is all done, we can exit the
    	; interrupt handler.
    	;-------------------------------------------------
    						; finally we restore w and status registers.
    						; also clears TMRO int flag now we are finished.
    						
    int_exit
    	INT_RETURN
    ENDASM
    Attached Images Attached Images  

Members who have read this thread : 0

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