Three unexplainable problems

I have a project that I have been working on for months now that I need some help on. I am trying to convert the speedometer in my classic car from mechanical to electronic. The MCU is a Nano Every. I am using a Hall Effect sensor to count revolutions of the drive shaft. I have two 0.91" OLED displays for the odometer and the trip odometer. I have a TCA9548A I2C multiplexer to interface them. I am using a gauge motor from a Mustang for the mechanical power, using an Adafruit dual H bridge to interface it.

I am having three anomalies that I need help dealing with:

  1. Whenever I get the value of millis(), it is one fifth the value I expect. I am checking the pulse count every 1/4 second, using a delay(250) in the loop(), but millis() returns 50. What gives here?

  2. In the calcMiles function, I have to put a Serial.print in to print the stored value of pulses per mile, or after about seven or eight times through the function, ppm becomes 0. What is causing this?

  3. Every sixth time through the calcMiles function, prevcount becomes 0. The next five times it will be the correct number, but that sixth one becomes 0. What is causing this, and how can I fix it?

My code:

#include <Comparator.h>
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <EEPROM.h>
#include <Stepper.h>
#include <EveryTimerB.h>

#define STEPS 686   //number of steps for 360 degree rotation
#define mphperstep 0.2879
//521 steps for 150 mph from 10-160.  0.2879 mph per step
//0-10 mph requires half that many.  0.5758 mph per step
const byte switchPin = 3; // the pin number for the switch
const byte pulsePin = 2; // the pin number for the Hall effect sensor
const int buttonInterval = 50; // number of millisecs between button readings

unsigned long tripmiles, totmiles;
unsigned int ppm;    //pulses per mile (11441 at 4 per rev)
volatile unsigned int pcount = 0; //Current pulse count
bool setting = false; //used in setPPM to determine whether we are setting the ppm or starting the measured mile
volatile unsigned long currentMillis = 0;
char Odometer[7];
float distance = 0;
unsigned long prevcount = 0;
unsigned long previousMillis = 0;

Stepper dial(STEPS, 4, 5, 8, 9); // create stepper object to control speedometer dial

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

