Go Down

Topic: [SOLUCIONADO] Reemplazar millis por defecto (Read 3427 times) previous topic - next topic

Lucario448

Argh, hasta vergüenza da admitir que apenas es que no salí gritando desesperado pidiendo ayuda para que me resolvieran el error de compilación; para que venga otro y diga que el error estaba en un maldito ';' que había olvidado colocar :smiley-sweat:

No me lo tomen a mal, no es que esté enojado o algo; lo que pasa es que se siente un tanto "humillante" haber hecho medio alboroto sólo por un error de novato (conste que novato no me considero, y que con mi experiencia programando no debería haber caído en esa trampa).

De cualquier manera... ¡gracias! :)



Sin embargo, ahora tengo otro error que esta vez estoy seguro que no es de novatos. Se trata de:
Code: [Select]
'millis1' was not declared in this scope
Ocurre ya en el sketch en sí; y no en el resto de archivos.

Lo único que sé de dicho error, es que no sé como "auto-instanciar" una librería. Digo... ¿dónde debería ir esto que no sea en el sketch (archivo .ino)?
Code: [Select]
Millis1 millis1;

Alfaville

#31
Jan 10, 2017, 01:57 am Last Edit: Jan 10, 2017, 02:11 am by Alfaville
Nada de humillante. ¿ Por que crees que he detectado tan pronto el <;> ?. Pues porque me ha pasado a mi muchas veces.

Las prisas, el indentado, los comentarios,... al final error de sintaxis que el compilador no ayuda a resolver y nos dá un mensaje un poco "de despiste".

Alfaville

Para salir del paso crea la instancia antes del setup() en el bloque de declaracion de variables del sketch
Code: [Select]

#includes...
#defines...
variables...
Millis1 millis1;

void setup() {}
void loop() {}

noter

Prueba poniendo en Millis1.h, justo antes del #endif final:
Code: [Select]

extern Millis1 millis1;


Y en Millis1.cpp, puedes completar el constructor (en este caso creo que no sería necesario, pues no hay que proporcionarle parámetros y se ejecutaría el constructor por defecto; pero así de paso ya sabes cómo lo harías en caso de que sí fueran necesarios dichos parámetros).

Code: [Select]

Millis1 millis1=Millis1();

Alfaville

Otra buena solucion es esta:
Code: [Select]
#ifndef Millis1_h
#define Millis1_h

#include "config.h"

#ifdef ISR_COMPENSATION
#define COUNTS_PER_MILLISECOND ((F_CPU / 1000L) - 24)
#else
#define COUNTS_PER_MILLISECOND ((F_CPU / 1000L) - 1)
#endif


class Millis1 {
  public:
  Millis1();
  void start();
  void stop();
  void reset();
  unsigned long millis();
} millis1;                // <<<==== aqui puedes declararla

#endif

 Puedes declararla así con lo que queda oculta para el resto del programa.

Lucario448

No he probado la sugerencia de Alfaville, pero me parce que la de ambos funciona igual (a menos de que haya especial en la palabra reservada extern que no sepa). Y sí, por fin pude compilar.

En el primer intento, noté que la característica de AUTO_START parece no funcionar; todas las llamadas de millis1.millis() retornaban cero a menos de que llame explícitamente a start.
Después de llamar a start como primera instrucción del setup, este fue el resultado:

Code: [Select]
Comparando ambos millis con 10 muestras, con un intervalo delay de 1000 milisegundos...
1 2 3 4 5 6 7 8 9 10
Resultados:
millis millis1
24 24
1027 1027
2026 2027
3026 3027
4026 4027
5026 5027
6027 6027
7026 7027
8027 8027
9027 9027

Viendo esto llegue a las siguientes conclusiones:

  • delay parece ser bastante preciso a la hora de paralizar el flujo del programa.
  • El millis original tiene su cosa, pero no es para tanto. Además, se puede apreciar las veces en que se aplica la compensación del número fraccionario.
  • Sorprendentemente, mi implementación de millis parece dar lecturas muy estables; a pesar de no haber usado el experimental ISR_COMPENSATION.

Adjuntaré de nuevo la carpeta con todo; solo que esta vez tal y como estuvo en esta prueba. La idea es que compartan sus resultados y así ver cómo se comporta con otros microcontroladores AVR y/o distintas frecuencias de reloj.


Además, no se que piensan ustedes pero... será necesario que también lo pruebe en lapsos mucho más largos?

noter

#36
Jan 11, 2017, 12:20 am Last Edit: Jan 11, 2017, 12:25 am by noter
No he probado la sugerencia de Alfaville, pero me parce que la de ambos funciona igual (a menos de que haya especial en la palabra reservada extern que no sepa). Y sí, por fin pude compilar.
Pues la versión de tu último zip a mí no me compilaba, hasta que puse la línea de inicialización de millis1 en Millis1.cpp.

