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

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

Desconectado JLIGUAL

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 226
    • Habilitacion Naval
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #60 en: 22 de Marzo de 2008, 17:20:24 »
Me descubro ante Vds Sres. progamadores, me teneis alucinado, con que facilidad preparais una aplicacion para gestionar algo que ni siquiera teneis claro de lo que va a hacer, solo con saber lo que quiere uno y pensar en como utilizar cada herramienta para lograr el funcionamiento perfecto.

Este proyecto empezo por una pequeña idea de generar un "equipo" (llamemosle asi) que fuese capaz, por un precio razonable, de comunicarnos con los equipos situados en un velero  y hacer que estos nos hagan generar rios de adrenalina como si en realidad nos encontrasemos a la caña del timon de ese Cheminee Poujoulant en su victoria de la regata Velux five oceansel pasado mes de marzo de 2.007
http://www.bernardstamm.com/

O bien Jean Pierre Dick en su llegada de la Barcelona Wordl race, el presente año
http://www.jpdick.com/p-jpdickcompubfr/display.aspx?srv=p-jpdickcom&typ=pub&lang=fr&cmd=view&style=styles/home.xsl

Espero que al terminar la parada de mantenimiento mecanico, que por fin terminamos el Lunes, pueda dedicar mas horas a la parte de la cubierta y de esa manera poder iniciar el manejo de los diferentes enrolladores, velas, y resto de equipos.

Con respecto al servo que venia de Hong Kong, se supone que debe de venir en un tren de renfe, porque ya lleva una semana de retraso, muy malas fechas, pero si da la potencia anunciada, ya esta hecha la eleccion del 75 % de la gestion de los controles, ya que con 13 kgs, esta capacitado para casi todas las funciones.

Un saludo

Juan Luis Igual


Desconectado gu1llermo

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 217
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #61 en: 25 de Marzo de 2008, 21:35:06 »
Hola JLIGUAL yo creo que todo esto empezó por tu iniciativa del barco vela, que entusiasmó a muchos (me incluyo) es un buen proyecto en donde toda la comunidad seremos beneficiados.

Con respecto a lo de la programación de eso no te preocupes que aquí hay un nivel elevado de programadores y lo que se necesite se hace  8) :wink: para mi programar es como jugar  :mrgreen: y creo que para varios también.

Por otro lado quería agregar unas observaciones, como todos sabemos los temblores de los servos se deben a que la señal de pwm que le aplicamos no cumple exactamente los 2,5ms, sino que a veces un poco más ó un poco menos y esto es debido a las instrucciones en alto nivel del c que no podemos observar esas pequeñas diferencias con respecto a cuánto se llevan a cabo estas, en el pic18 hay instrucciones que pueden llevar 2 ó 3 ciclos del procesador y esto reflejado en las interrupciones se presenta el caso de que cuando se entra en ellas, se puede entrar con 1, 2 ó 0 ciclos de más, esto es lo e podido observar haciendo simulaciones en el mplab, voy a intentar ser un poco más gráfico con un ejemplo, vamos a utilizar la interrupción del timer1 para el mismo:

Supongamos que ajustamos un valor del timer1 tal que queremos lograr una interrupción a los 1ms exactos, una vez que entramos en la interrupción hacemos cero el contador del STOPWATCH en el mplab y observamos el tiempo que se tarda en llegar nuevamente en llegar a la misma, si hacemos esto podemos observar que a veces entra a los 1ms+1ciclo_de_instrucción, otras veces 1ms+2ciclos_de_instrucción y en otras 1ms+0ciclo_de_instrucción, esto hace que el ciclo útil del servo se alargue o se acorte, traducido en temblores para los servos.

Sumado a esto en la rutina de interrupción hay instrucciones condicionales, en donde el número de ciclos de instrucción que se ejecutan si es cierta la condición no es el mismo número de ciclos que si la condición es falsa, por lo tanto crea algo que yo llamo "desequilibrio" que traducido en el servo es tembladera.
Y como son varias instrucciones, esto hace que el desequilibrio sea más grande por lo tanto más visible en los servos.

Todo esto lo e solucionado en el código que e expuesto aquí, para todo aquel que le interese lo pueda observar.

Nota curiosa:
...
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:...

Leyendo los comentarios anteriores me encontré con éste tuyo AKENAFAB y ya tenías la idea desde un principio, exactamente así funciona el código.  :mrgreen: así que no estás zombie sino que tenías una buena  :idea: :wink:

Saludos.
« Última modificación: 25 de Marzo de 2008, 21:42:51 por gu1llermo »

Desconectado INGJHOM

  • PIC10
  • *
  • Mensajes: 5
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #62 en: 08 de Mayo de 2008, 13:40:43 »
he estado estudiando tu programa, pero hay algo que no puedo todavia entender cual es la parte en el programa donde colocas el flag_phase en 1. 