void TCA9548A(uint8_t bus)  {
  uint8_t data;
  bool err = false;
  Wire.beginTransmission(0x70);  // TCA9548A address is 0x70
  Wire.write(1 << bus);          // send byte to select bus

void magnet_detect() {//Called whenever a magnet is detected
  pcount++; //increment pulse count
  currentMillis = millis();   // capture the latest value of millis()

void writemiles() {
  char miles[7];
  //Serial.print("Write Miles: "); Serial.println(totmiles);
  unsigned long tmiles;
  if (totmiles > 9999999) totmiles -= 10000000; //totmiles is tenths of a mile.  Limit to under one million to avoid overflow
  tmiles = totmiles / 10; //Gets rid of tenths.  Reduces the output to six digits.
  sprintf(miles, "%06lu", tmiles);
  TCA9548A(7); // tell the TCA9548A we want to use I2C bus number seven (to talk to the OLED)
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.drawStr(1, 28, miles); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display

void writetrip()  {
  char trip[7];
  if (tripmiles > 999999) tripmiles -= 1000000; //Tripmiles is tenths of a mile.  Limit to under 100000 to avoid overflow
  sprintf(trip, "%06lu", tripmiles);
  TCA9548A(6); // tell the TCA9548A we want to use I2C bus number six (to talk to the OLED)
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFontMode(1);  // activate transparent font mode
  u8g2.setDrawColor(1); // color 1 for the box
  u8g2.drawBox(106, 0, 21, 32);
  u8g2.drawStr(1, 28, trip); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display

void dialSweep(float deltadist, unsigned long deltatime) {
  float curspeed;
  static float pastspeed[5] = {0, 0, 0, 0, 0};
  int nosteps;
  static int prevsteps = 0;
  static int i = 0;
  if (deltadist = 0) {
    curspeed = 0;
  } else {
    curspeed = 36e5 * deltadist / deltatime; //distance is in tenths of a mile, time in millisecs.  3600 s/hr * 1000 ms/s / 10 tenths of a mile/miles = 360000
  pastspeed[i] = curspeed;
  curspeed = (pastspeed[0] + pastspeed[1] + pastspeed[2] + pastspeed[3] + pastspeed[4]) / 5;
  if (i > 5) i = 0;
  /*Complicated logic following is because my speedometer has a scale that is half as broad from 0-1 mph as other 10 moh intervals.
  if (curspeed >= 10) {   //17 steps = 10 mph, speed above 10 mph
    nosteps = (int)(((curspeed - 10) / mphperstep) - prevsteps + 17); //get steps from 10 mph to current speed, subtract prev step value.  Add 17 to get up to 10 mph
  if (curspeed < 10 && curspeed > 0) { //speed below 10 mph
    nosteps = (int)((curspeed / (2 * mphperstep)) - prevsteps);
  if (curspeed = 0) {
    nosteps = -prevsteps - 20; //to ensure that we don't get creep, reset the needle as far left as it will go.
  prevsteps += nosteps;

void calcMiles() {
  unsigned long curcount;
  unsigned long curMillis;
  unsigned long deltatime;
  float deltadist=0;
  curcount = pcount;
  curMillis = millis();
  if (curcount>prevcount) {
      Serial.print(""); Serial.print(ppm);  //Serial.write(9);
      //Serial.print(curcount); Serial.write(9); Serial.print(prevcount);Serial.write(9);
      //Serial.print(curMillis); Serial.write(9); Serial.print(previousMillis);Serial.write(9);
  /*if (previousMillis = 0) {
    previousMillis = CurrentMillis; //initialize previousMillis for use later
  } else {*/
    if (curcount > prevcount) {
      deltadist += ((curcount - prevcount) * 10.0) / ppm; //Total miles and Trip miles stored as tenths of a mile for accuracy
      prevcount = curcount;
    } else  {
      deltadist = 0;
    deltatime = curMillis - previousMillis;
    previousMillis = curMillis;
    dialSweep(deltadist, deltatime);

void checkTimer()  {
  if (distance >= 1) {
    distance -= 1;
    totmiles += 1;
    tripmiles += 1;

void setup(void) {

  int EEaddr = 0;
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  u8g2.setFont( u8g2_font_inb24_mn);  // choose a suitable font at

  // Configure relevant comparator parameters
  Comparator.input_p = in_p::in0;       // Use positive input 0 (PD2)
  Comparator.input_n = in_n::dacref;    // Connect the negative pin to the DACREF voltage
  Comparator.reference = ref::vref_2v5; // Set the DACREF voltage to 2.5V
  Comparator.dacref = 255;              // Gives us 2.5V -> (255 / 256) * 2.5V = 2.5V
  Comparator.hysteresis = hyst::large;  // Use a 50mV hysteresis
  Comparator.output = out::disable;     // Use interrupt trigger instead of output pin
  // Initialize comparator
  // Set interrupt (supports RISING, FALLING and CHANGE)
  Comparator.attachInterrupt(ShutDown, FALLING);
  // Start comparator
  Comparator.start();  //analogComparator.setOn(AIN0,AIN1);

  //analogComparator.enableInterrupt(ShutDown, FALLING);
  pinMode(switchPin, INPUT_PULLUP);
  pinMode(pulsePin, INPUT_PULLUP);
  attachInterrupt(pulsePin, magnet_detect, RISING);//second pin of arduino used as interrupt
  attachInterrupt(switchPin, switch_detect, LOW);
  EEPROM.get(EEaddr, totmiles);
  EEaddr += sizeof(unsigned long);
  //Serial.print("EEProm totmiles: "); Serial.println(totmiles);
  EEPROM.get(EEaddr, tripmiles);
  EEaddr += sizeof(unsigned long);
  EEPROM.get(EEaddr, ppm);

      Serial.print(""); Serial.print("ppm");Serial.write(9);
      Serial.print("curcount"); Serial.write(9); Serial.print("prevcount");Serial.write(9);
      Serial.print("curMillis"); Serial.write(9); Serial.print("prevMillis");Serial.write(9);

void loop()  {
  delay(250);  //Check speed and distance every quarter of second.

Since you're using the Comparator library, I'll assume you're using MegaCoreX. Which is a good thing!
BTW did you know that MegaCoreX has printf added to its print class? This means you can print to your display without using sprintf and a separate buffer:

u8g2.setCursor(x_coord, y_coord);
u8g2.printf("Millis since start: %ld\n", millis());

// You can also do Serial.printf
Serial.printf("Millis since start: %ld\n", millis());
  1. It looks like the EveryTimerB.h library messes with a type B timer, which is used to generate millis. Try to remove this. If you load the standard blink sketch, does the LED toggle every second or every four seconds?

For points 2 and 3, try to remove code until it doesn't behave weird. It's difficult to follow along when global variables are shared between multiple functions.

Removing EveryTimerB.h fixed it. Thanks for the tip. One down and two to go. I actually had removed the code using EveryTimerB, but had failed to remove the include. I removed it because it didn't work. We sure do need a better timer library, something that a simpleton like me can use, and it work, and not interfere with millis(). Thanks again.