Real time clock + external interrupt in one PIC possible?


Closed Thread
Results 1 to 34 of 34

Hybrid View

  1. #1
    Join Date
    Jan 2008
    Location
    Selm, Germany
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Hello Henrik,

    thank you in advance for your input. I get one pulse per driveshaft revolution that drives the car ca. 0.6m .
    I don´t expect any road mission like this to exceed 8 minutes so 600 seconds as upper limit should do.

    regards and greetings to sweden (had some nice days in Malmö 4 years ago)

    Mugelpower

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


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Thanks, give me some time and I'll get back to you with a starting point.
    Is it likely that the distance traveled will be more than 39km?

    /Henrik.

  3. #3
    Join Date
    Jan 2008
    Location
    Selm, Germany
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Hello Henrik,

    no, the maximum distance we have experienced were less than 3 km, so 10km will be sufficcient. Problem would be that the road mission is on public roads that are temporary closed for about 2 hours and it´s difficult here in Germany, especially in Northrhein Westfalia to find roads that long which could be blocked from public access so the Oldtimers could drive their road mission. Northrhein Westfalia is the most dense populated federal state in Germany and has 524 People per square km. For comparison Sweden has 24 People per square km.

    regards
    Mugelpower

  4. #4
    Join Date
    Apr 2014
    Location
    OK
    Posts
    557


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Laying in bed thinking about this project, I'm guessing you want to calculate an average speed from the time you hit the go pedal. I pondered how to do that with minimal code. Essentially I came up with:

    Durchschnittlich var WORD ;Speed
    Geschwindigkeit var WORD ;Average
    Teiler VAR WORD ;Divisor
    Gesamt VAR LONG ;Total

    DO
    Durchschnittlich = TMR3 ;Using T3CKI with TMR1
    Gesamt = Gesamt + Durchschnittlich
    Teiler = Teiler + 1
    Geschwindigkeit = Gesamt / Teiler
    LOOP

    Of course, the DO/LOOP would be paced per TMR1 Interrupt

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


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Hi,
    I've written some code targeting the 18F1320, I thought I had a couple of those in stock and I just set out to build up a test circuit to verify the code but it was the 18F1330 I had and as it turns out it's a completely different beast (lacking a TMR2 which the code relies on for example).

    I guess I could change the code to suit a device that I do have but then that might not be what you intend to run it on anyway and we'd still need some back and forth so I'll just post the code as is and ask you to kindly remember that it is untested. Hopefully though it serves its purpose and show you the overall idea of one way that this can be done without external RTC chips or interrupts.

    There is a bit of code but I tried to make it as complete as I could for a first pass, I'm sure there are things I didn't think of though.

    Feel free to pick it apart, ask questions why this or that.

    Code:
    '****************************************************************
    '*  Name    : Speedometer.pbp                                   *
    '*  Author  : Henrik Olsson                                     *
    '*  Notice  : Copyright (c) 2017 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 2017-09-13                                        *
    '*  Version : 1.0                                               *
    '*  Notes   : Uses TMR1 configured as a counter to measure      *
    '*            distance traveled and TMR2 as a 2ms timebase to   *
    '*            measure real time.                                *
    '*            An active low start/stop button is used to start  *
    '*            and stop the measurement.                         *
    '*                                                              *
    '*          : Target is 18F1320 but running on internal 8MHz    *
    '*            oscillator but should work on any device having   *
    '*            a TMR1 and TMR2 with or without minor changes.    *
    '*          :                                                   *
    '****************************************************************
    
    '-------------------- Device configuration ----------------------
    #CONFIG
        CONFIG  OSC = INTIO2	            ; Internal RC oscillator, port function on RA6 and port function on RA7
        CONFIG  FSCM = ON                   ; Fail-Safe Clock Monitor enabled
        CONFIG  IESO = ON                   ; Internal External Switchover mode enabled
        CONFIG  PWRT = OFF                  ; PWRT disabled
        CONFIG  BOR = ON                    ; Brown-out Reset enabled
        CONFIG  BORV = 27                   ; VBOR set to 2.7V
        CONFIG  WDT = ON                    ; WDT enabled
        CONFIG  WDTPS = 512                 ; 1:512
        CONFIG  MCLRE = ON                  ; MCLR pin enabled, RA5 input pin disabled
        CONFIG  STVR = ON                   ; Stack full/underflow will cause Reset
        CONFIG  LVP = OFF                   ; Low-Voltage ICSP disabled
        CONFIG  DEBUG = OFF                 ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
        CONFIG  CP0 = OFF                   ; Block 0 (00200-000FFFh) not code-protected
        CONFIG  CP1 = OFF                   ; Block 1 (001000-001FFFh) not code-protected
        CONFIG  CPB = OFF                   ; Boot Block (000000-0001FFh) not code-protected
        CONFIG  CPD = OFF                   ; Data EEPROM not code-protected
        CONFIG  WRT0 = OFF                  ; Block 0 (00200-000FFFh) not write-protected
        CONFIG  WRT1 = OFF                  ; Block 1 (001000-001FFFh) not write-protected
        CONFIG  WRTC = OFF                  ; Configuration registers (300000-3000FFh) not write-protected
        CONFIG  WRTB = OFF                  ; Boot Block (000000-0001FFh) not write-protected
        CONFIG  WRTD = OFF                  ; Data EEPROM not write-protected
        CONFIG  EBTR0 = OFF                 ; Block 0 (00200-000FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTR1 = OFF                 ; Block 1 (001000-001FFFh) not protected from table reads executed in other blocks
        CONFIG  EBTRB = OFF                 ; Boot Block (000000-0001FFh) not protected from table reads executed in other blocks
    #ENDCONFIG
    
    '---------- Variables ------------
    Seconds         VAR WORD                ' elapsed time, seconds
    ms              VAR WORD                ' elapsed time, milliseconds
    State           VAR BYTE                ' State machine variable, keeps track of what we're doing
    Distance        VAR WORD                ' Distance traveled in metres, calculated based on pulsecount
    AverageSpeed    VAR WORD                ' Final result of measurement, in units of 0.1km/h (123=12.3km/h)
    Temp            var WORD                ' Used during calculation
    DebounceCount   VAR BYTE                ' Used to debounce the start/stop button
    TimeOverflow    VAR BIT                 ' Gets set if the seconds variable grows too big.
    
    '---------- Constants -------------
    Idle            CON 0
    Starting        CON 1
    Counting        CON 2
    Stopping        CON 3
    Done            CON 4
    
    '------------ Aliases --------------
    StartStopButton VAR PortB.0             ' Low when pressed
    ReadyIndicator  VAR LATB.2              ' High when idle/ready
    RunIndicator    VAR LATB.3              ' High when counting/timing
    ErrorIndicator  VAR LATB.4              ' High on count or time overflow
    TMR1ON          VAR T1CON.0             ' Run/stop bit for TMR1
    TMR2ON          VAR T2CON.2             ' Run/stop bit for TMR2
    TMR1IF          VAR PIR1.0              ' TMR1 interrupt flag
    TMR2IF          VAR PIR1.1              ' TMR2 interrupt flag
    
    '--------- Hardware setup -----------
    ADCON1 = %11111111                      ' All pins as digital
    LATB   = %00000000                      ' All pins low
    TRISB  = %01000001                      ' RB0=Button, RB1=TX, RB2=LED, RB3=LED, RB4=LED, RB6=Counter input
    OSCCON = %01110010                      ' Internal oscillator, 8MHz
    T1CON  = %00000010                      ' External clock on RB6, timer OFF for now.
    T2CON  = %00000010                      ' 1:16 prescaler, TMR2 off for now
    PR2    = 249                            ' T2 interrupt flag set every 250*16 tick
    
    RCSTA  = $90                            ' Enable serial port & continuous receive
    TXSTA  = $20                            ' Enable transmit, BRGH = 0
    SPBRG  = 12                             ' 38400 Baud @ 8MHz, 0,16%
    SPBRGH = 0
    BAUDCTL.3 = 1                           ' Enable 16 bit baudrate generator
    
    PAUSE 500
    
    Start:
        HSEROUT["Program start",13]
    
        For Temp = 0 to 9
            ReadyIndicator = 1
            Pause 250
            ReadyIndicator = 0
            Pause 250
        NEXT
    
        ReadyIndicator = 1
    
    
    Main:
        Select CASE State
            
            Case Idle
                If StartStopButton = 0 THEN             ' If the button is pressed we
                    Seconds = 0
                    ms = 0
                    TMR1H = 0                           ' reset the pulse count
                    TMR1L = 0
                    TMR2 = 0                            ' reset the timebase
                    TMR1IF = 0                          ' clear the overflow flag
                    TMR2IF = 0                          ' clear the timebase tick flag
                    TMR1ON = 1                          ' enable the counter to count pulses from the driveshaft
                    TMR2ON = 1                          ' enable the 2ms timer tick
                    ReadyIndicator = 0                  ' update status LEDs
                    RunIndicator = 1
                    ErrorIndicator = 0
                    TimeOverflow = 0                    ' clear overflow flag
                    State = Starting                    ' and move to the next state.
                ENDIF
    '---------------------------------------------------------------------------------------------------            
            CASE Starting
                IF TMR2IF THEN                          ' TMR2IF gets set every 2ms
                    TMR2IF = 0                          ' reset flag
                    GOSUB UpdateTime                    ' update our time registers
                    
                    ' Wait for the button to be released before transitioning to the next state.
                    If StartStopButton = 1 THEN         ' Button released?
                        DebounceCount = DebounceCount + 1
                    ELSE
                        DebounceCount = 0               ' Button must be released 10 ticks in a row.
                    ENDIF
                    
                    IF DebounceCount = 9 THEN           ' Button has been released for 10 ticks
                        DebounceCount = 0
                        State = Counting                ' Transition to next state.
                    ENDIF
                ENDIF
    '---------------------------------------------------------------------------------------------------             
            
            Case Counting
                IF TMR2IF THEN                          ' 2ms tick?
                    TMR2IF = 0                          ' clear flag and
                    GOSUB UpdateTime                    ' update our time registers
                    
                    If StartStopButton = 0 THEN         ' Button pressed?
                        RunIndicator = 0
                        TMR1ON = 0                      ' Disable pulse counter
                        TMR2ON = 0                      ' Disable timer
                        State = Stopping
                    ENDIF
                 ENDIF
                 
                 IF TMR1IF THEN                         ' Counter overflow
                    ErrorIndicator = 1             
                 ENDIF
                 
                 ' Here we can do anything else that needs doing while the
                 ' system is counting but it's very important that it does
                 ' not take longer than 2ms or we will lose time.                    
    '---------------------------------------------------------------------------------------------------              
            CASE Stopping
                ' Wait for the button to released before transitioning to the next state,
                If StartStopButton = 1 THEN             ' Is button released?
                    DebounceCount = DebounceCount + 1
                ELSE
                    DebounceCount = 0
                ENDIF
                
                IF DebounceCount = 10 THEN              ' Button released for duration of debounde time?
                    DebounceCount = 0
                    State = Done                        ' Transition to next state.
                ENDIF
                
                ' The timer is no longer running so we pause here for the same duration.
                PAUSE 2            
    '---------------------------------------------------------------------------------------------------  
            
            CASE Done
                ' This is where we perform the calculations and present the result.
                
                If TMR1IF THEN                      ' Interrupt flag is set if counter has rolled over
                    HSEROUT["ERROR: Pulse counter overflow, can't compute...", 13]
                    Goto Abort
                ENDIF
                
                IF TimeOverflow THEN                ' Flag set if seconds variable has rolled over
                    HSEROUT["ERROR: Seconds counter overflow, can't compute...", 13]
                    Goto Abort
                ENDIF
                
                ' Each count from the driveshaft equals 0.6m of car movement.
                ' Lets say the pulse count is 12345 and the seconds count is 503.
                ' We've traveled 12345*0.6=7407 metres in 503 seconds, 7407/503*3.6=53.0km/h
                ' Using the ** operator allows us to effectively multiply by fractions of 65536 so:
                '
                ' 12345 ** 39322 = 7407
                ' 7407 * 36 = 266652
                ' 266652 / 503 = 530 which we interpret as 53.0km/h
                ' 
                ' 6045 pulses in 312 seconds,
                ' 6045*0.6/312*3.6=41.85km/h:
                ' 6045 ** 39322 = 3627
                ' 3627 * 36 = 130572
                ' 130572 / 312 = 418 which we interpret at 41.8km/h
                '
                ' 53203 pulses in 1412 seconds,
                ' 53203*0.6/1412*3.6=81.39km/h:
                ' 53202 ** 39322 = 31922
                ' 31922 * 36 = 1149192
                ' 1149192 / 1412 = 813 which we interpret as 81.3km/h
                
                Distance.HIGHBYTE = TMR1H
                Distance.lowbyte = TMR1L
                Distance = Distance ** 39322        ' Multiply by 0.6, Distance is now in metres
                
                Temp = Distance * 36
                AverageSpeed = DIV32 Seconds        ' 215 for 21.5km/h
                
                HSEROUT[DEC (TMR1H * 256 + TMR1L), " pulses",13]
                HSEROUT[DEC Distance, "m", 13]
                HSEROUT[DEC Seconds, ".", DEC3 ms, "s",13]
                HSEROUT[DEC AverageSpeed/10,".", DEC AverageSpeed//10, "km/h",13]
    Abort:
                ReadyIndicator = 1
                ErrorIndicator = 0
                State = Idle      
            
        END SELECT
        
    Goto Main
    
    '-------------------------------------- Subroutines ------------------------------------------------
    UpdateTime:
        ' Our timebase is 500Hz.
        ms = ms + 2
        If ms = 1000 then
            ms = 0
            seconds = seconds + 1
            
            ' We're using DIV32 to calculate the average speed. It does not allow the divisor
            ' to be larger than 32767 (which is 9 hours and some minutes so it should be fine)
            ' but since we're good programmers we're going to check for it anyway.
            If Seconds > 32767 THEN
                TimeOverflow = 1
                ErrorIndicator = 1
            ENDIF
    
        ENDIF
    RETURN

  6. #6
    Join Date
    Jan 2008
    Location
    Selm, Germany
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Hello Henrik,

    thanks a lot, I´ve never be able to program that way and so long, I´m more the "Hello World" guy.

    Is it possible to put a "LCDOUT" in betwen or does it take more than 2ms ? I need a display as interface.

    Do I need a serial LCD display?

    regards

    Mugelpower

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


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    You can use a LCD and replace the HSEROUT statements with LCDOUT if you want. When the measurement is complete it doesn't matter how long it takes because then we're not timing anymore.

    If you want the display to update DURING the measurment (like showing elapsed time) it'll be a bit more complicated - you never said anything about that I don't think :-)

    It's certainly doable but we'll need to think about how to best do it. But highly I suggest getting a prototype up and running FIRST.

    /Henrik.

  8. #8
    Join Date
    Jan 2008
    Location
    Selm, Germany
    Posts
    116


    Did you find this post helpful? Yes | No

    Default Re: Real time clock + external interrupt in one PIC possible?

    Hello Harry,

    sorry about that . For me it was so obvious you have to drive the car with constant speed so you need to check the speedo the whole time. And I want to build a precise speedo that shows not only the actual speed but the average speed including stops, accelerations etc. Its impossible to drive a constant speed without a closed loop. Its not a straight road to drive but the roads have turns and maybe a stop. And we don´t know wheres the end of
    the measured distance so we have to maintain the average speed until the end of the road mission is cleary marked.
    So yes, we have to look constantly on the speedo , aybe more on the speedo than on the road.
    Regards
    Mugelpower

  9. #9
    Join Date
    Jan 2008
    Location
    Selm, Germany
    Posts
    116


    Did you find this post helpful? Yes | No

    Cool Re: Real time clock + external interrupt in one PIC possible?

    Yes I´m beginning to build the prototype next weekend.

    Greetings to all earthlings

Similar Threads

  1. real time clock
    By maria in forum Code Examples
    Replies: 44
    Last Post: - 1st March 2022, 12:13
  2. Real time clock + external interrupt in one PIC possible?
    By Mugelpower in forum mel PIC BASIC
    Replies: 1
    Last Post: - 10th September 2017, 17:11
  3. Real Time Clock
    By in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 2nd June 2012, 04:52
  4. Real time clock
    By PlantBob in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 10th February 2011, 13:01
  5. Real Time Clock
    By savnik in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 8th December 2006, 02:02

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