In my project I am using PIC32MX250F128B controller and 23LC1024 SRAM. I have written a code to sample the analog signal from the vibration sensor. For this I am triggering my ADC with the help of timer 3 and have set the sampling freq at 20khz. First I checked my system by giving 50Hz sine wave to a vibration sensor and took the analog samples from there. At that time I was getting the data as my set sampling frequency (20 khz). But when I checked my system to collect vibration data from the motor(with same sensor) my sampling frequency has reduced to only about 200 samples per second. My code is such as I am sampling one data and then displaying that data through serial monitor then again I am sampling data and displaying it. I have attached my code here. Can someone please help me why I am losing this much sampling frequency? Thank you.
#include <p32xxxx.h> // include chip specific header file
#include <plib.h> // include peripheral library functions
#include <stdlib.h>
// Configuration Bits
#pragma config FNOSC = FRCPLL // Internal Fast RC oscillator (8 MHz) w/ PLL
#pragma config FPLLIDIV = DIV_2 // Divide FRC before PLL (now 4 MHz)
#pragma config FPLLMUL = MUL_20 // PLL Multiply (now 80 MHz)
#pragma config FPLLODIV = DIV_2 // Divide After PLL (now 20 MHz)
// DEVCFG1
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_2 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECME // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Enabled)
#pragma config WDTPS = PS1 // Watchdog Timer Postscaler (1:1)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_75 // Watchdog Timer Window Size (Window Size is 75%)
// DEVCFG0
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
// Defines
#define SYSCLK 40000000L
#define RAM_WRITE_CMD (0x2000000) // top 8 bits -- 24 bits for address this is starting point(2^25))
#define RAM_READ_CMD (0x3000000) // top 8 bits -- 24 bits for address(this is recoverable exception)
// Macros
// Equation to set baud rate from UART reference manual equation 21-1
#define Baud2BRG(desired_baud) ( (SYSCLK / (16*desired_baud))-1)
// Function Prototypes
int SerialTransmit(const char *buffer);
unsigned int SerialReceive(char *buffer); //, unsigned int max_size);
int UART2Configure( int baud);
char a2dvals[30000];
int adcptr,num_channels,k,i;
char sampling;
int ADC_RSLT0,totaldata,totaldata1,chunks_sent,data_count,l;
short temp;
BOOL a2don;
volatile unsigned int channel4;
volatile SpiChannel spiChn = SPI_CHANNEL2 ; // the SPI channel to use
volatile int spiClkDiv = 2 ; // 20 MHz max speed for this RAM
int dummy,dummy1,junk;
unsigned char tempstr[5];
inline void Mode16(void){ // configure SPI2 for 16-bit mode
SPI2CONSET = 0x400;
SPI2CONCLR = 0x800;
}
inline void Mode8(void){ // configure SPI2 for 8-bit mode
SPI2CONCLR = 0x400;
SPI2CONCLR = 0x800;
}
inline void Mode32(void){ // configure SPI2 for 32-bit mode
SPI2CONCLR = 0x400;
SPI2CONSET = 0x800;
}
void modesetbyte(){
int junk;
Mode16();
mPORTBClearBits(BIT_0);
WriteSPI2(0x0100);
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2();
mPORTBSetBits(BIT_0);
}
//void modesetsequential(){
//int junk;
//Mode16();
//mPORTBClearBits(BIT_0);
//WriteSPI2(0x0140);
//while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
//junk = ReadSPI2();
//mPORTBSetBits(BIT_0);
//}
void ram_write_byte(int addr, char data){
int junk;
// set 32-bit transfer for read/write command ORed with
Mode32();
mPORTBClearBits(BIT_0);
WriteSPI2(RAM_WRITE_CMD | addr); // addr not greater than 17 bits
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2(); // must always read, even if nothing useful is returned
Mode8();// actual address// set 8-bit transfer for each byte
WriteSPI2(data); // data write
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2();
//mPORTBSetBits(BIT_0);
return ;
}
int ram_read_byte(int addr){
int junk, data;
Mode32();
mPORTBClearBits(BIT_0);
WriteSPI2(RAM_READ_CMD | addr); // addr not greater than 17 bits
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2();
Mode8();
WriteSPI2(junk); // force the read
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
data = ReadSPI2();
//mPORTBSetBits(BIT_0);
return data;
}
void __ISR(_ADC_VECTOR, IPL2AUTO) ADCHandler(void) // Fonction d'interruption Timer 3
{
int junk;
mAD1ClearIntFlag();
//junk = 0xcccc;
PORTBbits.RB7 ^= 1;
temp = ReadADC10(0);
WriteSPI2((temp&0x300)>>8);
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2();
WriteSPI2(temp&0x0ff);
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
junk = ReadSPI2();
//a2dvals[k] = (temp);
k++;
if (k>totaldata1)// && sampling == 's')
{
T3CONCLR = 0x8000;
mPORTBSetBits(BIT_0);
a2don=FALSE;
chunks_sent = 0;
totaldata = k/2;
k = 1;
PORTBbits.RB7 = 0;
}
}
void main(void)
{
char buf[1024]; // declare receive buffer with max size 1024
//volatile SpiChannel spiChn = SPI_CHANNEL2 ; // the SPI channel to use
//volatile int spiClkDiv = 4 ; // 20 MHz max speed for this RAM
PPSOutput(2, RPB5, SDO2);//SDO2 (MOSI) is in PPS output group 2, could be connected to RPB5 which is pin 14
PPSInput(3,SDI2,RPA2);//SDI2 (MISO) is PPS output group 3, could be connected to RPA2 which is pin 9
mPORTBSetPinsDigitalOut(BIT_0);//
mPORTBSetBits(BIT_0);
SpiChnOpen(spiChn, SPI_OPEN_ON | SPI_OPEN_MODE16 | SPI_OPEN_MSTEN | SPI_OPEN_CKE_REV , spiClkDiv);
PPSInput (2, U2RX, RPB11); //Assign U2RX to pin RPB11 -- Physical pin 22 on 28 PDIP
PPSOutput(4, RPB10, U2TX); //Assign U2TX to pin RPB10 -- Physical pin 21 on 28 PDIP
SYSTEMConfigPerformance(SYSCLK);
UART2Configure(9600); // Configure UART2 for a baud rate of 9600
U2MODESET = 0x8000; // enable UART2
ANSELBbits.ANSB2 = 1; // set RB2 (AN4) to analog
TRISBbits.TRISB2 = 1; // set RB2 as an input
//adcConfigureManual(); // Configure ADC
//AD1CON1SET = 0x8000; // Enable ADC
SYSTEMConfig(SYSCLK, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
// the ADC ///////////////////////////////////////
// configure and enable the ADC
CloseADC10(); // ensure the ADC is off before setting the configuration
// define setup parameters for OpenADC10
// Turn module on | ouput in integer | trigger mode auto | enable autosample
// ADC_CLK_AUTO -- Internal counter ends sampling and starts conversion (Auto convert)
// ADC_AUTO_SAMPLING_ON -- Sampling begins immediately after last conversion completes; SAMP bit is automatically set
// ADC_AUTO_SAMPLING_OFF -- Sampling begins with AcquireADC10();
#define PARAM1 ADC_MODULE_ON|ADC_FORMAT_INTG32 | ADC_CLK_TMR | ADC_AUTO_SAMPLING_ON //
// define setup parameters for OpenADC10
// ADC ref external | disable offset test | disable scan mode | do 1 sample | use single buf | alternate mode off
#define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF
//
// Define setup parameters for OpenADC10
// use peripherial bus clock | set sample time | set ADC clock divider
// ADC_CONV_CLK_Tcy2 means divide CLK_PB by 2 (max speed)
// ADC_SAMPLE_TIME_5 seems to work with a source resistance < 1kohm
#define PARAM3 ADC_CONV_CLK_SYSTEM | ADC_SAMPLE_TIME_5 | ADC_CONV_CLK_Tcy2 //ADC_SAMPLE_TIME_15| ADC_CONV_CLK_Tcy2
// define setup parameters for OpenADC10
// set AN4 and as analog inputs
#define PARAM4 ENABLE_AN4_ANA
// define setup parameters for OpenADC10
// do not assign channels to scan
#define PARAM5 SKIP_SCAN_ALL
// use ground as neg ref for A | use AN4 for input A
// configure to sample AN4
SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN4 ); // configure to sample AN4
OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using the parameters defined above
ConfigIntADC10(ADC_INT_PRI_2 | ADC_INT_ON);
EnableADC10(); // Enable the ADC
OpenTimer3(T3_ON | T3_SOURCE_INT | T3_PS_1_1,2000);
INTEnableSystemMultiVectoredInt();
mPORTBSetPinsDigitalOut(BIT_7); //Set port as output
PORTBbits.RB7 = 0;
SerialTransmit("Hello! Enter 'a' to do ADC conversion \r\n");
unsigned int rx_size;
while( 1){
rx_size = SerialReceive(buf); //, 1024); // wait here until data is received
SerialTransmit(buf); // Send out data exactly as received
SerialTransmit("\r\n");
}
/*while(1)
{
while(a2don);
a2don=TRUE;
}*/
return 1;
} // END main()
/* UART2Configure() sets up the UART2 for the most standard and minimal operation
* Enable TX and RX lines, 8 data bits, no parity, 1 stop bit, idle when HIGH
* Input: Desired Baud Rate
* Output: Actual Baud Rate from baud control register U2BRG after assignment*/
int UART2Configure( int desired_baud){
U2MODE = 0; // disable autobaud, TX and RX enabled only, 8N1, idle=HIGH
U2STA = 0x1400; // enable TX and RX
U2BRG = Baud2BRG(desired_baud); // U2BRG = (FPb / (16*baud)) - 1
// Calculate actual assigned baud rate
int actual_baud = SYSCLK / (16 * (U2BRG+1));
return actual_baud;
} // END UART2Configure()
/* SerialTransmit() transmits a string to the UART2 TX pin MSB first
*
* Inputs: *buffer = string to transmit */
int SerialTransmit(const char *buffer)
{
unsigned int size = strlen(buffer);
while(size)
{
while( U2STAbits.UTXBF); // wait while TX buffer full
U2TXREG = *buffer; // send single character to transmit buffer
buffer++; // transmit next character on following loop
size--; // loop until all characters sent (when size = 0)
}
while( !U2STAbits.TRMT); // wait for last transmission to finish
return 0;
}
/* SerialReceive() is a blocking function that waits for data on
* the UART2 RX buffer and then stores all incoming data into *buffer
*
* Note that when a carriage return '\r' is received, a nul character
* is appended signifying the strings end
*
* Inputs: *buffer = Character array/pointer to store received data into
* max_size = number of bytes allocated to this pointer
* Outputs: Number of characters received */
unsigned int SerialReceive(char *buffer) //, unsigned int max_size)
{
//unsigned int num_char = 0;
/* Wait for and store incoming data until either a carriage return is received
* or the number of received characters (num_chars) exceeds max_size */
while(1)
{
while( !U2STAbits.URXDA); // wait until data available in RX buffer
*buffer = U2RXREG; // empty contents of RX buffer into *buffer pointer
if (*buffer == 'a')
{
ram_write_byte(0x0,0x0);
mPORTASetBits(BIT_0);
num_channels = 1;
totaldata1 = 25500;
a2don=TRUE;
T3CONSET = 0x8000;
k=0;
PORTBbits.RB7=1;
while(a2don);
//(i=0);
//for (i=0;i<5000;i++);
int temp1=ram_read_byte(0x0) ;
for(i=0;i<2000;i++)
{
WriteSPI2(junk); // force the read
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
temp1 = (ReadSPI2()&0x03)<<8;
WriteSPI2(junk); // force the read
while (SPI2STATbits.SPIBUSY); // wait for it to end of transaction
temp1 += ReadSPI2();
dummy = temp1/1000 ;
tempstr[0] = dummy + 0x30;
dummy1 = temp1- dummy*1000;
dummy = dummy1/100;
tempstr[1] = dummy + 0x30;
dummy1 = dummy1 - dummy*100;
dummy = dummy1/10;
tempstr[2] = dummy + 0x30;
dummy1 = dummy1 - dummy*10;
tempstr[3] = dummy1 + 0x30;
//tempstr[4] = "\0";
//printf("%d\n",a2dvals[i]);
//PORTBbits.RB7=0;
printf("%c%c%c%c \n", tempstr[0],tempstr[1],tempstr[2],tempstr[3]);
}
a2don=TRUE;
mPORTBSetBits(BIT_0);
}
PORTBbits.RB7=0;
}
return 1;
}// END SerialReceive()