relatorio livia

Post on 18-Jan-2016

64 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

microproc

TRANSCRIPT

Cálculo de FFT usando Hardware-in-the-Loop Lívia Lisandro Judice Godoy - 110073797

1 INTRODUÇÃO

1.1 OBJETIVO O objetivo deste projeto é utilizar o software de simulação PSIM© para simular um circuito inversor de

Eletrônica de Potência e fazer o cálculo da DFT (Transformada Discreta de Fourier) – que serve para

analisar o espectro de harmônicos da onda - da tensão senoidal de saída deste circuito utilizando-se um

algoritmo de FFT (Transformada Rápida de Fourier). O algoritmo da FFT será implementado no

controlador dsPIC33F64MC802 da Microchip©, que receberá os dados da forma de onda de saída do

inversor, enviados pelo PSIM© utilizando o bloco DLL (Dynamic Link Library). Neste bloco serão

configurados a abertura e fechamento das portas e a forma de transmissão desses dados, feita via

comunicação serial.

1.2 HARDWARE-IN-THE-LOOP (HIL) A simulação em Hardware-in-the-loop (HIL) é uma técnica usada no desenvolvimento e teste de

sistemas complexos em tempo real, substituindo os testes com o protótipo físico, ou porque o mesmo

não se encontra pronto ou pra evitar danos materiais ou mesmo por redução de custos. A complexidade

da planta a ser controlada é adiciona à plataforma de teste adicionando-se uma representação

matemática dos sistemas dinâmicos relacionados a ela, que são as plantas de simulação. O sistema

testado interage com essa planta de simulação.

A HIL é um tipo de simulação em tempo real, com a diferença de que se adiciona um componente real

no loop de simulação, que pode, por exemplo, ser um ECU (“Electronic Control Unit”). O objetivo da HIL

é prover todos os estímulos elétricos necessários para que o ECU entenda que o protótipo está

conectado ali. Portanto, a simulação (circuito inversor de Eletrônica de Potência) deve ser composta de

todos os detalhes da planta e de um ECU que, neste caso, será o controlador dsPIC33F64MC802 da

Microchip©.

1.3 DYNAMIC LINK LIBRARY (DLL) O bloco DLL do PSIM© é uma biblioteca dinâmica que permite que o usuário escreva um código em C-

C++, compile-o e linke-o ao PSIM©. Esse bloco recebe os valores do PSIM© como entradas, realiza os

cálculos previstos e manda o resultado de volta pro PSIM© a cada time step de simulação. Porém,

quando as entradas do bloco DLL são conectadas a elementos discretos, como o zero-order hold ou o

unit delay, o bloco só é chamado nos intervalos de amostragem discretos.

1.4 FAST FOURIER TRANSFORM (FFT) A Transformada de Fourier é uma transformada integral que passa um sinal do domínio do tempo para o

domínio da frequência, reconstruindo-o adicionando-se uma ou mais senoides puras de amplitude, fase

e frequência apropriada. Para uma função f=f(t) contínua ela é dada por:

(1)

Para o uso em processamentos digitais, como é o caso deste trabalho, são utilizados sinais discretos no

tempo, que possuem um número finito de pontos. Para isso é usada a Transformada Discreta de Fourier

(DFT), que define uma representação discreta no domínio da frequência.

Sendo uma sequência de N números complexos, tomadas no sinal, pode-se transformá-la

numa sequência periódica de N números complexos de diferentes frequências.

(2)

Onde cada tem a amplitude e fase da componente senoidal da função . A frequência da senoide é

ciclos por segundo e a amplitude e fase são dadas por:

(3) (4)

Esse cálculo pode ser bastante lento na prática, então geralmente é usada a Transformada Rápida de

Fourier (FFT), que é um algoritmo para calcular a Transformada Discreta de Fourier (DFT), tornando-se

possível a leitura das frequências relacionadas a essa onda. Ela pode ser usada quando o tamanho N da

