millis calculation failing

I'm having a problem with my current program and i have no idea what to look for because ta simple long math is failing:
letme start by doing a quick review of the current state, i'm using the serial monitor and all "debug" lines for debugging.

Program reads SLO pin, i'm gonna start with SLO in high that is the "relaxed" state.

Serial monitor in this case prints:
la diferencia actual es: 23
la diferencia actual es: 1051
la diferencia actual es: 2081
la diferencia actual es: 3111
la diferencia actual es: 4142
la diferencia actual es: 5172
la diferencia actual es: 6202

which is the result of Serial.println((long)( millis() - fin_retardo )); //debug
so far so good because we load 0 in fin_retardo so millis()-0 = millis() and the program shows us how millis advances with a 1s delay...

now i switch SLO to LOW and this is where everything fails....
Serial monitor shows:
el fin del delay es: 1213392
13392
la diferencia actual es: 13455
contando
Testeando! loop: 0

Now here's the problem, the first IF is executing correctly if ((slo_state == LOW) && (contando == false)){ because contando is false and slo has been asserted low.

so program puts current millis() value in currenttime variable, then in the fin_retardo variable puts the currenttime+delta(which is 1200000) and sets the contando flag to true.
Then Prints the fin_retardo variable(1213392), in the next line the currenttime(13455)

This is where it goes wrong: the result of the operation (long)( millis() - fin_retardo) should be a negative number as fin_retardo is larger!, why is this failing?, yesterday i got this same program working and the only difference was that i declared the constant values at the beginning today and yesterday i was hardcoding them in the line itself...
thus since the result is a positive number, the second IF block if ((contando == true) && ((long)( millis() - fin_retardo ) >= 0)) is evaluated (falsely) true and program continues...

