Autor Tema: Dadle una ojeada..  (Leído 1910 veces)

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

Desconectado portololo

  • PIC10
  • *
  • Mensajes: 2
Dadle una ojeada..
« en: 26 de Agosto de 2006, 15:02:38 »

#include <p18f4550.h> /*Afegim la lliberira del nostre PIC*/

#include <pwm.h> /*Afegim les llibreries referents al modulador d'amplada d'impulsos*/

#include <timers.h> /*Afegim les llibreries dels timers*/

#include <adc.h> /*Afegim la llibreria del conversor analògic digital*/

#pragma config WDT = ON , WDTPS = 128 /*Activem el watchdog i posem el watchdog postscaler a 1:128,*/

#pragma config OSC = HS /*Seleccionem l'oscil·lador HS*/

#pragma config BOR = ON /*El Brown-out resset només per hardware, l'SBOREN està deshabilitat*/

#pragma config BORV = 2 /*Escollim 2 bits pel Brown-out*/

#pragma config VREGEN = ON /*Habilitem el regulador de voltatge de l'USB*/

#pragma config MCLRE = ON /*MCLR habilitat per tant el pin RE3 queda deshabilitat*/

#pragma config PLLDIV = 5 /*Dividim per 5 (Per un cristall de 20 MHz)*/
 
//Definim les variables globals

char direccio,velocitat,gir;

int lent=300,normal=800,rapid=1000,aturat=0,consigna,velreal_a,velreal_b;

//Funció de retard per causar el gir de 30 graus

void delay_gir30 (void)

{
   int i;

   for (i = 0; i < 100; i++)
    ;
}

//Funció de retard per causar el gir de 60 graus

void delay_gir60 (void)

{
   int i;

   for (i = 0; i < 1000; i++)
    ;
}

//Funció de retard per causar el gir de 90 graus

void delay_gir90 (void)

{
   int i;

   for (i = 0; i < 10000; i++)
    ;
}

void control_PID (void) /* Funció de control amb PID */

{
   float u_a,u_2_ant_a,e_a,e_ant_a,e_2_ant_a,u_escalat_a,u_b,u_2_ant_b,e_b,e_ant_b,e_2_ant_b,u_escalat_b; /*Declarem variables locals*/

   int K1,K2,K3,K; /*Declarem les constants del PID*/

   K1=1.4; /* Els hi donem una valors trobats empíricament*/

   K2=-2.8;

   K3=1.3;

   K=2;

   e_a=velreal_a-consigna; /*Aquest és l’error del motor 1*/

   e_b=velreal_b-consigna; /*Aquest és l’error del motor 2*/

   u_a=u_2_ant_a+K1*e_a+K2*e_ant_a+K3*e_2_ant_a; /*Duem a terme el control PID del motor 1*/

   u_escalat_a=u_a*K;

   u_b=u_2_ant_b+K1*e_b+K2*e_ant_b+K3*e_2_ant_b; /*Duem a terme el control PID*/

   u_escalat_b=u_b*K;

    SetDCPWM1(u_escalat_a);

    SetDCPWM1(u_escalat_b);

   if(u_escalat_a>1023) /*Marquem els marges del motor 1*/
        {
         u_escalat_a=1020;
        }
   if(u_escalat_a<1)
      {
          u_escalat_a=1;
        }
   if(u_escalat_b>1023) /*Marquem els marges del motor 2*/
        {
         u_escalat_b=1020;
        }
   if(u_escalat_b<1)
      {
          u_escalat_b=1;
        }
   u_2_ant_a=u_ant_a; /*Actualitzem els senyals*/

   u_ant_a=u_a;

   e_2_ant_a=e_ant_a;

   e_ant_a=e_a;
   
   u_2_ant_b=u_ant_b; /*Actualitzem els senyals*/

   u_ant_b=u_b;

   e_2_ant_b=e_ant_b;

   e_ant_b=e_b;
}

void lectura_velreals (void) /*Aquesta funció ens servirà per llegir les velocitats dels dos motors.*/

