Autor Tema: Robots cooperativos  (Leído 9109 veces)

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

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
Robots cooperativos
« en: 31 de Marzo de 2005, 13:50:00 »
hola amigos. Hace unos dias pedi algunos consejos sobre el control de un motor dc y un servo, y lo meti en lenguaje c para pics, pero bueno pienso que estaría mejor aca.

Bueno les cuento. Debemos realizar un proyecto de dos robots cooperativos, uno controlado por pc y otro que obedezca algun tipo de orden dada por el cacharrito controlado por el pc. De momento estamos empezando y ya tenemos mas o menos claro el control de motores. Un cacharrito dispone de dos motores dc y otro de un motor dc y un servo direccional. Ademas cada cacharrito dispone de dos pics, uno para el control de movimiento y otro para adquisicion de datos y envio de ordenes al pic de control de motores mediante comunicacion serie. Mas o menos tenemos esa idea y bueno, como ya les dije pedi consejo en otro subforo y el amigo pocher me contesto y tal y me dio alguna informacion.  Si les parece, podria colgar todos los programas que vayamos haciendo y poco a poco y con los consejos de unos cracks como ustedes que salga una cosa bonita al final. No me importaria, conforme vayan saliendo las cosas (programas, construccion etc...) compartir este proyecto con ustedes.

Aqui les dejo el codigo del control del movimiento del cacharrito del servo y el motor. Tengo algunas dudas asi que me encantaría que le echarán un ojo y comentaran consejos posibles mejoras, etc....

Les comentos por encima: El portA es de entrada, donde los cuatro primeros bits indican la velocidad que nos servira para calcular el duty necesario para aplicarlo al motor. Los dos ultimos bits del mismo puerto indican la dirección del servo. Mis dudas son (lo tienen indicado en la linea de programa):

1. cada vez que haya un cambio de dirección, quiero que el motor dc se pare, empezar a meter pulsos al servo y despues de un tiempo volver a conectar el motor. Como ven eso ya lo he conseguido, el problema es que se me para siempre que sale del bucle incluso cuando hay un cambio de velocidad, cosa que no quiero.
2. En el instante que el cacharrito debe ir hacia atras, la posicion del servo es recto (la correcta), pero el pwm que le meto al motor, no se.... asi como lo tengo supongo ira hacia delante o dependiendo del duty.... No lo tengo claro.
 Un apunte final, los bits de entrada del port a son los que tendra que mandar el otro pic mediante la comunicacion de los mismos.

Ahi va el codigo:



#include <16F876.H>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use Delay(Clock=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_a = 5   // Identificador asociado al registro de dirección 5
#byte port_b = 6   // Identificador asociado al registro de dirección 6
#byte port_c = 7   // Identificador asociado al registro de dirección 7


void main(void){

 set_tris_a(0b111111);        //PortA entrada
 set_tris_b(0b00100000);      //RB5 es entrada de on / off
 set_tris_c(0b0000000);       //PortC salida

int x, xx, y, dutycalculado, n;

setup_timer_2(T2_DIV__BY_16,249,1)  // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1(CCP_PWM)                 //Configuguro PWM


   while (1)

   {

      while (input(PIN_B5))
      {



       x=port_a                            // Leo estado del puerto

       xx=0b110000 & x                    // And lógica para ver estado de los bits que me marcan la direccion

       y=0b001111 & x                     // And logica para ver estado de los bits de velocidad

       dutycalculado=y/(16*(1/4000000))   // Calculamos duty


         while(x==port_a)                    // mientras no haya cambios (direccion o velocidad)
         {

         port_c=0x00                      //AQUI TENGO DUDAS!!!!!!!!!!!!!!!!!!!

          switch(xx)
            {
             case 0:                          //recto

               output_high (pin_c1)
               delay_us (1200)
               output_low (pin_c1)
               delay_us (18800)

               for (n=0;1;1)
                {

                delay_ms(2000)
                set_pwm1_duty(dutycalculado)
                }


              break;

              case 16:                      //derecha

                 output_high (pin_c1)
                 delay_us (1733.333)
                 output_low (pin_c1)
                 delay_us (18266.667)

                 for (n=0;1;1)
               {

                delay_ms(2000)
                set_pwm1_duty(dutycalculado)
               }

              break;


              case 32:                     //izquierda

                output_high (pin_c1)
               delay_us (666.666)
              output_low (pin_c1)
              delay_us (19333.333)

                or (n=0;1;1)
               {

              delay_ms(2000)
              set_pwm1_duty(dutycalculado)
               }

             break;


      case 48:                             //atras ?????????? Como hago que vaya hacia atras

         output_high (pin_c1)
         delay_us (1200)
         output_low (pin_c1)
         delay_us (18800)

            for (n=0;1;1)
            {

            delay_ms(2000)
            set_pwm1_duty(dutycalculado)
            }


        break;
    }
   }

   }
   }
}

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
RE: Robots cooperativos
« Respuesta #1 en: 01 de Abril de 2005, 03:05:00 »
Dices que no quieres que salga del bucle con los cambios de velocidad, sólo con los cambios de dirección, pero en tu programa aparece esto:

