TODOPIC

Mecatrónica => Robótica => Mensaje iniciado por: aupadeportivo en 31 de Marzo de 2005, 13:50:00

Título: Robots cooperativos
Publicado por: aupadeportivo 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;
    }
   }

   }
   }
}
Título: RE: Robots cooperativos
Publicado por: Nocturno 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?
Título: RE: Robots cooperativos
Publicado por: pocher 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
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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
Título: RE: Robots cooperativos
Publicado por: pocher 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.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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.
Título: RE: Robots cooperativos
Publicado por: pocher 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
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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.
Título: RE: Robots cooperativos
Publicado por: pocher 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
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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);
                        

                       
                       
                        }
                        }
                 }
             }
     
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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);
                     
                        }
                        }
                 }
             }
      }
Título: RE: Robots cooperativos
Publicado por: pocher 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)
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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!
Título: RE: Robots cooperativos
Publicado por: pocher en 07 de Abril de 2005, 23:24:00
¡¡¡ De acuerdo !!!, con esas posiciones solo necesitas 2 pines.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo 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!!

Título: RE: Robots cooperativos
Publicado por: pocher en 13 de Abril de 2005, 05:38:00
Antes de responder a lo que preguntas, me parece que no se consigue que vaya:

- Atrás-Izquierda y
- Atrás-Derecha               ¡¡¡ Intenta solucionarlo !!!

Respecto a parar el motor de d.c. un tiempo, pero que se sigan mandando pulsos al Servo durante ese tiempo, tendrás que hacer la temporización por interrupción de algún TMR. Primero detectas si ha habido un cambio en esos dos bits, si lo ha habido cargas el TMR para un determinado tiempo. Para conseguir que este tiempo, sea más grande tendrás que aumentar el valor de una variable cada vez que se entre en la interrupción. Cuando esa variable llegue a un valor determinado (dependiendo de cuanta temporización desees) activarás al set_pwm1_duty(dutycalculado);

Previamente cuando hayas detectado un cambio en esos dos bits el set_pwm1_duty(dutycalculado); tendrá que estar desactivado con lo cual el motor de d.c. cuando se realice la temporización estará parado.

Los 4, set_pwm1_duty(dutycalculado); que utilizas en el programa los puedes borrar y usar un único set_pwm1_duty(dutycalculado); que lo pondrás antes del swich(input(pin_a4)). Este set_pwm1_duty(dutycalculado); estará condicionado por la temporización.

Si no quieres complicarte tanto, porqué no pones un pin más de PARO. Lo paras cambias lo que te dé la gana: velocidad o orientación y de nuevo lo pones en marcha.

Un saludo.

PD. Lo de la velocidad veo que ya lo has solucionado, conforme lo has pensado todos los números que pasen del 10 paran al motor d.c.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 13 de Abril de 2005, 08:26:00
Gracias maestro!
Respecto a que vaya atras izquierda y atras derecha, no quiero que vaya asi de momento. Atras- recto por ahora. Ya mirare esto de la interrupcion o alguna otra forma de mandar pulsos al servo previo paro del motor durante unos 2 0 3 segundos (para que de algun modo el servo se posicione correctamente con el motor desconectado). Bueno ya comento algo.

De nuevo mil gracias

Un saludo desde Valencia.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 21 de Abril de 2005, 08:55:00
Ey que tal? Bueno aqui el codigo el cual ha sido probado fisicamente con osciloscopio y funciona "a medias". Digo a medias xq el pic me hace todo correctamente. Al final configure tmr1 para que salte a interrupcion cada 20ms (por eso de los pulsos del servo) y en la rutina de interrupcion le digo ya el tiempo que debe estar a on el pulso (duty). Funciona to muy bien la única pega es que para los pulsos del servo necesito meter en el delay un numero en microsegundos y no me lo coge, en el osciloscopio sale nada un pulso de apenas microseg cuando si realmente le estoy diciendo que me meta un delay de 1200 us  no me lo hace.

Lo gracioso es que en el delay cuando en vez de poner us lo pongo en ms y pongo varios anchos de pulso (1 2 3....)ms me lo hace perfecto.

He probado mil cosas, meterle un float y meterselo en milisegundos y nada el rollo parece darselo en milis pero no veo la forma de que funcione y no se muy bien xq no funciona la verdad.