sequência é uma potência de 2. A diferença de complexidade é bastante considerável: enquanto a DFT

requer N² operações, a FFT requer apenas NlogN operações.

Existem diversos algoritmos usados para calcular a FFT de um sinal. No desenvolvimento deste trabalho

será usado o algoritmo de Cooley-Tukey, que expressa uma DFT de tamanho em duas DFT’s

menores de tamanhos e recursivamente. O método calcula primeiramente as componentes pares

( ) e ímpares ( ) do sinal e posteriormente combina os dois

resultados para produzir a sequência completa. Substituindo na equação (2):

O fator

multiplica os dados e é chamado de “twiddle factor”:

Onde o primeiro somatório é a DFT da parte par de e o segundo da parte ímpar. Como a DFT é

periódica, e . Portanto, a equação acima torna-se:

(5)

Mas o “twiddle factor” também pode ser escrito como:

Então, a parte de

na equação (5) torna-se:

e

Pode-se, portanto, expressar uma DFT de tamanho N em duas DFT’s de tamanho N/2.

2 PROJETO

2.1 CÓDIGO PARA GERAR A DLL O primeiro passo foi escrever o programa da DLL de forma que esteja pronto para realizar a

comunicação serial. Isso foi feito inicialmente tomando como base o exemplo “general_dll_block_test3”

disponível na biblioteca de exemplos do PSIM©.

Após uma análise do exemplo “MOD1DLL” encontrado em (2), ficou clara a necessidade de se adicionar

a estrutura COMMTIMEOUTS ao projeto do DLL, que contém os parâmetros de intervalo para a

comunicação. A parte ReadIntervalTimeout especifica o tempo máximo (em ms) permitido entre a

chegada de dois caracteres na linha de comunicação. A ReadTotalTimeoutMultiplier especifica o

multiplicador (em ms) usado para calcular o intervalo total para operações de leitura. Para cada uma

este valor é multiplicado pelo número de bytes a serem lidos. A ReadTotalTimeoutConstant especifica a

constante (em ms) usada para calcular o intervalo total para operações de leitura. Para cada uma este

valor é adicionado ao produto do ReadTotalTimeoutMultiplier e do número de bytes a serem lidos. A

WriteTotalTimeoutMultiplier especifica o multiplicador (em ms) usado para calcular o intervalo total

para operações de escrita. Para cada uma, este valor é multiplicado pelo número de bytes a serem

escritos. A WriteTotalTimeoutConstant especifica a constante (em ms) usada para calcular o intervalo

total para operações de escrita. Para cada uma este valor é adicionado ao produto do

WriteTotalTimeoutMultiplier e do número de bytes a serem escritos.

O envio de dados pelo PSIM© é feito de acordo com os parâmetros definidos no bloco zero-order hold,

que faz com que a DLL só seja chamada em intervalos discretos de amostragem. Para calcular o passo

(parâmetro de intervalo), foi utilizado o Teorema da Amostragem.

O Teorema da Amostragem diz que um sinal analógico que tem maior frequência Fm, limitado em Banda,

que foi amostrado (ou seja, convertido em uma função discreta), pode ser recuperado a partir de uma

sequência infinita de amostras, se a taxa de amostragem for maior que 2Fm amostras por segundo.

Porém, se um sinal contiver uma componente exatamente em Fm Hertz, e amostras espaçadas de

exatamente 1/(2Fm) segundos, não se consegue recuperar totalmente o sinal

É necessário também definir as funções relativas a comunicação serial. Uma explicação sobre essa

aplicação no DLL do PSIM© está disponível em (3) e (4). Para isso, foram definidos os vetores e

protótipos de função que servem para enviar e receber dados. Na escrita, foi usada a variável auxTx

para receber os dados em 16 bits e passá-los para inteiro, a bufferTx para dividi-los em duas partes e

transmiti-los em 8 bits. Na leitura dos dados recebidos, os dados em 8 bits são concatenados para 16

bits usando a variável auxRx.