En el primer intento, noté que la característica de AUTO_START parece no funcionar;
Tal vez lo que esté ocurriendo es que el define no alcance a tu condición. Prueba a lanzar error en el #ifdef AUTO_START. Si no se lanza error, es que no está detectando la definición.
delay parece ser bastante preciso a la hora de paralizar el flujo del programa.
Esto es porque delay mide el tiempo transcurrido utilizando micros, no millis.

El millis original tiene su cosa, pero no es para tanto. Además, se puede apreciar las veces en que se aplica la compensación del número fraccionario.
"Quod erat demostrandum"  ;)  ;)  ;)

Sorprendentemente, mi implementación de millis parece dar lecturas muy estables; a pesar de no haber usado el experimental ISR_COMPENSATION.
.../...
Además, no se que piensan ustedes pero... será necesario que también lo pruebe en lapsos mucho más largos?
No habiendo problemas con la rutina de interrupción, la estabilidad a lo largo del tiempo es ya cuestión de hardware y no de software. El software se limita a leer el reloj que hemos arrancado.

Alfaville

Bueno, a la vista de los resultados y aun a riesgo de estar equivocado opino que:

- No se gana demasiado en precision con millis1 respecto a millis, pese a que utilizamos un timer de 16 bits y un clock de 62.5 nseg. contra un timer de 8 bits y clock de 4 useg.

- Que delay se mantiene razonablemente preciso aun cuando se apoya en millis, ya que el calculo de microsegundos lo realiza haciendo una extrapolacion del tiempo obtenido con millis

- Que una aplicacion mas estricta en la medida de tiempos deberia extremar el uso de los timer perdiendo "universalidad" de uso del MCU a favor de la precision.

@Lucario448: el tema no está agotado, ¿ seguiras profundizando en el ?

No he probado la sugerencia de Alfaville, pero me parce que la de ambos funciona igual (a menos de que haya especial en la palabra reservada extern que no sepa). Y sí, por fin pude compilar.
Que alguien me corrija, pero creo recordar que extern le indica al compilador que la variable a la que precede está definida en otra unidad del proyecto y como te dice noter si no la defines en ninguno dá error de compilación.
Por eso a veces utilizo la definicion en la misma declaracion de la clase.

Lucario448

Pues la versión de tu último zip a mí no me compilaba, hasta que puse la línea de inicialización de millis1 en Millis1.cpp.
Yo usé la versión 1.6.7 de IDE de Arduino. Si no compilaba tal y como estaba; pues no sé que tienes para eso...


Tal vez lo que esté ocurriendo es que el define no alcance a tu condición. Prueba a lanzar error en el #ifdef AUTO_START. Si no se lanza error, es que no está detectando la definición.
Sí da error de compilación cuando lo defino; pero sigue sin iniciar implícitamente.


Bueno, a la vista de los resultados y aun a riesgo de estar equivocado opino que:

- No se gana demasiado en precision con millis1 respecto a millis, pese a que utilizamos un timer de 16 bits y un clock de 62.5 nseg. contra un timer de 8 bits y clock de 4 useg.
No estas equivocado...
Code: [Select]
Comparando ambos millis con 18 muestras, con un intervalo delay de una hora.
Resultados:
millis millis1
3600000 3600000
7200026 7200026
10800053 10800053
14400079 14400080
18000106 18000107
21600133 21600134
25200160 25200160
28800187 28800187
32400214 32400214
36000240 36000241
39600267 39600268
43200293 43200294
46800321 46800321
50400348 50400348
54000374 54000375
57600401 57600402
61200428 61200428
64800455 64800455

Así que me doy por vencido :( Solo tendría utilidad si se necesitara el timer0 para otra cosa.


@Lucario448: el tema no está agotado, ¿ seguiras profundizando en el ?
Ya no en el tema de reemplazar millis, pero sí en solucionar los problemas que uno podría encontrarse a la hora de probar una librería creada por uno mismo.
Por si no lo has notado, mis preguntas ahora están dirigidas a la creación de una librería; más que a la inquietud inicial.

Alfaville

Pues tienes dos caminos: o seguimos por aquí hasta que aprendamos a declarar e implementar clases (librerias en lenguaje vulgar aunque no son lo mismo), o abres otro tópico especifico donde corresponda y allí con la ayuda de todos conseguimos entender a fonde el tema.

Tú decides.

Lucario448

Bueno, tal parece el tema ya quedó abandonado; así que ya puedo dar por terminado este hilo.

¡Muchas gracias a todos los que respondieron, porque de ustedes aprendí algo nuevo! :D



Hora de colocar la "palabra mágica" al título; la que indica que este hilo ya no tiene planes para seguir activo.
Los que llevamos bastante tiempo aquí saben a lo que me refiero...

Go Up