Lavanya rajan
Well-known member
Hello All,
I'm reading data from 24 bit ADC with 30kSps, and trying to remove offset and plot FFT. I'm attaching the code I have been testing with. But the serial monitor is not printing the peak frequency value. Also I want to remove DC offset in the signal, but I dont know how to do it. can anyone help me on this, please
In serial monitor , it outputs only ads1256 test program, after that it stops
I'm reading data from 24 bit ADC with 30kSps, and trying to remove offset and plot FFT. I'm attaching the code I have been testing with. But the serial monitor is not printing the peak frequency value. Also I want to remove DC offset in the signal, but I dont know how to do it. can anyone help me on this, please
Code:
#include <SPI.h>
#include <arduinoFFT.h>
// PIN assignments
#define CS_PIN 14
#define DRDY_PIN 15
#define RST_PIN 16
// SPI
#define SPISPEED 2500000
#define SAMPLES 1000
#define SAMPLING_FREQUENCY 1024
arduinoFFT FFT = arduinoFFT();
#define BUFFER_SIZE 30000
unsigned int sampling_period_us;
unsigned long microseconds = 0;
double vReal[SAMPLES];
double vImag[SAMPLES];
// ADS1256 registers
#define STATUS_REG 0x00
#define MUX_REG 0x01
#define ADCON_REG 0x02
#define DRATE_REG 0x03
// ADS1256 commands
#define WAKEUP_CMD 0x00 // completes SYNC and exits standby mode
#define RDATA_CMD 0x01 // read data
#define RREG_CMD 0x10 // read register (register ID in low nibble)
#define WREG_CMD 0x50 // write register (register ID in low nibble)
#define SELFCAL_CMD 0xF0 // offset and gain self-calibration
#define SYNC_CMD 0xFC // synchronize the A/D conversion
#define STANDBY_CMD 0xFD // begin standby mode
#define RESET_CMD 0xFE // reset to power-up values
#define VREF (2.5) // for conversion of raw ADC data to Volts
#define DRATE_30K (0xF0) // 30 kSPS
#define STATUS_REG_0x03 (0x03) // MSB first, Auto-Cal Dsbl, Input Buffer Enbl
#define ADCON_REG_VALUE (0x21) // 0 01 00 001 => Clock Out Freq = fCLKIN, Sensor Detect OFF, gain 2 7.68MHz
#define DRATE_REG_VALUE (DRATE_30K)
#define MUX_REG_VALUE (B00001000) // AINCOM
volatile int DRDY_state = HIGH;
float adc_volt[SAMPLES];
void writeRegister(uint8_t address, uint8_t value)
{
SPI.transfer(WREG_CMD | address);
SPI.transfer(0x00);
SPI.transfer(value);
delayMicroseconds(100);
}
void setup()
{
Serial.begin(115200);
while (!Serial) {}
Serial.println("ADS1256 test program");
START_SPI();
attachInterrupt(DRDY_PIN, DRDY_Interrupt, FALLING);
}
void loop()
{
int sampleCount = 0;
while (true) {
uint32_t t0 = micros();
for (int i = 0; i < SAMPLES; i++) {
waitDRDY();
adc_volt[i] = READ_ADC();
delayMicroseconds(10);
sampleCount++;
if (sampleCount >= SAMPLES) {
sampleCount = 0;
break; // Exit the loop after completing the required samples
}
}
fft(adc_volt); // Call fft function with the adc_volt array
Serial.println("Cycle completed");
}
}
void fft(float* samples)
{
for (int i = 0; i < SAMPLES; i++)
{
microseconds = micros();
vReal[i] = samples[i];
vImag[i] = 0.0;
while (micros() < (microseconds + sampling_period_us)) {
}
}
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
Serial.print("Peak frequency is: ");
Serial.println(peak);
}
float READ_ADC()
{
int32_t adc_raw;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1));
digitalWriteFast(CS_PIN, LOW);
SPI.transfer(RDATA_CMD);
delayMicroseconds(5); // delay MUST be >= 5 us
adc_raw = 0;
adc_raw |= SPI.transfer(0);
adc_raw <<= 8;
adc_raw |= SPI.transfer(0);
adc_raw <<= 8;
adc_raw |= SPI.transfer(0);
digitalWriteFast(CS_PIN, HIGH);
SPI.endTransaction();
if (adc_raw & (1 << 23)) {
adc_raw |= 0xFF000000;
}
float v = adc_raw * (float)(VREF / (1 << 23));
return v;
}
void DRDY_Interrupt()
{
DRDY_state = LOW;
}
void waitDRDY()
{
while (DRDY_state == HIGH) {
continue;
}
DRDY_state = HIGH;
}
void START_SPI()
{
sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
pinMode(DRDY_PIN, INPUT);
pinMode(RST_PIN, OUTPUT);
digitalWrite(RST_PIN, LOW);
delay(1);
digitalWrite(RST_PIN, HIGH);
delay(500);
SPI.begin();
delay(500);
while (digitalRead(DRDY_PIN)) {}
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1));
digitalWriteFast(CS_PIN, LOW);
delayMicroseconds(100);
}
In serial monitor , it outputs only ads1256 test program, after that it stops