Hot!TMR3 Random Count Error (PIC18F, XC8, MPLAB X)

Page: 12 > Showing page 1 of 2
Author
physapp
New Member
  • Total Posts : 17
  • Reward points : 0
  • Joined: 2017/08/28 05:59:31
  • Location: 0
  • Status: offline
2017/11/14 11:44:24 (permalink)
0

TMR3 Random Count Error (PIC18F, XC8, MPLAB X)

Hi guys,
 
I have been working on a project where a Timer (TMR3) is used to measure the time between two external interrupts. Another timer (TMR1) is used to count if any overflows have occurred. The first interrupt starts the timer, the second turns it off and calls a function for some subsequent calculations. Then it is displayed on an LCD.
 
PIC18F26K40 @64MHz Internal Oscillator, TMR3 and TMR1 have no pre- or post-scale. TMR3 is sync'd to FCYC and TMR1 is triggered on the TMR3OUT bit.
 
Currently I am displaying both timer values and the calculated value on the LCD.  I also have the external interrupts set up to an oscilloscope to accurately measure the time between them. In Excel I have taken the time from the scope and multiplied by FCYC (16MIPS).
 
The problem I have at the moment is random count errors in the main timer, TMR3. I am getting an average of 1,783 more (extra) "ticks" in the TMR registers but its all over the place (see attached JPEG). This is causing significant error in the calculation. If it were consistent, I could subtract this average in the calculation.
 
Here are the relevant segments of code:
 
void OSCILLATOR_Initialize(void)
{
    // NOSC HFINTOSC; NDIV 1;
    OSCCON1 = 0x60;
    // CSWHOLD may proceed; SOSCPWR Low power;
    OSCCON3 = 0x00;
    // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCEN = 0x00;
    // HFFRQ 64_MHz;
    OSCFRQ = 0x08;
    // TUN 0;
    OSCTUNE = 0x00;
}
 
void TMR3_Initialize(void)
{
    T3CON = 0x00;   //CKPS 1:1; nT3SYNC synchronize; TMR3ON off; T3RD16 enabled;
    T3GCON = 0x00;  //T3GE disabled; T3GTM disabled; T3GPOL low; T3GGO done; T3GSPM disabled;
    T3GATE = 0x00; //GSS T3G_pin;
    T3CLK = 0x01; //CS FOSC/4;
    TMR3H = 0x00;  //TMR3H 0;
    TMR3L = 0x00;  //TMR3L 0;
    timer3ReloadVal=(uint16_t)((TMR3H << 8) | TMR3L);  // Load the TMR value to reload variable
    PIR4bits.TMR3IF = 0;  // Clearing IF flag before enabling the interrupt.
    PIE4bits.TMR3IE = 1;  // Enable TMR3 interrupt.
}
   
    void TMR1_Initialize(void)
{
    T1CON =  0x09;  //CKPS 1:1; nT1SYNC synchronize; TMR1ON off; T1RD16 enabled;
    T1GCON = 0x40; //0xE0;  //T1GE enabled; T1GTM enabled; T1GPOL high; T1GGO done; T1GSPM disabled;
    T1GATE =  0x04; // tmr3 overflow  //GSS TMR0_Overflow;
    T1CLK = 0xA; //tmr 3 overflow  //CS TMR0_Overflow;
    TMR1H = 0x00;   
    TMR1L = 0x00;
    timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L);  // Load the TMR value to reload variable
    PIR4bits.TMR1IF = 0;  // Clearing IF flag before enabling the interrupt.
    PIE4bits.TMR1IE = 1; // Enable TMR1 interrupt.
    TMR1_StartTimer();  // Start TMR1
}
 

void interrupt high_priority ISR_high(void)
{
    if (PIR0bits.INT0IF && PIE0bits.INT0IE == 1)            //Check if the first beam has been broken
    {
        PIR0bits.INT0IF = 0;    //Toggle the Flag
        TMR1H = 0x00;   //RESET all TIMER registers
        TMR1L = 0x00;
        TMR3H = 0x00;
        TMR3L = 0x00;
        
       
        T3CONbits.TMR3ON = 1;   //Turn on the Timer
       //T1CONbits.TMR1ON = 1;   //Turn on the Overflow Counter
        
              LATAbits.LATA5 = 0;  //TURN ON BNC
         
    }
    
     if (PIR0bits.INT1IF && PIE0bits.INT1IE == 1)         
                                   
  {
      PIR0bits.INT1IF = 0;  //Toggle the Flag
      T3CONbits.TMR3ON = 0;  //Turn off the Timer
      //T1CONbits.TMR1ON = 0;  //Turn off Overflow counter
      LATAbits.LATA5 = 1;  //TURN OFF BNC
      Velocity();
  }                        
}
   
   
void interrupt low_priority ISR_low(void)
{  
     if (PIR4bits.TMR3IF == 1)   //TMR3 Interrupt Service Routine
     {        
            PIR4bits.TMR3IF = 0;        
      TMR3H = 0x00;
    TMR3L = 0x00;
    
     }                                
 if (PIR4bits.TMR1IF == 1)   //TMR1 Interrupt Service Routine
     {        
            PIR4bits.TMR1IF = 0;        
      TMR1H = 0x00;
    TMR1L = 0x00;
    
     }   
}
   
   
 
 
 

