Flavio Lencina / Mbed 2 deprecated TCC_MCSA

Dependencies:   SDFileSystem TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  --------------------------------------------------------------
00003  Universidade Luterana do Brasil
00004  Departamento de Engenharia Elétrica
00005  Trabalho de Conclusão de Curso de Engenharia Elétrica
00006  MCSA - Motor Current Signature Analysis - Diagnóstico por Análise Espectral de Corrente de Motor
00007  Aluno: Flávio Dutra Lencina
00008  Orientador: Prof. Eng. Eletricista João Daniel de Oliveira Klein
00009  Data: 20/03/2016
00010  Dispositivo de Coleta e envio de dados espectrais de Corrente
00011  Desenvolvido para plataforma NXP FRDM-K64F co processador ARM Cortex-M4 MK64FN1M0VLL12 MCU
00012  utilizando Kinetis Devlopment Studio da NXP
00013  ADC0 :coleta de dados de corrente
00014  FFT para análise em frequência dos  4096 pontos
00015  Envio dos dados de |FFT| x freq[k] pela serial em 115200bps
00016  Grava dados no SD card \sd\Estreito\EE_Coletaxx.csv ou \sd\Estreito\EA_Coletaxx.csv
00017  ou envia para serial
00018  Leitura da AN0 para o teclado.
00019  Teste com LCD 20x4 
00020 
00021 -------------------------------------------------------------- */
00022 
00023 // 15-04-2016:
00024 // Mudança de estratégia de interrupções para utilização do teclado com LCD Shield do Arduino.
00025 // Colocar Interrupção para a porta serial e retirar das teclas SW2 e SW3. Utilização do teclado do Shield.
00026 // 15-06-2016:
00027 // Revisado para AN2 - Coleta a 4096 SPS e AN1 - 512 SPS
00028 // 03-08-2016: Revisão para adicionar PGA com CD4066 e controle com CD4028 BCD para decimal
00029 // 21-08-2016: Ajuste de RTC.
00030 
00031 #include "mbed.h"
00032 #include "SDFileSystem.h"
00033 #include "math.h"
00034 #include "mbed_debug.h"
00035 #include "TextLCD.h"
00036 #include <complex>
00037 
00038 #define ZRef 0.5 // Eleva para metade
00039 #define Ts 244.14062    //4096Hz
00040 
00041  // SD-CARD Interface
00042 #define SD_MOSI        PTE3
00043 #define SD_MISO        PTE1
00044 #define SD_SCLK        PTE2
00045 #define SD_CS          PTE4
00046 #define SD_DETECT      PTE6
00047 
00048 // Interface LCD 20x04 - 4bits de dados
00049 #define RS PTC12 //D8 // instead PTA0 pin 34, we have to use PTC12 -  pin 84
00050 //#define RW  GND-3
00051 #define EN PTC4  //D9
00052 #define DB7 PTC3 //D7
00053 #define DB6 PTC2 //D6
00054 #define DB5 PTA2 //D5
00055 #define DB4 PTB23 //D4
00056 
00057 // Teclas do Teclado Shield
00058 #define btn1 1
00059 #define btn2 2
00060 #define btn3 3
00061 #define btn4 4
00062 #define btn5 5
00063 #define btnNONE 0
00064 
00065 
00066  // modos de envio de dados
00067 
00068 #define SERIAL 01
00069 #define SDCARD 02
00070 
00071 // Canais analógicos
00072 AnalogIn kbd(A0); // Teclado funcional
00073 AnalogIn ainc(A1); // Entrada analógica espectro curto 
00074 AnalogIn ainl(A2); // Entrada analógica espectro longo
00075 DigitalIn SD_OK(SD_DETECT,PullDown);  // Card Detect
00076 //Saídas Digitais
00077 DigitalOut GV0(PTA1);  //A
00078 DigitalOut GV1(PTB9);  //B
00079 DigitalOut GV2(PTC17); //C
00080 
00081 // Tipo Complexo
00082 typedef complex<float> Complex; 
00083 
00084 // Protótipos de Funções
00085 void Coleta(uint8_t mult);
00086 uint16_t reverse(uint16_t x);
00087 void fft(uint16_t N_FFT_);
00088 void gravar(uint8_t mult);
00089 uint16_t Countfile(uint8_t n);
00090 uint8_t le_teclado(void);
00091 
00092 // Inicializa SD card
00093 SDFileSystem sd(SD_MOSI, SD_MISO, SD_SCLK, SD_CS, "sd");
00094 // Inicializa LCD
00095 TextLCD lcd(RS, EN, DB4, DB5, DB6, DB7,TextLCD::LCD20x4); // rs, e, d4-d7
00096 // Inicializa Serial
00097 Serial pc(USBTX, USBRX); // tx, rx
00098 
00099 // Variáveis
00100 const long N=4096;
00101 const unsigned int m = 12;
00102 //float t[N]
00103 float f[N/2+1];
00104 double x0[N];
00105 Complex y2[N/2+1];
00106 bool sdsel=false;
00107 bool conectado = true;//false;
00108 char buffer[32]; // para o rtc
00109 // Interrupção de leitura da serial
00110 void SerialRecInt(void)
00111 {
00112     
00113     if (sdsel==false)
00114     {
00115         unsigned char msg;
00116         uint32_t tempo=0;
00117         char UTS[11];
00118         time_t seconds = time(NULL);
00119         strftime(buffer,32,"%d/%m/%Y %H:%M:%S\n",localtime(&seconds));
00120         msg=pc.getc();
00121         while(!pc.writeable()){}
00122         switch (msg){
00123         case 'C':// Iniciar conexão
00124         {
00125             pc.printf("OK\n");
00126             conectado = true;
00127             break;
00128         }
00129         case 'D':// Terminar conexão
00130         {
00131             pc.printf("OK\n");
00132             conectado = false;
00133             break;
00134         }
00135         case 'E': // Espectro Estreito
00136         {
00137             // Envia espectro Curto via Serial.
00138             if (conectado)
00139             {
00140                 Coleta(4);
00141                 for(int n=0;n<N/2;n++)
00142                     pc.printf("%8.4f;%8.4f\n",f[n],x0[n]);
00143             }       
00144             break;
00145         }
00146         case 'L': // Espectro Longo
00147         {
00148             // Envia espectro Amplo via Serial.
00149             if (conectado)
00150             {
00151                 Coleta(1);
00152                 for(int n=0;n<N/2;n++)
00153                     pc.printf("%8.4f;%8.4f\n",f[n],x0[n]);
00154             }       
00155             break;
00156         }
00157         case 'R': // Relógio
00158         {
00159             pc.gets(UTS,11); // Recebe o valor de Timestamp
00160             for(int n=0;n<10;n++)
00161             {
00162                 tempo = tempo * 10  + (UTS[n] -48);
00163                 
00164             }
00165             set_time(tempo);  
00166             pc.printf("%s",buffer);
00167             break;
00168         }
00169         case 'T': // Teste
00170         {
00171             pc.printf("%s",buffer);
00172             if (SD_OK.read())
00173                 debug("Cartao SD Ok-> %d\n",SD_OK.read());
00174             else
00175                 debug("Cartao SD NOk-> %d\n",SD_OK.read());
00176             break;
00177         }
00178         default:
00179             break;
00180         }
00181         //tm.start();       
00182     }
00183 
00184         //msg = ' ';
00185 }
00186 // Leitura do teclado
00187 uint8_t le_teclado(void)
00188 {
00189     uint16_t tecla = kbd.read_u16();
00190     if (tecla > 60000) return btnNONE; //sem tecla
00191     if (tecla > 40000) return btn5;
00192     if (tecla > 30000) return btn4;
00193     if (tecla > 15000) return btn3;
00194     if (tecla > 5000) return btn2;
00195     if (tecla >= 0) return btn1;
00196     return btnNONE;
00197 }
00198 
00199 int main()
00200 {
00201     //Timer tm0;
00202     uint8_t tecla;
00203     pc.baud(115200);
00204     pc.attach(&SerialRecInt,pc.RxIrq); // Chamada de IRQ para Serial
00205     lcd.cls();
00206     lcd.printf("TCC  - MCSA - ULBRA\n"); // linha 0
00207     // debug("MCSA - Aquisição de Motor.\n\r");
00208    // tm0.start();
00209     while(1) {
00210           // Comando via teclado
00211           tecla=le_teclado();
00212           lcd.locate(0,3); // aponta para linha 3
00213           lcd.printf("1- Amplo / 2- Curto"); 
00214           //lcd.printf("%d",tecla); // tecla pressionada
00215           switch(tecla){
00216           case btn1: // Espectro Longo
00217           {
00218               sdsel=true;
00219               Coleta(1);
00220               gravar(1);
00221               sdsel=false;
00222               break;
00223           }
00224           case btn2: // Espectro Curto
00225           {
00226               sdsel=true;
00227               Coleta(4);
00228               gravar(4);
00229               sdsel=false;
00230               break;
00231           }
00232           case btn3: // Limpa comando
00233           {
00234               lcd.locate(0,1);
00235               lcd.printf("                 ");
00236               break;
00237           }
00238           case btn4: // Créditos
00239           {
00240               lcd.cls();
00241               lcd.printf("ULBRA  ENG. ELETRICA\n");
00242               lcd.printf("      TCC - MCSA \n   ");
00243               lcd.printf("Flavio Dutra Lencina\n");
00244               lcd.printf("Prof. Joao D. Klein \n");
00245               while(1)
00246               {
00247                  tecla=le_teclado();
00248                  if tecla(<> btnNONE)
00249                     break;
00250                  wait_ms(200);   
00251               }
00252               lcd.cls();
00253               lcd.printf("TCC  - MCSA - ULBRA\n"); // linha 0
00254               break;
00255           }
00256           default:
00257               break;
00258           }
00259           wait_ms(300);
00260     //    tm0.reset();
00261     //    while(tm0.read_ms()<500);
00262           lcd.locate(0,2);
00263           // Verifica se há cartão SD
00264           if (SD_OK.read())
00265             lcd.printf("                   ");
00266           else
00267             lcd.printf(" Insira o Cartao SD");
00268           
00269      }
00270 }
00271 // Coleta de dados
00272 void Coleta(uint8_t mult)
00273 {
00274     Timer tm;
00275     tm.stop();
00276     double max,z;
00277     uint8_t Ganho =0;
00278     float fs,df;//,dt;
00279     // multiplicador
00280     if(mult<1) 
00281         mult=1;
00282     else
00283         mult=4;
00284     
00285     // Informações para LCD
00286     
00287     lcd.locate(0,1);
00288     lcd.printf("                  ");
00289     lcd.locate(0,1);
00290     lcd.printf("Ajustando Ganho...");
00291           
00292     // Fazer Ajuste de ganho
00293         
00294     tm.start(); // Ativa Timer
00295     while(1)//Ganho < 5) // de 0 até 5
00296     {   
00297         tm.reset();
00298         max = ainl.read();
00299         for (int n=1;n<137;n++)
00300         {
00301              while (tm.read_us()<(Ts));
00302              tm.reset();
00303              z=ainl.read();
00304              if (max < z) max=z;
00305         }
00306     //  tm.stop();
00307         //debug
00308         lcd.locate(0,2);
00309         lcd.printf("Max: %4.2f",max);
00310         if (max < 0.632)     
00311         {
00312             Ganho++;
00313             if (Ganho > 5) // Ganho máx
00314             {   
00315                 Ganho = 5;
00316                 break;
00317             }   
00318             ///Saidas para PGA
00319             GV0 =  Ganho & 0x01;
00320             GV1 = (Ganho & 0x02)>>1;
00321             GV2 = (Ganho & 0x04)>>2;
00322             //debug
00323             lcd.printf("%d %d %d\n", (uint8_t)GV0,(uint8_t)GV1,(uint8_t)GV2);
00324         }
00325         else
00326             break;
00327     //  tm.start(); 
00328     }
00329     tm.stop();
00330     lcd.locate(0,1);
00331     lcd.printf("Coletando dados...");
00332     // Cálculo de espectro de frequência
00333     fs= (float)1000/(Ts*mult); // frequência de amostragem 4098kHz~4096
00334     df= 1000*(fs/N);           // delta de frequência
00335     f[0]=0.0001;
00336     for (int n=1;n<N/2;n++)
00337          f[n]= f[n-1]+df; 
00338     tm.start(); // Retiva Timer
00339     for (long int n=0;n<N;n++){
00340         tm.reset();
00341         // Por enquanto Espectro longo e curto no mesmo
00342         //if (mult==1)
00343            x0[n]= ainl.read(); // espetro longo
00344         // else
00345         //   x0[n]= ainc.read(); // espectro curto
00346         while (tm.read_us()<(Ts*mult)); // freq de amostragem: 4096 Hz ou 512 Hz
00347         for (int i=0;i<mult;i++)
00348         {   __NOP();
00349             __NOP();
00350             __NOP();
00351             //__NOP();
00352         }
00353      }
00354      tm.stop(); // Para o Timer
00355      // Reseta Ganho
00356      GV0=0;
00357      GV1=0;
00358      GV2=0;
00359      // Ajuste de zero
00360      for (long int n=0;n<N;n++){
00361 
00362         x0[n]=x0[n]-ZRef;
00363      }
00364      //debug("Foi ate o N:%d\n ",N);
00365 
00366 
00367      fft(N);
00368      // Módulo da FFT
00369      for(long int n=0;n<N/2;n++)
00370          x0[n]=(double)sqrt(y2[n].real()*y2[n].real()+y2[n].imag()*y2[n].imag());
00371      // encontra maior valor
00372      max=x0[0];
00373      for (int n=1;n<N/2;n++)
00374           if (x0[n] > max) max =x0[n];
00375      // Normaliza valores a 1 máx   (linear)  
00376      // for (int n=0;n<N/2;n++){
00377      //     x0[n]= x0[n]/max;     
00378      // }
00379      
00380      
00381      
00382      // Normaliza valores
00383      for (int n=0;n<N/2;n++){
00384           x0[n]= 20* log10(x0[n]/max);
00385      }
00386      lcd.locate(0,1);
00387      lcd.printf("                  ");
00388      
00389 }
00390 
00391 // A FFT por decimação de frequência
00392 void fft(uint16_t N_FFT_)
00393 {
00394     Complex u_[N_FFT_],wTable_[N_FFT_];
00395     Complex uTmp;
00396     uint16_t bTable_[N_FFT_];
00397     uint16_t nHalf = N_FFT_/2;
00398     Complex arg = Complex(0, -6.283185f/N_FFT_);
00399     
00400     uint16_t nShift = __clz(N_FFT_) + 1; // Apenas no mbed
00401     for (uint16_t k=0; k<N_FFT_; k++){
00402          wTable_[k] = exp(arg*(float)k);
00403          bTable_[k] = __rbit(k) >> nShift; // Apenas no mbed
00404          //bTable_[k] = reverse(k);
00405          u_[k]=x0[k];
00406          //debug("%d ",k);
00407     }
00408     for (uint16_t stg=1; stg<N_FFT_/2; stg*=2)
00409      {
00410           uint16_t nHalf2 = nHalf*2;
00411           for (uint16_t kp=0; kp<N_FFT_; kp+=nHalf2)
00412           {
00413                uint16_t kx = 0;
00414                     for (uint16_t k=kp; k<kp+nHalf; k++)
00415                     {
00416                         // Butterfly operation
00417                         Complex uTmp = u_[k+nHalf];
00418                         u_[k+nHalf] = (u_[k] - uTmp)*wTable_[kx];
00419                         u_[k] = u_[k] + uTmp;
00420                         kx = kx + stg;
00421                     }
00422                 }
00423                 nHalf = nHalf/2;
00424        }
00425      // Last stage
00426       y2[0] = u_[0] + u_[1];
00427       y2[0] = u_[0] + u_[1];
00428       y2[N_FFT_/2] = u_[0] - u_[1];
00429       for (uint16_t k=2; k<N_FFT_; k+=2)
00430            u_[k] = u_[k] + u_[k+1];
00431       // Reorder to bit reversal
00432       for (uint16_t k=1; k<N_FFT_/2; k++)
00433           y2[k] = u_[bTable_[k]];
00434 }
00435 // Bit reverso
00436 uint16_t reverse(uint16_t x)
00437 {
00438    uint16_t NO_OF_BITS = sizeof(x) * 8;
00439    uint16_t reverse_num = 0;
00440    for (uint16_t i = 0; i < NO_OF_BITS; i++)
00441    {
00442        if((x & (1 << i)))
00443            reverse_num |= 1 << ((NO_OF_BITS - 1) - i);
00444    }
00445    return (reverse_num >> (NO_OF_BITS-m));
00446 }
00447 // Grava em SD Card
00448 void gravar(uint8_t x)
00449 {
00450     char arquivo[64];
00451     if (SD_OK.read())
00452     {
00453        // debug("Gravando em cartao SD\n\r");
00454         lcd.locate(0,1);
00455         lcd.printf("Gravando dados...");
00456         if (x==1) // Amplo
00457         {
00458             mkdir("/sd/Amplo", 0777);
00459             sprintf(arquivo, "/sd/Amplo/EA_Coleta%03d.csv", Countfile(1));
00460             //  pc.printf("Arquivo: %s\n\r",arquivo);
00461         }
00462         else // Estreito
00463         {
00464             mkdir("/sd/Estreito", 0777);
00465             sprintf(arquivo, "/sd/Estreito/EE_Coleta%03d.csv", Countfile(2));
00466         }
00467         FILE *fp =fopen(arquivo,"w");
00468         fprintf(fp,"Freq[Hz];Amplitude[dB]\r\n");
00469 
00470         for(int n=0;n<N/2;n++){
00471             //fputc(0x0A,fp);
00472             // 
00473             fprintf(fp,"%8.4f;%8.4f\r\n",f[n],x0[n]);
00474         }
00475 
00476         //fputc(0x0D,fp);
00477         fclose(fp);
00478         lcd.locate(0,1);// (0,1);
00479         lcd.printf("                 ");
00480     }
00481     else
00482     {
00483         //debug("Sem cartao SD.\n\r");
00484         lcd.locate(0,1);
00485         lcd.printf("Sem cartao SD.\n");
00486     } 
00487     //tm.start();   
00488 }
00489 // Manipulação de arquivos
00490 uint16_t Countfile(uint8_t n)
00491 {
00492     struct dirent *p;
00493     uint16_t numFiles = 0;
00494     DIR * sdDir;
00495     if (n==1){
00496         sdDir = opendir("/sd/Amplo");
00497     }
00498     else
00499         sdDir = opendir("/sd/Estreito");
00500     while ((p = readdir( sdDir )) != NULL)
00501             numFiles++;
00502     closedir(sdDir);
00503     return numFiles;       
00504 }
00505        
00506        
00507        
00508        
00509