[SOLUCIONADO] Reemplazar millis por defecto

probá asi

#define COUNTS_PER_MILLISECOND ((F_CPU / 1000L) - 1)

Gracias por la sugerencia, pero... nada :frowning:

¿ Seria Ud. tan amable de poner el codigo de Millis1 ?,... jajaja

En serio. Seria de ayuda porque a mi me compila sin problemas esa asignacion.

Esto es lo que he averiguado hasta el momento, y no sé como encaja en tu programa:

Lucario448:
Pero bueno, más bien trataré de no deshabilitar micros al cambiar de millis. Para esto, necesito saber: ¿puedo redefinir una ISR con una librería? Algo como:

#ifdef DISABLE_ORIGINAL_MILLIS

ISR(TIMER0_OVF_vect) {
 // Solo incrementar el "overflow count"
}
#endif

La respuesta es que NO.
Cualquier intento de redefinir una funcion acaba con un error de compilacion.

Lucario448:
Para hacer lo anterior, supongo que debo incluir el archivo que hace referencia a la variable usada por micros, ¿cierto?

Bueno, creo que no necesita comentarios.

Lucario448:
¿Hay algún lugar donde pueda yo saber el nombre de las de definiciones que indican el microcontrolador a usar?

Si, aquí: "D:\arduino-1.6.7\hardware\tools\avr\avr\include\avr\io.h"
cambiando la unidad segun tu propia instalacion.

El archivo <io.h> está incluido por defecto en los sketch y determina el archivo a incluir especificamente con cada MCU de las que podamos usar (AVR, por supuesto).
A su vez ese archivo referenciado, que es el <iom328p.h> para nuestro ATmega 328P, contiene la definicion de todos los registros, vectores de interrupcion y otros.
Está en la misma carpeta.

Espero que esto te aporte algo de ayuda

Lucario448:
Gracias por la sugerencia, pero... nada :frowning:

a mi me compila, lo probé antes de postearlo

Muy bien entonces, esto es lo que tengo hasta el momento (en el adjunto por supuesto).

Como ni siquiera lo he podido probar, por el momento no tiene la estructura propia de una librería; sino que es una sola carpeta con el sketch y demás archivos.

De hecho ahí también está una copia modificada del "wiring.c"; para poner en práctica lo que noter había dicho, y que ojalá resulte como yo lo espero.

Sin más preámbulo, ¡aquí está mi progreso actual!

MillisTest.zip (5.85 KB)

@Lucario; Ya está cazado el error que te dá en la compilación. ¿ Te lo sigue dando ?

Pues corrige:

void Millis1::start()
{
    if (!_counting)
   {
       // set up Timer 1
      TCCR1A = 0;          // normal operation
      TCCR1B = 9   // CTC, no pre-scaling    <<=== ERROR falta <;>
      OCR1A = COUNTS_PER_MILLISECOND;
      TIMSK1 = 2;             // interrupt on Compare A Match
      _counting = true;
   }
}

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 :sweat_smile:

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! :slight_smile:

Sin embargo, ahora tengo otro error que esta vez estoy seguro que no es de novatos. Se trata de:

'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)?

Millis1 millis1;

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".

Para salir del paso crea la instancia antes del setup() en el bloque de declaracion de variables del sketch

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

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

Prueba poniendo en Millis1.h, justo antes del #endif final:

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).

Millis1 millis1=Millis1();

Otra buena solucion es esta:

#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.

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:

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?

MillisTest.zip (5.86 KB)

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.

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.

Lucario448:
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.

Lucario448:
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.

Lucario448:
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" :wink: :wink: :wink:

Lucario448:
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.

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.

noter:
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...

noter:
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.

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.

No estas equivocado...

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 :frowning: Solo tendría utilidad si se necesitara el timer0 para otra cosa.

Alfaville:
@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.

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.

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! :smiley:

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...