{

   int result_1,result_2,result_3,result_4; /*Declarem variables enteres*/

   // Configurem la conversió: la freqüència a la qual treballarà la conversió és la meitat de la del pic,
   // posem la justificació de la conversió a la dreta, escollim el temps d'adquisició, preparem els canals que
   // seran utilitzats que són el canal 0,1,2 i 3 i finalment deshabilitem la interrupció per final de conversió.

   OpenADC(ADC_FOSC_2&ADC_RIGHT_JUST&ADC_12_TAD&ADC_CH0&ADC_CH1&ADC_CH2&ADC_CH3&ADC_INT_OFF);

   SetChanADC(ADC_CH0);

   ConvertADC(); /*Comencem la conversió.*/

   WhileADC(BusyADC();); /*Ens esperem fins que acabi la conversió.*/

   result_1 = ReadADC();

   SetChanADC(ADC_CH1);

   ConvertADC(); /*Comencem la conversió.*/

   WhileADC(BusyADC();); /*Ens esperem fins que acabi la conversió.*/

   result_2 = ReadADC();
 
   SetChanADC(ADC_CH2);

   ConvertADC(); /*Comencem la conversió.*/

   WhileADC(BusyADC();); /*Ens esperem fins que acabi la conversió.*/

   result_3 = ReadADC();

   SetChanADC(ADC_CH3);

   ConvertADC(); /*Comencem la conversió.*/

   WhileADC(BusyADC();); /*Ens esperem fins que acabi la conversió.*/

   result_4 = ReadADC();

   velreal_a=result_1-result_2; /*Busquem el valor en borns del motor 1, o sigui, la tensió equivalent a la velocitat actual.*/

   velreal_b=result_3-result_4; /*Busquem el valor en borns del motor 2, o sigui, la tensió equivalent a la velocitat actual.*/

   CloseADC(); /*Deshabilitem el conversor un cop hem fet la conversió.*/

}

void lectura_bateria (void) /*Es preten saber el nivell de càrrega de la bateria*/

{

   int nivell_bateria;

   // Configurem la conversió: la freqüència a la qual treballarà la conversió és la meitat de la del pic,
   // posem la justificació de la conversió a la dreta, escollim el temps d'adquisició, preparem els canals que
   // seran utilitzats que són el canal 1,2 i 3 i finalment deshabilitem la interrupció per final de conversió.

   OpenADC(ADC_FOSC_2&ADC_RIGHT_JUST&ADC_12_TAD&ADC_CH5&ADC_INT_OFF);

   SetChanADC(ADC_CH5);

   ConvertADC(); /*Comencem la conversió.*/

   WhileADC(BusyADC();); /*Ens esperem fins que acabi la conversió.*/

   nivell_bateria = ReadADC();

   if (nivell_bateria<=1000)

         {

            PORTDbits.RD0 = 1; /*Si el nivell de bateria és inferior al desitjat encenem el led 3*/      

         }


}

void recepcio_dades (void) /*Aquesta funció configura el recptor inalàmbric  i llegeix el que n'hi arriba tot posant-ho en una variable.*/

