Hi all,
I collect data from adxl1005, use 24bit ads1256 30k SPS and send data via usb to PC - Python app and plot data. But there are huge spikes.
Any suggestion where is problem?
My code is:
In Python I have:
Thank you
I collect data from adxl1005, use 24bit ads1256 30k SPS and send data via usb to PC - Python app and plot data. But there are huge spikes.
Any suggestion where is problem?
My code is:
Code:
#include <SPI.h>
// PIN assignements
#define CS_PIN 21
#define DRDY_PIN 22
#define RST_PIN 8
// SPI
#define SPISPEED 1950000
// 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 BUFFER_SIZE (30000) // samples
#define DRATE_15K (0xE0) // 15 kSPS
#define DRATE_30K (0xF0) // 30 kSPS
#define STATUS_REG_0x01 (0x01) // MSB first, Auto-Cal Dsbl, Input Buffer Dsbl
#define STATUS_REG_0x03 (0x03) // MSB first, Auto-Cal Dsbl, Input Buffer Enbl
#define STATUS_REG_0x07 (0x07) // MSB first, Auto-Cal Enbl, 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 (BUFFER_SIZE==15000 ? DRATE_15K : DRATE_30K)
#define MUX_REG_VALUE (B00000111) // AIN7
bool dataReadyToSend = false; // Flag indicating if data is ready
volatile int DRDY_state = HIGH;
char inChar;
void writeRegister(uint8_t address, uint8_t value)
{
SPI.transfer( WREG_CMD | address );
SPI.transfer( 0x00 );
SPI.transfer( value );
delayMicroseconds( 100 );
}
volatile bool streaming = false; // make it volatile since it could be changed in interrupt context
void setup() {
Serial.begin(9600);
while (!Serial) {}
START_SPI();
attachInterrupt(digitalPinToInterrupt(DRDY_PIN), DRDY_Interrupt, FALLING);
}
void loop() {
// Check if data is available to read from the serial port
if (Serial.available() > 0) {
char inChar = Serial.read();
// Start streaming if 'r' is received
if (inChar == 'r') {
streaming = true;
}
// Stop streaming if 's' is received
else if (inChar == 's') {
streaming = false;
}
}
if (streaming && DRDY_state == LOW) {
float voltage = READ_ADC();
Serial.write((const byte*)&voltage, sizeof(voltage));
}
}
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)) { // if 24-bit MSB == 1
adc_raw |= 0xFF000000; // value is negative, sign-extend to 32 bits
}
float v = adc_raw * (float)(VREF / (1<<23));
return( v );
}
// DRDY falling-edge interrupt function
void DRDY_Interrupt()
{
DRDY_state = LOW;
}
void waitDRDY()
{
// wait for DRDY_state to be LOW
while (DRDY_state == HIGH) {
continue;
}
// then set it back to HIGH
DRDY_state = HIGH;
}
void START_SPI ()
{
// configure I/O pins
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH); // init CS high (disable)
pinMode(DRDY_PIN, INPUT);
pinMode(RST_PIN, OUTPUT);
// hardware reset ADS1256 by toggling pin LOW then HIGH
digitalWrite(RST_PIN, LOW);
delay(1);
digitalWrite(RST_PIN, HIGH);
delay(500); //500
// start the spi-bus
SPI.begin();
delay(500); //500
// wait for DRDY signal LOW
while (digitalRead(DRDY_PIN)) {}
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1));
digitalWriteFast(CS_PIN, LOW);
delayMicroseconds(100); //100
// reset to power-up state
SPI.transfer( RESET_CMD );
delay(5);
// configure registers
writeRegister( STATUS_REG, STATUS_REG_0x03 );
writeRegister( ADCON_REG, ADCON_REG_VALUE );
writeRegister( DRATE_REG, DRATE_REG_VALUE );
writeRegister( MUX_REG, MUX_REG_VALUE );
// auto-calibrate (send command, wait DRDY = LOW, then wait DRDY = HIGH)
SPI.transfer( SELFCAL_CMD );
uint32_t t0 = micros();
while (digitalReadFast(DRDY_PIN)!=LOW && micros()-t0 < 10000) {}
while (digitalReadFast(DRDY_PIN)!=HIGH && micros()-t0 < 10000) {}
digitalWriteFast(CS_PIN, HIGH);
SPI.endTransaction();
}
In Python I have:
Code:
import serial
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.widgets import Button
ser = serial.Serial('COM8', 2000000, timeout=1)
streaming = False
filter_range = None
fs = 30000
window_size = 30000
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
line, = ax.plot([], [], 'r-')
ax.set_ylim(-3, 3)
def fft_filter(data_array, fs, low_cut, high_cut):
N = len(data_array)
freq = np.fft.fftfreq(N, d=1/fs)
fft_data = np.fft.fft(data_array)
mask = ((freq > low_cut) & (freq < high_cut)) | ((freq < -low_cut) & (freq > -high_cut))
filtered_fft = fft_data * mask
filtered_signal = np.fft.ifft(filtered_fft).real
return filtered_signal
def init():
ax.set_xlim(0, window_size)
ax.set_ylim(-3, 3)
return line,
def update(frame):
global y_data
if streaming:
data = ser.read(4 * window_size)
if len(data) < 4 * window_size:
return line,
y_data = np.frombuffer(data, dtype=np.float32).copy()
y_data -= np.mean(y_data) # Remove mean
y_data /= 0.020 # Normalize to g
if filter_range:
y_data = fft_filter(y_data, fs, *filter_range)
line.set_data(np.arange(len(y_data)), y_data)
return line,
def start(event):
global streaming
streaming = True
ser.write(b'r')
def stop(event):
global streaming
streaming = False
ser.write(b's')
def filter_10_1000(event):
global filter_range
filter_range = (10, 1000)
def filter_500_15000(event):
global filter_range
filter_range = (500, 15000)
def no_filter(event):
global filter_range
filter_range = None
# Adjusted button creation and placement
button_configs = [
(0.05, 0.05, 'Start', start, 0.1), # Increased width for longer labels
(0.16, 0.05, 'Stop', stop, 0.1),
(0.27, 0.05, '10-1000Hz', filter_10_1000, 0.15), # Adjusted for label length
(0.43, 0.05, '500-15000Hz', filter_500_15000, 0.17), # Adjusted for label length
]
buttons = []
for x, y, label, action, width in button_configs:
axbutton = plt.axes([x, 0.01, width, 0.075])
button = Button(axbutton, label)
if action:
button.on_clicked(action)
buttons.append(button)
ani = FuncAnimation(fig, update, init_func=init, blit=False, interval=100, cache_frame_data=False)
plt.show()
Thank you