Desconectado DESKREP

  • PIC10
  • *
  • Mensajes: 1
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #63 en: 15 de Mayo de 2008, 03:33:35 »
MUY INGENIOSO TU METODO , DE DIVIDIR EN VENTANAS PARA CONTROLAR EN ACADA UNO DE ELLSO INDEPENDIENTEMENTE CADA SERVO.
SOLO COMENTARTE QUE SI HE PODIDO CONTROLAR HASTA 6 SERVOS TODOS AL MISMO TIEMPO(EN LA MISMA VENTANA PODRIA DECIRSE). SIN PROBLEMA ALGUNO... TALVES OMITISTE ALGUN PEQUEÑO DETALLE EN EL PROGRAMA CUANDO LO PROBASTE.

NUEVAMENTE REITERO MUY INGENIOSA LA FORMA DE CONTROLAR TUS 8 SERVOS... LA PONDRE A PRUEBA A VER QUE TAL LOS RESULTADOS

Desconectado Deirdre

  • PIC10
  • *
  • Mensajes: 10
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #64 en: 20 de Junio de 2008, 08:47:58 »
Hola! he estado siguiendo el hilo...bueno, intentándolo, y la verdad que es un poco lío. Yo estoy intentando controlar 8 servos, pero no todos a la vez, si no que cuando pulse una tecla se mueva uno y cuando pulse otra otro, etc. He probado el rpogarma de redpic, pero he tenido que hacer alguna modificación, además no lo entiendo muy bien, porque yo uso el 16F876A, pero funcionaba bien. Me gustaría saber como podría modificarlo para que no sean todos a la vez, si no controlar uno por uno. Pobré otro programa publicado en otro hilo, pero no se porque, puede ser por lo que decían de los tiempos del puerto serie, al mover uno se movían los demás. Agradezco toda la ayuda que me podáis prestar, estoy un poco agbiada. Gracias

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #65 en: 20 de Junio de 2008, 13:56:08 »
Saludos Deirdre!
Con el método del maestro redpic controlas todos los servos a la vez...
Claro que no quiere decir que tengas que moverlos todos al mismo tiempo...
Pero recuerda que en los servos, para garantizar que se mantenga en la misma posición, debes enviarle la señal de forma continua, de otra forma perdería fuerza y podría perder fácilmente la posición deseada.
Estoy seguro de que puedes modificar el programa para ajustarlo a tus requerimientos.
Cuídate, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Deirdre

  • PIC10
  • *
  • Mensajes: 10
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #66 en: 21 de Junio de 2008, 13:43:02 »
Hola!muchas gracias por responder :-/ Voy a ver si consigo leermelo otra vez (y ya van unas cuantas) y entenderlo bien,y así a ver si puedo modificarlo. Cierto es que hasta ahora he tenido muchos porblemas por el tema de tener que mandar la señal de forma constante, ya que al implementar la interrupción por teclado, cuando  pulsaba una tecla se me esajustaba todo. A ver que puedo hacer!!!!!

Desconectado Deirdre

  • PIC10
  • *
  • Mensajes: 10
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #67 en: 30 de Junio de 2008, 08:25:48 »
Ya está, aunque parezca mentira, solo con poner 65534 en lugar de 65535 todo funciona perfectamente. Supongo que será cosa de que el reloj no hace exacyamente 20ms. Gracias por todo!!!! :-/

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #68 en: 30 de Junio de 2008, 10:45:55 »
Felicitaciones Deidre! Me alegro que lo hayas logrado.
Saludos, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado INGJHOM

  • PIC10
  • *
  • Mensajes: 5
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #69 en: 02 de Septiembre de 2008, 18:35:27 »
He estado utilizando el codigo de control de ocho servos, para volverlo dinamico es decir que no sea solo la posición central y de extremo a extremo, sino que se pueda mover a cualquier grado, lo simulo pero no funciona muy bien que digamos.

que podria ser??

dejo adjunto el programa.

con la variable ticknumber le proporciono el valor de las ticks correspondiente al servo..

gracias

Desconectado raulsmat

  • PIC10
  • *
  • Mensajes: 11
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #70 en: 03 de Junio de 2009, 11:28:26 »
Hola, vengo rebotado de este hilo por Veguepic

http://www.todopic.com.ar/foros/index.php?topic=26265.0

en el que cuento que intento susbstituir el procesador de una emisora de 4ch por un Pic para poder añadir un menu y poder
hacer mezclas de servos (delta, H3...etc). Tengo el tema medio solucionado excepto porque no se cual es el tipo de trama que envia el procesador al modulo RF para comunicarse con el receptor, quizas tu lo conozcas.

  Gracias.

Desconectado ivrj

  • PIC10
  • *
  • Mensajes: 2
