Versão 2022

Dependencies:   PTC3471 QEI USBDevice mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "QEI.h"
00003 #include "USBSerial.h"
00004 #include "PTC3471.h"
00005 
00006 #define Ts 0.01                                                                 //periodo de amostragem
00007 #define pi 3.141592653589793
00008 
00009 /******************************************************************************/
00010 /****************  Definição de Variaveis, Objetos e Funções ******************/
00011 /******************************************************************************/
00012 
00013 USBSerial  pc;                                                                  // Objeto de comunicação serial com o TeraTerm
00014 
00015 Ticker Control_Interrupt;                                                       // Interrupção de Tempo para acionamento do algoritmo de controle
00016 
00017 QEI Encoder_Motor (PTD0,PTB17,NC, 300, QEI::X4_ENCODING);   // Objeto de leitura do encoder do motor
00018 QEI Encoder_Pendulo (PTA12,PTA13,NC, 600, QEI::X4_ENCODING);// Objeto de leitura do encoder do pêndulo
00019 
00020 DigitalOut Horario(PTC1);                                   // DigitalOut que sinaliza se deve virar o motor no sentido horário
00021 DigitalOut AntiHorario(PTD5);                               // DigitalOut que sinaliza se deve virar o motor no sentido anti-horário
00022 PwmOut Motor(PTD6);      
00023 
00024 
00025 bool Flag_Controle = false;
00026 int PlotCount = 0;
00027 
00028 double phi0 = 0;                                                                // phi0 -> Ângulo lido pelo Encoder_Braco
00029 double phi1 = 0;   
00030 
00031 double th0 = 0;                                                                 // th0 -> Ângulo do braço
00032 double th1 = 0;                                                                 // th1 -> Ângulo do pêndulo
00033 
00034 double th0_f = 0;                                                                 // th0 -> Ângulo do braço
00035 double th1_f = 0;                                                                 // th1 -> Ângulo do pêndulo
00036 
00037 double tau = 5e-2; 
00038 
00039 double th0_a = 0;                                                               // Valor de th0 um período de amostragem anterior
00040 double th1_a = 0;                                                               // Valor de th1 um período de amostragem anterior
00041 
00042 float  u=0;
00043                                                                                 
00044 void Init(void);                                                                // Função de Inicialização
00045 void Sensor_Read(void);                                                         // Função de leitura dos sensores
00046 void Control_Function(void);                                                    // Função de flag do controle, a ser chamada pela interrupção
00047 
00048 
00049 /******************************************************************************/
00050 /*************************** Corpo de Funções *********************************/
00051 /******************************************************************************/
00052 
00053 /*************************** Função Principal *********************************/
00054 // A main chama todas as inicializações e então aguarda o sinal de que deve
00055 // realizar controle. Esse sinal é dado pela flag "Controle" e é setada por uma
00056 // interrupção de tempo.
00057 //
00058 // Para garantir a execução imediata do algoritmo de controle nenhum wait deve
00059 // ser chamado durante a execução do controle e o uso de printfs deve ser 
00060 // esporádico.
00061 int main() {
00062 
00063     /*********************************************************************************/
00064     /** Inicialização do algoritmo de proteção. NUNCA DEVE SER RETIRADO DO PROGRAMA **/
00065     /**/                                wait(5);                                   /**/
00066     /**/         Protecao_Init(&Encoder_Motor, &Control_Interrupt, pi);        /**/
00067     /** Inicialização do algoritmo de proteção. NUNCA DEVE SER RETIRADO DO PROGRAMA **/
00068     /*********************************************************************************/
00069     
00070     Init();
00071     while(1) {
00072         
00073         if(Flag_Controle){
00074             
00075             Sensor_Read();                                                      // Executa a leitura dos sensores
00076             
00077             PlotCount++;
00078             if(PlotCount>=5){                                                  // Controla para que o printf ocorra apenas uma vez a cada 10 iterações
00079                 PlotCount = 0;
00080                 pc.printf("%f \t %f\n\r", phi0, phi1);
00081                
00082             }
00083             
00084             Flag_Controle = false;                                                   // Sinaliza que deve-se esperar o próximo sinal da interrupção de tempo para executar o próximo passo de controle
00085         }
00086     }
00087 }
00088 
00089 
00090 /************************* Função de Inicialização *****************************/
00091 // Esta função concentra todas as inicializações do sistema
00092 void Init(void){
00093     
00094     Motor.period(0.0001);
00095     Horario = 0;
00096     AntiHorario = 0;
00097     Motor = 0.0;
00098     Control_Interrupt.attach(&Control_Function, Ts);
00099    
00100 }
00101 
00102 /********************** Função de leitura dos sensores *************************/
00103 // Cada vez que esta função é chamada deve-se calcular os ângulos e velocidades
00104 // angulares por algum método conhecido
00105 void Sensor_Read(void){
00106     
00107     th0_a=th0;                                                    
00108     th1_a=th1;                                                    
00109     
00110     /** Leituras cruas dos ângulos do encoder **/
00111     phi0 = pi*Encoder_Motor.getPulses()/600.0;                                  // (eventos_lidos/eventos_por_volta)*2*pi = angulo_em_radianos
00112     phi1 = pi*Encoder_Pendulo.getPulses()/1200.0;                               // (eventos_lidos/eventos_por_volta)*360  = angulo_em_graus
00113     
00114     th0 = phi0;
00115     /** Tratamento do ângulo lido para ser zero na vertical para cima **/       // Como o encoder é incremental quando inicializamos o programa com o pêndulo na posição
00116     if(phi1>0)                                                                   // vertical para baixo esta passa a ser lida como 0º. Porém, para o algoritmo de controle
00117         th1 = phi1-pi;                                                           // funcionar corretamente 0º deve ser o pêndulo na posição vertical para cima. Para 
00118                                                                                 // garantir que isso aconteça subido o pêndulo no sentido horário ou anti-horário fazemos
00119     else if(phi1<=0)                                                             // th1 = th1-sgn(th1)*pi, onde sgn(x) é o sinal de x.
00120         th1 = phi1+pi;                                                           // Para ficar mais claro o funcionamento destes "if else" plote o sinal de th1 no tera term
00121     
00122     // Filtro (1/tau*s +1) nos angulos
00123     th0_f = (tau/(Ts+tau))*th0_f + (Ts/(Ts+tau))*th0;
00124     th1_f = (tau/(Ts+tau))*th1_f + (Ts/(Ts+tau))*th1;    
00125     
00126 }
00127 
00128 /**************** Função de flag do algoritmo de controle ******************/
00129 // Esta função avisa a main quando executar o próximo passo do algoritmo de 
00130 // controle. O uso de uma interrupção para o acionamento da flag garante que
00131 // haja exatamente Ts segundos entre execuções.
00132 void Control_Function(void){
00133      Flag_Controle = true;
00134  }