(Uno) My micros() function drifts horribly

unsigned long m = 0;
int second = 1;

void setup() {
  Serial.begin(115200);
}

void loop() {
  m = micros();
  if(m>second*1000000) {
    Serial.println(m);
    second++;
  }
}

Results in being an entire second too slow after 15 minutes, at a insanely precise rate. Is this a problem with my specific unit? The issue even happens without doing serial prints, but I thought this was the simplest way to show the problem.

If it is an Arduino Uno or the like, that drift is expected.

The manufacturers use an inexpensive crystal or resonator for the main CPU clock, and not only is the frequency inaccurate, it is also strongly temperature-dependent.

Use a temperature compensated RTC, like the DS3231, for accurate timekeeping (if the module has a battery, even when the Arduino is powered down).

Can you show a photo of your board ? I think that the cheapest crystal is still better than a resonator. A cheap crystal might stop working with freezing temperatures (below 0°C). For a accurate timing, you need a board with a crystal and using millis() is easier.

It's a brand new Arduino Uno Rev3. Looking into it further I see someone saying that the crystal on the board is only for USB communication and the CPU uses a ceramic res. I cannot believe how much time I spent learning about timers on arduino for this project without anyone saying "oh yeah but they insanely inaccurate"

Most of us don't think that. The accuracy is fine for the intended purposes, just not for time keeping.

Whose job do you think it was to tell you that? What research did you do before choosing that board?

Hi,

You set second to int.
if(m>second*1000000)
then this operation will fail.
Try like this:

Unsigned long second;

and
if(m>second*1000000ul)

I understand that, sure. I'm not mad that it is this way, if I knew I wanted really accurate timing before I got to this point I would have done the research. But pretty much all forum posts and guides talk about micros() like it IS accurate down to 4μs. I just wish I found out sooner is all.

For the effort, you have gained valuable knowledge regarding AVR timers and clock accuracy.

Yes, the 4µs is true, but not for a clock.
For a clock you can use millis(), it is as accurate as the crystal/resonator.

afbeelding

The Arduino Leonardo has a crystal, and a cheap Uno clone can have a crystal. The Pro Micro has a crystal, and there are more.

For Date and Time, the DS3231 should be the first choice as jremington already wrote.

Try:

void loop() {
  m = micros();
  if(m>second*998890) {
    Serial.println(m);
    second++;
  }

The serial IO causes lag ...

1 second in 15 minutes is about 0.1% accurate.
(which is more-or-less about the accuracy expected from a resonator.)

0.1% is pretty much only "insanely inaccurate" when implementing a clock.

forum posts and guides talk about micros() like it IS accurate down to 4μs.

micros() is precise to 4us, which is different than accurate. Accuracy and precision - Wikipedia