Te agradeceria si le podias echar un vistazo y si hay alguna restriccion en la funcion delay u otra forma de poder darle ese retardo (1200us, 600us etc). Si lo pongo en ms como float no me funciona, y debo ponerlo como float xq quiero pulsos de 1.2 0.6 etc. Si lo pongo en microsegundos como 1200... no me funciona.

¿Alguien sabe porque?????



#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

//int y,x, retardo;//

void main() {
int pe, dutycalculado, xx;
set_tris_a(0x00);  // Puerto A como salida
set_tris_b(0xFF);    // Puerto B entrada
set_tris_c(0x00);  
output_a(0x00);    // Todos los pines de PORTA en 0
output_b(0x00);    // Idem con PORTB
output_c(0x00);

setup_timer_2(T2_DIV_BY_16,249,1) ; // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1 (CCP_PWM);               //Configuracion PWM
enable_interrupts(GLOBAL);     // Activamos interrupciones globales
enable_interrupts(INT_TIMER1); // ... y la interrupcion por TMR1
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);  //Configuracion TMR1 y preescaler

set_timer1(45536);   // Cada 20 ms salto a interrupcion  65536-(temporizacion*Fosc/4*preescaler)            

   while(1) {

set_pwm1_duty(0);
delay_ms(3000);

pe=0b11110000 & port_b;


while ((pe)==((0b11110000)&(port_b)))  //mientras no cambio en posicion del servo...
{



xx= 0b00001111 & port_b; //velocidad (1=10%, 2=20%......10=100%)


if(xx>10) //
{
xx=0;
set_pwm1_duty(0); //Si es mayor a 10 duty=0
}
else
{
dutycalculado= 25 * xx ; // Valor a cargar en duty
set_pwm1_duty(dutycalculado);
}

switch(input(pin_c6))
{
case 0: //motor alante

output_high(pin_c7);

break;

case 1: // motor atras

output_low(pin_c7);

break;
}
}                      
   
   }
             

}

#INT_TIMER1                  
void interrupcion()
{
long retardo;
int y, x;
set_timer1(45536);
x=port_b;

y=0b11110000 & x;

switch(y){
case 0:          // 0000 servo recto

// retardo=1200;  //recto
 retardo=1;
break;
case 16:
//retardo=1466;
 retardo=2;   //giro derecha abierto 0001
break;

case 48:
//retardo=1800;
 retardo=3;   //giro derecha cerado  0011
break;
case 64:
//retardo=933;
 retardo=4;  // giro izquierda abierto 0100
break;

case 192:
//retardo=600;
 retardo=5;    // giro izquierda cerrado  1100
break;


}

output_high(pin_c0);
delay_ms(retardo);
output_low(pin_c0);                        

}



Muchas gracias y espero que me hayas entendido.

Gracias maestro!!
Un saludo.
Título: RE: Robots cooperativos
Publicado por: pocher en 22 de Abril de 2005, 00:00:00
Sí, lo de porqué no te funciona está claro. La función delay_ms o delay_us si lo que hay dentro del paréntesis es una variable solo admite valores enteros entre 0 y 255, sin embargo si es una constante puedes meterle hasta 65535.

Puedes hacer al final de todo: if (retardo==5); delay_us(600) etc

Un saludo
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 25 de Abril de 2005, 16:49:00
buenas de nuevo. Montando fisicamente el cacharrito se ve que a la hora de meterle los pulsos al servo es bastante inestable.

He leido por ahi una respuesta tuya pocher sobre crear una base de tiempo mas pequeña que mis 20ms necesarios y con dos contadores poder hacer qe este en alto el duty necesario y el resto de los 20ms a off. Quisiera probar eso pero estoy dandole vueltas y no se. en proteus por lo menos no me funciona.

Alguna idea o algo xq la verdad toy ya desesperao. Muchas gracias de nuevo xavalote, me estas ayudando mucho y aprendiendo bastante con tus consejos

Un saludo.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 28 de Abril de 2005, 11:31:00
Bueno aca esta el programita para controlar el movimiento de un robotito. La direccion la proporciona un servo y el movimiento un motor dc (ambos controlados mediante pwm).

#include <16F876A.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

int periodo, dutty;       // Definimos variables globales

