TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Archangels en 01 de Junio de 2017, 10:52:25

Título: Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 01 de Junio de 2017, 10:52:25
Como podría hacer para qué en un PIC actualmente el 16F687 pueda calcular el tiempo qué ha pasado desde qué he pulsado un pulsador hasta qué lo he soltado?

Estoy utilizando actualmente CCS.

No veo ninguna función qué me devuelva el tiempo actual, me da igual si el resultado viene en ms o s o minutos.

Mi idea es cojer tiempo actual, al soltar el pulsador qué coja tambien el tiempo y después restar y ver cuanto es el tiempo transcurrido.

Un saludo y a ver si me pueden ayudar.
Gracias!
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: KILLERJC en 01 de Junio de 2017, 11:28:35
Ya varias veces se hablo del tema, te dejo un link:

http://www.todopic.com.ar/foros/index.php?topic=14427.0

No hay funciones magicas como en Arduino. Vas a tener que creartelas vos y aprender sobre los modulos involucrados.
Basicamente vas a tener que utilizar un Timer, o CCP si posee el micro para medir el pulso.

El concepto es simple. La entrada de reloj es de Fosc/4, es decir si tenes 4Mhz de oscilador, Tu timer va a aumentar cada 1us ( si el preescaler es de 1:1 )
Si en tu timer tenes la cuenta 100 cuando detectas el boton, y luego tenes la cuenta 1000 ( supongamos que es de 16bits) entonces pasaron 900 ciclos, ciclos que en el ejemplo son de 1us, por lo tanto pasaron 900us.

Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 01 de Junio de 2017, 12:21:00
Muchas gracias por tu pronta respuesta, una ultima duda, si yo tengo qué utilizar el ccp y quiero usar pwm también y solo tiene un pin que hace las 2 cosas podria hacer las 2 cosas a la vez ??
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: AKENAFAB en 01 de Junio de 2017, 12:50:38
Muchas gracias por tu pronta respuesta, una ultima duda, si yo tengo qué utilizar el ccp y quiero usar pwm también y solo tiene un pin que hace las 2 cosas podria hacer las 2 cosas a la vez ??

Si es un solo pin NO, tendrás que hacer una o la otra y dependiendo la frecuencia/velocidad de reloj puedes hacer cualquiera por software.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 01 de Junio de 2017, 13:10:36
Teniendo en cuenta las soluciones "mágicas" que tiene Arduino ¿Por qué no te pasas a Aduino?

En esa plataforma yo podría ayudarte. En PIC me da muuucha pereza. No solo porque el código sea más difícil, es que además el código resultante no se suele reutilizar.
En Arduino creas una librería para solucionar esto y puede servir para otros.
Vendría muy bien porque esta duda sobre pulsadores se plantea muy a menudo.


La solución fácil en Arduino (sin interrupciones) es leer la función millis() al pulsar y al soltar el pulsador. Luego restas los valores y ya está.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 01 de Junio de 2017, 15:39:50
El problema qué la placa de arduino es muy grande jaja y yo necesito ahorrar espacio. Hmm y si uso solamente el chip del arduino, funcionaria también no ? Qué otros componentes aparte del cristal harían falta ?
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 01 de Junio de 2017, 16:13:36
Un par de condensadores y la resistencia de reset.

Puedes desarrollar con la placa y luego pasarlo a un micro con encapsulado tqfp.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: KILLERJC en 01 de Junio de 2017, 16:14:57
Citar
La solución fácil en Arduino (sin interrupciones) es leer la función millis() al pulsar y al soltar el pulsador. Luego restas los valores y ya está.

Creo que millis usa la interrupcion, es mas ni siquiera hay que complicarse por eso. Arduino ya posee una funcion mas simple que le da el tiempo de pulso si es que no le molesta "esperar".

https://www.arduino.cc/en/Reference/PulseIn
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 01 de Junio de 2017, 16:38:19
Un par de condensadores y la resistencia de reset.

Puedes desarrollar con la placa y luego pasarlo a un micro con encapsulado tqfp.

Saludos.

Pues voy a intentar hacerlo con un atmega328 qué si no me equivoco es el del UNO, una última duda, si compro el chip sin bootloader, es dificil ponerlo teniendo ya una placa de uno en casa ?
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 02 de Junio de 2017, 10:57:40
No entiendo bien la pregunta.
Si quieres grabar un programa en un Atmega328 (o un bootloader), se puede hacer fácilmente con otro Arduino:

https://www.arduino.cc/en/Tutorial/ArduinoISP