Re: Algoritmo para controlar 16 servos (en C) pic18f4550
« Respuesta #71 en: 09 de Junio de 2009, 11:50:32 »
Bueno aquí está el código para controlar 16 servos con el pic18f4550, le podemos enviar comandos tanto vía serial RS232 como vía USB, la trama es (SERVO,POSICIÓN), SERVO=[0..15] y POSICIÓN=[5..25], donde 5=extremo izquierdo y 25=extremo derecho.

Código: [Seleccionar]
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN,NOBROWNOUT
#use delay(clock=48000000)//48MHz

#USE RS232 (baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)

//#build(reset=0x000800,interrupt=0x000808:0x000818)
// Necesario para indicarle al compilador a partir de donde alojar mi programa
// Si se quiere usar bootloader se pueden habilitar estás dos líneas
//#ORG 0x000, 0x07FF {} // Espacio reservado para alojar el bootloader

#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84

/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines.  For dynamic configuration of the CCS Library
// for your application several defines need to be made.  See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE     FALSE             //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    2                 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    2                 //size to allocate for the rx endpoint 1 buffer

/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here.  If you are
// not using connection sense, comment out this line.  Without connection
// sense you will not know if the device gets disconnected.
//       (connection sense should look like this:
//                             100k
//            VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
//                     |
//                     +----/\/\/\/\/\-----GND
//                             100k
//        (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2  //CCS 18F4550 development kit has optional conection sense pin

/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#include <pic18_usb.h>     //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h>        //Configuración del USB y los descriptores para este dispositivo
#include <usb.c>           //handles usb setup tokens and get descriptor reports

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

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

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

#define i_usb     recibe[0]// es el índice que se recibe vía usb
#define pos_usb   recibe[1]// es la posición que se recibe vía usb

#define n 16// número de servos
            //para otro número de servos hay que hacer mediciones de tiempo

#define max_theCount 200// 200*100us=20ms
#define derecha  25// 25*100us=2,5ms
#define centro   15// 15*100us=1,5ms
#define izquierda 5// 5*100us =0,5ms

#define val_timer0 127

int8    theCount=1;
int8    duty[n];

#INT_TIMER0
void isr_timer0(){
   delay_cycles(5);
   if (duty[0] >= theCount)// Cada 100us llega aqui de forma cíclica
      {
         servo_00=1;
      }
      else
      {
         servo_00=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[1] >= theCount)
      {
         servo_01=1;
      }
      else
      {
         servo_01=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[2] >= theCount)
      {
         servo_02=1;
      }
      else
      {
         servo_02=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[3] >= theCount)
      {
         servo_03=1;
      }
      else
      {
         servo_03=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[4] >= theCount)
      {
         servo_04=1;
      }
      else
      {
         servo_04=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[5] >= theCount)
      {
         servo_05=1;
      }
      else
      {
         servo_05=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[6] >= theCount)
      {
         servo_06=1;
      }
      else
      {
         servo_06=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[7] >= theCount)
      {
         servo_07=1;
      }
      else
      {
         servo_07=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[8] >= theCount)
      {
         servo_08=1;
      }
      else
      {
         servo_08=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[9] >= theCount)
      {
         servo_09=1;
      }
      else
      {
         servo_09=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[10] >= theCount)
      {
         servo_10=1;
      }
      else
      {
         servo_10=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[11] >= theCount)
      {
         servo_11=1;
      }
      else
      {
         servo_11=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[12] >= theCount)
      {
         servo_12=1;
      }
      else
      {
         servo_12=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[13] >= theCount)
      {
         servo_13=1;
      }
      else
      {
         servo_13=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[14] >= theCount)
      {
         servo_14=1;
      }
      else
      {
         servo_14=0;
         #asm
            nop
         #endasm
      }
     
      if (duty[15] >= theCount)
      {
         servo_15=1;
      }
      else
      {
         servo_15=0;
         #asm
            nop
         #endasm
      }
     
      theCount=theCount+1;
      if (theCount>max_theCount)
      {
         theCount=1;
      }
      else
      {
         delay_us(1);
         #asm
            nop
         #endasm
      }
      set_timer0(val_timer0);
}

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