Attached Image(s)

#1

23 Replies Related Threads

    jtemples
    Super Member
    • Total Posts : 10278
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/14 12:40:08 (permalink)
    0
    What is the purpose of these statements?
     
    timer3ReloadVal=(uint16_t)((TMR3H << 8) | TMR3L);
    timer1ReloadVal=(uint16_t)((TMR1H << 8) | TMR1L);
     
    The code you've shown will just load them with 0.  Is that expected?
     
    Do you have the timers in 16-bit mode?
    #2
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/14 12:48:32 (permalink)
    0
    Timers are in 16 bit mode. Those lines are so that I could load them with different initial values for different timer periods
     
    #3
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/14 13:07:30 (permalink)
    0
    Might be simpler using the capture/compare modules? I have done that in the past for pulse measurements. Just a thought...
    #4
    1and0
    Access is Denied
    • Total Posts : 7134
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/14 13:39:27 (permalink)
    +1 (1)
    Agree with Jack on using Capture/Compare module.

     I might have missed something, but I don't think you need the interrupts for Timer3 and Timer1.  Clearing TMR3x in the ISR will introduce error.

    Edit: show your velocity() function. Are you reading the timers values in the correct order.
    post edited by 1and0 - 2017/11/14 14:25:32
    #5
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 07:17:27 (permalink)
    0
    void Velocity (void)
    {
    Lcd_Clear();
     
    //  THIS DISPLAYS THE TIMER VALUES ON THE LCD FOR DEBUGGING
        Lcd_Set_Cursor(2,8);
       unsigned int t = TMR3_ReadTimer();
        unsigned char n[];
        utoa(n,t,10);
        LCDPutStr(n);
        
         Lcd_Set_Cursor(2,1);
          unsigned char c[];
          unsigned int ov = TMR1_ReadTimer();
          utoa(c,ov,10);
          LCDPutStr(c);
             
          
        
       //This is the actual calculation
        unsigned int z = TMR1_ReadTimer()*41;  //convert overflow count to 0.01 ms //true overflow rate is 0.004096 s
        unsigned int d = TMR3_ReadTimer();   // Current timer value
        unsigned int s = (d/1600);  //convert current timer count to 0.01 ms
        
        
        //unsigned int t = s + z;     // Current timer value + 16 bit overflow multiplied by the # of times overflowed
     
    //Calculate the speed of the projectile
        unsigned long speed = (60700/(s + z));   //0.001m/s  //2.34 inches = 0.0607 meters, v = dx/dt;
        
        Calc_Speed(speed); //function to convert from XXXX to XX.XX
    }
    #6
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 08:38:32 (permalink)
    +1 (1)
    I think you should post the TMR1_ReadTimer() and TMR3_ReadTimer() functions (code), only way to answer the question in post#5
    #7
    1and0
    Access is Denied
    • Total Posts : 7134
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 09:28:15 (permalink)
    0
    In addition to showing the code for the two TMRx_ReadTimer() functions, assign a size to the n[] and c[] arrays.
     
    #8
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 09:28:26 (permalink)
    0
    unsigned int TMR1_ReadTimer(void)
    {
        uint16_t readVal;
        uint8_t readValHigh;
        uint8_t readValLow;
        
        readValLow = TMR1L;
        readValHigh = TMR1H;
        
        readVal = ((uint16_t)readValHigh << 8) | readValLow;

        return readVal;
    }
     
    uint16_t TMR3_ReadTimer(void)
    {
        uint16_t readVal;
        uint8_t readValHigh;
        uint8_t readValLow;
        
        readValLow = TMR3L;
        readValHigh = TMR3H;
        
        readVal = ((uint16_t)readValHigh << 8) | readValLow;

        return readVal;
    }
     
     
     
    Also, I have attached a probe to an unused pin and in the TMR3 Overflow ISR I am toggling this pin to show both the overflow frequency and any latency in starting the timer, triggering on the falling edge of a button press that at the moment is initiating the INT0 ISR.
     
    This may be where the issue is, as there is a long and variable period before the timer appears to overflow, see attached waveform
     
    post edited by physapp - 2017/11/22 09:32:47

    Attached Image(s)

    #9
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 10:48:49 (permalink)
    0
    You say the timers are in 16 bit mode howeer this line of code says otherwise:

     T3CON = 0x00;   //CKPS 1:1; nT3SYNC synchronize; TMR3ON off; T3RD16 enabled;

    Your comment says enabled however bit 1 of T3CON must be set high (0x02) to enable 16 bit read/write mode.
    Same issue with Timer3
    #10
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 11:06:57 (permalink)
    0
    This has been corrected, however the issue still persists.
     
    #11
    1and0
    Access is Denied
    • Total Posts : 7134
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 11:18:18 (permalink)
    0
    physapp
    Also, I have attached a probe to an unused pin and in the TMR3 Overflow ISR I am toggling this pin to show both the overflow frequency and any latency in starting the timer, triggering on the falling edge of a button press that at the moment is initiating the INT0 ISR.

    Button bounces.?
     
    #12
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 11:56:07 (permalink)
    0
    I don't think so. The blue trace is the button capture. I dont see any bounces, do you? I believe that I have properly implemented debounce circuitry although this is a useful suggestion
    #13
    RISC
    Super Member
    • Total Posts : 4591
    • Reward points : 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 12:34:35 (permalink)
    +1 (1)
    Hi,
    One possible issue is that interrupts occur while you access the same variable in the main loop.
    Because timers are 16bits you cannot read them aomically (in a single instruction).
    Therefore if an interrupt occurs e.g. between these 2 lines and you change the value of TMR1H, it will have a wrong value... 

       readValLow = TMR1L;
    // if interrupt occurs here TMR1H could be changed by your ISR
        readValHigh = TMR1H;

    To avoid this, you can either make the sequence atomic (*) or garantee in your SW that no interrupt can occur within this sequence.

    di();
       readValLow = TMR1L;
        readValHigh = TMR1H;
    ei();

    Regards
     
    #14
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 12:59:10 (permalink)
    0
    If I read your timer settings correctly Timer3 should be operating from a 16 Mhz clock (FOSC/4). This should result in an overflow interrupt after approx. 4 mS. I do not see that in your screen shot (or am I reading the scope image incorrectly?).
     
    EDIT: had a typo on the time WAS 244 s/b 4 .
    post edited by jack@kksound - 2017/11/22 13:01:19
    #15
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 13:35:22 (permalink)
    0
    RISC:
    I like your suggestion, and hadn't thought about that possibility. It should be pretty easy to add this, and therefore I will.
     
    jack@kksound:
    Yea, I have been changing stuff since the first post trying to get rid of this error(s).
     
    I started with the internal oscillator @ 64 MHz, then added/switched to a 16 MHz crystal with no PLL and then changed the config bits again to use the 16 MHz crystal with 4x PLL. Captured in the scope is the 16 MHz crystal with 4x PLL (therefore SW FOSC = 64 MHz, FCYC = 16 MHz).
     
    Still getting real weird and random behavior showing up in the scope.
     
    I've also tried to toggle this same pin before and after the timer is turned on in the INT0_ISR (with a __delay_ms(1) to allow the pin time to toggle). Sometimes I get two pulses that the timer got turned on but always around the falling edge of the button push, even though INTCON = 0xE3;
    #16
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 14:14:08 (permalink)
    0
    If edge triggered interrupts are triggering on the wrong edge (falling when you have rising selected) then the signal to the interrupt pin is suspect, it has glitches, it rises/falls to slowly, it bounces, etc. Have you used the pps feature to move the INT0 function to a different pin (default is RB0)? Are you sure that the pin is set for digital input mode (any analog feature disabled? PORT B defaults to analog input mode).
    #17
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 14:55:52 (permalink)
    0
    I'm not sure if this will help or not, just sort of thinking out-loud. What if I make it a single shot?
     
    Perhaps in Calc_Speed(), (which is called from Velocity(), which is called from the INT1 ISR), add a loop to poll a pin attached to a button, and loop causes it to wait there, with interrupts disabled, until the button is pressed, re-enabling interrupts as well as clearing the TMR registers.
     
    Not entirely sure how this may help, or may not help. Just sort of stabbing at things to try to solve it at this point.
    post edited by physapp - 2017/11/22 15:05:53
    #18
    physapp
    New Member
    • Total Posts : 17
    • Reward points : 0
    • Joined: 2017/08/28 05:59:31
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 15:03:34 (permalink)
    0
    jack@kksound:
    I have used the PPS register to move the interrupt pins. And I am sure that the LAT, TRIS, ANSEL, WPU and ODCON registers associated with them are correct. Also, the pins are set-up and the system is initialized for quite a while before the interrupts are initialized. The system is started, which sets up the oscillator and pins, then the LCD is initialized (which takes ~30ms) then 3 pins are toggled and then finally the interrupt is initalized just before the main loop.
     
    Here is the PPS input change routine, to ensure that I did it properly:
     
     
     bool state = (unsigned char)GIE;
        GIE = 0;
        PPSLOCK = 0x55;
        PPSLOCK = 0xAA;
        PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS
       
          
        INT1PPSbits.INT1PPS = 0x0A;   //RB5 (S4)->EXT_INT:INT1;
        INT0PPSbits.INT0PPS = 0x0D;   //RB2 (S1)->EXT_INT:INT0;
      
        PPSLOCK = 0x55;
        PPSLOCK = 0xAA;
        PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS

        GIE = state;
     
     
    #19
    jack@kksound
    code tags!
    • Total Posts : 2086
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: TMR3 Random Count Error (PIC18F, XC8, MPLAB X) 2017/11/22 15:37:25 (permalink)
    0
    Gasping at straws and not sure it is relevent to the issues here but have you taken care of the NVMREG errata issue of the K40 pics?
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2017 APG vNext Commercial Version 4.5