{

   int recepcio[4], n; /* Declarem una estructura i una variable entera.*/

   // Configurem el mòdul receptor/transmissor en mode recepció.

   PORTDbits.RD4 = 1; /*Posem TX del Radometrix a nivell alt.*/

   PORTDbits.RD5 = 0; /*Posem RX del Radometrix a nivell alt.*/

   PORTCbits.RC6 = 0; /*Posem TXD a nivell baix car així ens ho indica el fabricant si només volem treballar com a receptor.*/
  
   //  Codifiquem el missatge de tal manera que es començarà a llegir si primer arriba una seqüència tipus 10101010. Llavors la informació
   //  arribarà en quatre bits. Els dos primers ens indiquen la velocitat de tal manera que 00 significa aturat, 01 significa lent, 10 significa
   //  normal i 11 significa ràpid. Els altre dos bits següents ens indiquen la direcció de tal manera que 00 significa endavant, 01 significa
   //  enrera, 10 significa gir a dretes i 11 significa gir a esquerres.

   if (PORTCbits.RC7 == 1;) /*Si arriba un 1 per la pota RC7 esperarem que la següent sigui un 0*/

      {

         if (PORTCbits.RC7 == 0;) /*Si arriba un 1 per la pota RC7 esperarem que la següent sigui un 0*/

            {

               if (PORTCbits.RC7 == 1;) /*Si arriba un 0 per la pota RC7 esperarem que la següent sigui un 1*/

                  {

                     if (PORTCbits.RC7 == 0;) /*Si arriba un 1 per la pota RC7 esperarem que la següent sigui un 0*/

                        {
                        
                           if (PORTCbits.RC7 == 1;) /*Si arriba un 0 per la pota RC7 esperarem que la següent sigui un 1*/
                        
                              {
                     
                                 if (PORTCbits.RC7 == 0;) /*Si arriba un 1 per la pota RC7 esperarem que la següent sigui un 0*/

                                    {

                                       if (PORTCbits.RC7 == 1;) /*Si arriba un 0 per la pota RC7 esperarem que la següent sigui un 1*/

                                          {

                                             if (PORTCbits.RC7 == 0;) /*Si arriba un 1 per la pota RC7 esperarem que la següent sigui un 0*/

                                                {

                                                   for (n=0;n<=4;n++) /*Si*/

                                                      {

                                                         recepcio[n] = PORTCbits.RC7; /*Anem col·locant dins l'estructura recepcio els 4 bits*/
                                                            

                                                      }

                                                }

                                          }

                                    }   
                        
                              }
                  

                        }

                  }

            }

      }

   //En funció del valor dels bits rebuts actuem d'una maner o altre

   if ((recepcio[0]==0)&&((recepcio[1]==0))

      {

         velocitat=0; /*Posem la variable velocitat igual a zero que significarà aturat.*/

      }

   if ((recepcio[0]==1)&&((recepcio[1]==0))

      {

         velocitat=1; /*Posem la variable velocitat igual a u que significarà lent.*/

      }   

   if ((recepcio[0]==0)&&((recepcio[1]==1))

      {

         velocitat=2; /*Posem la variable velocitat igual a dos que significarà normal.*/

      }

   if ((recepcio[0]==1)&&((recepcio[1]==1))

      {

         velocitat=3; /*Posem la variable velocitat igual a tres que significarà ràpid.*/

      }
   if ((recepcio[2]==0)&&((recepcio[3]==0))

      {

         direccio=1; /*Posem la variable direccio igual a u que significarà endavant.*/

      }
   if ((recepcio[2]==1)&&((recepcio[3]==0))

      {

         direccio=2; /*Posem la variable direcció igual a dos que significarà enrera.*/

      }
   if ((recepcio[2]==0)&&((recepcio[3]==1))

      {

         direccio=3; /*Posem la variable direcció igual a tres que significarà gir a dretes.*/

      }
   if ((recepcio[2]==1)&&((recepcio[3]==1))

      {

         direccio=4; /*Posem la variable direcció igual a qautre que significarà gir a esquerres.*/

      }

}


void main (void)
{

//Manca configurar uns interrupció perquè cada cop que ens arriba quelcom interessant via radiofreqüència anem a la funció recepció

// Configurem els ports.

TRISA = 0b00001111; /*Configurem com a entrades RA0, RA1, RA2, RA3  i la resta com a sortides.*/

TRISB = 0b00000111; /*Configurem com a entrades RB0, RB1, RB2 i la resta com a sortides.*/

TRISC = 0b10110001; /*Configurem com a entrades RC0, RC4, RC5, RC7  i la resta com a sortides.*/

TRISD = 0b00001111; /*Configurem com a entrades RD0, RD1, RD2, RD3  i la resta com a sortides.*/

// Configurem el mòdul receptor/transmissor en mode consum baix.

PORTDbits.RD4 = 1; /*Posem TX del Radometrix a nivell alt.*/

PORTDbits.RD5 = 1; /*Posem RX del Radometrix a nivell alt.*/

// Configurem el timer 2 a fi i efecte d'utilitzar el PWM.La configuració és la següent: Interrupció deshabilitada, prescaler 1:1 i postescaler 1:8.

OpenTimer2( TIMER_INT_OFF &T2_PS_1_1 &T2_POST_1_8 );

// Aquest valor determina la freqüència del PWM1 mitjançant la següent fòrmula: PWM period =[(period ) + 1] x 4 x TOSC x TMR2 prescaler
// Pot ser un valor des de 0x00 fins a 0xff.

OpenPWM1(0xff);

// Aquest valor determina la freqüència del PWM2 mitjançant la següent fòrmula: PWM period =[(period ) + 1] x 4 x TOSC x TMR2 prescaler
// Pot ser un valor des de 0x00 fins a 0xff.

OpenPWM2(0xff);

// El valor del dutycicle pot ser un nombre de 10 bits, per tant entre 0 i 1023. El duty cicle pot ser calculat mitjançant la següent
// fòrmula: PWM x Duty cycle = (DCx<9:0>) x TOSC. On DCx<9:0> són els 10 bits especificats a la funció.Aquesta funció escriu el nou valor del duty cicle del PWM1.
// Incicialment el posem a zero.

SetDCPWM1(0);

// El valor del dutycicle pot ser un nombre de 10 bits.El duty cicle pot ser calculat mitjançant la següent fòrumula: PWM x Duty cycle = (DCx<9:0>) x TOSC
// On DCx<9:0> són els 10 bits especificats a la funció.Aquesta funció escriu el nou valor del duty cicle del PWM2. Incicialment el posem a zero.

SetDCPWM2(0);

lectura_bateria(); /*Cridem la funció que ens controla l'estat de la bateria.*/

While (1) /*El programa romandrà dins d'aquest llaç fins que no apaguem l'aparell*/

   {

      // Quan "direccio" sigui igual a 1 significarà "endavant". LLavors haurem d'actuar amb la mateixa velocitat als dos motors i aquesta podrà ser
      // lenta, normal o ràpida en funció de si "velocitat" és igual a 1, a 2 o a 3.

      if (direccio==1)

            {

               // Mitjançant la combinació del led 4 i el led 5 indicarem en quin dels quatre moviments estem, en aquest cas 00 és endavant               

               PORTDbits.RD1 = 0;   

               PORTDbits.RD2 = 0;               

               // Configurerm les dues rodes girant a dretes. O sigui el robotet endavant.

               PORTDbits.RD7 = 1; /*Posem la pota RD7 a nivell alt. Posem el motor 1 gir a dretes, o sigui, endavant.*/

               PORTDbits.RD6 = 1; /*Posem la pota RD6 a nivell alt. Posem el motor 2 gir a dretes, o sigui, endavant.*/

               if(velocitat==0)
                           {
                              consigna=aturat; /* Posem la consigna a aturat*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/
         
                              control_PID(); /*Duguem a terme el control de velocitat en funció de la consigna*/
   
                           }
            
               if(velocitat==1)
                           {
                              consigna=lent; /* Posem la consigna a velocitat lenta*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/
         
                              control_PID(); /*Duguem a terme el control de velocitat en funció de la consigna*/
   
                           }

               if(velocitat==2)
                           {
                              consigna=normal; /* Posem la consigna a velocitat normal*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                              control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/
   
                           }

               if(velocitat==3)
                           {
                              consigna=rapid;   /* Posem la consigna a velocitat ràpida*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                              control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/

                           }
            }

      // Quan "direccio" sigui igual a 2 significarà "enrera". LLavors haurem d'actuar amb la mateixa velocitat als dos motors però en sentit contrari.   
        // Aquesta velocitat podrà ser lenta, normal o ràpida en funció de si "velocitat" és igual a 1, a 2 o a 3.

      if (direccio==2)

            {

               
               // Mitjançant la combinació del led 4 i el led 5 indicarem en quin dels quatre moviments estem, en aquest cas 01 és enrera               

               PORTDbits.RD1 = 0;   

               PORTDbits.RD2 = 1;               

               //Configurerm les dues rodes girant a esquerres. O sigui el robotet enrera.

               PORTDbits.RD7 = 0; /*Posem la pota RD7 a nivell baix. Posem el motor 1 gir a esquerres, o sigui, enrera.*/

               PORTDbits.RD6 = 0; /*Posem la pota RD6 a nivell baix. Posem el motor 2 gir a esquerres, o sigui, enrera.*/


               if(velocitat==0)
                           {
                              consigna=aturat; /* Posem la consigna a aturat*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/
         
                              control_PID(); /*Duguem a terme el control de velocitat en funció de la consigna*/
   
                           }

               if(velocitat==1)
                           {
                              consigna=lent;   /* Posem la consigna a velocitat lenta*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                              control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/

                           }

               if(velocitat==2)
                           {
                              consigna=normal; /* Posem la consigna a velocitat normal*/   

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                              control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/
                  
                           }

               if(velocitat==3)
                           {
                              consigna=rapid;   /* Posem la consigna a velocitat ràpida*/

                              lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/         
                           
                              control_PID();   /*Duguem a terme el controlde velocitat en funció de la consigna*/                     
   
                           }

            }

      //Quan "direccio" sigui igual a 3 significarà "gir a dretes". LLavors el motor A anirà endavant i el B enrera, però tant un com l'altre a velocitat lenta
      //durant més o menys temps en funció del que volguem girar.

      if (direccio==3)

            {

               // Mitjançant la combinació del led 4 i el led 5 indicarem en quin dels quatre moviments estem, en aquest cas 10 és gir a dretes               

               PORTDbits.RD1 = 1;   

               PORTDbits.RD2 = 0;

               //Configurerm el motor 1 a gir dretes i el motor 2 a gir a esquerres. O sigui, el robot girarà a dretes.

               PORTDbits.RD7 = 1; /*Posem la pota RD7 a nivell alt. Posem el motor 1 gir a dretes, o sigui, endavant.*/

               PORTDbits.RD6 = 0; /*Posem la pota RD6 a nivell baix. Posem el motor 2 gir a esquerres, o sigui, enrera.*/
            
   
               if(gir==1) /*Quan la variable gir sigui igual a 1 farem un gir curt de 30 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/
                     
                     control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/
                     
                     delay_gir30(); /*Durant aquest temps girarem*/                  

                  }

               if(gir==2) /*Quan la variable gir sigui igual a 2 farem un gir mig de 60 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                     control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/

                     delay_gir60(); /*Durant aquest temps girarem*/
                  
                  }

               if(gir==3) /*Quan la variable gir sigui igual a 3 farem un gir llarg de 90 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                     control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/

                     delay_gir90(); /*Durant aquest temps girarem*/

                  }
            
            }

      //Quan "direccio" sigui igual a 4 significarà "gir a esquerres". LLavors el motor A anirà enrera i el B endavant, però tant un com l'altre a velocitat lenta
      // durant més o menys temps en funció del que volguem girar.

      if (direccio==4)

            {

               // Mitjançant la combinació del led 4 i el led 5 indicarem en quin dels quatre moviments estem, en aquest cas 11 és gir a esquerres               

               PORTDbits.RD1 = 1;   

               PORTDbits.RD2 = 1;

               //Configurerm el motor 1 a gir esquerres i el motor 2 a gir a dretes. O sigui, el robot girarà a esquerres.

               PORTDbits.RD7 = 0; /*Posem la pota RD7 a nivell baix. Posem el motor 1 gir a esquerres, o sigui, enrera.*/

               PORTDbits.RD6 = 1; /*Posem la pota RD6 a nivell alt. Posem el motor 2 gir a dretes, o sigui, endavant.*/
               
               if(gir==1) /*Quan la variable gir sigui igual a 1 farem un gir curt de 30 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                     control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/
                     
                     delay_gir30();   /*Durant aquest temps girarem*/                  

                  }   

               if(gir==2) /*Quan la variable gir sigui igual a 2 farem un gir mig de 60 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                     control_PID(); /*Duguem a terme el controlde velocitat en funció de la consigna*/

                     delay_gir60(); /*Durant aquest temps girarem*/
                  
                  }

               if(gir==3) /*Quan la variable gir sigui igual a 3 farem un gir llarg de 90 graus*/

                  {
                     consigna=lent; /* Posem la consigna a velocitat lenta*/

                     lectura_velreals(); /*Llegim les velocitats reals tant d'un motor com de l'altre*/

                     control_PID(); /*Duguem a terme el control de velocitat en funció de la consigna*/

                     delay_gir90(); /*Durant aquest temps girarem*/

                  }
            }

   }

CloseTimer2();  //Desactivem el timer 2 un cop ja ha fet el servei



}


Desconectado portololo

  • PIC10
  • *
  • Mensajes: 2
Re: Dadle una ojeada..
« Respuesta #1 en: 26 de Agosto de 2006, 15:03:28 »
Estoy haciendo un proyecto y he hecho un programa en C para un pic 18f4550. Sería de mi agrado que le echarais una ojeada para decirme que errores puede haber pues no lo voy a poder hacer rular. Las especificaciones sob las siguientes:

-Mediante un L298 voy a actuar sobre unos motores de 6 voltios. Dándole un valor eficaz de 0 a 6 v actuando con los PWM sobre las entradas enable y escojiendo la direccion con las entradas input, pero solo podre escojer entre adelante y atrás pues pondré la misma entrada invertida a IN1 y IN2 y los mismo para IN3 y IN4.

-Luego leeré la fuerza contraelectromotriz del los bornes de los motores a través de un divisor de tension para llevar a cabo un control PID.

-Mediante un receptor/emisor radiometrix voy a recibir un código de 12 bits, los 8 primeros son un identificador y los siguientes quatro la información y sinceramen te no se si este método será efectivo, bien si alguien quiere proponer una solucion.

-Además me gustaria saber libreria he de incluir para luego poder cambiar algunas variables mediante USB.

Bien me parece que lo importante ya está comentado, si veis que falta algo, o que algo está mal planteado decidmelo por favor. Por cierto, si algo no se entiende mucho, hay comentarios, estan en catalán pero se entiende perfectamente.

Si hay alguna duda para poder entender bien el programa preguntadmenlo.
« Última modificación: 27 de Agosto de 2006, 22:22:15 por portololo »