Codigo:
x=port_a // Leo estado del puerto

xx=0b110000 & x // And lógica para ver estado de los bits que me marcan la direccion

y=0b001111 & x // And logica para ver estado de los bits de velocidad

dutycalculado=y/(16*(1/4000000)) // Calculamos duty


while(x==port_a) // mientras no haya cambios (direccion o velocidad)
{


por lo que saldrá del bucle con cualquier cambio.
Yo probaría a cambiar la condición del bucle por esta otra:

while (xx==(0b110000 & x)) // mientras no haya cambios de dirección

Teóricamente, así sólo debería salir con cambios de dirección.

Para dar marcha atrás habría que saber cómo tienes conectados los motores DC. Supongo que los tendrás colgando de un puente en H, ¿no?

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #2 en: 01 de Abril de 2005, 13:04:00 »
Sería conveniente que nos mostrases una foto con la mecánica.

Leyendo el programa, quizá sea esto: Dos ruedas motrices delanteras controladas por un solo motor de dc y direccionadas por el servo, más una rueda loca trasera.

Si es así dudo que el programa que has expuesto funcione. Lo dicho una imagen, o una explicación, a ver si lo hechamos a andar.

Un saludo

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #3 en: 01 de Abril de 2005, 21:15:00 »
el robotito dispone de dos ruedas traseras y un solo motor dc para estas. delante una rueda que gira solidaria al servo.  ya probare estos consejitos nano y os comento. Bueno la estructura es basicamente esa: un motor dc que mueve las dos ruedas traseras y el servo que hace girar la rueda delantera.

Gracias pocher ya comento los cambios. Espero no ser pesao y de nuevo mil gracias. Y como dije, todo lo que vaya saliendo bien del robotito lo ire colgando aca.

Saludos.Giño

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #4 en: 02 de Abril de 2005, 06:10:00 »
Para que vaya marcha atrás:

El control del motor d.c. se hace mediante pwm usando un driver L293 por ejemplo. Para controlar el motor usaras 3 entradas del L293 y 2 salidas.

De las 3 entradas 2 son para poder invertir la polaridad del motor y hacer que vaya delante-atrás y la otra entrada va al Enable del L293 y por ahí introducirás el PWM. Luego del PIC tienen que salir 3 salidas que iran al L293.

La fórmula que usas para el pwm del motor támpoco creo que está bien: no creo que alcance mucha velocidad.

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #5 en: 05 de Abril de 2005, 06:42:00 »
gracias pocher.  Esta noche colgare el programita corregido a ver que tal. ya me di cuenta que mi formula del pwm no funciona. Otra cosita, debo hacer una comunicacion serie entre dos pics. ¿ Cual resultaria mas facil de implemetar y mas factible para este caso? Utilizo dos pics 16f876. He visto algo de i2c, spi.... Si has experimentado con alguna de estas cual te resulto mejor??

Gracias pocher.

Un saludo desde valencia.

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #6 en: 05 de Abril de 2005, 12:17:00 »
Yo he experimentado mucho más con I2C que con SPI, aunque puedes realizar la comunicación entre PICs con cualquiera de las dos. Casi que te recomendaría el I2C porque aunque con SPI se puede realizar la comunicación entre PICs con solo 2 líneas solo es en el caso que sea unidireccional, sin embargo si es bidireccional hay que usar 3. Depende de lo que vayas a hacer con los dos PIC.

Un saludo

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #7 en: 06 de Abril de 2005, 06:32:00 »
bueno, al simular el programita (corregido y con cambios), y aunque teoricamente deberia funcionar, no funciona. El problema es que al servo hay que estar continuamente enviandole la señal pwm con su duty correspondiente, cosa que no consigo.

Me han comentado usar el timer para contar 20 ms (necesarios para hacer trabajar al servo) y cuando acabe la cuenta, pasar a una rutina de interrupcion que me de el pulso necesario para poner el servo en la posicion correcta.

A primera vista  esto parece que funcionaria. No se muy bien como configurar el timer para esos 20 ms, ademas cuando acabara la cuenta deberia seguir contando para que a los proximos 20 ms, pasara a la interrupcion para dar el pulso necesario.
Estaria continuamente entrando en la interrupcion ya que los pulsos para el servo son continuos. SI tienes un enlace o algo que explique como realizar esto te lo agradeceria.

Gracias pocher.
SAludos.

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #8 en: 06 de Abril de 2005, 10:42:00 »
Sin interrupción, conforme lo habías pensado,  también te debe de funcionar. Pega lo que has hecho y no te funciona en PROTEUS y si tengo tiempo lo miraré.

En el caso que haya que realizar muchas "operaciones" en el while, conviene hacerlo conforme te han indicado, por interrupción.

Por interrupción creo que sería así:

#INT_TIMER1                          //Caso de querer Servo en posicion central

interrupcionTMR1()

{
output_high (pin_C4);
delay_us(1500);
output_low (pin_C4);
set_timer1 (47036);        //18500us (Preesc=1)

}

FORMULA: Valor a cargar en TMR1= 65536 - (Temp · fosc)/(4 · Preesc)

Un saludo

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #9 en: 06 de Abril de 2005, 14:26:00 »
He hecho algunos cambios, incluso dejandolo mas facil y dejando de parar el motor cuando haya que girar sigue sin funcionar. Probare con interrupcion por tim aver que tal.  gracias un saludo pocher




#include <16F876.H>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use Delay(Clock=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_a = 5   // Identificador asociado al registro de dirección 5
#byte port_b = 6   // Identificador asociado al registro de dirección 6
#byte port_c = 7   // Identificador asociado al registro de dirección 7


void main(void){

int x,dutycalculado, n;

set_tris_a(0b111111);
set_tris_b(0b00100000);      //RB5 es entrada de on / off
set_tris_c(0b0000000);


setup_timer_2(T2_DIV_BY_16,249,1) ; // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1 (CCP_PWM);

   while (1)
   {

      while (input(PIN_B5))
      {

       
            x=0b110000 & port_a;            //direccion

            while (x==(0b110000 & port_a))     // mientras no haya cambios de dirección

             {

              dutycalculado=0b001111 & x;            //velocidad

             if(dutycalculado>10)
             {

             dutycalculado=0;
             }
              else
             {
              dutycalculado= 25 * dutycalculado ;
             }

                  if (!pin_a5)  //recto o derecha
                  {

                     if (!pin_a4) //recto
                     {
                     
                     set_pwm1_duty(dutycalculado);
                     output_high(pin_b4);           //al L293 xa distinguir adelante atras  

                     while (!pin_a4)
                     {
                     output_high (pin_c1);
                       delay_us (1200);
                     output_low (pin_c1);
                     delay_us (18800);
                    
                   

                     
                     }
                     }

                     else  //derecha
                     
                     {
                     
                     set_pwm1_duty(dutycalculado);
                     output_high(pin_b4);
                     
                     while (pin_a4)
                     {
                      output_high (pin_c1);
                     delay_us (1800);
                     output_low (pin_c1);
                     delay_us (18200);
                  
                   
                   
                     
                     }
                     }
                  }
                 else   //atras o izquierda
                 {

                        if(pin_a4)  //atras
                        {

                        set_pwm1_duty(dutycalculado);
                        output_low(pin_b4);
                       
                        while (pin_a4)
                        {

                        output_high (pin_c1);
                          delay_us (1200);
                        output_low (pin_c1);
                        delay_us (18800);
                       

                       
                       
                        }
                        }
                        else     //izquierda
                        {
                        set_pwm1_duty(dutycalculado);
                        output_high(pin_b4);
                        while (!pin_a4)
                        {
                        output_high (pin_c1);
                        delay_us (600);
                        output_low (pin_c1);
                        delay_us (19400);
                        

                       
                       
                        }
                        }
                 }
             }
     

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #10 en: 06 de Abril de 2005, 18:15:00 »
Esto es lo que he hecho usando la interrupcion del timer 1, no se que tal estara (seguramente mal) pero bueno espero que vayan mejorando las cosas.

Gracias pocher, espero tus comentarios maestro!

#include <16F876.H>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use Delay(Clock=4000000)
#use fast_io(A)
#use fast_io(B)
#byte port_a = 5   // Identificador asociado al registro de dirección 5
#byte port_b = 6   // Identificador asociado al registro de dirección 6
#byte port_c = 7   // Identificador asociado al registro de dirección 7



#INT_TIMER0
void interrupcion()
   {
  switch(pin_a5){
 
   case 0:   //recto o derecha
   
      if (!pin_a4)  //recto
      {
      output_high (pin_c0);
      delay_us(1200);
      output_low (pin_c0);
      set_timer1 (46736);
      }
      else  // derecha
      {
      output_high (pin_c0);
      delay_us(1800);
      output_low (pin_c0);
      set_timer1 (47336);
     
      }
      break;
 
      case 1:   //atras o izquierda
        if (!pin_a4)  //izquierda
      {
      output_high (pin_c0);
      delay_us(600);
      output_low (pin_c0);
      set_timer1 (46136);
      }
      else  // atras
      {
      output_high (pin_c0);
      delay_us(1200);
      output_low (pin_c0);
      set_timer1 (46736);
     
      }
      break;
  }
}

void main(void){

int x,dutycalculado, n;
set_tris_a(0b111111);
set_tris_b(0b00100000);      //RB5 es entrada de on / off
set_tris_c(0b0000000);


setup_timer_2(T2_DIV_BY_16,249,1) ; // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1 (CCP_PWM);  
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1 ); // Timer 1 configurado con preescaler 1
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);

set_timer1(45536);   // Valor de carga


   while (1)
   {
         while(pin_b5){

         setup_ccp1(CCP_OFF);
         delay_ms(1000)
         x=0b110000 & port_a;            //direccion

            while (x==(0b110000 & port_a))     // mientras no haya cambios de dirección

             {

              dutycalculado=0b001111 & x;            //velocidad

             if(dutycalculado>10)
             {

             dutycalculado=0;
             }
              else
             {
              dutycalculado= 25 * dutycalculado ;
             
             }
               
               
                set_pwm1_duty(dutycalculado);

                  if (!pin_a5)  //recto o derecha
                  {

                     if (!pin_a4) //recto
                     {
                     
                     set_pwm1_duty(dutycalculado);
                     output_high(pin_b4);           //al L293 xa distinguir adelante atras  

                   
                     }

                     else  //derecha
                     
                     {
                     
                     set_pwm1_duty(dutycalculado);
                     output_high(pin_b4);
                     
                     
                     }
                  }
                 else   //atras o izquierda
                 {

                        if(pin_a4)  //atras
                        {

                        set_pwm1_duty(dutycalculado);
                        output_low(pin_b4);
                       
                     
                        }
                        else     //izquierda
                        {
                        set_pwm1_duty(dutycalculado);
                        output_high(pin_b4);
                     
                        }
                        }
                 }
             }
      }

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #11 en: 07 de Abril de 2005, 07:26:00 »
He estado mirando el primer programa (sin interrupción).

Comentarios:

- Eliges una frecuencia de trabajo para el pwm del motor de d.c. de 250Hz (T=4ms). ¡Perfecto!

- Por lo tanto el Duty tendría que variar entre 0 y 4ms.

- Veamos como calculas el Dutymáx:

x=0b110000 & port_a ---> Te quedaría: x=RA5 RA4 0 0 0 0

dutycalculado=0b001111 & x ---> Te quedaría: 0 0 0 0 0 0 ¡¡¡ Sin comentarios !!!

Luego esta programación si no me he equivocado la tienes que cambiar.

Por otra parte te hago una reflexión:

Cogiendo RA3..RA0 para el Duty y RA4-RA5 para posicionar al Servo el máximo Duty para el motor de contínua sería:

1111 · z = 4ms de donde z=266,6 > 255 que es el máximo valor que admite el registro CCPR1L ¿No crees que tendrías que usar un pin más para el Duty del motor?

- Otra cosa:

Con dos pines para posicionar al Servo solo vas a tener 4 combinaciones. Las que tú pones son:

Adelante-Recto, Adelante-Derecha, Atrás-Recto y Atrás-Izquierda ¿No te interesaría que fuese también Adelante-Izquierda y Atrás-Derecha?

Para incluir a estas necesitarías un pin más.

Espero no haberme equivocado con las reflexiones. Piénsalo

Un saludo

PD. Me gustaba más el anterior programa donde usabas swhich (control_dir)

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #12 en: 07 de Abril de 2005, 14:42:00 »
gracias pocher. Ya lo mirare y corregire cositas a ver. Las posibles direcciones serian adelante recto, adelante derecha, adelante izquierda y atras. Bueno ya miro el programita del switch, el problema esta que el servo no puede dejar de recibir pulsos, ahi es donde.... bueno ya lo miro y comento. A ver si la semana esta corriendo ya por ahi que ya es horaLlorando

de nuevo mil gracias maestro!

Desconectado pocher

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: Robots cooperativos
« Respuesta #13 en: 07 de Abril de 2005, 23:24:00 »
¡¡¡ De acuerdo !!!, con esas posiciones solo necesitas 2 pines.

Desconectado aupadeportivo

  • PIC10
  • *
  • Mensajes: 18
RE: Robots cooperativos
« Respuesta #14 en: 12 de Abril de 2005, 20:48:00 »
Bueno amigo Pocher, despues de muchas pruebas y tal por fin hice algo con algo de sentido.

a0..a3 -> Determinan la velocidad
a4,a5-> Sentido   00 recto, 10 izquierda, 11 atras, 01 derecha.

    Me gustaria hacer que cuando hubiera un cambio de direccion         (cambio en a4 o a5),  dejar de enviar la señal PWM al motor durante 2 o 3 segundos, pero continuar enviando pulsos al servo. Asi, en el caso de cambio de posicion del servo, con el cacharrito parado tendre un poco mas de control a la hora de direccionar. La verdad por mas vueltas que le doy no consigo sacarlo.
Y otra gran duda. ¿Es posible que debido a la ejecucion del programa al cabo de un cierto tiempo haya un retraso en el envio de pulsos al servo?
Me explico, tengo que enviar un pulsito cada 20 ms, pero conforme el programa se ejecute 1000 veces por decir algo, me generara algun retraso y los pulsos ya no seran de periodo 20ms sino algo mas, ya que estoy un periodo pequeño de tiempo sin enviar nada. ¿Esto puede influir en el funcionamiento del servo? Si es asi, no tengo ni idea de como arreglar ese desajuste.
Bueno ahi va el programa:

#include <16F876.H>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use Delay(Clock=4000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#byte port_a = 5 // Identificador asociado al registro de dirección 5
#byte port_b = 6 // Identificador asociado al registro de dirección 6
#byte port_c = 7 // Identificador asociado al registro de dirección 7


void main(void){
int dutycalculado, x,xx;
set_tris_a(0b111111); //PortA entrada
set_tris_b(0b00000000);
set_tris_c(0b0000000); //PortC salida

                                   
setup_timer_2(T2_DIV_BY_16,249,1) ; // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1 (CCP_PWM);               //Conf PWM
while (1)
{
      x = port_a;
      xx= 0b001111 & port_a;    //velocidad (1=10%, 2=20%......10=100%)
   

      if(xx>10)     //
         {
         xx=0;       //Si es mayor a 10 duty=0
         }   
         dutycalculado= 25 * xx ;    // Valor a cargar en duty
         
         
            switch(input(pin_a4))
            {
            case 0:              //recto o izquierda
                           
               if (input(pin_a5))     //izquierda
                 {
                  output_high(pin_b6);
                  delay_us(600);
                  output_low(pin_b6);
                  delay_us(19400);
                 
                  set_pwm1_duty(dutycalculado);
                  output_high(pin_b7);
               }
               
               else       // recto
               {
                 output_high(pin_b6);
                 delay_us(1200);
                 output_low(pin_b6);
                 delay_us(18800);
                 
                 set_pwm1_duty(dutycalculado);
                 output_high(pin_b7);
               }
           
               break;
               
             case 1:            //derecha o atras
            
               if (input(pin_a5))     //atras
                 {
                  output_high(pin_b6);
                  delay_us(1200);
                  output_low(pin_b6);
                  delay_us(18800);
                 
                  set_pwm1_duty(dutycalculado);
                  output_low(pin_b7);
               }
               
               else       // derecha
               {
                 output_high(pin_b6);
                 delay_us(1800);
                 output_low(pin_b6);
                 delay_us(18200);
                 
                 set_pwm1_duty(dutycalculado);
                 output_high(pin_b7);
               }

            break;
   }
}
}


Gracias maestro Pocher por tu tiempo y sugerencias.

Un saludo desde Valencia!!



 

anything