Autor Tema: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)  (Leído 89565 veces)

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

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #30 en: 09 de Febrero de 2008, 07:28:25 »
Hola a tod@s

Creo que se puede simplificar un poco el codigo utilizando bit_set() y bit_clear, en vez de output_high() y output_low() para poner el servo en alto y en bajo respectivamente, siempre que se disponga de un puerto completo para ello.

Ademas si el micro lo permite, creo que es mejor utilizar #int_CCPx para controlar el tiempo que esta en alto el servo, ya que hace que no sea tan critica la velocidad del micro y se pueden uilizar micros mas lentos.

Un ejemplo de como yo lo hago habitualmente:

Código: [Seleccionar]

////////////////////////////////////////////////////////////////////////////////////
//
// Moviendo 8 servos con un solo timer
//
//     
// Propósito: Mover hasta 8 servos eficientemente
//
// Conectar 8 servos al PORT_B
//
////////////////////////////////////////////////////////////////////////////////////


#include <16f876.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOWRT
#use delay(clock=20000000)      //Cambiar segun el cristal utilizado

#define VAL_TIMER1 53000        // 65536-53000=12536 * 0,0002 = 2,5 milisegundos

float const uSxTick = 0.2;           // Microsegundos por Tick de TMR1 a 20 Mhz
int8 servo=0;                            // Numero de servo
int1 flag_timer1=FALSE;   


#int_timer1
void handle_timer1_int()               // Se activa cada 2,5 ms
{
    flag_timer1=TRUE;
    set_timer1(VAL_TIMER1);          // 65536-53000=12536*0,0002 = 2,5 ms
}



#int_ccp2                                   // Interrupción timer1 modo compare
void handle_ccp2_int()
{
    bit_clear(*6,servo);              // Pone en bajo el servo. Igual que output_low(PIN_Bx) pero le puedo pasar un parametro.  *6=PORTB
}




////////////////////////////////////////////////////////////////////////////////////
//
// PROGRAMA PRINCIPAL
//
////////////////////////////////////////////////////////////////////////////////////

void main()
{
    ////////////////////////////////////////// INICIALIZACIONES GENERALES
    delay_ms(333);                           // Espero a que todo se estabilice e ...
    disable_interrupts(global);              // Inicializo el Micro y ...
    disable_interrupts(int_timer1);          // deshabilitando todo lo no necesario ...
    disable_interrupts(int_rda);
    disable_interrupts(int_ext);
    setup_adc_ports(NO_ANALOGS);
    setup_adc(ADC_OFF);
    setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
    setup_timer_2(T2_DISABLED,0,1);

    setup_ccp2(CCP_COMPARE_INT);            // Configura CCP2 en modo COMPARE
    set_timer1(VAL_TIMER1);                      // 65536-53000=12536*0,0002 = 2,5 ms


    // Habilito las interrupciones necesarias
    enable_interrupts(int_timer1);          //Int timer 1
    enable_interrupts(int_ccp2);             // Habilito la interrpción INT_CCP2
    enable_interrupts(global);              //Habilita interrupciones

    do
    {
        if(flag_timer1==TRUE)              // Cuando se activa la int_timer1 -> cada 2,5 ms   
        {
            servo++;                            //Controla secuencialmente cada servo
            if (servo>=9) servo=1;       
   
            bit_set(*6,servo);              // Pongo en alto el servo.  Igual que output_high(PIN_Bx) pero le puedo pasar un parametro.  *6=PORTB
   
           
            CCP_2 = VAL_TIMER + pos_servo(servo);         // Cargo CCP con el tiempo que tiene que estar en alto el servo
                                                                  // La funcion pos_servo() debe devolver la posicion del servo en microsegundos

            flag_timer1=FALSE;       
        }

    }
    while (TRUE);
}


Saludos a tod@s

Desconectado AKENAFAB

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3227
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #31 en: 09 de Febrero de 2008, 08:38:18 »
HOla Redpic !

