Feather M4 CAN millis() is off

I was testing the Feather M4 Can using the CAN Example code on the Adafruit site:

I noticed that the timing seemed off. I serial print the value of timestamp every 1000ms which should be once a second. In the example below this is printing out a new line about every .35 seconds. Note that the value being printed is about 1000ms greater each time but that it is printing out that value faster than it should.

If I remove the strip.show() from being called in every loop it will print out a value closer to every 1 second as expected.

/*
 * Adafruit Feather M4 CAN Speed Test
 */

#include <CANSAME5x.h>
#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel strip(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

uint32_t timestamp;
int hue = 0;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  Serial.println("CAN NeoPixel speed test");

  strip.begin();
  strip.setBrightness(50);

  timestamp = millis();
}

void loop() {

  hue++;
  if (hue > 25500) hue = 0;
  
  strip.setPixelColor(0, Wheel(hue / 100));
  strip.show();

// stripshow() call above in each loop is making millis() speed up..
// test the speed of printed timestamps with it there and commented out

  // every 1000 ms print a timestamp - except that 1000ms isn't 1 second as it should be
  if ((millis() - timestamp) > 1000) {
    Serial.print("Timestamp ");
    Serial.print(timestamp);
  
    Serial.println("...sent!");
    timestamp = millis();
  }
}


uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

With the strip.show() being called each loop it speeds up millis() making it hit a 1000 increase about 3 times faster. Removing it makes millis() increase 1000 in what appears to be 1 second. So what happens if we call it some loops but not every loop?

Next I put in a loop counter so that it only calls strip.show() every Nth loop through. Starting with 1000, it slows down a little and prints out every .5 seconds. Printing out stripcount shows that strip.show is being called 1000 times per (what it thinks is) "1000ms" in that scenario.

 flip++;
  if (flip > 1000) {
    flip = 0;
    strip.setPixelColor(0, Wheel(hue / 1000));
    strip.show();
    stripcount++;
  }

Important to note that strip.show() takes time to call. If I lower the flip counter delay below 1000 and it'll still only be called 1000 times. But increasing the delay to 2000 will reduce the stripcount to be 500 and a .5 seconds per 1000 millis(). Setting the delay to 10k reduces strip count to 167 and the timing to .8 sec per 1000 millis().

This leads me to believe that there is something up with the Adafruit_NeoPixel library that is messing with millis() when used on the Feather M4.

Thoughts?

Found this..

Adafruit_NeoPixel_ZeroDMA

DMA-based NeoPixel library for SAMD21 and SAMD51 microcontrollers (Feather M0, M4, etc.) Doesn't require stopping interrupts, so millis() and micros() don't lose time, soft PWM (for servos, etc.) still operate normally.

I swapped it out with this library and it now works as expected..

#include <Adafruit_NeoPixel_ZeroDMA.h>
Adafruit_NeoPixel_ZeroDMA strip(1, PIN_NEOPIXEL, NEO_GRB);

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.