#INT_TIMER1                  //Rutina de atención a la interrupcion
void interrupcion()
   {
   set_timer1(65472);            //Recarga el timer a 100us (-36us) Base de tiempo

   periodo=periodo+1;            // cada vez que se entre incrementamso periodo

      if(periodo<dutty)             //Duracion de estado alto PWM segun posicion servo
      {
      output_high(pin_c0);
      }
      else
      {
      output_low(pin_c0);
      }
      if(periodo==200)              // Acaba el periodo
      {
      periodo=0;
      }
   }  

   void main()
   {
   int pe, xx, dutycalculado;
   set_tris_a(0x00);                            // Puerto A como salida
   set_tris_b(0xFF);                            // Puerto B entrada
   set_tris_c(0b01000000);                      // Pin C6 indica sentido del motor alante o atras
   output_a(0x00);                              // Todos los pines de PORTA en 0
   output_c(0b0000000);                         // Todos los pines de PORTC en 0
   enable_interrupts(GLOBAL);                   // Activamos interrupciones globales
   enable_interrupts(INT_TIMER1);               // ... y la interrupcion por TMR1
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);  //Configuracion TMR1 y preescaler
   setup_timer_2(T2_DIV_BY_16,249,1) ;          // Div=16 ; PR2=249 ; Postscale=1
   setup_CCP1 (CCP_PWM);                        //Configuracion PWM
   set_timer1(65472);                              // Cada 100 us salto a interrupcion  65536-(temporizacion*Fosc/4*preescaler)  (-36us)
   periodo=dutty=0;                                
 

   while(1)
   {



   pe=0b11110000 & port_b;
   switch (pe)             // Comprobacion para posicionar el servo
   {

   case 192:               // servo cerrado izquierda pulso de 600us 1100...
   dutty=6;
   break;

   case 48:                // servo cerrado derecha  pulso de 1800us  0011...
   dutty=18;
   break;

   case 240:               // servo recto pulso de 1200us  1111...
   dutty=12;
   break;

   case 16:                // servo abierto derecha  pulso de 1500us  0001...
   dutty=15;
   break;

   case 128:               // servo abierto izquierda pulso de 900us  1000...
   dutty=9;
   break;
   }

   set_pwm1_duty(0);       //Apagamos motor durante 1.5 sg para posicionar correctamente el servo
   delay_ms(1500);
             
    while ((pe)==((0b11110000)&(port_b)))      //mientras no cambios en posicion del servo (4 bits de mayor peso en port b)
    {
      xx= 0b00001111 & port_b;                   //velocidad (1=10%, 2=20%......10=100%)
      if(xx>10) //
      {
      xx=0;                                      // Si es mayor a 10 la parte baja de portb qe marca la velocidad
      set_pwm1_duty(0);                          //Paramos motor
      }
      else
      {
      dutycalculado= 25 * xx ;                   // Valor a cargar en duty segun relacion
      set_pwm1_duty(dutycalculado);
      }
      switch(input(pin_c6))
      {
      case 0: //motor alante

      output_high(pin_c7);

      break;

      case 1: // motor atras

      output_low(pin_c7);

      break;
      }
   }

 }


}
Título: RE: Robots cooperativos
Publicado por: pocher en 28 de Abril de 2005, 13:08:00
Bien, me alegra que lo hayas resuelto. Si tengo un rato lo simulo.

Un saludo
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 11 de Mayo de 2005, 05:16:00
Ey que hay de nuevo amigo?

Bueno hemos estado probando la comunicacion i2c y no nos funciona. Una duda:

La rutina esta que hay por el foro de comunicacion i2c que funciona, utiliza un servicio a interrupcion para leer el dato recibido y almacenarlo vale, pero en mi programita donde ya tengo una interrupcion para el servo (servicio cada 100us), ¿habria algun problema en meter hay esa rutina de comunicacion i2c con interrupcion o se armaria un cacao el pic, ya que me tendria que atender a las dos interrupciones y se pudiera dar el caso de conflictos? Ahi no puedo dar prioridad a interrupcion ya que cada 100 us me esta entrando ala del servo y es imprescindible que me entre alli, pero si recibo un dato mientras estoy atendiendo a la otra interrupcion......Llorica

Hay alguna otra forma de comunicacion i2c que no sea de este tipo y funcione?


Gracias, un saludo.
Título: RE: Robots cooperativos
Publicado por: aupadeportivo en 19 de Mayo de 2005, 06:38:00
Ey pocher ya ta resuelto esto del i2c y tal. Ya puse el programita alla en eficacia de pwm por software pa la gente si le interesaba y tal. Ahora pasaremos a programar el esclavo que recoja la informacion de los sensores y con varios modos de funcionamiento. Ya ire comentando cosillas segun vayan saliendo.  

Un saludo