y HOla todos!!  :mrgreen:


Hace tiempo que realice mi controladora de servos , controlo de igual manera 8 servos , atendiendo cada servo de forma individual y de 8 pues sabemos qu eno da mas por el periodo.

Por falta de tiempo no he podido depurar el programa y realizar otro soft para poder manejar "X" servos.

Bueno aqui la idea:

Utilizar el método de la burbuja(consiste en ordenar n numeros de forma consecutiva, sea 1-2-3-15 'o 20-19-3-2-1),


ordenar el ciclo activo del servo de menor a mayor.
cargar el timer con el ciclo activo menor
esperar interrupción y verificar si 1 ó mas registros de posición de los servos son iguales y poner la señal de esos mismos a estado bajo.
tomar el siguiente valor y restarle el que termino.
repetir pasos.

No he programado nada espero tener un rato libre.

habría que checar también que tanto demora ese método en acomodar los datos y pues abríamos si es factible con nuestra controladora o esta muy fumado.

Hasta luego

Que estén bien!!

Atentamente
  Akenafab

Agregando

En teoria  :D , bueno bueno en mi mente soñadora  :D ... tenemos 2.5 ms por maximo que estarian trabajando los servos y 17.5 ms libres para realizar todas las operaciones necesarias.

Estoy zombie    :shock:...
« Última modificación: 09 de Febrero de 2008, 08:41:17 por AKENAFAB »

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #32 en: 09 de Febrero de 2008, 08:48:00 »
Muy interesante tu análisis, Akenafab, habrá que estudiarlo con mas detalle.

Lo único que se me ocurre, así sin pensar demasiado, es la situación en la que todos o casi todos los servos estén en valores muy próximos, sin ser iguales, y se requiera mucho proceso para ordenar dichos valores y haya muy poco tiempo para hacerlo, precisamente porque los servos estás como agrupados.

Pero la idea como te digo es muy interesante.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #33 en: 09 de Febrero de 2008, 08:52:12 »

Creo que se puede simplificar un poco el codigo utilizando bit_set() y bit_clear, en vez de output_high() y output_low() para poner el servo en alto y en bajo respectivamente, siempre que se disponga de un puerto completo para ello.



Si, Juanelete, esa fué mi primera intención. Y como tú dices "siempre que se disponga de un puerto completo para ello", incluso llegué a sacar mi RRBOARD2 en la que tengo puertos completos disponibles.

Pero me dije, y la verdad es que la realidad me dió después la razón, que lo normal es tener pines dispersos disponibles y que cualquier solución debía pasar por poder usar cualquier combinación de pines disponibles.

Otra cosa sería tener una variable de 8 bits con los estados de cada servo y en vez de moverla a un puerto invocar una función que mueva bit a bit a los pines que correspondan, pero para eso preferí el mucho mas simple output_high y output_low.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #34 en: 12 de Marzo de 2008, 20:38:35 »
Bueno, pues resulta que el amigo Juan Luis Igual, el del    
Proyecto Barco a Vela RC con PIC
, me ha mandado un pila de servos para pruebas, que junto a mi propia pila de servos hacen una pila al cuadrado de servos. Y la ocasión hay que aprovecharla.  :mrgreen:

Así que me he tirado a diseñar una PCB para 16 Servos y a ver qué resulta de ello, veremos si soy capaz de abrir un hilo titulado  Algoritmo para controlar hasta 16 servos con una sola interrupción en C (o dos si son pequeñas)

El caso es que el diseño está listo, voy a ver cómo fabrico la PCB que para mi es lo peor de todo este invento.

Está montado alrededor de un 18F4550 con conexión USB y/o TTL Serie. Para los servos he destinado los puertos B y D completos, y he puesto otros de A y del C para poder recibir info de sensores y cosas así.









Paciencia si las imágenes tardan en cargar, el servidor casero tiene estas cosas.
« Última modificación: 12 de Marzo de 2008, 20:53:20 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #35 en: 13 de Marzo de 2008, 02:07:00 »
Si me permites un consejo, Don Diego, coloca los componentes SMD en la cara bottom, y te ahorrarás un huevo de vías.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #36 en: 13 de Marzo de 2008, 06:06:19 »
Si me permites un consejo, Don Diego, coloca los componentes SMD en la cara bottom, y te ahorrarás un huevo de vías.

 :shock: :shock: :shock: :shock: :shock:

Nunca "me se" hubiera "oscurrido"

Lo haré. Gracias Maestro.  :mrgreen:

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #37 en: 13 de Marzo de 2008, 20:17:07 »
Cuando digo que no se qué sería de mí sin ustedes es cierto hasta límites insospechados. En este caso, otro más, el consejo del Maestro de Maestros Don Manuel Nocturno ha dado sus frutos de forma espectacular.  :mrgreen:

He movido todos los componentes SMD de la cara Top a la Bottom y he ruteado (a mano) de nuevo. El resultado aquí lo tenéis, con sólo seis puentes, o sea 12 vías, he conseguido rehacer la PCB con docenas de conexiones del PIC publicadas.

Si no lo veo, y lo hago, no lo creo. Dejo tal como está el diseño anterior, no lo sobre-escribo para que sean visibles y comparables los dos resultados.







Si, estoy seguro de que este consejo merece unos cuantos de estos ...  :-/ :-/ :-/
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania


Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #39 en: 13 de Marzo de 2008, 20:20:55 »
Es más ... veo que moviendo un poco hacia arriba las dos vías que tienen pistas por la cara Top con esquinas, para dejar dichas pistas totalmente rectas, podría solo insolar la cara Botton y por la Top poner simples puentes, con un hilo. Y asi poderla hacer a simple cara.  :shock: :shock: :shock:

La ostia.  :D :D :D
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #40 en: 14 de Marzo de 2008, 03:56:36 »
..
Una dudilla y aviso que la hago desde el más profundo de los desconocimientos en el tema. Sería posible generar las señales para controlar los servos de la misma forma en que se controlan los leds RGB por software? ...

Yo creo que si se puede, pero necesito un poco de ayuda para ver si entre todos lo podemos resolver, hice un programa para manejar 16 servos, claro lo tengo pensado para manejar cuántas I/O de nuestro pic sea posible, no sé si es por la hora y estoy imaginándome cosas no sé, pero creo que con un poco de deteniemiento y análisis lo podemos lograr sino es que lo han hecho antes, a continuación voy a colocar el programa con el que pienso controlar los servos mediante PWM usando el principio de los RGB por software, no sin antes hacer mención al código en el que me basé para hacer esto, lo pueden leer aqui

Código: [Seleccionar]
#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,PUT
#use delay (clock=20000000)
#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)

#byte RCSTA=             0x018
#bit  CREN=              RCSTA.4      // Se activa para recepción continua
#bit  OERR=              RCSTA.1      // Error de Overrun

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)

