Autor Tema: Función de retardo vacía,  (Leído 1034 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado DanielTrenxz

  • PIC10
  • *
  • Mensajes: 3
Función de retardo vacía,
« en: 13 de Septiembre de 2021, 12:12:46 »
Muy buen dia, soy nuevo en el foro estuve indagando sobre los temas ya existentes pero no encontré mucho, resulta que estoy astascado con los timers, si configuro uno por interrupción sin que el bucle tenga algo funciona perfecto pero mi idea era como poder crear una función/método y llamarla en un momento dado del programa a forma de __delay_ms() para que por 1segundo no haga nada y al salir siga en curso el programar (esto para controlar la inversión de giro de un motor pero quisiera primero detenerlo, darle 1seg apagado y después invertir el giro) el pic es el 18f4550 con oscilador interno de 8MHz, ya tengo el valor del TMR=3036 con preescalador 8 y a 16bits, esto para contabilizar 0.25seg alguna idea?

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Función de retardo vacía,
« Respuesta #1 en: 13 de Septiembre de 2021, 13:57:46 »
Hola.

¿Has intentado crear tu código por estados o tareas cooperativas?

Por ejemplo en main tienes varias tareas:

Código: C
  1. estadoTarea1 = 0;
  2. estadoTarea2 = 0;
  3. ...
  4. estadoTarean = 0;
  5.  
  6. void main(void)
  7. {
  8.         while(1)
  9.        {
  10.              tarea1();
  11.              tarea2();
  12.              ....
  13.              tarean();
  14.         }
  15. }
]


Y cada tarea se divide en estados, de tal manera que ninguna se apropie de CPU 100%

por ejemplo
Código: C
  1. void tarea1(void)
  2. {
  3.        switch(estadoTarea1)
  4.        {
  5.             case 0x00:
  6.             {
  7.                 /** escribes tu poco de tu proceso aquí **/
  8.                 estadoTarea = siguienteEstado;  
  9.                 break;
  10.             }
  11.             case 0x01:
  12.             {
  13.                 /** escribes tu poco de tu proceso aquí **/
  14.                 estadoTarea = siguienteEstado2;  
  15.                 break;
  16.             }
  17.             ....
  18.              default; //ultimo case
  19.             {
  20.                 /** escribes tu poco de tu proceso aquí **/
  21.                 estadoTarea = siguienteEstadoM;  
  22.             }
  23.        }
  24. }

Utilizar los delays de PICC y otros compiladores son mala idea, ya que se apoderan del CPU y bloquean las interrupciones, por ejemplo, si tu delay es de 1000 ms, durante un segundo, el CPU del microcontrolador estará "colgado" sin ejecutar algo útil y puede perder la atención a una interrupción.

Entonces para no ocupar esos delays y generar retardos apropiativos ineficientes, debes usar un temporizador como a continuación te explico:

Dices que tienes un temporizador de 16 bits, este temporizador lo tienes activado que corra o funcione sin restricciones.

No estoy seguro de que micro usas , per supongamos que se incrementa con 4us, entonces con 16 bits tu podrías generar máximo 262.144ms, por lo que no nos sirve el pre escaler.

Con un preescaler de 16 bits, máximo puedes generar 524.288 ms.

Entonces se necesita una variable auxiliar por cada tarea que necesita un retardo (Esto es más fácil con temporizadores de 32 bits)

Regresando a la opción 1, vamos a contar valores mucho más pequeños de 262.144 ms, digamos 30ms.

El temporizador necesita 4us para incrementarse en una unidad, entonces para alcanzar 30ms sería Ciclos necesario = 30ms/4us = 7500

Y para generar 1000 ms se necesita 1000ms/30ms = 33 333, que sería lo que tiene la variable auxiliar.

Entonces para producir un retardo sería así para una tarea, digamos la 1.

