Using int for millis()

Hello,

I am working on a project where apart from other functions i have to determine the elapsed time between input state changes, then if it is below a set threshold, enable the outputs.
The code needs to run pretty fast, as it handles two inputs of a camshaft sensor, one is 1 cycle/rotation, the other is 6 cycle/rotation. Expected max RPM is 3750.

Here are the relevant lines from my code :

unsigned long CurrTime;
unsigned long StrobeTime;

void loop(){

CurrTime=millis(); 

if (input state change detection) {
StrobeTime = millis();
}

if (CurrTime-StrobeTime > 500 ){
  
  /disabling outputs/ 
}

Now when i use unsigned long for the variables, the code runs very slow, the outputs are acting funny, dropping out, etc.

I have tried using int, it runs perfectly even up to 4200 RPM, the max rpm of my drill that i use to test it.

If i use unsigned int, it behaves exactly like when using unsigned long.
Video:
unsigned long/int: unsigned long - YouTube
int: integer - YouTube
The three leds represent the outputs.

Is this simple math really this slow when using unsigned or long variables?
Can cause any problems if i use normal int for storing the millis() output?

It can't be caused by difference between unsigned int and int, it more probable that you have an error(s) in your code.

Please show your sketch in full.

#include <digitalWriteFast.h>
const int ident = 6;  //pin 6 = cylinder identification input
const int cyl = 7;    //pin 7 = cylinder strobe input
const int cyl14 = 2;  //pin 2 = 1-4 cylinder output
const int cyl52 = 3;  //pin 3 = 5-2 cylinder output
const int cyl36 = 4;  //pin 4 = 6-3 cylinder output


int identState = 0;
int cylState = 0;
int LastIdentState = 0;
int LastCylState = 0;
bool sync = 0;
int counterCyl = 0;
int counterIdent = 0;
int CurrTime;
int StrobeTime;



void setup() {
  //define IO pins
  pinModeFast(cyl14, OUTPUT);
  pinModeFast(cyl52, OUTPUT);
  pinModeFast(cyl36, OUTPUT);
  pinModeFast(ident, INPUT);
  pinModeFast(cyl, INPUT);
  Serial.begin(2000000);
}



void loop() {


  identState = digitalReadFast(ident);

if (identState != LastIdentState) {

 if (identState == HIGH) {
  counterIdent++;

  counterCyl = 1;

    } else {

  counterIdent++;
  counterCyl = 4;
    }
  }

  LastIdentState = identState;

  if (counterIdent > 1) {
    sync = true;
  } else {
    sync = false;
  }

  if (counterIdent > 4) {
    counterIdent = 2;
  }

  cylState = digitalReadFast(cyl);

  CurrTime = millis();

  if (cylState != LastCylState) {

    if (cylState != HIGH) {
      counterCyl++;
      Serial.print("current cylinder: ");
      Serial.println(counterCyl);
      StrobeTime = millis();
    }
  }

  LastCylState = cylState;

  if (CurrTime - StrobeTime > 500) {

    counterIdent = 0;
  }

  if (counterCyl > 6) {
    counterCyl = 1;
  }

  //writing outputs depending on where the counter sits and sync is ok

  if ((counterCyl == 1 || counterCyl == 4) && sync == true) {

    digitalWriteFast(cyl14, HIGH);
  } else {
    digitalWriteFast(cyl14, LOW);
  }
  if ((counterCyl == 5 || counterCyl == 2) && sync == true) {

    digitalWriteFast(cyl52, HIGH);
  } else {
    digitalWriteFast(cyl52, LOW);
  }
  if ((counterCyl == 3 || counterCyl == 6) && sync == true) {

    digitalWriteFast(cyl36, HIGH);
  } else {
    digitalWriteFast(cyl36, LOW);
  }

  //end of loop
}

Well if StrobeTime > CurrTime even for 1ms this expression will return true if you use unsigned long and false if you use int.

1 Like

You never update StrobeTime , so your timers runs only once after program statrts.
But if you using int for timer, it overflow after 32 seconds and the program start you logic from the beginning

1 Like

INT is either 16-bit or 32-bit, depending upon hardware architecture: UNO, Mega, etc. being 8-bit uC but C/C++ does the 16-bit integer manipulation. Due and other more advanced microcontrollers are 32-bit architecture and C++ honors that native datatype.

Other casts in C++ are very efficient, a few clock cycles used only. Compilers are very optimized in this fundamental area.

I would not think your experience is indicative of INT byte-size or format.

It would be simple to test in loop() by just capturing micros() at the beginning, perform some integer math in a do-while loop, and capturing the elapsed time using micros before the close of loop(). Maybe to the inner loop for 10^4 - 10^5 times just to get a decent interval.

Repeat above only with an unsigned int.

Compare. And please post the results if you perform the experiment. Your current sketch is not provided, so further help is not possible.

UPDATE
See you posted your code and others are offering assistance.

So basically i have created a scenario, when StrobeTime > CurrTime can be true when using unsigned long, and this causes the errors?

Isnt StrobeTime being updated every time when
` if (cylState != LastCylState) {

if (cylState != HIGH) {`

is true?

Sorry but i have just picked up an arduino a week ago, this is the first ever program that i wrote in my life, sooo.. I dont really understand what you are saying :sweat_smile:

looks like the code turns on one of 3 LEDs depending on which pair of cylinders are being recognized and depending on identState that presumably toggles at once per rotation

shouldn't identState be the only thing resetting counterCyl ? i see counterCyl being set to 1, 4 depending on indentState and later reset to 1 when > 6

if identState toggles once per rotation, shouldn't it only reset counterCyl to something once (can't say it harmless otherwise

please point the exact line of the code where you updated it.

INT or int?

I want to use it for ditching the distributor on a 6 cylinder engine, and using a wasted spark coilpack.
counterCyl is reset to 1 when it is more that 6, to jump back to cyl #1 after detecting cyl#6.
identState resets counterCyl to 1 or 4 to eliminate incorrect counts if one input of cylState is not read for some reason.

xedos6 elosztó jelek felirat
This is the oscillogram of the two signals.
counterCyl cant be anything else than 1 when ident is going high. also it cant be anything else than 4 when ident is going low.

Seriously?
in code, int
in a paragraph to denote emphasis:

  • INT
  • INT
  • int

You struck a pet-peeve, pet peeve at DuckDuckGo

Do i need to reset CurrTime and StrobeTime to zero at the begining of the loop?

Don't use 'int', but 'unsigned int' is allowed, or even uin8_t Don't use uint8_t, see reply #25.
If your 'unsigned int' is 16 bits, then a millis-timer can run up to 65 seconds. As always, you have to carefully check your code that it is not doing funny things after another 65 seconds.

I used the 16-bit unsigned int in my millis_overdone.ino to run 400 millis-timer on a Arduino Uno. Try the sketch in Wokwi here: millis_overdone.ino - Wokwi Arduino and ESP32 Simulator (all the timers blink the led, but that is not visible in Wokwi).

1 Like

It depends on your algorithm
But as far I understand your code - no

I don’t know, and tbh don’t want to know, but you were looking for difference in behaviour when changing var type, feel free to investigate

it looks ident rises just before the cylinder pulse and could be used to set the cylinder count to zero because the cylinder input would rise just after it and set it to 1

i think you're using sync as a flag to indicate the events are occurring and can toggles the LEDs and flag is reset after a timeout to inhibit toggling LEDs after a timeout period.

It has nothing to do with personal liking/disliking; it is the Compiler that puts objection against the usage of INT.

Rather it has everything to do with petty responses to how written communications are utilized. Not only wasting my time but yours; my time is better utilized to go for a fresh cup of coffee.

That means that the written communication can violate C++ Language's established conventions?