Hi everyone, I’m new to Arduino and electronics, and this is my first post. I've had success with previous projects thanks to this forum, but I’m currently stuck on a new one.
The project: I'm measuring vibrations (up to 20kHz) using a Joy-it piezoelectric disk sensor (SEN-VIB01) and an Arduino Due. I need to record the signal for a few minutes at a sampling rate of 50kHz.
The data is converted to binary and recorded in Python (using Spyder), but the results seem off. I’m getting constant jumps between 0 and 60,000.
To check the system, I record data without touching the piezo, then press it to see if I can detect the impulse in the time domain.
Note: Reducing the baud rate to 115200 and sampling rate to 5kHz gives better results (I can detect the impulse), but the values are still higher than expected.
Attached is a picture of my setup (the USB connects to my laptop):
Here is my arduino code:
#include <Arduino.h>
#define BUFFER_SIZE 20000 // Adjust buffer size as needed
volatile uint16_t bufferIndex = 0; // Index to track buffer position
uint8_t buffer[BUFFER_SIZE]; // Buffer to hold sensor values
volatile bool bufferFull = false; // Flag to indicate buffer is full
void setup() {
// Initialize Serial communication at 921600 baud rate
Serial.begin(921600);
// Configure the ADC for fast readings
pmc_enable_periph_clk(ID_ADC); // Enable the ADC clock
ADC->ADC_MR |= ADC_MR_FREERUN_OFF; // Disable free-run mode (manual trigger mode)
ADC->ADC_MR |= ADC_MR_PRESCAL(1); // Set ADC clock prescaler for faster readings
ADC->ADC_CHER |= ADC_CHER_CH0; // Enable channel 0 (A0 pin)
// Set up Timer Counter (TC0, Channel 0) for 50kHz (20 µs interval)
pmc_set_writeprotect(false); // Disable write protection
pmc_enable_periph_clk(ID_TC0); // Enable clock for TC0
// Configure Timer Counter
TC_Configure(TC0, 0, TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC);
uint32_t rc = 840; // Set compare value for 50kHz (84MHz / 2 / 50kHz = 840)
TC_SetRC(TC0, 0, rc); // Set the compare match register
TC_Start(TC0, 0); // Start the timer
// Enable the interrupt for the TC0 handler (Timer Counter 0)
TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Enable interrupt on RC compare
NVIC_EnableIRQ(TC0_IRQn); // Enable TC0 interrupt in the NVIC
}
void loop() {
// If buffer is full, send it via Serial
if (bufferFull) {
bufferFull = false;
Serial.write(buffer, BUFFER_SIZE); // Send the buffer
}
}
// Timer Counter 0 Interrupt Service Routine (ISR)
void TC0_Handler() {
TC_GetStatus(TC0, 0); // Clear the interrupt flag
// Start an ADC conversion
ADC->ADC_CR = ADC_CR_START;
// Wait until the conversion is complete
while (!(ADC->ADC_ISR & ADC_ISR_EOC0)) {
// Do nothing, wait for conversion to complete
}
// Read the ADC value from channel 0 (A0 pin)
uint16_t sensorValue = ADC->ADC_CDR[0];
// Store high and low bytes in the buffer
buffer[bufferIndex++] = (sensorValue >> 8) & 0xFF; // High byte
buffer[bufferIndex++] = sensorValue & 0xFF; // Low byte
// Check if buffer is full
if (bufferIndex >= BUFFER_SIZE) {
bufferIndex = 0; // Reset buffer index
bufferFull = true; // Set flag to indicate buffer is ready to send
}
Here is my Python code:
# -*- coding: utf-8 -*-
"""
"""
import serial
import time
import struct
import os
baudr = 921600 # adjust baud rate to file
# Open the serial connection (adjust COM port and baud rate)
ser = serial.Serial('COM6', baudr, timeout=1)
time.sleep(2) # Give some time for the connection to establish
# Open a binary file to store the data
with open('data.bin', 'wb') as file:
try:
while True:
# Read 2 bytes (16 bits) from the serial port
raw_data = ser.read(2)
if len(raw_data) == 2:
# Write binary data to the file
file.write(raw_data)
# Optional: Convert to 16-bit integer and print to console
sensor_value = struct.unpack('>H', raw_data)[0] # Big-endian 16-bit int
print(sensor_value)
#voltage = sensor_value *(3.3/1023)
#print(voltage)
# Print raw byte data
print(f"Raw data (bytes): {raw_data}")
except KeyboardInterrupt:
print("Data collection stopped.")
finally:
# Ensure the serial port is closed properly
ser.close()
print("Serial port closed.")
print(os.getcwd())
The output in Python looks like that :
Raw data (bytes): b'\x7f\xd0'
34567
Raw data (bytes): b'\x87\x07'
49040
Raw data (bytes): b'\xbf\x90'
34687
Raw data (bytes): b'\x87\x7f'
36999
Raw data (bytes): b'\x90\x87'
32720
Raw data (bytes): b'\x7f\xd0'
1927
Raw data (bytes): b'\x07\x87'
and here is a graph showing the absolute nonsense I get:
I would really appreciate it if any of you could help me figure out whats wrong with my setup / program.
Thank you.