TODOPIC
Microcontroladores PIC => dsPIC => Mensaje iniciado por: carlosvalencia en 17 de Octubre de 2008, 14:54:22
-
Amigos:
les cuento, estoy desarrollando mi proyecto de titulo y se trata de lo siguiente:
Programar la FFT en un dspic30F4013, el cual estara tomando lecturas de sensores conectados a los ADC del dspic. El sistema consta de 2 esclavos y un maestro. El maestro es un PIC16F876A y los esclavos son dspic30F4013. La comunicacion entre los dispositivos es de manera inalambrica con tres antenitas de RF, entonces el esquema de comunicacion es el siguiente:
Maestro envia un caracter "1" al aire, Esclavo 1 responde cuando recibe un caracter 1, tomando 128 datos del sensor, realizando la FFT y enviando los datos de vuelta para que el maestro los envie a un PC. Asimismo para el Esclavo 2 solo que maestro enviara un caracter 2 al aire y respondera el esclavo 2.
La FFT ya la tengo programada y funcionando, conecto el dspic a mi pc y puedo ver los resultados de la FFT , los que han sido corroborados con MATLAB.
El problema que tengp ahora es para armar el sistema completo, necesito que los esclavos reciban los caracteres que envia maestro y es ahi donde me he complicado un monton, pues no se como insertar en micodigo la funcion para recibir un caracter y para luego enviar el buff con los datos del resultado de la FFT. les dejo el codigo para que me hagan sus comentarios.
#include <p30F4013.h>
#include <dsp.h>
#include "fft.h"
#include <stdio.h>
/* Device configuration register macros for building the hex file */
_FOSC(CSW_FSCM_OFF & XT_PLL16); /* XT with 16xPLL oscillator, Failsafe clock off */
_FWDT(WDT_OFF); /* Watchdog timer disabled */
_FBORPOR(PBOR_OFF & MCLR_EN); /* Brown-out reset disabled, MCLR reset enabled */
_FGS(CODE_PROT_OFF); /* Code protect disabled */
/* Entrada a la FFT*/
fractcomplex sigCmpx[FFT_BLOCK_LENGTH] __attribute__ ((section (".ydata, data, ymemory"), aligned (FFT_BLOCK_LENGTH * 2 *2)));//vector de entrada FFT
fractional inputSignal[FFT_BLOCK_LENGTH];
fractional Hn[FFT_BLOCK_LENGTH]; //aloja ventana
/* Definiciones globales*/
int offset;
int doFFT;
fractional *p_real;
fractional *iPtr;
fractional *Hptr;
#define RD2 LATDbits.LATD2 //hacer parpadear
#define RD1 LATDbits.LATD1 //hacer parpadear
#define RD0 LATDbits.LATD0 //hacer parpadear
extern int adcPtr;
extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]__attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2)));
float a,b;
int e,d;
int main(void)
{
int i;
TRISDbits.TRISD2=0;
TRISDbits.TRISD1=0;
TRISDbits.TRISD0=0;
iPtr = &inputSignal[0] ; //inicializa puntero
Hptr = &Hn[0]; //inicializa puntero al primer elemento de la ventana Hn
HanningInit(FFT_BLOCK_LENGTH, Hptr); //genera la ventana (la campana)
doFFT=0;
RD0=1;
RD1=1;
RD2=1;
delay_ms(1000);
RD1=0;
RD0=0;
RD2=0;
init_adc();
while(1)
{
if(doFFT)
{
init_uart(1);
adc_int(0); //desactiva interrupción ADC
iPtr=&inputSignal[0]; //inicializa puntero
RD0=1;//para comprobar
delay_ms(200);
RD0=0;
RD2=1;
VectorWindow(/*20uS*/FFT_BLOCK_LENGTH, iPtr, iPtr, Hptr);//Aplica ventana
for(i=0;i<FFT_BLOCK_LENGTH;i++)
{
printf(" xn,%f\n\r",Fract2Float(inputSignal ) );
}
for(/*40uS*/i=0;i<FFT_BLOCK_LENGTH;i++) //Llena el vector complejo con data del CAD
{
sigCmpx.real=inputSignal;
sigCmpx.imag=0;
}
// printf("sigCmpx");
// for(i=0;i<FFT_BLOCK_LENGTH;i++)
// { /*imprime señal dentro del vector complejo (comprobación)*/
// printf("\n \r %f + j*%f",Fract2Float(sigCmpx.real ),Fract2Float(sigCmpx.imag ) );
// }
//
/*calcula FFT*/ //FFT queda en sigCmpx
FFTComplexIP (/*320uS*/LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));
/* Ordena en órden correcto*/
BitReverseComplex (/*32uS*/LOG2_BLOCK_LENGTH, &sigCmpx[0]);
// printf("Xw");
// for(i=0;i<FFT_BLOCK_LENGTH;i++)
// { /*imprime salida de FFT*/
// printf("\n \r %f+j*%f",Fract2Float(sigCmpx.real),Fract2Float(sigCmpx.imag));
// }
/* calcula la suma de los cuadrados de cada elemento complejo de sigCmpx*/
SquareMagnitudeCplx(/*18uS*/FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real );
RD2=0;
RD1=1;
delay_ms(500);
RD1=0;
doFFT=0,
iPtr=&inputSignal[0];
adc_int(1); //activa la interrupción ADC
}
}
}
Este codigo agrega las librerias fft.h dsp.h stdio.h , trabajo con un cristal de 7,3Mhz a 16Khz 30MIPS app.
Actualmente puedo mostrar en pantalla el resultado de la FFT, lo que necesito ahora es recibir un dato por UART y luego realizar la FFT, para posterior enviar el resultado por UART
Encontre este codigo aca mismo pero nose como agregarlo en mi programa, es claro que debo definirme por UART1 o UART2, el codigo que encontreesta para UART2
void __attribute__((__interrupt__)) _U2RXInterrupt(void)
{
IFS1bits.U2RXIF = 0; // borra bit señalador de interrupción de recepción
pulsado = ReadUART2();
datos_uart[indice_datos]=pulsado;
indice_datos++;
}
/*FIN INTERRUPCIÓN UART2*******************/
void configura_uart(void)
{
unsigned int baudvalue; /* Pone el valor del registro baud */
unsigned int U2MODEvalue; /* Pone el valor del registro de configuración de la uart*/
unsigned int U2STAvalue; /* Modos de interrupción de TX y RX*/
__C30_UART=2; //Le digo que voy a utilzar la usart2
CloseUART2(); /* Apaga el modulo UART2 */
/* Configura las interrupciones de la UART2, transmisión y recepción */
ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR6 & UART_TX_INT_DIS & UART_TX_INT_PR2);
/* Configura el modulo UART2 para transmitir con 8 bits de datos y uno de parada */
baudvalue = 191; //9600 baudios
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_CHAR &
UART_ADR_DETECT_DIS &
UART_RX_OVERRUN_CLEAR;
OpenUART2(U2MODEvalue, U2STAvalue, baudvalue); //Inicializa la uart
}
Amigos espero su ayuda.... y de ante mano ya muchas gracias!!!
-
Que pasa si en al informacion de los datos .. se envia un caracter 2 o 1 ... ???
-
Hola, estas son las funciones GetCom y SedCom que te hablaba, las puedes usar asi:
#include <p30f4013.h>
// definición de librerías y funciones
float REF;
int ACT;
char orden;
void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void);
void SendCom(unsigned int k, char *p);
void GetCom(unsigned int k, char *p);
vo¡d configUART2();
extern int __C30_UART;
void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void)
{
IEC1bits.U2RXIE=0;
GetCom(sizeof(orden),(char *)&orden);
IEC1bits.U2RXIE=1;
IFS1bits.U2RXIF=0;
}
void SendCom(unsigned int k, char *p)
{
for(;k;--k)
{
while(BusyUART2()==1);
putcUART2(*p);
p++;
}
}
void GetCom(unsigned int k, char *p)
{
for(;k;--k)
{
while(DataRdyUART2()==0);
*p=getcUART2();
p++;
}
}
int main (void)
{
__C30_UART=2; //Para utilizar la UART2.
configUART2();
putcUART2('B');
SendCom(sizeof(REF),(char *)&REF);
SendCom(sizeof(ACT),(char *)&ACT);
.....
.....
}
Debes configurar configUART2()
saludos,,
-
muchas gracias por tu respuesta renatox... te comentare como me va con esto....
-
Una duda, Renatox.
Interpreto que esas funciones convierten los números a cadenas de caracteres y los envían uno a uno por la USART.
Si esto es así, ¿cómo formatean esas cadenas?, especialmente me interesa saberlo en el caso de los float con decimales.
-
hola...
les cuento... logre recibir un caracter desde hyperterminal, hace la funcion que le indico, ahora... al agregarlo en mi codigo se queda pegado y no entra hacer la FFT, alguien podria echarme una manito con eso... la idea que tengo es asi:
- Enviar caracter al dspic (en este caso un 1)
- recibo un caracter y lo almaceno en una variable del tipo char
- luego
getcUART2(); // Recibe dato desde UART2
if(dato == '1') // Si dato es igual a 1 entra
{
init_adc()
}
if(doFFT)
{ HACE LA FFT ... PERO NO ENTRA SE QUEDA PEGADO... }
como se que se qeuda pegado? por unos leds indicadores que muestran como va la FFT.
espero que me ayuden y gracias nuevamente.... saludos a todos
-
Una duda, Renatox.
Interpreto que esas funciones convierten los números a cadenas de caracteres y los envían uno a uno por la USART.
Si esto es así, ¿cómo formatean esas cadenas?, especialmente me interesa saberlo en el caso de los float con decimales.
Para pasar de cadena de caracteres a un numero se usa la funcion atof para flotantes y atoi para enteros ... esto no es novedad ... el problema está en pasar de flotante a cadena de caracteres ... en este caso hay que considerar el tamaño de la cadena y el espacio donde se almacenará ... implementé esto una vez en un proyecto y como tenia un rango definido de números ( de -99.99 a 99.999 ) supuse que con 6 caracteres estaria bien y hice la siguiente rutina:
#define ASCII_NUMBERS 6
void float2ascii( char * dest_ptr, float value )
{
float ref1 = 1.0;
char dot = 0;
char i = 0;
if( value >= 10.0 ) ref1 = 10.0;
if( value < 0 )
{
*(dest_ptr) = '-';
i++;
value = -value;
}
for( ; i <= (ASCII_NUMBERS-1) ; i++ )
{
*(dest_ptr + i) = (char)( value / ref1 ); //El resultado siempre redondea hacia abajo
value -= (*(dest_ptr + i))*ref1; //Se actualiza el valor
*(dest_ptr + i) += 0x30; //Se convierte a ASCII
if( (value < 1.0) & (dot == 0) ) //Verifica si ya se llegó al punto
{
i++;
*(dest_ptr + i) = '.';
dot = 1;
}
ref1 = ref1/10.0;
}
}
El primer termino es un puntero a un arreglo de datos de tamaño ASCII_NUMBERS, el segundo es el valor en flotante a convertir...
Por supuesto ... la rutina la hice rapidamente para terminar el proyecto .. pero seria util una rutina que analice el número flotante y que determine la mejor longitud .. se podria hacer de tal manera que como parametro se aplique la precisión de decimales ..1, 2, 3, 4 ... etc decimales... ademas que devuelva los punteros de inicio y final de la cadena en memoria dinámica... seria bonito hacer esta rutinita para entrenar un poco la mente ... jajaja
Saludos
-
amigos... les cuento nuevamente....
pude compilar el codigo .. pero con el siguiente detalle.... se supone que al presionar la tecla 1 deberia hacer la FFT, pero sucede todo lo contrario... puedo presionar cualkier tecla y entra a la FFT y al presionar la 1 se detiene y queda a la espera de que llegue un numero para meterse a la FFT.
Les dejo el codigo para que opinen.
#include <p30F4013.h>
#include <dsp.h>
#include "fft.h"
#include <stdio.h>
#include <uart.h>
//////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////* CONFIGURACION DEL DISPOSITIVO *//////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
_FOSC(CSW_FSCM_OFF & XT_PLL16); /* Oscilador XT con 16xPLL */
_FWDT(WDT_OFF); /* Watchdog timer desactivado */
_FBORPOR(PBOR_OFF & MCLR_EN); /* Brown-out reset desactivado, MCLR reset activado */
_FGS(CODE_PROT_OFF); /* Proteccion de codigo desactivada*/
//////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////* ENTRADA A LA FFT *///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
fractcomplex sigCmpx[FFT_BLOCK_LENGTH] __attribute__ ((section (".ydata, data, ymemory"), aligned (FFT_BLOCK_LENGTH * 2 *2)));//vector de entrada FFT
fractional inputSignal[FFT_BLOCK_LENGTH];
fractional Hn[FFT_BLOCK_LENGTH]; //aloja ventana
//////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////* DEFINICION DE VARIABLES*/////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
int doFFT;
int i;
char dato;
float REF;
int ACT;
fractional *p_real;
fractional *iPtr;
fractional *Hptr;
#define RD2 LATDbits.LATD2 //hacer parpadear
#define RD1 LATDbits.LATD1 //hacer parpadear
#define RD0 LATDbits.LATD0 //hacer parpadear
extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2]__attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2)));
//////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////* CONFIGURACION UART 2*///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void);
void SendCom(unsigned int k, char *p);
void GetCom(unsigned int k, char *p);
void configUART2();
extern int __C30_UART;
void configUART2(void)
{
unsigned int baudvalue; // Pone el valor del registro baud
unsigned int U2MODEvalue; // Pone el valor del registro de configuración de la uart
unsigned int U2STAvalue; // Modos de interrupción de TX y RX
__C30_UART=2; // Le digo que voy a utilzar la usart2
CloseUART2(); // Apaga el modulo UART2
ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR6 & UART_TX_INT_DIS & UART_TX_INT_PR2); // Configura las interrupciones de la UART2, transmisión y recepción */
baudvalue = 191; // Configura el modulo UART2 para transmitir con 8 bits de datos y uno de parada
// y a 9600 baudios
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_CHAR &
UART_ADR_DETECT_DIS &
UART_RX_OVERRUN_CLEAR;
OpenUART2(U2MODEvalue, U2STAvalue, baudvalue); // Inicializa la uart
}
//////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////* CONFIGURACION DE INTERRUPCIONES *///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void)
{
IEC1bits.U2RXIE=0; // Interrupcion de recepcion
GetCom(sizeof(dato),(char *)&dato); // Se guarda el dato que se recibe
IEC1bits.U2RXIE=1; // en la variable dato
IFS1bits.U2RXIF=0;
}
void SendCom(unsigned int k, char *p) // Funcion que envia datos
{
for(;k;--k)
{
while(BusyUART2()==1);
putcUART2(*p);
}
}
void GetCom(unsigned int k, char *p) // Funcion que recibe datos
{
//for(;k;--k)
//{
while(DataRdyUART2()==0);
*p=getcUART2();
//}
}
//////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////* PROGRAMA PRINCIPAL *////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
int i;
TRISDbits.TRISD2=0;
TRISDbits.TRISD1=0;
TRISDbits.TRISD0=0;
iPtr = &inputSignal[0] ; //inicializa puntero
Hptr = &Hn[0]; //inicializa puntero al primer elemento de la ventana Hn
HanningInit(FFT_BLOCK_LENGTH, Hptr); //genera la ventana (la campana)
doFFT=0;
RD0=1;
RD1=1;
RD2=1;
delay_ms(1000);
RD1=0;
RD0=0;
RD2=0;
__C30_UART=2; // Para utilizar la UART2.
configUART2(); // Configura la UART2 ;
while(1)
{
getcUART2(); // Recibo dato y lo mando a la variable dato
if(dato == '1')
{
init_adc();
}
if(doFFT)
{
adc_int(0); //desactiva interrupción ADC
iPtr=&inputSignal[0]; //inicializa puntero
RD0=1;//para comprobar
delay_ms(200);
RD0=0;
RD2=1;
VectorWindow(/*20uS*/FFT_BLOCK_LENGTH, iPtr, iPtr, Hptr);//Aplica ventana
// for(i=0;i<FFT_BLOCK_LENGTH;i++)
// {
// printf(" xn,%f\n\r",Fract2Float(inputSignal[i] ) );
// }
//
for(/*40uS*/i=0;i<FFT_BLOCK_LENGTH;i++) //Llena el vector complejo con data del CAD
{
sigCmpx[i].real=inputSignal[i];
sigCmpx[i].imag=0;
}
// printf("sigCmpx");
// for(i=0;i<FFT_BLOCK_LENGTH;i++)
// { /*imprime señal dentro del vector complejo (comprobación)*/
// printf("\n \r %f + j*%f",Fract2Float(sigCmpx[i].real ),Fract2Float(sigCmpx[i].imag ) );
// }
//
/*calcula FFT*/ //FFT queda en sigCmpx
FFTComplexIP (/*320uS*/LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));
/* Ordena en órden correcto*/
BitReverseComplex (/*32uS*/LOG2_BLOCK_LENGTH, &sigCmpx[0]);
printf("Xw");
for(i=0;i<FFT_BLOCK_LENGTH;i++)
{ /*imprime salida de FFT*/
printf("\n \r %f+j*%f",Fract2Float(sigCmpx[i].real),Fract2Float(sigCmpx[i].imag));
}
/* calcula la suma de los cuadrados de cada elemento complejo de sigCmpx*/
SquareMagnitudeCplx(/*18uS*/FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real );
RD2=0;
RD1=1;
delay_ms(500);
RD1=0;
doFFT=0,
iPtr=&inputSignal[0];
adc_int(1); //activa la interrupción ADC
}
}
}
Gracias de nuevo...
-
Hola como están, Carlos esto está mal:
getcUART2(); // Recibo dato y lo mando a la variable dato
No lo debes poner, el dspic porsi solo entra a la rutina de interrupción apenas reciba 1 byte. También has quitado esta linea "p++;" a las rutinas SendCom y GetCom.
Hola Nocturno lo que hace SendCom es enviar los bytes de una variable, por ejm los 4 bytes de un flotante donde el primer dato enviado en el de menos peso. El otro dspic usaría el GetCom para armar nuevamente el dato, por ejm:
en el dspic 1:
float REF=-123.456;
SendCom(sizeof(REF),(char *)&REF);
en el dspic 2:
float REF;
GetCom(sizeof(REF),(char *)&REF);
REF++; // REF=-122.456
En el dspic2 puedes trabajar a REF como flotante.
Blackat cuanto demora tu rutina para convertir un flotante a cadena,,
saludos.
-
En total tardó aproximadamente 7500 ciclos de instrucción. Esto con un dsPIC a 40MIPS seria 0.2ms ... MMMmmm :? :? :? ... dura mucho ¿¿¿verdad???
-
Hola amigo.
he tomado todo este codigo, que se supone es el ejemplo de MPLAB C30, pero en el momento que lo compilo, resulta este error, amigo guiame hazme el favor en eese proceso de compilado, porque realmente no se que hacer.
Debug build of project `C:\Archivos de programa\Microchip\MPLAB C30\proyecto\prueba6.mcp' started.
Language tool versions: pic30-as.exe v3.12, pic30-gcc.exe v3.12, pic30-ld.exe v3.12, pic30-ar.exe v3.12
Preprocessor symbol `__DEBUG' is defined.
Fri Jan 28 12:56:32 2011
----------------------------------------------------------------------
Make: The target "C:\Archivos de programa\Microchip\MPLAB C30\proyecto\prueba6.o" is out of date.
Executing: "C:\Archivos de programa\Microchip\MPLAB C30\bin\pic30-gcc.exe" -mcpu=30F4013 -x c -c "prueba6.c" -o"prueba6.o" -D__DEBUG -g -Wall
prueba6.c:3:17: error: fft.h: No such file or directory
prueba6.c:13: error: 'FFT_BLOCK_LENGTH' undeclared here (not in a function)
prueba6.c:15: error: requested alignment is not a constant
prueba6.c:21: error: requested alignment is not a constant
prueba6.c: In function 'main':
prueba6.c:38: error: 'LOG2_BLOCK_LENGTH' undeclared (first use in this function)
prueba6.c:38: error: (Each undeclared identifier is reported only once
prueba6.c:38: error: for each function it appears in.)
prueba6.c:77: error: 'SAMPLING_RATE' undeclared (first use in this function)
prueba6.c:80:2: warning: no newline at end of file
Halting build on first failure as requested.
----------------------------------------------------------------------
Debug build of project `C:\Archivos de programa\Microchip\MPLAB C30\proyecto\prueba6.mcp' failed.
Language tool versions: pic30-as.exe v3.12, pic30-gcc.exe v3.12, pic30-ld.exe v3.12, pic30-ar.exe v3.12
Preprocessor symbol `__DEBUG' is defined.
Fri Jan 28 12:56:32 2011
----------------------------------------------------------------------
BUILD FAILED