#byte PORTA      = 0x05
#byte PORTB      = 0x06
#byte PORTC      = 0x07
#byte PORTD      = 0x08
#byte PORTE      = 0x09

#bit servo_01     = PORTB.0
#bit servo_02     = PORTB.1
#bit servo_03     = PORTB.2
#bit servo_04     = PORTB.3
#bit servo_05     = PORTB.4
#bit servo_06     = PORTB.5
#bit servo_07     = PORTB.6
#bit servo_08     = PORTB.7

#bit servo_09     = PORTD.0
#bit servo_10     = PORTD.1
#bit servo_11     = PORTD.2
#bit servo_12     = PORTD.3
#bit servo_13     = PORTD.4
#bit servo_14     = PORTD.5
#bit servo_15     = PORTD.6
#bit servo_16     = PORTD.7

#define n 16// números de servos

#define multiplo 1// Podemos cambiarlo para ajustar
#define max_theCount 1000000
#define retardo 300// Son us

int8 servo[n];// Contiene los bytes bajo y alto de los servos
int8 i=0;// es el índice exclusivo de servo[] en la recepción serial

// Declaración de Funciones
void theDelay(void);

// Recepción de datos
#int_rda
void serial_isr(void){//Está listo para recibir 32 bytes
     servo[i]=getc();
     i++;
     if (i>(2*n-1)) i=0;
}