void main()
{
    int     k;
    int8    i=0;// es el índice exclusivo de duty[] en la recepción serial
    int1    band=0;
    int8    recibe[2];// Buffer de recepción vía usb                 
  //int8    envia[2];// Habilitar en caso de necesitar
   
    set_tris_b(0x00);
    set_tris_c(0b10000000);
    set_tris_d(0x00);
   
    PORTB=0x00;
    PORTD=0x00;
   
    port_b_pullups(FALSE);
   
    for(k=0;k<=(n-1);k++)
      duty[k]=centro;//

    setup_adc_ports(NO_ANALOGS);
    setup_adc(ADC_OFF);

    setup_timer_0(RTCC_DIV_8 | RTCC_8_BIT);

    set_timer0(val_timer0);
   
    enable_interrupts(INT_TIMER0);
    enable_interrupts(GLOBAL);
   
    usb_init();//inicializamos el USB

    usb_task();//habilita periférico usb e interrupciones
    usb_wait_for_enumeration();//esperamos hasta que el PicUSB sea configurado por el host

   while (TRUE)
   {
      if(usb_enumerated())//si el PicUSB está configurado
         //if (TRUE)
      {
// Recepción de datos via rs232
         if (kbhit()){
            if (band==0){
               i=getc();
               band=1;
            }
            else{
               duty[i]=getc();
               band=0;   
            }
         }
// Recepción vía USB         
         if (usb_kbhit(1))//El endpoint de salida contiene datos del host (EP1)?
         {
            usb_get_packet(1, recibe, 2);// Recibimos los 2 bytes: (servo,pos)
            duty[i_usb]=pos_usb;
         }
      }
   }
}

Adjunto archivos de simulación en Proteus, Driver y Aplicación.

Adicionalmente realicé una sencilla interfaz (Gracias a J1M) para controlar los servos vía usb, aquí una imagen funcionando:



Hola Guillermo

Felicitaciones!!!   lo trato de probar ahora :-/
... esta muy padre
...

Gracias nuevamente  :lol: en verdad es muy agradable cuando reconocen nuestro trabajo y no cualquier trabajo sino el que se hace con esfuerzo, empeño y por supuesto con cariño también, así como muchos foristas que todavía no me sé todos los nombres porque soy relativamente nuevo en el mismo pero si me pidieran nombres estos son los que me suenan (no hay ningún orden en específico): Palitroquez, Nocturno, RedPic, Maunix, J1M, JLIGUAL, MGLSOFT, PICmouse, Modulay, entre otros destacados y a todos los foristas en general porque cada día hacemos que éste foro sea el mejor foro en internet en cuanto a pic y un poco más ;-), saludos a todos, pero absolutamente a todos y gracias!, muchas gracias!!!

Que la pasen bien.

olá!
Su proyecto es perfecto! Es exactamente lo que necesito para utilizar en mi proyecto.
Me gustaría saber cómo lo hizo para calcular el timer0?
Cuanto más leo material sobre el cálculo del timer0, tengo más e más  preguntas.
En mi caso, voy a utilizar sólo el 8 servos. Me di cuenta de que el duty  ha cambiado cuando se utiliza sólo el 8 servos.
Si he entendido bien, se utiliza un TIMER por debajo de la ideal  e incluye la instruccion nop para compensar el intervalo?
gracias.

Desconectado INGJHOM

  • PIC10
  • *
  • Mensajes: 5
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #72 en: 13 de Agosto de 2009, 22:07:55 »
Cuando empece a programar en C, Quise aplicarlo en un proyecto de robotica.. asi que diseñe un brazo robotico con servomotores Hitec. Para esto necesitaba manejar almenos 6 servos. Entonces fue hay cuando me di cuenta del codigo para el manejo de 8 servos... La verdad este foro me ayudo mucho en el objetivo planteado y puedo contarles que lo logre.

Mi proyecto fue llevado a cabo inclusive construi el brazo y los PCB. El brazo se puede controlar a través de un teclado 4X4 y una lCD 20X4 o tambien a través de un PC por medio de la interfaz Rs232.

Muchas gracias compañeros del foro, no solo a los de este sino a los de todos los foros.. ps el conocimiento es libre y asi debe de seguir siendo.

Me despido pero no sin antes decirles que adjunto al mensaje les dejo los programas de los PICs.. Hay librerias que les pueden servir y son muy faciles de implementar.

Cualquier comentario.. no duden en hacermelo llegar..

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5552
    • Picmania by Redraven
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #73 en: 14 de Agosto de 2009, 05:20:32 »
Me alegro de que hayas llevado a buen puerto tu proyecto. Y muchas gracias por tu aporte.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado INGJHOM

  • PIC10
  • *
  • Mensajes: 5
Re: Algoritmo para controlar hasta 8 servos con una sola interrupción (en C)
« Respuesta #74 en: 14 de Agosto de 2009, 11:39:16 »
De nada redpic, ahora me gustaria saber como implementar el bootloader en los PICs y asi no estar desarmando y armando el circuito nuevamente, con el fin de agregarle a los PICs nuevas funcionalidades en el software..

Me gustaria saber cuales son las lineas de codigo. Se que talves este no sea el foro sobre ese tema. Pero de todas maneras me gustaria saber y asi mejorar aún más el proyecto..

En el archivo que adjunte en el anterior mensaje se encuentra la simulación en proteus. Esta simulación posee dos paginas, si lo tratan de simular en la primera les arroja un error, deben correr la simulación desde la segunda hoja..

Exitos con las pruebas.


 

anything