Hallo liebe Community,
ich nutze aktuell im Rahmen einer Abschlussarbeit den Raspberry PI und bin quasi absoluter Python-Neuling, jedoch kein Programmierneuling, da ich quasi jeden Tag mit MATLAB arbeite und im Studium auch C/C++ gelernt habe.
Die Aufgabenstellung ist etwas zu komplex, um sie hier ausführlich darzustellen (wie gesagt -> Abschlussarbeit), daher habe ich mir ein simples Programm überlegt, bei dem ich vor exakt dem selben Problem stehe.
Ich möchte mithilfe des PIs (PI 3 Model B), einer externen Soundkarte (Daffodil US01), einem Mikrofon (Mikrofon [Anzeige]) und einem Python-Skript die Schallgeschwindigkeit messen.
Das Programm gibt über einen Mono Lautsprecher einen Sound wieder (ein Sägezahn-beep als wav-Datei mit etwas Verzögerung vorher, da beep bei mir keine Tonausgabe erzeugt) und in einem fest definierten Abstand davor befindet sich das Mikrofon. Dieses Mikrofon nimmt dann wenige Sekunden auf (ich nutze pyaudio), anschließend wird das ganze in ein numpy-Array umgewandelt und über eine for-Schleife mit Schwellwerterkennung festgestellt, zu welchem Abtastwert dieser beep auftrat ..
Dass das mit dem Schwellwert noch nicht so optimal gelöst ist und mit dem wav-File auch, das sehe ich ein, das bereitet mir aber keine Probleme .. was mir Probleme bereitet ist, dass bei mehrfacher Ausführung die Startzeit des beeps um bis zu 30msec schwankt, bzw. etwa 1000-2000 (!) Abstastwerte .. was eigentlich klar ist, da ja die Zeit für das beepen und dem Beginn der Aufnahme in den seltensten Fällen exakt gleich bleiben wird ..
Meine Frage ist jetzt: wie bekomme ich das ganze synchron und reproduzierbar (für meine Zwecke später wären etwa 0,2-0,4msec, also 10-20 Abtastwerte Schwankung tolerierbar)
Hier mal der Quelltext:
import pyaudio
import numpy as np
from matplotlib import pyplot as plt
import os # for beep
import time
# switch to directory with wav-sound
os.system('cd /home/pi/Desktop/BA')
CHUNKSIZE = 8192 # fixed chunk size
RATE = 44100
# initialize audio object
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNKSIZE)
# initialize array with datatype int16 for audio samples
c=np.array([], dtype = np.int16)
# play sound
os.system('aplay Sawtooth1000Hzdouble.wav')
print "recording"
# record sound
for i in range(0,9):
data = stream.read(CHUNKSIZE)
tmpData = np.fromstring(data, dtype=np.int16)
c = np.hstack((c,tmpData))
print "recording done"
#plot data
#plt.plot(c)
#plt.show()
# close stream
stream.stop_stream()
stream.close()
p.terminate()
# preprocessing
for k in range(0, c.size):
if c[k]>500:
break # k is now the sample number
tim = k/44100. * 1000 # delay in msec
print "Sample no.: ", k, "Time: ", tim
Display More
Erzeugt diese Ausgabe:
Das Array sieht so aus:
Dass ich den Peak nicht genau treffe, okay, damit hab ich gerechnet, aber dabei hätte ich immernoch etwa 10 Abtastwerte als Genauigkeit, daran liegt es nicht ..
Ich habe es dann mal damit versucht, den beep als thread auszulagern, das hat die Situation verbessert, aber noch nicht im akzeptablen Rahmen:
import pyaudio
import numpy as np
from matplotlib import pyplot as plt
import os # for beep
import thread
import time
def beep():
time.sleep(0.5)
os.system('aplay Sawtooth1000Hzdouble.wav')
# switch to directory with wav-sound
os.system('cd /home/pi/Desktop/BA')
CHUNKSIZE = 8192 # fixed chunk size
RATE = 44100
# initialize audio object
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNKSIZE)
# initialize array with datatype int16 for audio samples
c=np.array([], dtype = np.int16)
# play sound
thread.start_new_thread(beep, ())
print "recording"
# record sound
for i in range(0,9):
data = stream.read(CHUNKSIZE)
tmpData = np.fromstring(data, dtype=np.int16)
c = np.hstack((c,tmpData))
print "recording done"
#plot data
#plt.plot(c)
#plt.show()
# close stream
stream.stop_stream()
stream.close()
p.terminate()
# preprocessing
for k in range(0, c.size):
if c[k]>500:
break # k is now the sample number
tim = k/44100. * 1000 # delay in msec
print "Sample no.: ", k, "Time: ", tim
Display More
Mit der Ausgabe:
Das sieht schon etwas besser aus, aber nur etwas ![]()
Vielleicht hat ja jemand eine Idee, eine libary, oder ein Stück Code, das mir hier helfen könnte ![]()
Viele Grüße ![]()