(https://www.arduino.cc/en/uploads/Tutorial/BreadboardAVR.png)

O con cualquier otro programador externo para ATmel.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 02 de Junio de 2017, 11:04:49
En realidad, si no necesitas mucha precisión, ni siquiera te hace falta poner el cristal. Puedes trabajar con el oscilador interno del Atmega.

Las placas Arduino modernas tampoco tienen cristal, en realidad es un resonador cerámico. Peor que un cristal, pero mejor que el oscilador interno.
Algunos clones de Arduino UNO si que traen cristal o al menos hueco para soldarlo, en el Atmega328.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 02 de Junio de 2017, 15:42:01
No entiendo bien la pregunta.
Si quieres grabar un programa en un Atmega328 (o un bootloader), se puede hacer fácilmente con otro Arduino:

https://www.arduino.cc/en/Tutorial/ArduinoISP

(https://www.arduino.cc/en/uploads/Tutorial/BreadboardAVR.png)

O con cualquier otro programador externo para ATmel.

Saludos.

Vale gracias por el esquema, yo pensaba qué tendría que sustituir en la placa un chip por el otro y luego poner el bootloader.

Muchas gracias de verdad !!
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 08 de Junio de 2017, 10:07:20
Estoy haciendo pruebas sobre una placa Arduino UNO utilizando el método de pulseIn(pin, HIGH); y tengo un problema, me es imposible probarlo porque no me cuenta bien los segundos, en cuanto acerco un poco el dedo al cable donde va conectado el botón se vuelve loco y alomejor en 1seg me da que ha estado pulsado durante 10s, como podría solucionar esto ? he intentado poner una resistencia a gnd para que no haga locuras pero sigue igual. La resistencia de 1k y estoy conectando el pulsador entre el pin 2 y 3.3v ( tambien he probado con el pin 4 y 7.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 08 de Junio de 2017, 18:22:44
¿Cómo es el programa y el esquema?
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 08 de Junio de 2017, 18:50:10
¿Cómo es el programa y el esquema?

Código: [Seleccionar]
const int btnV = 2;
int btnStatusV = 0;
unsigned long durBtnV;

void setup() {
  Serial.begin(115200);
  pinMode(btnV, INPUT);
  Serial.print("Setup Finalizado, continuando...\n");
}

void loop() {
  durBtnV = pulseIn(btnV, HIGH);
  Serial.print("durBtnV: ");
  Serial.print(durBtnV);
  Serial.print("\n");

  if (durBtnV >= 3000) {
    analogWrite(9, HIGH);
  }
}

En la placa tengo conectada directamente la resistencia desde el Pin 2 a GND ( si, llega bien ) y después uso un pulsador con cables soldados a las patillas e introduzco sus extremos entre el Pin 2 y el pin de 3.3v
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 09 de Junio de 2017, 02:27:14
La función devuelve el valor en microsegundos.
Que valores te devuelve?
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 09 de Junio de 2017, 11:22:15
Pues si mantengo las manos lejos de cualquier conexión que vaya a ese pin devuelve 0 (por lo tanto supongo qué hasta ahí todo bien) pero en cuanto toco un poco el botón ( sin pulsarlo ) o el cable qué va al pin 2 se dispara, si tengo la mano muy cerca del cable me da lecturas de 10000 - 12000 y si la alejo un poco alrededor de 6000 - 8000, todo esto con una pausa delay(1000).

Por lo tanto me resulta imposible que en 1000ms me de una lectura de 10000ms o incluso de 6000ms.

Edito:
Código: [Seleccionar]
2768ms - isPowered: 0 durBtnV: 0
3461ms - isPowered: 0 durBtnV: 0
3682ms - isPowered: 0 durBtnV: 3051
3702ms - isPowered: 0 durBtnV: 3644
3723ms - isPowered: 0 durBtnV: 4110
3742ms - isPowered: 0 durBtnV: 4528
3763ms - isPowered: 0 durBtnV: 4954
3783ms - isPowered: 0 durBtnV: 5256
3803ms - isPowered: 0 durBtnV: 5482
3823ms - isPowered: 0 durBtnV: 5689
3844ms - isPowered: 0 durBtnV: 5910
3863ms - isPowered: 0 durBtnV: 6131
3884ms - isPowered: 0 durBtnV: 6314
3903ms - isPowered: 0 durBtnV: 6491
3923ms - isPowered: 0 durBtnV: 6670
3944ms - isPowered: 0 durBtnV: 6922
3963ms - isPowered: 0 durBtnV: 7302
3984ms - isPowered: 0 durBtnV: 7647
4003ms - isPowered: 0 durBtnV: 7968
4024ms - isPowered: 0 durBtnV: 8280
4044ms - isPowered: 0 durBtnV: 8570
4064ms - isPowered: 0 durBtnV: 8929
4084ms - isPowered: 0 durBtnV: 9331
4105ms - isPowered: 0 durBtnV: 9752
4125ms - isPowered: 0 durBtnV: 10322
4145ms - isPowered: 0 durBtnV: 10662
4165ms - isPowered: 0 durBtnV: 10714
4185ms - isPowered: 0 durBtnV: 10683
4205ms - isPowered: 0 durBtnV: 10601
4225ms - isPowered: 0 durBtnV: 10536
4245ms - isPowered: 0 durBtnV: 10432
4265ms - isPowered: 0 durBtnV: 10332
4285ms - isPowered: 0 durBtnV: 10315
4305ms - isPowered: 0 durBtnV: 10224
4325ms - isPowered: 0 durBtnV: 10109
4345ms - isPowered: 0 durBtnV: 9888
4365ms - isPowered: 0 durBtnV: 9660
4385ms - isPowered: 0 durBtnV: 9430
4405ms - isPowered: 0 durBtnV: 9159
4425ms - isPowered: 0 durBtnV: 8897
4445ms - isPowered: 0 durBtnV: 8602
4464ms - isPowered: 0 durBtnV: 8280
4485ms - isPowered: 0 durBtnV: 7899
4504ms - isPowered: 0 durBtnV: 7584
4525ms - isPowered: 0 durBtnV: 7265
4544ms - isPowered: 0 durBtnV: 6946
4564ms - isPowered: 0 durBtnV: 6612
4584ms - isPowered: 0 durBtnV: 6318
4603ms - isPowered: 0 durBtnV: 6005
4624ms - isPowered: 0 durBtnV: 5743
4643ms - isPowered: 0 durBtnV: 5413
4664ms - isPowered: 0 durBtnV: 5058
4683ms - isPowered: 0 durBtnV: 4735
4704ms - isPowered: 0 durBtnV: 4446
4723ms - isPowered: 0 durBtnV: 4157
4744ms - isPowered: 0 durBtnV: 3787
5436ms - isPowered: 0 durBtnV: 0
6128ms - isPowered: 0 durBtnV: 0
6821ms - isPowered: 0 durBtnV: 0
7514ms - isPowered: 0 durBtnV: 0

Esto solo por acercar un poco el dedo al cable

Saludos !
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 09 de Junio de 2017, 19:20:54
Prueba con esto:

Código: C
  1. const int pushButton = 2;
  2.  
  3. void setup() {
  4.   long init, lapse;
  5.   int level;
  6.  
  7.   Serial.begin(115200);
  8.   pinMode(pushButton, INPUT_PULLUP);
  9.  
  10.   init = millis();
  11.   level = digitalRead(pushButton);
  12.   while(1) {
  13.      if (level != digitalRead(pushButton)) {
  14.        lapse = millis();
  15.        Serial.print("Level=");
  16.        if (level == 0) {
  17.          level = 1;
  18.          Serial.print("Level = LOW\t");
  19.        }
  20.        else {
  21.          level = 0;
  22.          Serial.print("Level = HIGH \t");
  23.        }
  24.        Serial.print("Lapse = ");
  25.        Serial.print(lapse - init);
  26.        Serial.println(" ms");
  27.        init = lapse;      
  28.      }
  29.   }
  30. }
  31.  
  32. void loop() {}

Tienes que quitar la resistencia (utiliza la resistencia interna de pullup) y llevar el pin 2 a GND.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 10 de Junio de 2017, 12:17:38
Me da este resultado con 1 solo click del botón:

Código: [Seleccionar]
Level=Level = HIGH Lapse = 7964 ms
Level=Level = LOW Lapse = 3 ms
Level=Level = HIGH Lapse = 0 ms
Level=Level = LOW Lapse = 0 ms
Level=Level = HIGH Lapse = 16 ms
Level=Level = LOW Lapse = 0 ms
Level=Level = HIGH Lapse = 1 ms
Level=Level = LOW Lapse = 776 ms
Level=Level = HIGH Lapse = 5 ms
Level=Level = LOW Lapse = 5 ms

He probado con 3 botones distintos por si acaso, qué tengo uno que está casi muerto el pobre.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 10 de Junio de 2017, 17:19:48
Ahora el resultado es más lógico.
De todas formas tienes muchos rebotes. Esa es la segunda tarea a realizar, filtrar rebotes para que sólo aparezca un pulso limpio.
Yo lo hago con una máquina de estados y con un contador. El estado sólo cambia a HIGH cuando se cuentan varios milisegundos seguidos en HIGH. En tu caso te conviene poner más de 5 milisegundos y así filtras todos esos rebotes que se ven.

Saludos.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: KILLERJC en 10 de Junio de 2017, 17:54:03
Y por que no realizarlo por HW ? en el protoboard me refiero...
Es ideal lo que comenta Picuino para ahorrar espacio y componentes, pero podria hacerlo con una resistencia y un capacitor.

Si queres aprender a hacerlo por software entonces adelante.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 10 de Junio de 2017, 18:32:19
Y por que no realizarlo por HW ? en el protoboard me refiero...
Es ideal lo que comenta Picuino para ahorrar espacio y componentes, pero podria hacerlo con una resistencia y un capacitor.

Si queres aprender a hacerlo por software entonces adelante.

Me gustaría qué fuese lo más compacto posible pero si solo hay qué poner una resistencia y un capacitador tampoco me importa demasiado, serian en serie ? y más o menos como calcular los valores ?

Ahora el resultado es más lógico.
De todas formas tienes muchos rebotes. Esa es la segunda tarea a realizar, filtrar rebotes para que sólo aparezca un pulso limpio.
Yo lo hago con una máquina de estados y con un contador. El estado sólo cambia a HIGH cuando se cuentan varios milisegundos seguidos en HIGH. En tu caso te conviene poner más de 5 milisegundos y así filtras todos esos rebotes que se ven.

Saludos.

El proyecto final va a utilizar un interuptor reed y detectar un iman, el campo magnetico afecta mucho a la función de pulseIn ?

Filtrar los rebotes lo haria con un if status high cuantos milisegundos high y si son mas de 5 significa que ya lo puedo dar por high definitivo ?
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 11 de Junio de 2017, 08:01:06
A mí no me gusta pulseIn()
Es una función que paraliza todo el sistema hasta que realiza la medida. Además está especializada en medida de tiempos muy pequeños (en microsegundos) y tú lo que necesitas es medir tiempos mucho mayores (milisegundos).

El campo magnético del reed no tiene por qué afectar para nada al microcontrolador.

La resistencia no te hace falta, solo un condensador en paralelo con el pulsador. La resistencia se puede sustituir por el PULLUP interno del microcontrolador.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 11 de Junio de 2017, 08:16:48
Si quieres filtrar por software:

1º Defines una variable con el estado del pulsador
   Estado 1: Estado bajo, pulsador a nivel bajo
   Estado 2: Estado bajo, pulsador a nivel alto
   Estado 3: Estado alto, pulsador a nivel alto
   Estado 4: Estado alto, pulsador a nivel bajo
2º Defines una variable de medida de tiempo en milisegundos.

Los estados 1 y 3 son estables. La medida de tiempo se asigna a cero
Los estados 2 y 4 son de transición. Tienes que medir cuanto tiempo se encuentra en ese estado y si supera un tiempo establecido, cambias el estado de 2 a 3 y de 4 a 1.
El cambio de estado entre 1 y 2 se produce al leer el nivel del pulsador.

Lo mejor es programarlo todo en una rutina y llamarla cada milisegundo:

Código: C
  1. unsigned long oldmillis;
  2. unsigned char pulsador2;
  3.  
  4. setup() {
  5.    oldmillis = millis()+1;
  6. }
  7.  
  8. loop() {
  9.    if (millis() >= oldmillis) {
  10.       oldmillis++;
  11.       teclado();  // Rutina de lectura del estado del teclado
  12.    }
  13.  
  14.    // Resto del programa
  15.    if (pulsador2 == HIGH) {
  16.       ....
  17.    }
  18.    ...
  19. }

En la función teclado se lee el pulsador y se actualiza el valor de la variable pulsador2 en consecuencia.

Esto te permite trabajar con el resto del programa sin que se paralice todo por la lectura del teclado.

Si quieres te comento cómo hacerlo con un RTOS muy sencillo que facilita las cosas.

Un saludo.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Picuino en 11 de Junio de 2017, 08:47:47
Este es un ejemplo que utiliza la librería SCoop (sistema operativo en tiempo real cooperativo) para leer el pulsador conectado al pin2 del Arduino. He añadido un filtro de 20ms a la lectura del pulsador:

Código: C
  1. #include <SCoop.h>
  2.  
  3. #define KEYB_FILTER_TIME  20
  4. #define KEYB_BUTTON        2
  5. volatile boolean keyb_button2;
  6. volatile int keyb_counter2;
  7.  
  8. void setup() {
  9.   pinMode(KEYB_BUTTON, INPUT_PULLUP);
  10.   mySCoop.start();
  11. };
  12.  
  13. void loop() {
  14.   digitalWrite(13, keyb_button2);
  15.  
  16.   yield();
  17. };
  18.  
  19. /************* SCOOP TASK FOR KEYBOARD *************/
  20.  
  21. defineTask(scoopTask2);
  22.  
  23. void scoopTask2::setup() {
  24.   keyb_counter2 = 0;
  25.   keyb_button2 = HIGH;
  26. };
  27.  
  28. void scoopTask2::loop() {
  29.   if (digitalRead(KEYB_BUTTON) == HIGH) {
  30.      if (keyb_button2 == LOW) {
  31.         if (++keyb_counter2 > KEYB_FILTER_TIME)
  32.           keyb_button2 = HIGH;
  33.      }
  34.      else keyb_counter2 = 0;
  35.   }
  36.   else {
  37.      if (keyb_button2 == HIGH) {
  38.         if (++keyb_counter2 > KEYB_FILTER_TIME)
  39.           keyb_button2 = LOW;
  40.      }
  41.      else keyb_counter2 = 0;    
  42.   }
  43.   sleep(1);
  44. };

El mismo concepto se puede utilizar para muchos pulsadores más. Incluso puedes establecer diferentes tiempos para nivel alto y para nivel bajo.

Tienes que instalar la librería SCoop para que funcione:
Fuentes originales: https://code.google.com/archive/p/arduino-scoop-cooperative-scheduler-arm-avr/downloads
Download directo: http://www.picuino.com/_static/SCoop.zip

Un saludo.
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: soymoe en 12 de Junio de 2017, 11:48:05
Esta el la rutina del timer escalado a 8 que uso para medir segundos, se basa en contar los medios segundos que pasaron:
Código: [Seleccionar]
void  TIMER1_isr(void)//Función de interrupción por desbordamiento TMR1 
{
      MedioSeg=MedioSeg+1;
      if (MedioSeg==2)
      {
       Segundos=Segundos+1;
       MedioSeg=0;
       SegundosRestantes=SegundosRestantes+1;
      }
Nada:
      set_timer1(0x0BDC);//(0x0BDC);//carga del TMR1
    //  restart_wdt();
}
Título: Re:Como calcular cuanto tiempo ha pasado
Publicado por: Archangels en 13 de Junio de 2017, 05:35:17
Si quieres filtrar por software:

1º Defines una variable con el estado del pulsador
   Estado 1: Estado bajo, pulsador a nivel bajo
   Estado 2: Estado bajo, pulsador a nivel alto
   Estado 3: Estado alto, pulsador a nivel alto
   Estado 4: Estado alto, pulsador a nivel bajo
2º Defines una variable de medida de tiempo en milisegundos.

Los estados 1 y 3 son estables. La medida de tiempo se asigna a cero
Los estados 2 y 4 son de transición. Tienes que medir cuanto tiempo se encuentra en ese estado y si supera un tiempo establecido, cambias el estado de 2 a 3 y de 4 a 1.
El cambio de estado entre 1 y 2 se produce al leer el nivel del pulsador.

Lo mejor es programarlo todo en una rutina y llamarla cada milisegundo:

Código: C
  1. unsigned long oldmillis;
  2. unsigned char pulsador2;
  3.  
  4. setup() {
  5.    oldmillis = millis()+1;
  6. }
  7.  
  8. loop() {
  9.    if (millis() >= oldmillis) {
  10.       oldmillis++;
  11.       teclado();  // Rutina de lectura del estado del teclado
  12.    }
  13.  
  14.    // Resto del programa
  15.    if (pulsador2 == HIGH) {
  16.       ....
  17.    }
  18.    ...
  19. }

En la función teclado se lee el pulsador y se actualiza el valor de la variable pulsador2 en consecuencia.

Esto te permite trabajar con el resto del programa sin que se paralice todo por la lectura del teclado.

Si quieres te comento cómo hacerlo con un RTOS muy sencillo que facilita las cosas.

Un saludo.

Muchas gracias por tus consejos, me voy a poner a ello ahora mismo, ya os iré contando qué tal va todo.
Un saludo y un abrazo muy grandes !!
Muchas gracias de nuevo por tu ayuda !!