Autor Tema: Rutina que se ejecute por un tiempo predeterminado.  (Leído 1991 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado JD007

  • PIC10
  • *
  • Mensajes: 4
Rutina que se ejecute por un tiempo predeterminado.
« en: 22 de Junio de 2015, 16:30:09 »
Hola, he estado desarrollando un programa que permita el movimiento de un carrito de forma autónoma, mediante unos sensores infrarrojos, un par de motores dc y un  pic 16f887. Soy nuevo en esto de la programación y me las he apañado como he podido.  :oops:

Tengo un problema y es que no he podido crear una rutina que ejecute por un tiempo pre establecido.

Mi idea es hacer dos rutinas una de demostración y otra de ejecución por un tiempo pre establecido y hay es donde esta el problema.

Adjunto el código y la simulación.
Código: [Seleccionar]
#include <16F887.h>

#fuses NOWDT, XT, NOPROTECT,MCLR              
#use delay(clock=4000000) // Crystal 4Mhz  
#USE Standard_io (C)
#USE Standard_io (A)
#USE Standard_io (D)
#USE Standard_io (B)

/* Definicion de la LCD */

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7
#define LCD_RS    PIN_B2
#define LCD_E     PIN_B3
#define use_portb_lcd TRUE         //definir portb lcd
#include <lcd1.c>


/*-------------------- Variables de movimiento-------------------------------*/

#define AVANCE          output_low(PIN_C2),output_low(PIN_C4),output_high(PIN_C3),output_high(PIN_C5)
#define RETROCESO       output_high(PIN_C2),output_high(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
#define PARO            output_low(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
#define GIRO_DERECHA    output_high(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_high(PIN_C5)
#define GIRO_IZQUIERDA  output_low(PIN_C2),output_high(PIN_C4),output_high(PIN_C3),output_low(PIN_C5)



/*------------------- Variables para lectura obstáculo ----------------------

#define Sensor_Frontal_Izq       output_low (PIN_A0)
#define Sensor_Frontal_Der       output_low (PIN_A1)
#define Sensor_Lateral_Izq       output_low (PIN_A2)
#define Sensor_Lateral_Der       output_low (PIN_A3) */



/*-------------------LECTURA DE OPCIONES---------------------*/

void mostrar_opciones(){ // VOID DE RUTINAS QUE SE MUESTRAN EN PANTALLA!!

lcd_gotoxy(1,1);
lcd_putc("\f");  
printf(lcd_putc,"D1 RUTINA 1");

lcd_gotoxy(1,2);
printf(lcd_putc,"D2 RUTINA 2 ");


}

/*----------------------RUTINAS-------------*/

void Rutina_Uno(){

lcd_gotoxy(1,1);
lcd_putc("\f");  
printf(lcd_putc,"EJECUTANDO 1");

AVANCE;
      delay_ms (500);
      
RETROCESO;
      delay_ms (500);
      
PARO;

 }

void Rutina_Dos(){

lcd_gotoxy(1,1);
lcd_putc("\f");  
printf(lcd_putc,"EJECUTANDO 2");

//DECLARACION DE VARIBALES!!

boolean A0,A1,A2,A3,B0;

inicio:  // GOTO!

A0=input(PIN_A0);
A1=input(PIN_A1);
A2=input(PIN_A2);
A3=input(PIN_A3);
B0=input(PIN_B0);






if ( ( A0==0) && (A1==0) && (A2==0) && (A3==0) )

      AVANCE;                                       // EJECUTA RUTINA
                   delay_ms(1000);          
          
if ( (A0==1) && (A1==1) && (A2==0) && (A3==0))

      RETROCESO ;                                  // EJECUTA RUTINA

                    delay_ms(1000);
                                              
if ( (A0==0) && (A1==0) && (A2==1) && (A3==0))  

      GIRO_DERECHA;                                 // EJECUTA RUTINA

                    delay_ms(1000);
                                              
if ( (A0==0) && (A1==0) && (A2==0) && (A3==1))

      GIRO_IZQUIERDA;                              // EJECUTA RUTINA

                    delay_ms(1000);
                                              
if ( (A0==1) && (A1==1) && (A2==1) && (A3==1))

      PARO;                                        // EJECUTA RUTINA

                    delay_ms(1000);

GOTO inicio;      // BUCLE DE ESCANEO

}  

/*-------------------------- PARTE PRINCIPAL DEL PROGRAMA!!---------------------*/

void main(){  
lcd_init();
output_high (PIN_A4);        

  

// ESCRIBIR LA BIENVENIDA

lcd_gotoxy( 1, 1);
           printf(lcd_putc,"   BIENVENIDOS   ");
 
lcd_gotoxy( 1, 2);
           printf(lcd_putc,"D0 IR A OPCIONES");
          
//DECLARACION DE VARIBALES!!

boolean D0,D1,D2,D3;

menu:  // GOTO!

D0=input(PIN_D0);
D1=input(PIN_D1);
D2=input(PIN_D2);
D3=input(PIN_D3);
          
          
          
  
IF ( ( D0==1) && (D1==0) && (D2==0) && (D3==0) )   // while (input(PIN_D0)==FALSE) //  FUNCION QUE ENVIA A LAS RUTINAS
     mostrar_opciones();          // LLAMADA DEL VOID

/* ---------RUTINA DE LLAMADA Y PUESTA EN FUNCION DE LAS RUTINAS-------*/
  

  
IF ( ( D0==1) && (D1==1) && (D2==0) && (D3==0) )
           Rutina_Uno();

IF ( ( D0==1) && (D1==0) && (D2==1) && (D3==0) )
           Rutina_Dos();
          
IF ( ( D0==0) && (D1==0) && (D2==0) && (D3==1) )
       mostrar_opciones();
      
IF ( ( D0==1) && (D1==1) && (D2==0) && (D3==1) )
        mostrar_opciones();  
        
        IF ( ( D0==1) && (D1==0) && (D2==1) && (D3==1) )
        mostrar_opciones();  
 
 
 GOTO menu;      // BUCLE DE ESCANEO
 
 
// LED QUE INDICA ENCENDIDO DEL SISTEMA

while(true){  
      output_high (PIN_A4);         //led on
    delay_ms(500);            
    output_low (PIN_A4);      //led off
   delay_ms(500);
   }



}  // Final del codigo

el problema de la rutina por tiempos, es la dos.
ademas de eso cuando ingresa en las opciones estas se quedan repitiendose en la pantalla.
y la opcion 1 se repite infinitamente, cuando solo deberia hacerlo una vez ( creo que es por el goto) si alguien tiene una mejor idea de como hacer la seleccion de opciones y asi arreglar esto, estare muy agradecido

 
¡Gracias! por la ayuda.
« Última modificación: 23 de Junio de 2015, 22:27:23 por JD007 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #1 en: 22 de Junio de 2015, 17:41:43 »
Utilizar GOTO en C .... es algo que no deberia hacerse simplemente, incluso por ahi menzclar ASM y C no es nada facil

un GOTO como tenes implmentado no es mas que un

while(1)
{
// aca codigo
}

si observas cuando termina el while comienza de nuevo.. en fin es eso.

Por otro lado no entiendo que estas tratando de hacer. Seria una buena idea que trataras de explicar lo que quieres hacer asi se te dan algunas ideas para que puedas mejorar o tal ves simplificar el programa.

Con respecto a tu pregunta original sobre "ejecucion por un tiempo pre establecido"
Podes hacerlo de distintas formas:

Opcion 1
Conociendo el tiempo que tarda en ejecutarse esa parte del programa, repetirlo X cantidad de veces tal que se cumple (X * tiempo) = tiempo establecido.
Esa es una... Suponete que tenes una funcion que tarda 50ms en hacer todo pero vos queres que marche constantemente por 1 segundo, entonces debo repetirlo 20 veces
Código: C
  1. i=0;
  2. while(i++<20)
  3. {
  4. // Codigo que se repite 20 veces
  5. }
o

Código: C
  1. for(i=0;i<20;i++)
  2. {
  3. }

Como ves es una ventaja lo simple que es, la desventaja es que tenes que conocer el tiempo de ejecucion y si por ahi cambia mucho el tiempo no podes aplicarlo, por otra parte el codigo SI o SI tiene que hacer las 20 vueltas esas.

Opcion 2
Utilizar un timer. Los timers permiten contar los pulsos de reloj, si tenes un reloj (cristal) de 4Mhz vas a tener un ciclo de 1us ( 4/4Mhz ) los timer tienen preescalers y dividen ese valor hasta unos 256 veces, o que es lo mismo que decir que aumenta 256 veces su periodo 256us, El 16F887 si no mal recuerdo tiene un timer de 16bits, el cual podes hacerlo contar hasta 0.5 segundos, entonces si quiero contar esos 0.5s hago esto

Código: C
  1. TMR1 = valor_para_los_0.5_segundos;
  2. Flag TMR1 = 0;
  3. while (!TMR1)    // Esto va a hacer que se ejecute hasta que el flag se ponga a 1, es decir cuando pasen los 0.5s
  4. {
  5. }
Un Poco mas complejo peeeero mas exacto, y no dependiente del codigo, tambien podemos usar una interrupcion y tomar como referencia cuantas veces entra a la interrupcion X * 0.5s , si entras 2 veces sabemos que ya paso 1 segundo. entonces ponemos a 1 una flag y eso hace que salga del while (donde el while pregunta por esa flag )

Como dije Ventajas: mas exacto, menos dependiente del codigo.
Desventajas: aun asi se queda ahi hasta que termine.


Cualquier otra opcion aparte que se me ocurra ya involucra cambios mas grandes en la forma de hacer las cosas, refriendome al programa.

Desconectado JD007

  • PIC10
  • *
  • Mensajes: 4
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #2 en: 22 de Junio de 2015, 19:48:43 »
KILLERJC gracias por tu respuesta, ya cambie los goto por los whiles.

Citar
Por otro lado no entiendo que estas tratando de hacer. Seria una buena idea que trataras de explicar lo que quieres hacer asi se te dan algunas ideas para que puedas mejorar o tal ves simplificar el programa.

Lo que quiero hacer es un carrito que se mueva evadiendo obstaculos mediante sensores infrarrojos, los sensores los simulos con puntas logicas que estan en el puerto A, y he implementado dos rutinas que serian la rutina 1 y la rutina 2. Que accedo a ellas mediante unos pulsadores ubicados en el puerto D.

el programa inicia aqui y le pide al usuario pulsar D0 para ir ha donde estan las opciones y escoger una de las que he mencionado

Citar
void main(){  
lcd_init();
output_high (PIN_A4);        

  

// ESCRIBIR LA BIENVENIDA

lcd_gotoxy( 1, 1);
           printf(lcd_putc,"   BIENVENIDOS   ");
 
lcd_gotoxy( 1, 2);
           printf(lcd_putc,"D0 IR A OPCIONES");

Despues de pulsar D0 te manda aqui
las letras aparecen en la lcd repitiendose de manera infinita y no se quedan fijas y nose por que, y no puedo solucionarlo.

Citar
void mostrar_opciones(){ // VOID DE RUTINAS QUE SE MUESTRAN EN PANTALLA!!

lcd_gotoxy(1,1);
lcd_putc("\f");  
printf(lcd_putc,"D1 RUTINA 1");

lcd_gotoxy(1,2);
printf(lcd_putc,"D2 RUTINA 2 ");


}


aqui esta donde se escogen las rutinas.

Si alguien tiene una idea de como hacer esta parte mejor, por favor comentarlo por que la verdad creo que aqui es donde esta problema.
Citar
while(1){

D0=input(PIN_D0);
D1=input(PIN_D1);
D2=input(PIN_D2);
D3=input(PIN_D3);
          
          
          
  
IF ( ( D0==1) && (D1==0) && (D2==0) && (D3==0) )   // while (input(PIN_D0)==FALSE) //  FUNCION QUE ENVIA A LAS RUTINAS
     mostrar_opciones();          // LLAMADA DEL VOID

/* ---------RUTINA DE LLAMADA Y PUESTA EN FUNCION DE LAS RUTINAS-------*/
  

  
IF ( ( D0==1) && (D1==1) && (D2==0) && (D3==0) ) // si se cumple llama a la rutina 1
           Rutina_Uno();

IF ( ( D0==1) && (D1==0) && (D2==1) && (D3==0) )  // si se cumple llama a la rutina 2

           Rutina_Dos();
          
IF ( ( D0==0) && (D1==0) && (D2==0) && (D3==1) ) // si se cumple llama al void de mostrar opciones

       mostrar_opciones();
      
IF ( ( D0==1) && (D1==1) && (D2==0) && (D3==1) ) // si se cumple llama al void de mostrar opciones
        mostrar_opciones();  
        
        IF ( ( D0==1) && (D1==0) && (D2==1) && (D3==1) ) // si se cumple llama al void de mostrar opciones
        mostrar_opciones();  
 
 
 }      // BUCLE DE ESCANEO
el ultimo error que tengo es que cuando ingresa la rutina 1 se ejcuta de manera infinita y no deberia ser asi, porque deberia ejecutarse y listo pero no lo hace.
Si tienen un consejo para esta parte se los agradeceria.
Citar
void Rutina_Uno(){

lcd_gotoxy(1,1);
lcd_putc("\f");  
printf(lcd_putc,"EJECUTANDO 1");

AVANCE;
      delay_ms (500);
      
RETROCESO;
      delay_ms (500);
      
PARO;

 }
si simulo esta parte por separado la ejecuta y ya, pero aqui junto con el resto del programa se repite de forma infinita(creo que es por la forma en que esta la parte de escoger las opciones).
« Última modificación: 22 de Junio de 2015, 19:54:27 por JD007 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #3 en: 22 de Junio de 2015, 23:58:37 »
Bueno basicamente queres hacer un menu. En el cual si presionas X boton hace tal cosa..
Hasta ahi esta bien. Y puedo darte una idea de como hacerlo.

Ahora cuando presionas algo, y por ejemplo comienza a hacer la rutina 1 o 2. Este tiene que continuar con la rutina 1 hasta cuando ? si presionas un boton deberia pararse? esas otras dudas son las que tengo para decirte bien como podrias hacerlo.

Desconectado JD007

  • PIC10
  • *
  • Mensajes: 4
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #4 en: 23 de Junio de 2015, 00:55:22 »
gracias por tu respuesta.

Citar
Ahora cuando presionas algo, y por ejemplo comienza a hacer la rutina 1 o 2. Este tiene que continuar con la rutina 1 hasta cuando ? si presionas un boton deberia pararse?

Lo que quiero es que al presionar un boton se ejecute la rutina 2 por un tiempo predeterminado (por ejemplo 30 segundos)y al finalizar esta, me devuelva al menu de opciones y de igual forma con la rutina 1.

pero con la rutina 1 tal como esta debería  ejecutarse una sola vez y finalizar , pero no lo hace en cambio se repite de forma indefinida(creo que es por el while del "menu" de opciones pero no nose como solucionarlo).
Citar
void Rutina_Uno(){

lcd_gotoxy(1,1);
lcd_putc("\f"); 
printf(lcd_putc,"EJECUTANDO 1");

AVANCE;
      delay_ms (500);
     
RETROCESO;
      delay_ms (500);
     
PARO;

 }



Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #5 en: 23 de Junio de 2015, 03:05:51 »
Este es mi codigo, no hay peor cosa que CCS con su standard_io, prefiero mil veces el FAST_IO y configurar los puertos a mi manera, por eso mismo solo toque los puertos que tenes como entradas, que son los puertos A y D. Setee como entrada nomas la parte baja. El por que ? por que si yo quiero leer todas las entradas y solo seleccionar las que me importan con el standard_io me las cambia a todas como entradas, a pesar que puede haber alguna que deberia estar como salida. De la misma forma si yo quiero cambiar los bits de salida modificando el puerto, no puedo hacerlo con sus funciones por que sino te cambia las entradas a salidas. Hasta las definiciones AVANCE/RETROCESO/etc se podrian hacer con una sola linea. si fueran FAST_IO

Como dije, este es mi codigo. Asumi que cuando presionas algo se pone a 1, sino esta en 0.

Comienza, muestra el mensaje de que presione D0 y espera.
Cuando presionas D0 te muestra las opciones
Apartir de aca si no se presiona nada no se hace nada. Solo hace algo si se presiona D1 o D2
Si se presiona D1 ejecuta el codigo de la primera rutina, termina, muestra las opciones y de vuelta se queda esperando.
Si se presiona D2 ejecuta el codigo de la segunda rutina unas 30 veces ( para los 30 segundos ), cuando termina de hacerlo muestra las opciones y se queda esperando.

Rutina 1 no tiene cambios
Rutina 2 saque B0 que no se usaba, y Reemplaze los if por un switch/case, cualquier otra combinacion de las que habia entran en default, por lo tanto en esas no hace nada TAL CUAL lo tenas en el codigo antes.

Código: C
  1. #include <16F887.h>
  2.  
  3. #fuses NOWDT, XT, NOPROTECT,MCLR              
  4. #use delay(clock=4000000) // Crystal 4Mhz  
  5. #USE Standard_io (C)
  6. #USE Fast_io (A)
  7. #USE Fast_io (D)
  8. #USE Standard_io (B)
  9.  
  10. /* Definicion de la LCD */
  11.  
  12. #define LCD_DB4   PIN_B4
  13. #define LCD_DB5   PIN_B5
  14. #define LCD_DB6   PIN_B6
  15. #define LCD_DB7   PIN_B7
  16. #define LCD_RS    PIN_B2
  17. #define LCD_E     PIN_B3
  18. #define use_portb_lcd TRUE         //definir portb lcd
  19. #include <lcd1.c>
  20.  
  21.  
  22. /*-------------------- Variables de movimiento-------------------------------*/
  23.  
  24. #define AVANCE          output_low(PIN_C2),output_low(PIN_C4),output_high(PIN_C3),output_high(PIN_C5)
  25. #define RETROCESO       output_high(PIN_C2),output_high(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
  26. #define PARO            output_low(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
  27. #define GIRO_DERECHA    output_high(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_high(PIN_C5)
  28. #define GIRO_IZQUIERDA  output_low(PIN_C2),output_high(PIN_C4),output_high(PIN_C3),output_low(PIN_C5)
  29.  
  30.  
  31. /*-------------------LECTURA DE OPCIONES---------------------*/
  32.  
  33. void mostrar_opciones(){ // VOID DE RUTINAS QUE SE MUESTRAN EN PANTALLA!!
  34.  
  35.         lcd_gotoxy(1,1);
  36.         lcd_putc("\f");  
  37.         printf(lcd_putc,"D1 RUTINA 1");
  38.  
  39.         lcd_gotoxy(1,2);
  40.         printf(lcd_putc,"D2 RUTINA 2 ");
  41.  
  42.  
  43. }
  44.  
  45. /*----------------------RUTINAS-------------*/
  46.  
  47. void Rutina_Uno(){
  48.  
  49.         lcd_gotoxy(1,1);
  50.         lcd_putc("\f");  
  51.         printf(lcd_putc,"EJECUTANDO 1");
  52.  
  53.         AVANCE;
  54.         delay_ms (500);
  55.  
  56.         RETROCESO;
  57.         delay_ms (500);
  58.      
  59.         PARO;
  60.  
  61.  }
  62.  
  63. void Rutina_Dos(){
  64.  
  65.         lcd_gotoxy(1,1);
  66.         lcd_putc("\f");  
  67.         printf(lcd_putc,"EJECUTANDO 2");
  68.  
  69.         switch((input_a()&0x0F)) {
  70.  
  71.         case 0x03:              //A0 y A1 = 1 ;;;; A2=A3=0
  72.                 AVANCE;
  73.                 break;
  74.         case 0x04:              //A2=1 ;;;; A0=A1=A3=0
  75.                 GIRO_DERECHA;
  76.                 break;
  77.         case 0x08:              //A3=1 ;;;; A0=A1=A2=0
  78.                 GIRO_IZQUIERDA;
  79.                 break;
  80.         case 0x0F:              //A0=A1=A2=A3=1
  81.                 PARO;
  82.                 break;
  83.         default:                // Cualquier otra combinacion que no se tomo en cuenta antes   
  84.                 break;
  85.         }
  86.        
  87.         delay_ms(1000);
  88.  
  89. }  
  90.  
  91. /*-------------------------- PARTE PRINCIPAL DEL PROGRAMA!!---------------------*/
  92.  
  93. void main(){
  94.  
  95.        
  96.         // Inicializacion de puertos solo los fast_io
  97.  
  98.         set_tris_a(0x0F);               //A3,A2,A1,A0 entradas
  99.         set_tris_d(0x0F);               //D3,D2,D1,D0 entradas
  100.  
  101.  
  102.         lcd_init();
  103.         output_high (PIN_A4);        
  104.  
  105.         // ESCRIBIR LA BIENVENIDA
  106.  
  107.         lcd_gotoxy( 1, 1);
  108.         printf(lcd_putc,"   BIENVENIDOS   ");
  109.         lcd_gotoxy( 1, 2);
  110.         printf(lcd_putc,"D0 IR A OPCIONES");
  111.            
  112.         //DECLARACION DE VARIBALES!!
  113.  
  114.         int estado=0,i;
  115.  
  116.         while(1)
  117.         {
  118.  
  119.                 switch(estado) {
  120.  
  121.                 case 0:
  122.                         if(input(PIN_D0))
  123.                         {
  124.                                 estado=1;
  125.                                 mostrar_opciones();
  126.                         }
  127.                         break;
  128.                 case 1:
  129.                         switch((input_d()&0x0F))                // PORTD & 0x0F
  130.                         {
  131.                         case 0x02:                              // D1= 1  => 0x02 = 0000 0010
  132.                                 Rutina_Uno();                   // Realiza 1 sola ves y sale
  133.                                 mostrar_opciones();             // Muestra nuevamente las opciones y queda esperando que se presione algo
  134.                                 break;
  135.                         case 0x04:                              // D2= 1  => 0x04 = 0000 0100
  136.                                 for(i=0;i<30;i++)               // repito las cosas para llegar a los 30 segundos , ya que tiene un delay de 1s + lo demas seran casi 30 seg
  137.                                 {
  138.                                         Rutina_Dos();
  139.                                 }
  140.                                 mostrar_opciones();             // Cuando termine que muestre las opciones
  141.                                 break;
  142.                         default:                                // D3 = 1, D0=1 o cualquier combinacion de 2/3 teclas que no este contemplado, no hace nada.
  143.                                 break;
  144.                         }
  145.                         break;
  146.                 default:                                        // Cualquier cosa que ocurra y pueda llegar a cambiar el valor de estado, lo vuelve al valor 1
  147.                         mostrar_opciones();
  148.                         estado=1;
  149.                         break;
  150.                 }
  151.         }
  152.  
  153. }  // Final del codigo

« Última modificación: 23 de Junio de 2015, 03:09:12 por KILLERJC »

Desconectado JD007

  • PIC10
  • *
  • Mensajes: 4
Re: Rutina que se ejecute por un tiempo predeterminado.
« Respuesta #6 en: 23 de Junio de 2015, 22:32:02 »
KILLERJC, ¡Gracias por tu ayuda!  :oops:
La verdad me has sacado de un  enrollo que tenia.
Seguiré con mi aprendizaje y tratare de agarrar mas experiencia en la programación.  :shock:


 

anything