Esses dados são manipulados no bloco DLL do PSIM© pelas funções OPENSIMUSER, RUNSIMUSER e

CLOSESIMUSER. A função OPENSIMUSER é executada no início da simulação e serve para abrir a porta

serial e configurá-la de acordo com o padrão do sistema operacional. A RUNSIMUSER é a função que, de

fato, vai ler e escrever os dados transferidos. Já a CLOSESIMUSER só é executada no final da simulação e

serve para fechar a porta serial. A configuração das portas também foi feita de acordo com o exemplo

encontrado em (3).

O código desenvolvido está disponível no Anexo [1].

2.2 CÓDIGO DO MPLABX PARA HIL Como já mencionado, o microprocessador utilizado é o dsPIC33F64MC802 da Microchip©. O código que

roda no dsPIC foi desenvolvido em linguagem C, no ambiente de desenvolvimento MPLAB IDE,

utilizando o compilador MPLAB C30 da Microchip.

O código inicia na função Main () com a configuração dos PORTS de I/O e inicialização das variáveis. Os

periféricos são configurados e iniciados com a função uart_init (), inicia a comunicação UART a 9600 bps,

8 bits de dados, sem paridade e 1 bit de parada.

Após os dados serem recebidos pelo dsPIC, o cálculo da FFT é feito pela função FFTComplexIP (), que

pertence à biblioteca DSP Library, assim como as três funções citadas a seguir. A seguir, os dados – que

já se encontram no domínio da frequência – são organizados pela função BitReverseComplex () e,

posteriormente, o sinal complexo é convertido para real através da função SquareMagnitudeCplx ().

Feito isso, a função VetorMax () retorna o índice da frequência de maior espectro, que é utilizado para

se calcular a frequência de maior espectro do sinal, que será lido no computador. Essas funções fazem

parte da DSP Library, que é chamada no código principal. A função transmite_dados () envia os dados

das 64 frequências para o computador, são enviados primeiramente a parte inteira, depois a parte

decimal e 3 bytes para controle da comunicação. O PSIM lê os dados e analisa os espectros de

frequência.

O código desenvolvido está disponível no Anexo [2].

3 SIMULAÇÃO

O circuito do inversor está mostrado na Figura 1. O controle foi feito utilizando-se a técnica de

modulação PMW de forma discreta, para otimizar o processamento do dsPIC.

Figura 1. Circuito inversor no PSIM

Para utilizar a DLL, como já mencionado no primeiro item, foi adicionado ao circuito o bloco DLL

disponível na biblioteca do PSIM©. A entrada do bloco é a tensão na qual será analisado o espectro e a

saída e essa forma de onda analisada.

Para criar a biblioteca dinâmica, foi criado no Microsoft Visual Studio um novo projeto formato DLL em

branco e adicionar nele o código fonte em C, como foi mostrado no item 2.1. Aberto o código fonte, foi

feito o debug, que gerou o arquivo .dll, posteriormente copiado para a pasta de simulação do onde

estava o circuito. O bloco DLL foi, finalmente, editado, com a extensão do arquivo.

4 CONCLUSÃO

Todo o trabalho de densenvolvimento de códigos tanto para o DLL do PSIM quanto para o MPLab foi

feito, faltando apenas a parte final de leitura dos dados no PSIM, que não foi feita.

Por isso, os resultados de simulação não se encontram neste trabalho.

5 BIBLIOGRAFIA

http://www.mat.uel.br/matessencial/superior/pdfs/tfourier.pdf (1)

http://www.powersimtech.com/download/VC2010_Express.zip(2)

http://www.psim-europe.com/openload2.php?doc=Tutorial-Using_SCI_for_Real-

Time_Monitoring_in_TI_F28335_Target.pdf (3)

http://www.psim-europe.com/openload2.php?doc=Help_Embedded_Software_Block.pdf (4)

http://conservancy.umn.edu/bitstream/140662/1/Rajavel_Tamil_July2012.pdf (5)

