Control de 8 Servos Con Pic

16
#include <16f877.h> #fuses HS,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_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 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 /////////////////////////////////////// PRINCIPAL /////////////////////////////////////

Transcript of Control de 8 Servos Con Pic

Page 1: Control de 8 Servos Con Pic

#include <16f877.h>#fuses HS,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_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 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

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

void main(){   int8    theCount=1;   int     k;   int8    duty[n];   int8    i=0;// es el índice exclusivo de duty[] en la recepción serial   int1    band=0;      set_tris_b(0x00);

Page 2: Control de 8 Servos Con Pic

   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]=izquierda;//

    setup_adc_ports(NO_ANALOGS);    setup_adc(ADC_OFF);    setup_timer_1(T1_DISABLED);    setup_timer_2(T2_DISABLED,0,1);

    disable_interrupts(global); 

   while (1)   {     delay_us(70);      #asm      nop      nop      nop      nop      #endasm// Cada 100us llega aqui de forma cíclica            if (duty[0] >= theCount)      {         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

Page 3: Control de 8 Servos Con Pic

            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

Page 4: Control de 8 Servos Con Pic

         #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

Page 5: Control de 8 Servos Con Pic

      }            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      }

// Recepción de datos// Las rutinas delays y los nop son para normalizar los tiempos      if (kbhit()){         if (band==0){           i=getc();           band=1;           delay_us(1);           #asm             nop             nop

Page 6: Control de 8 Servos Con Pic

           #endasm         }         else{           duty[i]=getc();           band=0;            }      }      else{         delay_us(3);         #asm          nop         #endasm      }   }}

La trama de envío es (Servo, Posición) dos bytes, el extremo izquierdo se logra con una posición igual a 5 y el extremo derecho con una posición igual a 25, y para el centro=15.

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.

#use delay(clock=48000000)//48MHz

Page 7: Control de 8 Servos Con Pic

#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

///////////////////////////////////////////////////////////////////////////////

Page 8: Control de 8 Servos Con Pic

// 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_TIMER0void isr_timer0(){   delay_cycles(5);   if (duty[0] >= theCount)// Cada 100us llega aqui de forma cíclica      {         servo_00=1;      }

Page 9: Control de 8 Servos Con Pic

      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

Page 10: Control de 8 Servos Con Pic

      {         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      {

Page 11: Control de 8 Servos Con Pic

         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;

Page 12: Control de 8 Servos Con Pic

         #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)

Page 13: Control de 8 Servos Con Pic

   {      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;         }      }   }}