Subtracting one long from another gives a weird result..

Hi..
Hope someone can explain something to me, I'm certain it's a nuance of the language...
Running this code on a UNO.

I have a couple of globals declared thus..
long runMillis = 0;
long timerA = 0;

In one of my methods I declare a local longs thus..

         long millisNow = millis();
         long delta = millisNow - timerA; // delta = how long since the timer was reset
 long timeToRun = runMillis - delta; // How many more millis left for the lights to run
 runMillis = runMillis - delta; // Load runMillis with the new value

Issue is that the last statement runMillis = runMillis etc... sets runMillis to a weird value (a small negative one)

to be a little more verbose, timerA is set a value in another method by..
timerA = millis();

timeToRun is set correctly, why isn't runMillis??

Thanks in advance

Dave

PS, full sketch below...

// Declare pin assignments

const int tButton       = 2;
const int runLed        = 8;
const int HrLed1        = 9;
const int HrLed2        = 10;
const int HrLed3        = 11;
const int HrLed4        = 12;

// const long OneHour  = 3600000;    //Milliseconds in an hour
const long OneHour  = 5000;    //Milliseconds in 10 secs (Testing)

//Declare variables
boolean lightsOn = false;
int  runHours  = 0;			// How many periods(Hrs??) the lights have to run for
long runMillis = 0;			// How many actual milliseconds the lights have to be on for
long timerA    = 0;			// Used to count how long between button presses

// Declared methods
void adjustTimer()
{
	if(runHours ==4)		// Max time reached, we need to roll over to zero and turn off everything
	{
		runHours = 0;
		runMillis = 0;
		lightsOn = false;
		digitalWrite(runLed, LOW);
	}
	else
	{
		runHours +=1;
		runMillis += OneHour;
		lightsOn = true;
		digitalWrite(runLed, HIGH);
	}
	
	Serial.print("runHours :");
	Serial.print(runHours);
	Serial.print(" runMillis :");
	Serial.println(runMillis);
}

void decTimer()		//Count lights on timer down
{
	// Check how long the lights have been on since last key press..
	
	 long millisNow = millis();
	 long delta = millisNow - timerA;		// delta = how long since the timer was reset
	 long timeToRun = runMillis - delta;	// How many more millis left for the lights to run
	 // runMillis = runMillis - delta;			// Load runMillis with the new value
	
	if(timeToRun <=0)			// Timer has counted down to zero - turn off everything
	{
		Serial.println("*** Timer Expired ***");
		Serial.print(" delta :");
		Serial.print(delta);
		Serial.print(" millisNow :");
		Serial.print(millisNow);
		Serial.print(" timerA :");
		Serial.print(timerA);
		Serial.print (" runMillis :");
		Serial.println(runMillis);
		
		runHours = 0;
		runMillis = 0;
		lightsOn = false;
		digitalWrite(runLed, LOW);
		
	}
	
}

void setup() {
  // put your setup code here, to run once:
    Serial.begin(115200);

  //Set pinmode for all pins...
  pinMode(tButton, INPUT);
  digitalWrite(tButton, HIGH);

  pinMode(HrLed1, OUTPUT);
  digitalWrite(HrLed1, LOW);

  pinMode(HrLed2, OUTPUT);
  digitalWrite(HrLed2, LOW);

  pinMode(HrLed3, OUTPUT);
  digitalWrite(HrLed3, LOW);

  pinMode(HrLed4, OUTPUT);
  digitalWrite(HrLed4, LOW);

  pinMode(runLed, OUTPUT);
  digitalWrite(runLed, LOW);

}

void loop() {
  // Get button event and act accordingly
  int b = checkButton();
  if (b == 1) clickEvent();
  
  if(lightsOn)
  {
	decTimer();
  }
}

void clickEvent()
{
	// Button has been clicked, so do the following..
	timerA = millis();		// restart the timer
	adjustTimer();
}

you should be doing time keeping using millis() with Unsigned Long (uint32_t) datatypes and unsigned subtraction... millis() returns an unsigned long, fyi.

the compiler interprets magic numbers in code as integer data eyes by default. Save yourself a future headache by getting in the habit of indicating UL during the assignment, it will come in very useful later if you want to sue bit-shifting methods:

unsigned long runMillis = 0UL;
unsigned long timerA = 0UL;

@jcm4101:
Why did you post just a snippet and not your entire sketch?

Thanx BulldogLowell, I'll make that change and remember that for the future :slight_smile:
odometer.. Yea, I realised I hadn't posted the entire sketch, so amended my post to include same.. apologies..

Anyhew, as usually happens, after sweating over this issue for hours, 2 minutes after posting here I realised there's a coding error, and there's no issue with the long maths, so apologies for cluttering up the feed...

thanks again

If you are still using long datatypes for time stamps then you still have a problem. You just won't see it until about 44 days from boot time, when millis() rolls over.

the compiler interprets magic numbers in code as integer data eyes by default.

The compiler does what?