6 ANEXOS

6.1 CÓDIGO DA DLL // TestBlock3.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include <math.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include "psimutil.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } // Simulation Functions DCB PortDCB; HANDLE hPort; COMMTIMEOUTS CommTimeouts; int i; unsigned int auxTx = 0; unsigned int auxRx = 0; char bufferTx[2 + 1] = {0}; char bufferRx[2 + 1] = {0}; int countRx = 0; DWORD dwNumBytesWritten; DWORD dwBytesTransferred; extern "C" __declspec(dllexport) void OPENSIMUSER(const char *szId, const char * szNetlist, void ** ptrUserData, int *pnError, LPSTR szErrorMsg, void * pPsimParams); extern "C" __declspec(dllexport) void RUNSIMUSER(double t, double delt, double *in, double *out, void ** ptrUserData, int *pnError, LPSTR szErrorMsg); extern "C" __declspec(dllexport) void CLOSESIMUSER(const char *szId, void ** ptrUserData);

extern "C" __declspec(dllexport) void OPENSIMUSER(const char *szId, const char * szNetlist, void ** ptrUserData, int *pnError, LPSTR szErrorMsg, void * pPsimParams) { /* Openning Port ------------------------------------------------------------*/ // Open the serial port. hPort = CreateFile( "COM8" , GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); /* Configuring Port ---------------------------------------------------------*/ PortDCB.DCBlength = sizeof (DCB); GetCommState(hPort, &PortDCB); PortDCB.BaudRate = 9600; // Current baud PortDCB.ByteSize = 8; // Number of bits/byte, 4-8 ------------- PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 -------------------- PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space ----------- SetCommState (hPort, &PortDCB); // Configuring Timeout -------------------------------------------------------- GetCommTimeouts (hPort, &CommTimeouts); CommTimeouts.ReadIntervalTimeout = 500; CommTimeouts.ReadTotalTimeoutMultiplier = 500; CommTimeouts.ReadTotalTimeoutConstant = 100; CommTimeouts.WriteTotalTimeoutMultiplier = 500; CommTimeouts.WriteTotalTimeoutConstant = 100; SetCommTimeouts (hPort, &CommTimeouts); } __declspec(dllexport) void RUNSIMUSER(double t, double delt, double *in, double *out, void ** ptrUserData, int *pnError, LPSTR szErrorMsg) { /* Writing ----------------------------------------------------------------*/ for(i=0; i<1; i++) // indice do looping eh referente a quantidade de entradas do bloco dll { auxTx = (unsigned int) (in[i]); // 12 bits resolucao bufferTx[1] = auxTx & 0xFF; bufferTx[0] = (auxTx >> 8) & 0xFF; WriteFile (hPort, bufferTx, 2, &dwNumBytesWritten, NULL); } /* Reading ------------------------------------------------------------------*/ ReadFile(hPort, bufferRx, 2, &dwBytesTransferred, NULL); auxRx = ((bufferRx[0] & 0x00FF) << 8) | (bufferRx[1] & 0x00FF); out[0] = (double) auxRx; /* ReadFile(hPort, bufferRx, 2, &dwBytesTransferred, NULL); auxRx = ((bufferRx[1] & 0x00FF) << 8) | (bufferRx[0] & 0x00FF); out[1] = (double) auxRx; ReadFile(hPort, bufferRx, 2, &dwBytesTransferred, NULL);

auxRx = ((bufferRx[1] & 0x00FF) << 8) | (bufferRx[0] & 0x00FF); out[2] = (double) auxRx; */ } __declspec(dllexport) void CLOSESIMUSER(const char *szId, void ** ptrUserData) { /* Closing Port -------------------------------------------------------------*/ CloseHandle(hPort); }

6.2 CÓDIGO DO MPLABX