/////////////////////////////////////// PRINCIPAL /////////////////////////////////////

void main()
{
   int32    theCount = 0;
   int8     k;
   int32    duty[n];// Cargamos el ciclo útil de los servos
   
   set_tris_b(0x00);
   set_tris_c(0b10000000);
   set_tris_d(0x00);
   
   PORTB=0x00;
   PORTD=0x00;
   
   port_b_pullups(FALSE);
   enable_interrupts(int_rda);
   enable_interrupts(global);
   
   for(k=0;k<=(2*n-1);k++)
      servo[k]=200;// **VALOR INCIAL** por ejem: 200

   while (1)
   {
      theCount++;
      if (theCount>max_theCount) theCount=0;
     
      for (k=0;k<=(n-1);k++) duty[k]=(int32)((servo[2*k+1]*256+servo[2*k])*multiplo);
     
      servo_01= (duty[0] > theCount);
      servo_02= (duty[1] > theCount);
      servo_03= (duty[2] > theCount);
      servo_04= (duty[3] > theCount);
      servo_05= (duty[4] > theCount);
      servo_06= (duty[5] > theCount);
      servo_07= (duty[6] > theCount);
      servo_08= (duty[7] > theCount);
      servo_09= (duty[8] > theCount);
      servo_10= (duty[9] > theCount);
      servo_11= (duty[10] > theCount);
      servo_12= (duty[11] > theCount);
      servo_13= (duty[12] > theCount);
      servo_14= (duty[13] > theCount);
      servo_15= (duty[14] > theCount);
      servo_16= (duty[15] > theCount);

      //theDelay();
   }
}


// Rutina de retardo
void theDelay(void){
   delay_us(retardo);//
}

Estoy seguro que variando los valores de:
max_theCount
multiplo
servo[k]// Los de cada servo

y midiendo las señales en un osciloscopio quizás se pueda lograr el objetivo, yo les coloqué unos valores alli por ponerles algo, pero debe haber una forma de poder determinarlos, lo que pasa es que no sé cuánto tiempo se tarda una instrucción en C ó mejor dicho no sé cómo medirla, alguién sabe como hacer? yo estaba pensando usar el timer en un punto y luego ver su valor en otro punto enviándolo al virtual terminal, solo es una suposición porque no sé  :?

Claro todo esto es una suposición, simplemente me imagino que se podría pero no doy todavía, si alguién le gustaría echarme una mano se lo agradecería  ;-)

Saludos, Felicitaciones y gracias por todos tus aportes RedPic, te botas con tus explicaciones, es decir son demasiado buenas. :wink:
« Última modificación: 14 de Marzo de 2008, 22:23:21 por gu1llermo »

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #41 en: 14 de Marzo de 2008, 18:01:29 »
Bueno, a esto me refería. Solo la cara Bottom y seis puentes rectos por la cara Top.

Lo dicho, si no lo veo no lo creo.  :shock: :mrgreen: :D







Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7918
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #42 en: 14 de Marzo de 2008, 18:38:15 »
Debo tener algun problema, no veo las imagenes, Diego... :? :shock:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #43 en: 14 de Marzo de 2008, 18:40:36 »
Debo tener algun problema, no veo las imagenes, Diego... :? :shock:

El servidor es un PC en mi casa y cuando hay mas de dos visitantes al mismo tiempo se queda "tieso" ... o un poco de paciencia o hay que esperar a otro momento mas oportuno.  :? :? :?
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania



 

anything