Serial Communication/ Analog Read/ FFT compute / LCD Text / Write on SD Card / read and write RTC application. K64F app developed for Electrical Engineering undergraduate final project at Ulbra university.
Dependencies: SDFileSystem TextLCD mbed
Serial, LCD 20x4, RTC, SD-Card, ADC features application. Included 5-key keyboard using AN0 channel, RTC update via serial, compute FFT and storage in SD-Card.
main.cpp
- Committer:
- flencina
- Date:
- 2016-08-24
- Revision:
- 4:398325c79937
- Parent:
- 3:ec85930e953c
File content as of revision 4:398325c79937:
/* -------------------------------------------------------------- Universidade Luterana do Brasil Departamento de Engenharia Elétrica Trabalho de Conclusão de Curso de Engenharia Elétrica MCSA - Motor Current Signature Analysis - Diagnóstico por Análise Espectral de Corrente de Motor Aluno: Flávio Dutra Lencina Orientador: Prof. Eng. Eletricista João Daniel de Oliveira Klein Data: 20/03/2016 Dispositivo de Coleta e envio de dados espectrais de Corrente Desenvolvido para plataforma NXP FRDM-K64F co processador ARM Cortex-M4 MK64FN1M0VLL12 MCU utilizando Kinetis Devlopment Studio da NXP ADC0 :coleta de dados de corrente FFT para análise em frequência dos 4096 pontos Envio dos dados de |FFT| x freq[k] pela serial em 115200bps Grava dados no SD card \sd\Estreito\EE_Coletaxx.csv ou \sd\Estreito\EA_Coletaxx.csv ou envia para serial Leitura da AN0 para o teclado. Teste com LCD 20x4 -------------------------------------------------------------- */ // 15-04-2016: // Mudança de estratégia de interrupções para utilização do teclado com LCD Shield do Arduino. // Colocar Interrupção para a porta serial e retirar das teclas SW2 e SW3. Utilização do teclado do Shield. // 15-06-2016: // Revisado para AN2 - Coleta a 4096 SPS e AN1 - 512 SPS // 03-08-2016: Revisão para adicionar PGA com CD4066 e controle com CD4028 BCD para decimal // 21-08-2016: Ajuste de RTC. #include "mbed.h" #include "SDFileSystem.h" #include "math.h" #include "mbed_debug.h" #include "TextLCD.h" #include <complex> #define ZRef 0.5 // Eleva para metade #define Ts 244.14062 //4096Hz // SD-CARD Interface #define SD_MOSI PTE3 #define SD_MISO PTE1 #define SD_SCLK PTE2 #define SD_CS PTE4 #define SD_DETECT PTE6 // Interface LCD 20x04 - 4bits de dados #define RS PTC12 //D8 // instead PTA0 pin 34, we have to use PTC12 - pin 84 //#define RW GND-3 #define EN PTC4 //D9 #define DB7 PTC3 //D7 #define DB6 PTC2 //D6 #define DB5 PTA2 //D5 #define DB4 PTB23 //D4 // Teclas do Teclado Shield #define btn1 1 #define btn2 2 #define btn3 3 #define btn4 4 #define btn5 5 #define btnNONE 0 // modos de envio de dados #define SERIAL 01 #define SDCARD 02 // Canais analógicos AnalogIn kbd(A0); // Teclado funcional AnalogIn ainc(A1); // Entrada analógica espectro curto AnalogIn ainl(A2); // Entrada analógica espectro longo DigitalIn SD_OK(SD_DETECT,PullDown); // Card Detect //Saídas Digitais DigitalOut GV0(PTA1); //A DigitalOut GV1(PTB9); //B DigitalOut GV2(PTC17); //C // Tipo Complexo typedef complex<float> Complex; // Protótipos de Funções void Coleta(uint8_t mult); uint16_t reverse(uint16_t x); void fft(uint16_t N_FFT_); void gravar(uint8_t mult); uint16_t Countfile(uint8_t n); uint8_t le_teclado(void); // Inicializa SD card SDFileSystem sd(SD_MOSI, SD_MISO, SD_SCLK, SD_CS, "sd"); // Inicializa LCD TextLCD lcd(RS, EN, DB4, DB5, DB6, DB7,TextLCD::LCD20x4); // rs, e, d4-d7 // Inicializa Serial Serial pc(USBTX, USBRX); // tx, rx // Variáveis const long N=4096; const unsigned int m = 12; //float t[N] float f[N/2+1]; double x0[N]; Complex y2[N/2+1]; bool sdsel=false; bool conectado = true;//false; char buffer[32]; // para o rtc // Interrupção de leitura da serial void SerialRecInt(void) { if (sdsel==false) { unsigned char msg; uint32_t tempo=0; char UTS[11]; time_t seconds = time(NULL); strftime(buffer,32,"%d/%m/%Y %H:%M:%S\n",localtime(&seconds)); msg=pc.getc(); while(!pc.writeable()){} switch (msg){ case 'C':// Iniciar conexão { pc.printf("OK\n"); conectado = true; break; } case 'D':// Terminar conexão { pc.printf("OK\n"); conectado = false; break; } case 'E': // Espectro Estreito { // Envia espectro Curto via Serial. if (conectado) { Coleta(4); for(int n=0;n<N/2;n++) pc.printf("%8.4f;%8.4f\n",f[n],x0[n]); } break; } case 'L': // Espectro Longo { // Envia espectro Amplo via Serial. if (conectado) { Coleta(1); for(int n=0;n<N/2;n++) pc.printf("%8.4f;%8.4f\n",f[n],x0[n]); } break; } case 'R': // Relógio { pc.gets(UTS,11); // Recebe o valor de Timestamp for(int n=0;n<10;n++) { tempo = tempo * 10 + (UTS[n] -48); } set_time(tempo); pc.printf("%s",buffer); break; } case 'T': // Teste { pc.printf("%s",buffer); if (SD_OK.read()) debug("Cartao SD Ok-> %d\n",SD_OK.read()); else debug("Cartao SD NOk-> %d\n",SD_OK.read()); break; } default: break; } //tm.start(); } //msg = ' '; } // Leitura do teclado uint8_t le_teclado(void) { uint16_t tecla = kbd.read_u16(); if (tecla > 60000) return btnNONE; //sem tecla if (tecla > 40000) return btn5; if (tecla > 30000) return btn4; if (tecla > 15000) return btn3; if (tecla > 5000) return btn2; if (tecla >= 0) return btn1; return btnNONE; } int main() { //Timer tm0; uint8_t tecla; pc.baud(115200); pc.attach(&SerialRecInt,pc.RxIrq); // Chamada de IRQ para Serial lcd.cls(); lcd.printf("TCC - MCSA - ULBRA\n"); // linha 0 // debug("MCSA - Aquisição de Motor.\n\r"); // tm0.start(); while(1) { // Comando via teclado tecla=le_teclado(); lcd.locate(0,3); // aponta para linha 3 lcd.printf("1- Amplo / 2- Curto"); //lcd.printf("%d",tecla); // tecla pressionada switch(tecla){ case btn1: // Espectro Longo { sdsel=true; Coleta(1); gravar(1); sdsel=false; break; } case btn2: // Espectro Curto { sdsel=true; Coleta(4); gravar(4); sdsel=false; break; } case btn3: // Limpa comando { lcd.locate(0,1); lcd.printf(" "); break; } case btn4: // Créditos { lcd.cls(); lcd.printf("ULBRA ENG. ELETRICA\n"); lcd.printf(" TCC - MCSA \n "); lcd.printf("Flavio Dutra Lencina\n"); lcd.printf("Prof. Joao D. Klein \n"); while(1) { tecla=le_teclado(); if tecla(<> btnNONE) break; wait_ms(200); } lcd.cls(); lcd.printf("TCC - MCSA - ULBRA\n"); // linha 0 break; } default: break; } wait_ms(300); // tm0.reset(); // while(tm0.read_ms()<500); lcd.locate(0,2); // Verifica se há cartão SD if (SD_OK.read()) lcd.printf(" "); else lcd.printf(" Insira o Cartao SD"); } } // Coleta de dados void Coleta(uint8_t mult) { Timer tm; tm.stop(); double max,z; uint8_t Ganho =0; float fs,df;//,dt; // multiplicador if(mult<1) mult=1; else mult=4; // Informações para LCD lcd.locate(0,1); lcd.printf(" "); lcd.locate(0,1); lcd.printf("Ajustando Ganho..."); // Fazer Ajuste de ganho tm.start(); // Ativa Timer while(1)//Ganho < 5) // de 0 até 5 { tm.reset(); max = ainl.read(); for (int n=1;n<137;n++) { while (tm.read_us()<(Ts)); tm.reset(); z=ainl.read(); if (max < z) max=z; } // tm.stop(); //debug lcd.locate(0,2); lcd.printf("Max: %4.2f",max); if (max < 0.632) { Ganho++; if (Ganho > 5) // Ganho máx { Ganho = 5; break; } ///Saidas para PGA GV0 = Ganho & 0x01; GV1 = (Ganho & 0x02)>>1; GV2 = (Ganho & 0x04)>>2; //debug lcd.printf("%d %d %d\n", (uint8_t)GV0,(uint8_t)GV1,(uint8_t)GV2); } else break; // tm.start(); } tm.stop(); lcd.locate(0,1); lcd.printf("Coletando dados..."); // Cálculo de espectro de frequência fs= (float)1000/(Ts*mult); // frequência de amostragem 4098kHz~4096 df= 1000*(fs/N); // delta de frequência f[0]=0.0001; for (int n=1;n<N/2;n++) f[n]= f[n-1]+df; tm.start(); // Retiva Timer for (long int n=0;n<N;n++){ tm.reset(); // Por enquanto Espectro longo e curto no mesmo //if (mult==1) x0[n]= ainl.read(); // espetro longo // else // x0[n]= ainc.read(); // espectro curto while (tm.read_us()<(Ts*mult)); // freq de amostragem: 4096 Hz ou 512 Hz for (int i=0;i<mult;i++) { __NOP(); __NOP(); __NOP(); //__NOP(); } } tm.stop(); // Para o Timer // Reseta Ganho GV0=0; GV1=0; GV2=0; // Ajuste de zero for (long int n=0;n<N;n++){ x0[n]=x0[n]-ZRef; } //debug("Foi ate o N:%d\n ",N); fft(N); // Módulo da FFT for(long int n=0;n<N/2;n++) x0[n]=(double)sqrt(y2[n].real()*y2[n].real()+y2[n].imag()*y2[n].imag()); // encontra maior valor max=x0[0]; for (int n=1;n<N/2;n++) if (x0[n] > max) max =x0[n]; // Normaliza valores a 1 máx (linear) // for (int n=0;n<N/2;n++){ // x0[n]= x0[n]/max; // } // Normaliza valores for (int n=0;n<N/2;n++){ x0[n]= 20* log10(x0[n]/max); } lcd.locate(0,1); lcd.printf(" "); } // A FFT por decimação de frequência void fft(uint16_t N_FFT_) { Complex u_[N_FFT_],wTable_[N_FFT_]; Complex uTmp; uint16_t bTable_[N_FFT_]; uint16_t nHalf = N_FFT_/2; Complex arg = Complex(0, -6.283185f/N_FFT_); uint16_t nShift = __clz(N_FFT_) + 1; // Apenas no mbed for (uint16_t k=0; k<N_FFT_; k++){ wTable_[k] = exp(arg*(float)k); bTable_[k] = __rbit(k) >> nShift; // Apenas no mbed //bTable_[k] = reverse(k); u_[k]=x0[k]; //debug("%d ",k); } for (uint16_t stg=1; stg<N_FFT_/2; stg*=2) { uint16_t nHalf2 = nHalf*2; for (uint16_t kp=0; kp<N_FFT_; kp+=nHalf2) { uint16_t kx = 0; for (uint16_t k=kp; k<kp+nHalf; k++) { // Butterfly operation Complex uTmp = u_[k+nHalf]; u_[k+nHalf] = (u_[k] - uTmp)*wTable_[kx]; u_[k] = u_[k] + uTmp; kx = kx + stg; } } nHalf = nHalf/2; } // Last stage y2[0] = u_[0] + u_[1]; y2[0] = u_[0] + u_[1]; y2[N_FFT_/2] = u_[0] - u_[1]; for (uint16_t k=2; k<N_FFT_; k+=2) u_[k] = u_[k] + u_[k+1]; // Reorder to bit reversal for (uint16_t k=1; k<N_FFT_/2; k++) y2[k] = u_[bTable_[k]]; } // Bit reverso uint16_t reverse(uint16_t x) { uint16_t NO_OF_BITS = sizeof(x) * 8; uint16_t reverse_num = 0; for (uint16_t i = 0; i < NO_OF_BITS; i++) { if((x & (1 << i))) reverse_num |= 1 << ((NO_OF_BITS - 1) - i); } return (reverse_num >> (NO_OF_BITS-m)); } // Grava em SD Card void gravar(uint8_t x) { char arquivo[64]; if (SD_OK.read()) { // debug("Gravando em cartao SD\n\r"); lcd.locate(0,1); lcd.printf("Gravando dados..."); if (x==1) // Amplo { mkdir("/sd/Amplo", 0777); sprintf(arquivo, "/sd/Amplo/EA_Coleta%03d.csv", Countfile(1)); // pc.printf("Arquivo: %s\n\r",arquivo); } else // Estreito { mkdir("/sd/Estreito", 0777); sprintf(arquivo, "/sd/Estreito/EE_Coleta%03d.csv", Countfile(2)); } FILE *fp =fopen(arquivo,"w"); fprintf(fp,"Freq[Hz];Amplitude[dB]\r\n"); for(int n=0;n<N/2;n++){ //fputc(0x0A,fp); // fprintf(fp,"%8.4f;%8.4f\r\n",f[n],x0[n]); } //fputc(0x0D,fp); fclose(fp); lcd.locate(0,1);// (0,1); lcd.printf(" "); } else { //debug("Sem cartao SD.\n\r"); lcd.locate(0,1); lcd.printf("Sem cartao SD.\n"); } //tm.start(); } // Manipulação de arquivos uint16_t Countfile(uint8_t n) { struct dirent *p; uint16_t numFiles = 0; DIR * sdDir; if (n==1){ sdDir = opendir("/sd/Amplo"); } else sdDir = opendir("/sd/Estreito"); while ((p = readdir( sdDir )) != NULL) numFiles++; closedir(sdDir); return numFiles; }