/*** PROJETO DE MICROCONTROLADORES LÍVIA LISANDRO JUDICE GODOY UFRJ - 2014.1 O CÓDIGO A SEGUIR: - Analisa o espectro de frequencia atraves da Transformada Rapida de Fourier - FFT - Indica a frequencia com maior espectro e seu modulo - Envia o espectro de frequencia para o PSIM atraves da UART - Dados da FFT: Pontos: 128; 128 amostragens no tempo transformarao em 128 pontos de frequencia fs: 7,68 kHz; taxa de amostragem fo: 60 Hz; passo entre as frequencias */ //------------------ Inclui funções auxiliares ------------------------- #include "dsp.h" #include "p33Fxxxx.h" #include "fft.h" #include <timer.h> #include <outcompare.h> #include <uart.h> #include <stdio.h> #include "def.h" //---------------------- Define constantes ------------------------------- #define display PORTB //----------------- Declaração de variaveis globais----------------------------------- fractional sinal_Entrada [128]= { //vetor que ira armazenar os dados de entrada, declarados para simulacao. tb testa o programa. 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001,

0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x8001, 0x8001, 0x8001}; unsigned char *TXPtr; unsigned int n, buffer, buffercheio, dado, buffer16; float tempFloat, modulo; int picoFrequenciaBin = 0; unsigned long picoFrequencia = 0; fractional *temp3_pnt, tempFrac; // Entrada do sinal para a FFT declarada na memoria Y fractcomplex sinalComplexo[PONTOS_FFT]__attribute__ ((section (".ydata, data, ymemory"),aligned (PONTOS_FFT * 2 *2))); // ------------- Declara constantes ------------------------- // declara vetor dos coeficientes Twiddle da FFT na memoria de programa // Define 128 constantes "twiddle" da FFT: WN (kn) = exp [-(j*2*pi*k*n)/N] const fractcomplex twiddleFactors[] __attribute__ ((space(prog), aligned (PONTOS_FFT*2)))= { 0x7FFF, 0x0000, 0x7FD9, 0xF9B8, 0x7F62, 0xF374, 0x7E9D, 0xED38, 0x7D8A, 0xE707, 0x7C2A, 0xE0E6, 0x7A7D, 0xDAD8, 0x7885, 0xD4E1, 0x7642, 0xCF04, 0x73B6, 0xC946, 0x70E3, 0xC3A9, 0x6DCA, 0xBE32, 0x6A6E, 0xB8E3, 0x66D0, 0xB3C0, 0x62F2, 0xAECC, 0x5ED7, 0xAA0A, 0x5A82, 0xA57E, 0x55F6, 0xA129, 0x5134, 0x9D0E, 0x4C40, 0x9930, 0x471D, 0x9592, 0x41CE, 0x9236, 0x3C57, 0x8F1D, 0x36BA, 0x8C4A, 0x30FC, 0x89BE, 0x2B1F, 0x877B, 0x2528, 0x8583, 0x1F1A, 0x83D6, 0x18F9, 0x8276, 0x12C8, 0x8163, 0x0C8C, 0x809E, 0x0648, 0x8027, 0x0000, 0x8000, 0xF9B8, 0x8027, 0xF374, 0x809E, 0xED38, 0x8163, 0xE707, 0x8276, 0xE0E6, 0x83D6, 0xDAD8, 0x8583, 0xD4E1, 0x877C, 0xCF04, 0x89BE, 0xC946, 0x8C4A, 0xC3A9, 0x8F1D, 0xBE32, 0x9236, 0xB8E3, 0x9592, 0xB3C0, 0x9931, 0xAECC, 0x9D0E, 0xAA0A, 0xA129,

