Pages: [1] 2   Go Down
Author Topic: Re: Desbordamiento y millis()  (Read 2526 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yo creo que al final del bucle se puede comprobar si "tiempo" anterior es mayor que el que devuelve millis(). En ese caso, habríamos dado la vuelta al contador, y comienzo la cuenta desde cero.

if(millis() < tiempo) Tiempo1_k = millis()
« Last Edit: April 20, 2011, 12:41:52 am by Valen » Logged

Euskadi
Offline Offline
God Member
*****
Karma: 16
Posts: 711
Arduinotarrak
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hola,
En la referencia de Arduino sobre millis() dice que devuelve un unsigned long, y que a los 50 días más o menos empieza de cero. La variable unsigned long puede llegar hasta unos 4 Gigas, que son los milisegundos que hay en 50 días, más o menos.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ahhh...... Ok, es verdad...

gracias...!


Logged

Offline Offline
Edison Member
*
Karma: 23
Posts: 1375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Valen, si vas a usar millis de la forma que has puesto, nunca tendrás problemas con el overflow.

Otra cosa, si quieres que dure T1 "exacto" y luego le metes una espera de 10ms, ya estás metiendo 10ms de error como poco. Ese delay lo quitaría ya que no sirve para nada.

Un saludo
Logged

Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grcias, sí, quitaré el delay() del while().

aunque se necesite varios días para desbordar un long, hay máquinas que siempre están conectadas (podría ser el caso de mi módulo), y en ese caso, el "problema" se producirá.

Pero como millis() pasa ella solita a cero al desbordar, no parece problema controlar esa situación:

Cuando el valor de millis() se haga cero, durante ese ciclo, el valor almacenado en la variable "tiempo" será mayor. Testeando esta situación en cada ciclo, al cumplirse, actualizaremos la variable "tiempo" con el valor de millis(), y todo comienza de nuevo....

Bueno, esta es mi idea del asunto....

Logged

Offline Offline
Edison Member
*
Karma: 23
Posts: 1375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

En serio, al restar se anula el posible efecto del overflow, por lo que si lo usas de la manera que has puesto no tendrás problemas con el overflow nunca jamás, ni en trescientos mil millones de años que esté el Arduino continuamente encendido.
Logged

Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Albacete
Offline Offline
Full Member
***
Karma: 0
Posts: 140
Arduino mola que te pasas
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Usando una variable 'Extra long' (cuya existencia desconocia. Muchas gracias bokeaus), no obviarás el problema de millis(), ya que es la propia función milis() la que se resetea a los 50 dias. Por tanto, no cambia nada entre usar una variable long y una long long.
Con respecto a lo que comenta el compañero Chiva, apuntarte que podrias tener problema si el overflow se produce entre la asignacion de milis() a la variable y su evaluacion:
cuando asignas, imaginate que millis() esta a punto de desbordarse, y vale una barbaridad. Antes de evaluarla, se desborda, y cuando haces la comparación, pasa a valer 3 (por decir algo) entonces, y durante los proximos 50 dias, millis()-tiempo sera menor que cero, y el while  se estara ejecutando permanentemente.
Supongo que bastará con hacer un if millis-tiempo<0 dentro del while para eliminar del todo el problema.
Logged

Offline Offline
Edison Member
*
Karma: 23
Posts: 1375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pofenas, ten en cuenta que millis devuelve un unsigned long, por lo que no hay números negativos.

Imaginemos que tenemos un tipo de dato sin signo que puede almacenar de 0 a 1000 y queremos saber cuando han pasado 30ms

En un instante, millis() nos devuelve 350 y a la hora de comparar devuelve 390, entonces se cumple la condición ya que 390-350 > 30

Al volver a pasar por el mismo código, millis() devuelve 980 y luego 20 (ya que hemos pillado un overflow entre las lecturas), la condición se seguirá cumpliendo ya que: 20-980 = 40 (en verdad es 41, pero por simplificar el ejemplo redondeamos a 40)
« Last Edit: April 13, 2011, 10:57:59 am by chiva » Logged

Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Albacete
Offline Offline
Full Member
***
Karma: 0
Posts: 140
Arduino mola que te pasas
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

La clave esta en la linea

 while(millis()-tiempo < T1) delay(10);


'Al volver a pasar por el mismo código, millis() devuelve 980 y luego 20 (ya que hemos pillado un overflow entre las lecturas),'
millis=20 y tiempo =980

el while quedara:
while(20-980<T1) delay(10)

El ejemplo no es muy bueno, ya que el overflow lo tendremos cuando millis() alcance el maximo valor para un unsigned long: 4,294,967,295
Replanteemos el ejemplo con datos mas adecuados:
-el bucle se ejecuta cuando millis() esta a punto de desbordar, y obtenemos un valor de 4,294,967,294 para la variable tiempo
-cuando llegamos al while, millis() devuelve un valor de 5
-millis()-tiempo = 5-4,294,967,294= -4,294,967,289
-como el resultado es negativo, es menor que T1, y se evalua como verdadera la condicion para el while, que ejecuta el delay(10)
- se vuelve a evaluar la condicion del while, que da un numero aproximadamente 10 unidades mayor.
Es sencillo ver que esta situación se va a mantener siempre, ya que nunca millis() va a devolver un valor 10 unidades mayor que tiempo.

Lo ue no acabo de ver es porque dices que no devuelve un negativo... creo que seria diferente si hicieras
unsigned numero
numero = millis()-tiempo
« Last Edit: April 13, 2011, 01:34:04 pm by Pofenas » Logged

Offline Offline
Edison Member
*
Karma: 23
Posts: 1375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Me refería a que millis() funcionara con ese hipotético tipo de dato e hiciera overflow cada 1000ms, para tener números mas manejables.

No devuelve negativo por que estás trabajando con números sin signo, por lo que se aplican sus reglas.
Al igual que pasa de 4,294,967,294 a 0, al restar pasa de 0 a 4,294,967,294 y si no, no tienes más que escribir un par de líneas:

Code:
void setup(){
  Serial.begin(9600);
  unsigned long time = 50;
  Serial.print(time-4000);
}

void loop(){}
Logged

Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

¿Y has pensado en la utilización del watchdog?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buenas Noches.
Yo no estoy muy puesto en estas labores, pero mi solución, sin decir que es la mejor, fué:

Compruebo en cada ciclo de mákina que el contador millis() no ha pasado de cierto límite crítico.
        Si pasa ese límite, y no está haciendo "nada" que le influya, (ya he puesto el cierto límite con bastante holgura, un par de dias, por ejemplo)
              Resetea la makina, (por software claro). -- > problema solucionado.
       Si pasa ese límite, pero está haciendo algo, pues marco un bit como que hay que resetear cuando termine. (claro para que haga lo que tieene que hacer)
             Cuando ha terminado de hacer sus labores, y ya se puede, resetea la makina( por software en este caso también) ---> problema solucionado.

Es una pena, pero el code no lo tengo a mano ahora, si lo kieres o necesitas alguna aclaración más, me lo comentas y ya veremos, pero seguro que con los sesudos que hay por akí, falta no creo que te haga mucha.

Un Saludo y Gracias por motivarme todos los días a pensar en algo nuevo.
Logged

0
Offline Offline
Edison Member
*
Karma: 17
Posts: 1407
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

recuerdas como hacias el reseteo por software??
Logged

* Si preguntas, pon el código de tu programa, hace mucho mas fácil ayudarte. Y me ahorro un mensaje pidiendo que lo hagas.
* Si consigues solucionar tu problema, dedica unos minutos a explicar en tu post como lo conseguiste para beneficio de todos.
* Cambia el 'Subject' de tu hilo y añade 'SOLUCIONADO' cuando hayas llegado a una solución al problema que planteaste.
* Utiliza un 'Subject' para tu hilo que explique de que va el hilo.
Si estas empezando:
* Comienza a usar Arduino
* Guías de iniciación a Arduino
* Ejemplos
* Referencia del Lenguaje
* Conceptos básicos
Guia de usuario de arduino
Tutoriales en Ingles
Si necesitas que alguien te escriba el código: http://www.freelancer.com/  o esta  http://www.guru.com/

Offline Offline
Jr. Member
**
Karma: 0
Posts: 53
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yo creo que al final del bucle se puede comprobar si "tiempo" anterior es mayor que el que devuelve millis(). En ese caso, habríamos dado la vuelta al contador, y comienzo la cuenta desde cero.

if(millis() < tiempo) tiempo = millis();

 while(millis()-tiempo < T1);

Cada 50 días funcionado sin parar, un ciclo de programa durará unos milisegundos más. Algo insignificante en un control de una máquina eléctrica grande, como es el caso.
« Last Edit: April 20, 2011, 12:32:45 am by Valen » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sergegsx

Para hacer el reseteo por software:

Junto a los #include introduzco un función:

void(* resetFunc)(void=0);

luego viene el resto del code

void loop()
/......
y cuando la necesito usar la invoco con su nombre

resetFunc();

...../

en este ejemplo concreto declaré una variable que comparaba si habia superado el tiempo de reset y además la salida estaba inactiva.

if ((millis() > tiempoReset) && (salida == LOW))
    {
        resetFunc();
     }

Hay que tener en cuenta que la variable tiempoReset de este ejemplo debe ser tipo Long igual que lo es millis() .

Espero te / os sirva, no recuerdo bien de donde la saqué seguro que de este foro u otro parecido, debería de anotarme esas cosas también, el merito hay que reconocerselo al autor, y no a mi que solo soy un utilizador del recurso.






Logged

Pages: [1] 2   Go Up
Jump to: