Unsure how to add in a timer

I'm unsure how to format the following feature correctly. I have a couple of if-statements that use the same timer (orientTime). The sensor should print data every 500ms, fetch the X-Value after 6000ms, and enter the next switch-state after 10000ms.

However, with below example orientTime is ignored completely (i.e. the if-statements that use it aren't triggered). how should I do this differently?

unsigned long orientTime = 0;

case ORIENT:

    orientTime = millis();
    xl.readXYZTData(XValue, YValue, ZValue, Temperature);

    if(millis() - orientTime >= 6000) {
        xval = (XValue);
        Serial.print("xval=");
        Serial.println(xval);
      }

	if(millis() - lastPrintSample >= 500) {
	    lastPrintSample = millis();
      Serial.print("X=");
        Serial.print(XValue);
        Serial.print("\t Y=");
        Serial.print(YValue);
        Serial.print("\t Z=");
        Serial.println(ZValue);
      }

	if (millis() - orientTime >= 10000) {
      state = PRELOC;
      break;
      }
  break;

These statements are executed within microseconds after you set orientTime = millis() so no wonder none of the conditions involving orientTime triggers.

@Vitesze, you may want to move the orientTime = millis(); line just before the state = PRELOC; line. That way, after 10000ms, the timer will be reset. However, because you are using the same timer, if(millis() - orientTime >= 6000) will keep triggering until the timer is reset at 10000ms. I suggest you use two timers to separate the events and reset those timers each time their timeout events occur.

I decided to adapt my code a bit. I still don't understand it at all; whenever I run this code, it will always immediately timeout, even though it's not supposed to do it after at least 10 seconds.

It prints XYZ data just fine, assigns a value to xval1 just fine, but will timeout after one measurement.

case ORIENT:

    xl.readXYZTData(XValue, YValue, ZValue, Temperature);

	if(millis() - lastPrintSample >= 500) {
	    lastPrintSample = millis();
      Serial.print("X=");
        Serial.print(XValue);
        Serial.print("\t Y=");
        Serial.print(YValue);
        Serial.print("\t Z=");
        Serial.println(ZValue);
        break;
      }

  if ((XValue != 0 && XValue != -1) && (millis() - lastXSample >= 500)) {
      lastXSample = millis();
      xval1 = (XValue);
      Serial.print("xval1=");
        Serial.println(xval1);
        break;
      }

	if (millis() - orientTime >= 10000 && xval1 != 0) {
	    orientTime = millis();
	    Serial.println("timeout");
      state = PRELOC;
      break;
      }
 break;

@Vitesze, if you are setting the timers to zero initially, the first time through, all the timeouts will occur faster than their normal “cycle”. I’m not sure what the difference between the lastPrintSample and lastXSample timers is since, unless you have an invalid XValue, they both fire off at 500ms. Also, the orientTime if statement seems to call for a timeout if 10 seconds have passed and xval1 is not zero. That last part seems wrong. Is this the correct logic?

Oh yeah thanks for pointing out the lastPrintSample and lastXSample part. I never knew about timeouts occuring faster when set to 0.

It’s the correct logic, for now I just wanted an easier case to work with. The plan is to have it timeout using different conditions.

I still seem to have the same issue, when I define unsigned long orientTime;
When this state is entered, the next state is entered after 500ms, right after the first reading. The one reading it gives does seem to be accurate.

@Vitesze, the reason a software timer may time out faster on first pass when initialized to zero is that millis() count the number of milliseconds from reset. Several millis may go by before your code gets to the ORIENT state so the timers will be relative to the reset and not to the time you start the ORIENT state. The ideal situation is that you set all your timers to millis() in the state that switches to the ORIENT state.

Ahh, thanks so much for clearing this up about the timers. I’ve been quite confused about it the past few days as it’s one of the few things that I never could get to work properly in my code.

When adding orientTime = millis(); in the case preceding ORIENT, it works fine. Readings for 10 seconds, and then cuts to the next state. Thanks a bunch!!!

1 Like