0xA57E, 0xA57E, 0xA129, 0xAA0A, 0x9D0E, 0xAECC, 0x9931, 0xB3C0, 0x9592, 0xB8E3, 0x9236, 0xBE32, 0x8F1D, 0xC3A9, 0x8C4A, 0xC946, 0x89BE, 0xCF04, 0x877C, 0xD4E1, 0x8583, 0xDAD8, 0x83D6, 0xE0E6, 0x8276, 0xE707, 0x8163, 0xED38, 0x809E, 0xF374, 0x8027, 0xF9B8 } ; //----------------- Declara funcoes ------------------------------------------ void delayms (); void delayus (); void barg1 (); void envia_mensagem(char *pointer); //----------------- funcoes externas --------------------------------- // calcula a magnitude quadrada do vetor complexo extern void SquareMagnitudeCplx(int, fractcomplex*, fractional*); buffer++; //incrementa numero de amostragem if(buffer >= PONTOS_FFT) //confere se buffer de entrada esta cheio { buffer = 0; buffercheio = 1; DisableIntT1 ; //desabilita interrupcao do timer para executar os calculos da FFT } IFS0bits.T1IF = 0; /* limpa flag de interrupcao do timer */ void uart_init () //inicia modulo de comunicacao UART2, 9600,8,0,1 { unsigned int U2MODEvalue, U2STAvalue, baud; CloseUART2(); //fecha porta UART2 ConfigIntUART2 (UART_RX_INT_DIS & UART_RX_INT_PR5 & UART_TX_INT_DIS & UART_TX_INT_PR3); //configura interrupcoes UART2------ desabilitado interrupcoes baud = 191; //30 MIPS MHz e 9600 bps U2MODEvalue = UART_EN & UART_IDLE_CON & UART_RX_TX & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT; U2STAvalue = UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_3_4_FUL & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR ;

OpenUART2(U2MODEvalue, U2STAvalue, baud); //inicia UART2 } //********************** Envia dados para o computador pela serial UART *************** void transmite_dados () { unsigned int dadotx; int a, modulo_int; float modulo_dec; //-------------------------------------------------------------------- dadotx = 252; // inicio do bloco de dados while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); //-------------------------------------------------------------------- //envia parte inteira dos 64 sinais for ( a = 0; a < PONTOS_FFT/2; a++ ) //envia modulo das 64 frequencias pela serial { // Encontra o modulo de cada frequencia temp3_pnt = &sinalComplexo[0].real ; //inicializa ponteiro temp3_pnt = temp3_pnt + a; tempFrac = *temp3_pnt; tempFloat = tempFrac; tempFloat = tempFloat / 32767; // Converte fracionario para float modulo = sqrt (tempFloat); // Extrai a raiz quadrada da soma dos quadrados da parte real/imaginaria dadotx = (modulo * 100); // Escalona o sinal para enviar pela serial while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); } //------------------------------------------------------------------------ dadotx = picoFrequenciaBin + 65;//envia indice de maior frequencia while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); //------------------------------------------------------------------ dadotx = 253; //checa envio do bloco de dados while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); //------------------------------------------------------------------ //envia parte decimal dos 64 sinais for ( a = 0; a < PONTOS_FFT/2; a++ ) //envia modulo das 64 frequencias pela serial { // Encontra o modulo de cada frequencia temp3_pnt = &sinalComplexo[0].real ; //inicializa ponteiro temp3_pnt = temp3_pnt + a; tempFrac = *temp3_pnt; tempFloat = tempFrac;

tempFloat = tempFloat / 32767; // Converte fracionario para float modulo = sqrt (tempFloat); // Extrai a raiz quadrada da soma dos quadrados da parte real/imaginaria modulo_int = (modulo * 100); //encontra a partem inteira do sinal modulo_dec = (modulo * 100) - modulo_int; //encontra a parte decimal do sinal dadotx = (modulo_dec * 100); //escalona para enviar pela serial if ( dadotx > 164 ) dadotx = 164; //limita parte decimal de 0 a 99 while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); } //------------------------------------------------------------------ dadotx = 254; // fim do bloco de dados while(BusyUART2()); //aguarda fim da ultima transmissao WriteUART2(dadotx); //envia delayms(1); } //*********************************** MAIN int main (void) //inicio do programa { int i = 0; fractional *p_real = &sinalComplexo[0].real ; fractcomplex *p_complexo = &sinalComplexo[0] ; //-------------- Inicia pinos de I/O do dsPIC ---------------------------------- TRISB = 0xff0f; TRISFbits.TRISF0 = 0; TRISDbits.TRISD0 = 0; TRISDbits.TRISD1 = 0; //------------------ Inicia variaveis ------ n = 0; buffer = 0; buffercheio = 0; tempFloat = 0; //-----Inicia perifericos do dsPIC ----- uart_init (); //inicializa comunicacao UART