this is the code(sorry for the anotations in spanish, i think it's still understandable):

/*
Sketch cargador UC3906 en Arduino 0022
 Chequea que la bateria este a flote, 2 semanas despues inicia el test de carga
 activando un rele que desactiva el UC3906 y al mismo tiempo conecta la bateria a la resistencia de carga por 
 4 intervalos de 15 min con 15 min de descanso para enfriar las resistencias,
 Luego reconecta el cargador y sigue el ciclo.
 
 circuito:
 El flote se señaliza por las señales colector abierto del UC3906:
 State Level Output a traves del operacional TL081: 0 en Float, 1 Cargando
 OC Indicate output: 0 si esta en overcharge, 1 puede que sea float o charge
 * se puede monitorear Vbatt con un divisor de 36K y 18K o de 100K y 50K
 * en paralelo a la salida de rele conectar el LED de monitoreo de test
 
 pines:
 Pin 2 - input: Reset (interrupt 0)
 Pin 3 - input: SLO
 Pin 4 - output LED: Cargando 
 Pin 5 - output: Rele
 */

// Constantes globales y definicion pines
const byte SLO = 3;
const byte ledcharge = 4;
const byte rele = 5;
const byte reset = 2;
const long tiempo_en_prueba = 300000;  //15 min tiempo en prueba 900Kmsec, usar 300K para 5 min
const int tiempo_fraccion = tiempo_en_prueba/1000; //Para fraccionar los delays largos en el ejercicio
const unsigned long tiempo_para_ejercitar = 1200000; //20min hasta testear, en realidad tiene que ser 1209600000(2 semanas)
unsigned long fin_retardo = 0; //inicializo fin delay
boolean contando = false; //inicializo sin contar
volatile boolean reset_flag = false; //no esta reseteado
byte slo_state;

void setup(){
  pinMode(SLO, INPUT);
  pinMode(rele, OUTPUT);
  pinMode(ledcharge, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(0, reset_event, RISING);
}
void loop(){
posicion_inicio:
  if (reset_flag == true){
    fin_retardo = 0; //inicializo vars
    contando = false;
    digitalWrite (rele, HIGH); //activar rele
    digitalWrite (13, HIGH); // debug
    digitalWrite(ledcharge,LOW);
    Serial.println("Reset!!!!!!"); //debug
    delay(4000);
    digitalWrite (rele, LOW); //desactivar rele
    digitalWrite (13, LOW); //debug
  }

  slo_state = digitalRead (SLO); //leer pin SLO, recordar que esta negado

  if ((slo_state == LOW) && (contando == false)){ //esta en float, no estoy testeando carga y aún no estoy contando para testear
    unsigned long currenttime = millis();
    unsigned long fin_retardo = currenttime + tiempo_para_ejercitar; // fin retardo, tiempo actual+diff tiempo hasta ejercitar
    Serial.print("el fin del delay es: "); //debug
    Serial.println(fin_retardo); //debug
    Serial.println(currenttime); //debug
    contando = true; //Empieza el conteo regresivo a la ejercitacion
  } 
  else if (slo_state == HIGH && contando == true){
    contando = false; //Si mientras cuento se va de flote, abortar cuenta
  }

  if (slo_state == HIGH) {                // si no esta a flote, encender led de carga
    digitalWrite(ledcharge,HIGH);
  } 
  else digitalWrite(ledcharge,LOW);      // si esta a flote, apagarlo

  Serial.print("la diferencia actual es: ");  //debug
  Serial.println((long)( millis() - fin_retardo )); //debug
  if (contando == true)  Serial.println("contando"); //debug
  delay(1000); //debug

  if ((contando == true) && ((long)( millis() - fin_retardo ) >= 0)){ //Si termino la cuenta regresiva empezar a ejercitar
    contando = false; //termino la cuenta regresiva
    for(int l = 0; l < 4; l++){  // 4 loops de ejercitacion(0 a 3)
      if (reset_flag == true) goto posicion_inicio; //abortar si reset

      digitalWrite (rele, HIGH); //activar rele
      digitalWrite (13, HIGH); // debug
      Serial.print("Testeando! loop: "); //debug
      Serial.println(l); //debug

      //comienzo delay sintetizado
      for (int i = 0; i < 1000; i++) {
        delay (tiempo_fraccion);
        if (reset_flag == true) goto posicion_inicio; //abortar si reset
      } //fin delay sintetizado

        digitalWrite (rele, LOW); //desactivar rele
      digitalWrite (13, LOW); //debug
      Serial.println("Descansando!"); //debug

      //comienzo delay sintetizado
      for (int i = 0; i < 1000; i++) {
        delay (tiempo_fraccion);
        if (reset_flag == true) goto posicion_inicio; //abortar si reset
      } //fin delay sintetizado
    } //fin loop ejercitacion
  }
}
void reset_event(){
  reset_flag = true; //set reset
}

The line:

unsigned long fin_retardo = currenttime + tiempo_para_ejercitar; // fin retardo, tiempo actual+diff tiempo hasta ejercitar

inside your if() block is declaring a second fin_retardo variable that is only local and available within your if block (this block being the code inside the if's { and }). Once this block is left, that local variable goes out of scope and is gone. So your later print statement is referring to the global fin_retardo, which never got assigned anything and is thus still = 0.

Get rid of the unsigned long in that line. You don't want to declare a new variable, but use the global you've already declared.

you know i noticed the same thing after comparing yesterday version with this one(thank you dropbox!, it's a must for any developer! :grin:) and i have no idea why i declared it again inside there....
arfff.... looks like that was the culprit, overdeclaration... i should bash my head on the keyboard....

Your code will not work correctly as millis approaches the wrap.

why not?, the millis testing i've taken it from the millis wraparound example and i've modeled it in another sketch simulating the millis rollover and it worked ok:

// millis rollover smulator
unsigned long timer = 4294967295-100;  //4294967295 limit ulong -100
unsigned long destino = timer+1000; //destination time

void setup(){
  Serial.begin(9600);
}
void loop(){
  unsigned long pruebaa = destino-timer; //substracting un ulong
  long pruebab = (long) (timer-destino); //substracting as the rollover example
  Serial.print("timer actual: ");
  Serial.println(timer);
  Serial.print("el fin del delay es: ");
  Serial.println(destino);
  Serial.print("con ulong: ");
  Serial.println(pruebaa);
  Serial.print("con signed long: ");
  Serial.println(pruebab);
   delay(2000);
    timer += 10;
}

You failed to test this...

  if ((contando == true) && 

((long)( millis() - fin_retardo ) >= 0)  // <<<

){ //Si termino la cuenta regresiva empezar a ejercitar

but that's exactly the point i've testd, it's the only point i'm using millis for the long delay and i've taken it directly from http://arduino.cc/playground/Code/TimingRollover

  if( (long)( millis() - lWaitMillis ) >= 0)
  {
    // millis is now later than my 'next' time

    { do something }

so i'm not following on what's wrong :expressionless:

My apologies. The code is fine.

hahah you had me all intrigued for moment there, i rechecked the "rollover demo" sketch i built twice and the example code to see what was wrong and couldn't find anything :smiley: