Autor Tema: Interrupcion por recepcion en Rs232  (Leído 5396 veces)

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

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Interrupcion por recepcion en Rs232
« en: 11 de Noviembre de 2007, 22:20:45 »
saludos colegas estoy en un nuevo proyecto, he dejado suspendido algunos (como el de las matrices, y el de un control remoto que queria hacer), consiste en enviar datos por rs232 para mover dos motores un paso paso y un dc con una especie de encoder, jeje

hasta la parte de enviar el dato, todo bien, envio recibo, muevo motores pero supuestamente debo esperar a una interrupcion (rda) para volverlo a su lugar pero este sin interrupcion se detiene (supongo que es ruido), y no entiendo porque lo hace
quisiera hacer uqe cuadno pase una interrupcion de rda vuelvan a su estado original los motores el dc y el paso paso, esto puedo hacerlo contando los pasos de cada uno y regresarlos, esas no creo sea la parte complicada, sino lo que nose como hacer es de una interrupcion, salir de una rutina de movimiento y llevar la inicio de sus posiciones a los motores

me deje entender, si no avisenme, que de ser necesariom pongo el codigo, no lo pongo para no complicarles, jeje
.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Interrupcion por recepcion en Rs232
« Respuesta #1 en: 12 de Noviembre de 2007, 12:00:11 »
umm talvez no fui muy claro, lo que pretendo es enviar datos y hacer mover los motores segun esos datos, y mantener moviendo los motores mientras no se presione niguna tecla el la PC, en cuanto detecte una tecla presionada mediante la interrupcion rda que los motores vuelvan a su estado original, para ello llevo la cuenta de los pasos que se ha movido cada motor, y muevo esa cantidad para llevarlo otra vez al origen, en cuanto pase la interrupcion debe estar listo para recibir nuevos datos para mover en otras posiciones a los motores

mi problema esta en una vez detectada la interrupcion nose como volver al inicio, talvez en assembler lo solucionaria con un GOTO, pero antes debo salir de la interrupcion, y pues he ahi mi problema

un saludo, y gracias por su atencion.
.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Interrupcion por recepcion en Rs232
« Respuesta #2 en: 12 de Noviembre de 2007, 15:52:26 »
Cryn, te leí pero sigo sin entender donde está tu problema.

En leer el dato de la usart y que el programa siga su curso normal?
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Interrupcion por recepcion en Rs232
« Respuesta #3 en: 12 de Noviembre de 2007, 19:11:49 »
No, leo los datos correctamente, ahi no he tendo nigun problema, pensaba que por ruidos se ejecutaba la interrupcion, pero no era asi, tenia un error de codigo.

ahora el problema que tengo es el siguiente:

digamos que tengo mi main principal, que:

-recibe al inicio (solamente una vez) 2 datos (provenientes del hiperterminal) que los proceso y los convierto a int para la correcta manipulacion en el pic
-una vez con los datos correctos, debo hacer un ciclo infinito con movimientos de motores, hasta que tenga una interrupcion por el rda (#int_rda)
-cuando ocurra la interrupcion debo poner los motores a su posicion inicial (para ello no creo haya problema ya que cuento cada paso qeu doy, y solo es mover en el otro sentido la cantidad de pasos que conte)
-despues de volver a las posiciones iniciales debo iniciar nuevamente el programa, osea volver a pedir datos del hyperterminal

lo que nose como realizar es el ultimo paso que menciono, el que puse en negrillas, ya que el programa se encontraba en un ciclo infinito moviendo los motores y nose como salir de el despues de la interrupcion.

espero ahora si haberme dejado entender, un saludo mg
.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Interrupcion por recepcion en Rs232
« Respuesta #4 en: 13 de Noviembre de 2007, 03:27:35 »
Haber si te puedo ayudar, estoy tocando esto ahora.

Porque desde PC no envias bytes codificados, es decir si quieres mover los motores envias tres bytes los 2 primeros con los movimientos de los motores y el tercero un byte código (por ejemplo un *).

Cuando quieras poner a los motores a su posición inicial pues envias bytes de datos y terminas con otro byte código (por ejemplo un !).

El PIC Esclavo mediante interrupción RDA debe guardar en un buffer los 3 bytes que le entran e interpretar el último byte para hacer una cosa u otra.

Espero que se entienda. Un saludo

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Interrupcion por recepcion en Rs232
« Respuesta #5 en: 13 de Noviembre de 2007, 11:20:47 »
saludos, gracias por la respuesta.

El pic escalvo (en mi caso) mediante la interrupcion rda solo debe leer un dato, cualquier tecla y cuando ocurra ello llevar a las posiciones iniciales los motores (en la que no he tenido problema), una vez finalizada la interrupcion (la interrupcion solo debe llevar a pocisiones iniciales) se debe volver al inicio del programa para pedir nuevos datos (datos que no los pido por interrupcion sino por gets())
.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Interrupcion por recepcion en Rs232
« Respuesta #6 en: 13 de Noviembre de 2007, 11:51:00 »
saludos, gracias por la respuesta.

El pic escalvo (en mi caso) mediante la interrupcion rda solo debe leer un dato, cualquier tecla y cuando ocurra ello llevar a las posiciones iniciales los motores (en la que no he tenido problema), una vez finalizada la interrupcion (la interrupcion solo debe llevar a pocisiones iniciales) se debe volver al inicio del programa para pedir nuevos datos (datos que no los pido por interrupcion sino por gets())

Cryn, sabes lo que es una máquina de estados?

Básicamente tomas una variable y le haces cambiar el valor en función a lo próximo que tiene que hacer.

Ej.
    SI A = 0 -> no hace nada, inicio de aplicacion. o bien deja todo apagado
    Si A = 1 -> Mueve motor
    Si A = 2 -> Retrocede motor
    Si recibe dato nuevamente A=0 -> no hace nada

- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
Re: Interrupcion por recepcion en Rs232
« Respuesta #7 en: 13 de Noviembre de 2007, 12:34:40 »
Del gets() no guardo muy buen recuerdo. Va guardando bytes en una variable hasta que encuentra un CR y sale del gets() para seguir con la siguiente línea. Se usa desde el PC acabando con un CR o desde otro PIC con un puts().

El dichoso gets() me dió muchos problemas ya que no guardaba bien los datos. Lo solucioné con get_string() y desde luego la mejor solución es con interrupción RDA. Quizá para un solo byte no te dé problemas.

Creo que lo mejor es que pongas el programa para ver como lo tienes.

Un saludo

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Interrupcion por recepcion en Rs232
« Respuesta #8 en: 14 de Noviembre de 2007, 16:13:06 »
gracias por las rspuestas.

maunix, si creo saber eso que mencionas, pero no entiendo en que puede ayudarme ello, o que debo hacer, ya que nbo he tenido problemas en la parte de mover

pocher: no he tenido problemas por ahora con el gets() ya que he logrado recibir los datos correctamente, bueno es algo largo el codigo, asi que tratare de resumir algunas partes y tratar de enfocar mi problema:

Código: [Seleccionar]
#include <16F877a.h>
#include <string.h>
#include <stdlib.h>
#fuses XT,NOWDT,PUT,NOPROTECT,NOLVP,NOCPD,NOBROWNOUT,NODEBUG
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)
#byte port_a=0x05
#byte port_b=0x06
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#define up_dc PIN_C0
#define down_dc PIN_C1

int encoder_count=0,count,dc_on=0,go_up,rda;
int16 i,pasos_1,pasos_2,step_count=0,grad1,grad2;
char dato1[2],dato2[2];

#INT_TIMER0
void tmr_handler()
{
   count++;
   if(count==pasos_2)
   {
      dc_on=0;  // apago bandera del motor dc encendido, cuando se llegue a la cantidad de pasos necesitados
   }
   set_timer0(255);
}

void delay()
{
   delay_ms(25);                 // retardo entre paso
}

void derecha(int16 pasos_d)  // funcion para mover el motor paso a paso, la cantidad de pasos calculado con el dato recibido por rs232
{
   for(i=0;i<pasos_d;i++)
   {
      rotate_left(&port_b,1);
      step_count--;
      delay();
   }
}

void izquierda(int16 pasos_i) //para mover paso a paso pero a la izquierda
{
   for(i=0;i<pasos_i;i++)
   {
      rotate_right(&port_b,1);
      step_count++;
      delay();
   }
}

int a_entero(char c[],int16 dato)  // funcion para convertir la cadena recibida a un entero, el '9' '0' por ej. a 90
{
   dato=(c[0]-'0')*10;
   dato=(c[1]-'0')+dato;
   return dato;
}

void main()
{
   SETUP_ADC_PORTS(NO_ANALOGS);
   SETUP_ADC(adc_off);
   setup_timer_0(RTCC_EXT_H_TO_L | RTCC_DIV_1);
   enable_interrupts(global);
   enable_interrupts(int_timer0);
   set_tris_a(255);
   set_tris_b(0);
   set_tris_c(0xbc);
   port_b=0xcc;
   output_c(0);
   while(true)
   {
      SET_TIMER0(255);
      rda=0;
      printf("\r\nMotor A:");
      printf("\r\n 15' - 30' - 45' - 60' - 75' - 90'\r\n");
      printf("\r\nMotor B:");
      printf("\r\n 18' - 36' - 54' - 72' - 90'\r\n");
      printf("\r\nIngresar cantidad de grados Motor A y B:\r\n");
      gets(dato1); // obtengo primer dato y lo guardo en dato1
      puts(dato1); // muestro el dato obtenido
      gets(dato2); // obtengo segundo dato y guardo en dato2
      puts(dato2); // muestro dato obtenido
      grad1=a_entero(dato1,grad1); // convierto char (dato1) a int
      grad2=a_entero(dato2,grad2); // convierto char (dato2) a int
      pasos_1=grad1*3; // obtengo cantidad de pasos necesarios para girar la cantidad de grados obtenidos por dato1
      pasos_2=grad2/18; // obtengo cantidad de pasos necesarios para el otro motor
      if((grad1%15!=0)||(grad2%18!=0)) // si los datos no son multiplo de 15 y 18 respectivamente
         printf("\r\n error \r\n"); // muestro mensaje de error
      else
      {
         printf("\r\n ok \r\n"); // si datos estan en el rango comienzo el movimiento de los motores
         while(1)  // me qeudo en un ciclo infinito, porque esto debe hacerlo todo el tiempo hasta que se le envie cualqueir dato y ocurra una interrupcion en rda, talvez este redundante por el do de abajo, pero estaba funcionando
         {
            do
            {
               enable_interrupts(INT_RDA);
               dc_on=1; // bandera para anunciar que el motor dc estara encendido
               count=0; // contador de pasos del motor dc, via un encoder
               do //arriba para el motor dc
               {
                  if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
                  go_up=1; // bandera de marcha arriba seteada
                  output_high(up_dc); // pines de salida para el motor dc
                  output_low(down_dc);
               }while(dc_on==1);   // mientras bandera de encendido ed motor dc este en 1
               output_low(up_dc);  // motor dc apagado
               output_low(down_dc);
               if(rda==1){disable_interrupts(int_rda); break;}  // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               delay_ms(2000);  // retardo para que se quede sin movimiento por 2 seg
               if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               izquierda(pasos_1); //izquierda    // marcha a la izquierda del motor paso paso, la cantidad de pasos calculado
               if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               delay_ms(2000);  // retardo para que se quede sin movimiento por 2 seg
               if(rda==1){disable_interrupts(int_rda); break;}  // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               derecha(pasos_1);    //derecha //marcha a la izquierda del motor paso paso, la cantidad de pasos calculado
               if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               delay_ms(2000);  // retardo para que se quede sin movimiento por 2 seg
               dc_on=1;   // bandera del motor dc encendido
               count=0;   // contador de pasos del motor dc
               do    //abajo para el motor dc
               {
                  if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
                  go_up=0;  // bandera de marcha arriba limpiada
                  output_high(down_dc);  // pines de salida del motor dc
                  output_low(up_dc);
               }while(dc_on==1);   // mientras la bandera de motor dc este activa
               output_low(up_dc);   // detengo motor dc
               output_low(down_dc);
               if(rda==1){disable_interrupts(int_rda); break;} // si ha ocurrido la interrupcion se tiene qeu salir de este bucle
               delay_ms(2000);  // retardo para que se quede sin movimiento por 2 seg
            }while(KBHIT()==0); // mientras no reciba nada por rs232
            //disable_interrupts(int_rda);  // nose si esta linea tb vendria aca, porque antes del beak ya deshabilito
            dato1[0]=0;  // reestablezco todos los valores a 0
            dato1[1]=0;
            dato2[0]=0;
            dato2[0]=0;
            grad1=0;
            grad2=0;
            break;  // salgo del ciclo para comenzar de nuevo con otros datos
         }
      }
   }
}

#INT_RDA  // interrupcion por rs232
void usart_handler()
{
   output_low(up_dc);   // apago dc
   output_low(down_dc);
   delay_ms(3000); // retardo de 3 seg, mas apra saber que si ha entrado en la interrupcion
   if(step_count!=0)   // esto para volver al paso paso a su lugar de origen
   {
      do
      {
         derecha(1);
      }while(step_count!=0);
   }
   delay_ms(1000);  // retardo
   //pasos_2=pasos_2-count;
   dc_on=1;  // bandera del motor dc encendido
   do
   {
      go_up=0;
      output_high(down_dc);
      output_low(up_dc);
      if(get_timer0()==(count-1))
         dc_on=0;
   }while(dc_on==1);  // bajo la cantidad de pasaos necesarios
   output_low(down_dc);  // apago motor dc
   rda=1;  // bandera de que ha ocurrido interrupcion
   pasos_1=0;  // reestablezco valores
   pasos_2=0;
}

ahi esta el codigo completo no pude suprimir muchas lineas, espero se entienda.

lo que ha pasado ahora es que no ha salido de la rutina de interrupcion nunca, en simulacion tb se quedaba plantado en la int_rda, esto lo he visto con el .cof en proteus

un saludo y si no se entendio algo pues se los aclaro
« Última modificación: 14 de Noviembre de 2007, 17:52:49 por Cryn »
.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Interrupcion por recepcion en Rs232
« Respuesta #9 en: 14 de Noviembre de 2007, 18:49:38 »
creo haber dado con el problema de que no salia de la interrupcion, nunca recogia el dato qeu mande, entonces al inicio de mi interrupcion coloque: c=getc();
y listo con ello ya se sale de la interrupcion, parece que todo va bien ahora, me falto preguntar por el rda cuando da los pasos para el break despues de volver al inicio

beuno pues si tengo algun problema les aviso

el que ahora faltaria solucionar es qeu el encoder me de los pulsos necesarios para detenerme, a veces funciona bein y otros ratos no, y pues weno hay les aviso, un saludo, y gracias por sus respuestas
.


 

anything