I am implementing an FIR filter using Arduino. I am using an input signal as an audio signal. The audio signal has a duration of 3 seconds with total samples, 66150. What I am doing is reading this file in python and storing the data in an array. Using Serial, I want to send this sampled data to Arduino serial and process it, then send it back to serial and receive in Python.
Python Code
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from scipy.io import wavfile # get the api
import serial, time
samplerate, data = wavfile.read("sample.wav")
samples = len(data)
plt.plot(data[:20000])
arduino = serial.Serial('COM4', 9600, timeout=.1)
time.sleep(1) #give the connection a second to settle
for i in range(0,samples):
arduino.write(data[i])
time.sleep(1)
print(arduino.readline())
Arduino Code
void setup() {
Serial.begin(9600);
}
int i = 0;
int newdata[10];
void loop() {
if(Serial.available() > 0) {
int data = Serial.read();
newdata[i] = data;
Serial.print(newdata[i]);
i = i+1;
}
}
The problem I am facing is that I am stuck at very first step. As a check, I sent 10 samples values at start from Python to arduino using a loop and tried to recover them back to read on Python console. These values were not correct. When I entered a string inside the arduino.write(), it was receiving but when I input a variable inside the arduino.write(), it doesn't print that value after transferring back to python. I just tried many things like changing to string but I didn't get the desired result. The output for this code is attached. Tomorrow is my submission and I am stuck in this thing. Help will be highly appreciated.Python cmd window output
2 Answers 2
I have found a way to tackle this. Here is my arduino code:
char buf[100];
const double coefficients[28] = {
-0.006416610121367, -0.01179616274682, -0.01212859343535,-0.001491136183145,
0.0175211951058, 0.03193599126761, 0.0259553014052,-0.004580133449276,
-0.04206485416456, -0.05260424218688,-0.007566809377484, 0.09242896920118,
0.2100842841173, 0.2894365184419, 0.2894365184419, 0.2100842841173,
0.09242896920118,-0.007566809377484, -0.05260424218688, -0.04206485416456,
-0.004580133449276, 0.0259553014052, 0.03193599126761, 0.0175211951058,
-0.001491136183145, -0.01212859343535, -0.01179616274682,-0.006416610121367
};
int order_of_filter = 27;
int sample_array[28] = {};
double output_sample = 0;
void setup()
{
Serial.begin(9600);
Serial.setTimeout(50000);
}
void loop()
{
int sample_in;
int num_read = Serial.readBytesUntil('\n', buf, 100);
buf[num_read] = '0円';
sscanf(buf, "%d", &sample_in);
for (int i = order_of_filter; i > 0; i--)
{
sample_array[i] = sample_array[i-1];
}
sample_array[0] = sample_in;
for(int i = 0; i<=order_of_filter; i++)
{
output_sample = output_sample + sample_array[i]*coefficients[i];
}
Serial.println(output_sample);
output_sample = 0;
}
And here is my Python Code:
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from scipy.io import wavfile # get the api
import serial, time
import numpy as np
import sounddevice as sd
arduino = serial.Serial('COM4', 9600, timeout=1) #COM port depends on the USB port
time.sleep(3) #time to get connection ready
# %%
fs, data = wavfile.read('hfsound.wav')
samples = len(data)
#Plot the signal
plt.plot(data[:samples])
plt.ylabel("Amplitude")
plt.xlabel("Time")
plt.title("Time Domain Response of the Input Signal")
plt.grid()
plt.show()
#Plotting fft
fft_input = fft(data)
half_length = int(len(fft_input)/2)
omega_axis = np.linspace(0, fs/2, half_length)
fft_n = fft_input[:half_length]
plt.plot(omega_axis,abs(fft_n))
plt.xlabel('frequency')
plt.ylabel('Amplitude')
plt.title("Frequency Domain Response of the Input Signal")
plt.grid()
plt.show()
# %%
#Declare an Array of zeros
outputArray = np.zeros(64000)
#Sending data to aurdino
for i in range(samples):
number = data[i]
string = str(number).encode(encoding='utf-8') + b'\n'
arduino.write(string)
byt = arduino.read_until();
print(byt.strip())
outputArray[i] = byt.strip()
arduino.close()
# %%
#Plotting Output waveform
#Plot the time-domain output signal
plt.plot(outputArray[:len(outputArray)])
plt.ylabel("Amplitude")
plt.xlabel("Time")
plt.title("Time Domain Response of the Output Signal")
plt.grid()
plt.show()
#Plotting fft of output
fft_out = fft(outputArray)
half_length = int(len(fft_out)/2)
omega_axis = np.linspace(0, fs/2, half_length)
fft_n = fft_out[:half_length]
plt.plot(omega_axis,abs(fft_n))
plt.xlabel('frequency')
plt.ylabel('Amplitude')
plt.title("Frequency Domain Response of the Output Signal")
plt.grid()
plt.show()
# %%
#Playback code
sd.play(outputArray, fs)
# %%
arduino.write(data[i].tobytes())
time.sleep(.1)
print(int.from_bytes(arduino.readline(),byteorder='little') )
Is this what you whant?
Serial.write(data);