Взаимодействие Arduino с Python Serial

Я реализую КИХ-фильтр с помощью Arduino. Я использую входной сигнал в качестве аудиосигнала. Звуковой сигнал имеет продолжительность 3 секунды с общим количеством выборок, 66150. Что я делаю, так это читаю этот файл в python и сохраняю данные в массиве. Используя Serial, я хочу отправить эти выборочные данные в последовательный порт Arduino и обработать их, а затем отправить обратно в последовательный порт и получить в Python.

Код Python

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

  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;
        }
   }

Проблема, с которой я столкнулся, заключается в том, что я застрял на самом первом шаге. В качестве проверки я отправил 10 образцов значений при запуске из Python в arduino с помощью цикла и попытался восстановить их обратно для чтения в консоли Python. Эти значения неверны. Когда я ввел строку внутри arduino.write(), она была получена, но когда я ввожу переменную внутри arduino.write(), она не печатает это значение после передачи обратно в python. Я просто пробовал много вещей, таких как переход на строку, но не получил желаемого результата. Вывод для этого кода прилагается. Завтра мое представление, и я застрял в этом деле. Мы будем очень признательны за помощь.Вывод окна Python cmd

, 👍0

Обсуждение

Я хочу просто проверить, правильно ли значение, которое я пишу в arduino из python, или нет. Сначала я отправил строку из Python в Arduino, все было в порядке. Но когда я пробовал переменные данные, он не улавливал это значение. Самый первый шаг идет не так, поэтому я не могу двигаться дальше (для стадии обработки)., @Asad Sultan

значения int или значения с плавающей запятой, которые хранятся в массиве данных, не передаются в arduino. Поэтому, если я не могу получить правильное значение x[n] в какой-то момент, это не будет полезно для реализации КИХ-фильтра., @Asad Sultan

Я только что отредактировал вопрос с дополнительным объяснением. Пожалуйста, просмотрите его., @Asad Sultan

первая проблема. ты не перезагрузишь меня, @Juraj

вторая проблема. вы читаете байт/символ, а затем печатаете его как int. но print(int) выведет число как текст. используйте Serial.write(данные);, @Juraj


2 ответа


Лучший ответ:

1

Я нашел способ решить эту проблему. Вот мой код Arduino:

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;
}

А вот мой код Python:

    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)
 # %%
,

0
    arduino.write(data[i].tobytes())
    time.sleep(.1)
    print(int.from_bytes(arduino.readline(),byteorder='little') )

Это то, что вам нужно?

,