Go Down

Topic: Millis Accuracy Again (Read 6 times) previous topic - next topic

orly_andico

The RTCs I got (PCF8583) does output a 1Hz pulse. I was thinking of just using that instead of bothering with the I2C bus (would save pins, and less code needed).

GPS.. I have thought about it. But I don't like the idea of having to rely on a GPS fix. The Chronodot costs about the same.

Thing is - I don't need GPS or even Chronodot accuracy. 50ppm would be good enough! so in theory the Max32 should have no trouble achieving that with its 30ppm crystal.  But for some strange reason millis() doesn't give correct results even on that system.  I can't help thinking it must be some software bug.. but I can't find it.

afremont

I was only thinking of using the GPS temporarily to measure the accuracy of your board.  Here is my standard sketch that measures pulse length (the whole thing) on pin8 and outputs the number of microseconds since the last capture.  The first reading output is noise, but all other output will be very precisely measured by the hardware.  No software can introduce any jitter in the measurement since the ICF is completely done in hardware.

Code: [Select]

#include "Arduino.h"

volatile unsigned t1captured = 0;
volatile unsigned t1capval = 0;
volatile unsigned t1ovfcnt = 0;
volatile unsigned long t1time;
volatile unsigned long t1last = 0;

#define BUFFER_SIZE 32

volatile unsigned long int buffer[BUFFER_SIZE];
volatile int head = 0;
volatile int tail = 0;

void setup() {

  Serial.begin(9600); 

  TCCR1A = 0x0;    // put timer1 in normal mode
  TCCR1B = 0x2;    // change prescaler to divide clock by 8

  // clear any pending capture or overflow interrupts
  TIFR1 = (1<<ICF1) | (1<<TOV1);
  // Enable input capture and overflow interrupts
  TIMSK1 |= (1<<ICIE1) | (1<<TOIE1);
 
  pinMode(8, INPUT);   // This is where to feed the signal in
}

void loop() {

  if(head != tail) {
    head = (head + 1) % BUFFER_SIZE;
    Serial.println(buffer[head]);
  }
 
}

ISR(TIMER1_OVF_vect) {
 
   t1ovfcnt++;              // keep track of overflows

}


ISR(TIMER1_CAPT_vect) {
 
  unsigned long t1temp;

  // combine overflow count with capture value to create 32 bit count
  //  calculate how long it has been since the last capture
  //   stick the result in the global variable t1time in 1uS precision

  t1capval = ICR1;
  t1temp = ((unsigned long)t1ovfcnt << 16) | t1capval;
  t1time = (t1temp - t1last) >> 1;  // convert to full uS
  t1last = t1temp;
 
  tail = (tail + 1) % BUFFER_SIZE;
  buffer[tail] = t1time;
}
Experience, it's what you get when you were expecting something else.

PeterH

I won't have time to look into the code you posted until later, but if you haven't already done so I suggest it would be worth your time writing a minimal sketch that demonstrates the problem in the simplest way you can.

I assume that a simple sketch that just calls millis() repeatedly and prints the result won't reproduce the problem, because it didn't for me.

Something else you're doing within the sketch must be triggering it, and the suggestions that it's interrupt overflow seem like the most likely explanation. However, that would not occur on a well-behaved system.

You may find it's something that can be provoked by doing SPI writes, or SPI reads, or something else. If you can figure out by trial and error what the key factor is, that would help us understand the cause and get us closer to finding a resolution.
I only provide help via the forum - please do not contact me for private consultancy.

GoForSmoke


I won't have time to look into the code you posted until later, but if you haven't already done so I suggest it would be worth your time writing a minimal sketch that demonstrates the problem in the simplest way you can.

I assume that a simple sketch that just calls millis() repeatedly and prints the result won't reproduce the problem, because it didn't for me.

Something else you're doing within the sketch must be triggering it, and the suggestions that it's interrupt overflow seem like the most likely explanation. However, that would not occur on a well-behaved system.

You may find it's something that can be provoked by doing SPI writes, or SPI reads, or something else. If you can figure out by trial and error what the key factor is, that would help us understand the cause and get us closer to finding a resolution.


Exactly. He's getting way too much variation to conclude that millis() are the cause.
I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

JimEli



Exactly. He's getting way too much variation to conclude that millis() are the cause.



Exactly X2

I did a quick look at your code and offer these suggestions:

1. Delay() is bad, and it appears your code is planted there. Try using a non-blocking delay.
2. You are running lots of ISRs (Serial, SPI, ADC, to identify a few) which could be blocking. Try eliminating/minimizing some and see if your timer accuracy improves.


Go Up