Código: C
  1. case estado_A:
  2. {
  3.      /* valorTemporizado es de tipo unsigned*/
  4.      valorTemporizador = funcionQueLeeTMR1(); //valor de 16 bits
  5.      variableAuxParaTarea1 = 33333;
  6.      estadoTarea1 = estado_B;
  7.      break;
  8. }
  9. case estado_B:
  10. {
  11.      if ((funcionQueLeeTMR1() -  valorTemporizador) > 7500) //cuando pasa 30 ms, el if es verdadero
  12.      {
  13.             variableAuxParaTarea1--;
  14.             if (0 == variableAuxParaTarea1) //el if es verdadero cuando ha pasado 1 segundo
  15.             {
  16.                 /*Tu código de lo que desees hacer cuando han pasado 1000 ms*/
  17.             }
  18.             else // Si variableAuxParaTarea1 aun no es cero, debes capturar un nuevo valor del temp para nuevamente generar 30 ms
  19.            {
  20.                valorTemporizador = funcionQueLeeTMR1();
  21.            }
  22.      }
  23.      break;
  24. }

Puedes ver que no es apropiativo como los delays este proceso. El caso estado_B solo verifica si el tiempo ha alcanzado el valor deseado, si no continua para que otro case de otra tarea se ejecute.


« Última modificación: 13 de Septiembre de 2021, 14:07:17 por DominusDRR »
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DanielTrenxz

  • PIC10
  • *
  • Mensajes: 3
Re:Función de retardo vacía,
« Respuesta #2 en: 13 de Septiembre de 2021, 15:21:23 »
Buenas DominusDDR

Con esto me has dado una idea que posteriormente iba a resolver pero en cuestion, tengo el PIC 18F4550, el TMR0 funcionando a 16bits, mi reloj interno esta a 8MHz (8000000), inicio con un valor de TMR0 =3036 y esto me da 0.25s, lo que quiero realizar es lo siguiente:

Código: [Seleccionar]
if (RC5 == 1) {
                ApagadoPuertas();
                Sobrecarga();  //LEEMOS SI NO EXCEDE PARA SEGUIR CON LA OPERACION
                __delay_ms(500);  //TIMER DE 1/2SEG   (aqui es donde debo habilitar el timero, que cuente 1segundo (sin hacer nada) y                 
                                                                               posteriormente desabilitarlo y seguir con la tarea principal)
                while (RC2 == 0)
                {
                AbrirPuertas();////ABRIR PUERTAS
                Sobrecarga();
                }
                while(sobcar > 400)
                {
                if (RC2 == 1) {
                ApagadoPuertas();
                }
                Sobrecarga();
                }
                if (RC2 == 1) {
                ApagadoPuertas();
                }
                __delay_ms(500);//TIMER DE 1/2SEG  (de nuevo habilito el timer, cuenta 1 segundo sin hacer nada dentro del timer y cuando
                                                                              termine reanudar las tareas siguientes)

            }

el codigo es para controlar un motor, con un boton gira en sentido horario pero cuando se preciona el otro boton debe invertir el giro pero por proteccion del motor y de los demas componentes quisiera parar primero el motor, aqui iria el timer de 1 segundo sin hacer nada para darle tiempo de detenerce el motor un poco y posteriormente invierta el giro, no se si me explique bien pero esto me tiene muy atorado, agradezco la ayuda.

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Función de retardo vacía,
« Respuesta #3 en: 13 de Septiembre de 2021, 15:38:25 »
Hola.

O sea no estoy a favor de las funciones delay_ms, pero si ya ocupas delay_ms(500), ¿Por qué no usas delay_ms(1000)?
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DanielTrenxz

  • PIC10
  • *
  • Mensajes: 3
Re:Función de retardo vacía,
« Respuesta #4 en: 13 de Septiembre de 2021, 15:53:35 »
lo que pasa es que el motor tiene acoplado un encoder con el cual obtengo lecturas de rpm mediante INTERRUPCIONES INT0 RB0, igualmente coincido en no usar delays ya que perderia lecturas, por eso incursione sobre los timers, probaré el segundo metodo que comentaste, gracias por la ayuda.

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Función de retardo vacía,
« Respuesta #5 en: 13 de Septiembre de 2021, 16:00:44 »
Una recomendación, crear tu programa en tareas independientes te permite evitar errores como el siguiente.

En tu código, al inicio, luego de ApagadoPuertas y luego de Sobrecarga, cuando recién empiezas a ejecutar delay_ms(500), se produce una sobre carga. Hasta que transcurra ese tiempo y tu nuevamente llames a esa función para decidir desconectar la carga, pueda que sea muy tarde.

Sobrecarga debe ser una tarea independiente y de alta prioridad  sobre las demás de tal manera que cuando se produzca una sobre carga, desconecte al motor sin importar que esté haciendo el resto de tu código.
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32