Hello everybody,
I'm doing a university project and I haven't found help in the forum yet. I'm using Arduino Nicla Vision to record some audio that I want to save in .wav format with my python code in VScode.
Serial timeout seems doesn't work, it stops only when it reaches the size range of data acquisition.
Sampling Frequency (16KHz) and baudrate aren't the problem, beacuse I've changed both but the output is the same.
I've tried to test the code: I've recorded me counting until 30 seconds. The audio lasts 30 seconds but it results sped up. I finish to count 30 seconds before the 10th second of the .wav file and then microphone recorded more, until 90/100seconds but the code save all in a 30s wav file.
I think python lose many data because it's not fast enough and data are overwritten on the serial buffer by arduino.
Do you have some suggestion to solve it?
This is my python code:
import serial
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
freq = 16000 # sampling frequency
secs = 30 # length of audio data
size = freq*secs
ser = serial.Serial('COM8', 1000000, timeout=secs)
df_list = []
for i in range(size):
line = ser.readline() # read a byte
if line:
string = line.decode() # convert the byte string to a unicode string
audio_data = int(string) # convert the unicode string to an int
#print(audio_data)
df_list.append(audio_data)
with open('C:\\Users\\Stage.UPE3\\Desktop\\Wav_test\\readme.txt', 'w') as f:
f.write(str(df_list))
data = np.array(df_list, dtype=np.int16)
write("C:\\Users\\Stage.UPE3\\Desktop\\Wav_test\\recording0.wav", freq, data)
Arduino Code:
/*
This example reads audio data from the on-board PDM microphones, and prints
out the samples to the Serial console. The Serial Plotter built into the
Arduino IDE can be used to plot the audio data (Tools -> Serial Plotter)
Circuit:
- Arduino Nano 33 BLE board, or
- Arduino Nano RP2040 Connect, or
- Arduino Portenta H7 board plus Portenta Vision Shield
This example code is in the public domain.
*/
#include <PDM.h>
// default number of output channels
static const char channels = 1;
// default PCM output frequency
static const int frequency = 16000;
// Buffer to read samples into, each sample is 16-bits
short sampleBuffer[512];
// Number of audio samples read
volatile int samplesRead;
void setup() {
Serial.begin(1000000);
while (!Serial);
// Configure the data receive callback
PDM.onReceive(onPDMdata);
// Optionally set the gain
// Defaults to 20 on the BLE Sense and 24 on the Portenta Vision Shield
// PDM.setGain(30);
// Initialize PDM with:
// - one channel (mono mode)
// - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
// - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield
if (!PDM.begin(channels, frequency)) {
Serial.println("Failed to start PDM!");
while (1);
}
}
void loop() {
// Wait for samples to be read
if (samplesRead) {
// Print samples to the serial monitor or plotter
for (int i = 0; i < samplesRead; i++) {
if(channels == 2) {
Serial.print("L:");
Serial.print(sampleBuffer[i]);
Serial.print(" R:");
i++;
}
Serial.println(sampleBuffer[i]);
}
// Clear the read count
samplesRead = 0;
}
}
/**
* Callback function to process the data from the PDM microphone.
* NOTE: This callback is executed as part of an ISR.
* Therefore using `Serial` to print messages inside this function isn't supported.
* */
void onPDMdata() {
// Query the number of available bytes
int bytesAvailable = PDM.available();
// Read into the sample buffer
PDM.read(sampleBuffer, bytesAvailable);
// 16-bit, 2 bytes per sample
samplesRead = bytesAvailable / 2;
}
Thank you for your attention and answer.