init_timer1 (); //inicia timer1 para interromper a 7,68 k samples //---- Envio de mensagem ao PSIM while (1) //loop infinito { if (buffercheio) //confere se chegou fim das amostragens { p_real = &sinalComplexo[0].real ; //inicializa ponteiro p_complexo = &sinalComplexo[0]; //inicializa ponteiro for ( i = 0; i < PONTOS_FFT; i++ ) //move buffer do sinal de entrada (real)para vetor da FFT { *p_real = sinal_Entrada [i] ; *p_real++; //incrementa o ponteiro } p_real = &sinalComplexo[0].real ; //inicializa ponteiro for ( i = 0; i < PONTOS_FFT; i++ ) //Escalona o vetor para o range [-0.5, +0.5] { *p_real = *p_real >>1 ; //desloca 1 bit para a direita *p_real++; } p_real = &sinalComplexo[(PONTOS_FFT/2)-1].real ; //inicializa o ponteiro para parte real do vetor p_complexo = &sinalComplexo[PONTOS_FFT-1] ; for ( i = PONTOS_FFT; i > 0; i-- ) //Converte vetor real para vetor complexo { (*p_complexo).real = (*p_real--); (*p_complexo--).imag = 0x0000; //Não possui parte imaginaria, escreve valor zero } // Cálculo da FFT - Transformada Rapida de Fourier FFTComplexIP (LOG2_ESTAGIOS_BUTTERFLY, &sinalComplexo[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));

// Organiza dados da saída da FFT - Bit-reverso BitReverseComplex (LOG2_ESTAGIOS_BUTTERFLY, &sinalComplexo[0]); // Calcula a soma do quadrado das partes real e imaginária transformando vetor complexo em um vetor real. Sinal = real^2 + imaginario^2 SquareMagnitudeCplx(PONTOS_FFT, &sinalComplexo[0], &sinalComplexo[0].real); // Encontra a frequency Bin ( indice da frequencia) que possui a maior energia VectorMax(PONTOS_FFT/2, &sinalComplexo[0].real, &picoFrequenciaBin); // Calcula a frequencia em Hz com maior espectro picoFrequencia = picoFrequenciaBin*(TAXA_AMOSTRAGEM/PONTOS_FFT); // Encontra o modulo da frequencia de pico temp3_pnt = &sinalComplexo[0].real ; //inicializa ponteiro temp3_pnt = temp3_pnt + picoFrequenciaBin; tempFrac = *temp3_pnt; tempFloat = tempFrac; tempFloat = tempFloat / 32767; // Converte fracionario para float modulo = sqrt (tempFloat); // Extrai a raiz quadrada da soma dos quadrados da parte real/imaginaria //tempFloat = Fract2Float (tempFrac); //converte fracional para float, usando funcao da biblioteca DSP //modulo = sqrt (tempFloat); // Extrai a raiz quadrada da soma dos quadrados da parte real/imaginaria linha2 (11); //posiciona cursor do LCD buffer16 = modulo*100000; //ajusta valor para indicar no LCD lcdval16(); //envia modulo da frequencia para lcd linha1 (4); //posiciona cursor do LCD buffer16 = picoFrequencia; lcdval16(); //envia frequencia de pico para lcd transmite_dados (); //transmite dados pela serial UART (RS232) buffercheio = 0; EnableIntT1 ; //habilita interrupcao do timer para reiniciar amostragens } } } /* Fim */

top related