#include "mbed.h"Hier gibt es drei fertig übersetzte Hex-Dateien für unterschiedliche Abspielklänge, hoch, normal und tief. Man kann das jeweils gewünschte Programm direkt in den Calliope kopieren. Download: Recorder.zip
DigitalOut col0(P0_4, 0);
DigitalOut myled(p13);
//DigitalOut sl(p28, 0);
DigitalOut inl(p29, 0);
DigitalOut in2(p30, 1);
DigitalIn tasteA (p17);
DigitalIn tasteB (p16);
AnalogIn u2(p3); //P3 = MIC
PwmOut pwm1(p28);
int main() {
// float d[1000];
uint8_t d[2500];
uint16_t n=0;
pwm1.period_us(50);
while(1){
if (tasteA.read()==0){
myled = 1;
for (n=0; n<2500;n++){
d[n]= int(u2.read()*255);
wait_us(500);
}
myled = 0;
}
if (tasteB.read()==0){
for (n=0; n<2500;n++){
//printf("%d\r\n",n);
pwm1.write(float(d[n])/255);
wait_us(500);
// printf("%f\r\n",255*d[n]);
}
}
}
}
#include "mbed.h"
DigitalOut col0(P0_4, 0);
DigitalOut myled(p13);
DigitalOut nSleep(p28, 0); // P28 = Motortreiber enable
PwmOut in1(p29); // P29 = Motortreiber Eingang 1
DigitalOut in2(p30, 1); // P30 = Motortreiber Eingang 2
AnalogIn mic(p3); // P3 = MIC
DigitalIn tasteA(p17);
DigitalIn tasteB(p16);
DigitalOut pin1(p1, 0); // Port als Widerstand benutzen
int main() {
uint16_t len = 4000; // Anzahl Samples, Speicher reicht fuer max. 5000
uint16_t interval = 500; // Abtastintervall in us => Abtastrate in Hz = 1/(interval*1.000.000)
// (=> Aufnahmedauer in s = len*interval)
uint8_t buffer[len]; // Aufnahmepuffer
uint16_t n = 0;
in1.period_us(50); // Periodendauer der PWM
while(1) {
if (tasteA.read() == 0) { // Aufnahme
myled = 1;
for (n = 0; n < len; n++) {
buffer[n] = int(mic.read() * 255);
wait_us(interval);
}
myled = 0;
/* optional: Waveform auf serieller Schnittstelle ausgeben
for (n = 0; n < len; n++){
printf("%c", buffer[n]);
}
printf("\n");
*/
}
if (tasteB.read() == 0) { // Wiedergabe
nSleep.write(1);
for (n = 0; n < len; n++) {
in1.write(float(255-buffer[n]) / 255);
wait_us(interval);
}
nSleep.write(0);
}
}
}
Ihr Code hatte einen Eingang konstant auf 0 gelassen, den anderen konstant auf 1, dazu dann die PWM auf dem Enable-Eingang. Da könnte man meinen, dann bleibt auch ein Ausgang konstant null und der andere bildet eben die PWM ab. Leider kommt das am Ausgang der Brücke aber so nicht an. Wenn man beide *Ausgänge* auf 0 haben will, muss man beide *Eingänge* auf 1 (!) schalten („Bremsen“) und nicht auf 0. Also habe ich das ganze praktisch „invertiert“: D. h. einen Eingang dauerhaft auf 1, den anderen je nach Sampledaten zw. 0 und 1 wechselnd.
Die entscheidende dadurch nötige Zeile war: „in1.write(float(255-buffer[n]) / 255);“ also eben nicht den eigentlichen Samplingwert, sondern die Differenz zu den maximal möglichen 255. Denn 1,1 auf den Eingängen heißt ja 0,0 also „Stille“ auf den Ausgängen. Also schreibt man quasi ein „Negativ“ der gesampelten Daten auf den Eingang und bekommt das „Postitiv“ am Ausgang des Motortreibers.
Hier die beiden Hex-Files, einmal zur Wiedergabe am Motortreiber-Ausgang wenn Taste B gedrückt wird, einmal zum Schreiben der Rohdaten auf die serielle Schnittstelle, wenn B gedrückt wird; Aufnahme wie gehabt mit Taste A. Ich habe 2kHz Sampling-Frequenz und 2 Sek. Aufnahmedauer konfiguriert. Mit der derzeitigen Hardware und Software (Bibliotheken) funktionierts: Recorder2.zip
Noch etwas sehr cooles zum Wochenende! Ich hatte noch einen Fehler gefunden, der von Anfang an im Programm war: Bei der Aufnahme verbraucht die Ausführung der Zeile buffer[n] = int(mic.read() * 255); ja auch Zeit, bei der Wiedergabe die Ausführung der Zeile in1.write(float(255-buffer[n]) / 255);.
Man darf also nicht einfach z. B. bei 2kHz Abtastrate die 500us warten, sondern muss davon die Ausführungszeit abziehen! Das sind (gemessen) bei der Aufnahme 101us bei der Wiedergabe 72us. Bei 2kHz war es mir nicht aufgefallen, aber bei 8kHz war das Intervall bei der Aufnahme fast doppelt so lang (125+101)!
Wenn man das aber macht, dann hat die Wiedergabe erstens die richtige Tonhöhe (mittels Tongenerator und Spektralanalyse in Audacity geprüft) und auch auf dem Piezo des Calliope kann man tatsächlich erkennen, was man eingesprochen hat.
Ich habe in den angehängten Files die Abtastrate auf 4kHz erhöht (und die PWM), was die Qualität nochmal verbessert (angehängte .wav bzw. .mp3-Datei) und die Aufnahme auf 7500 Samples (bei Ausgabe auf serieller Schnittstelle sind nur 6000 möglich) erhöht. Anbei auch der neue Quelltext. Jetzt stimmt tatsächlich alles und weiter kann man es, so glaube ich auch nicht mehr „pushen“.
Download: Recorder3.zip
#include "mbed.h"
DigitalOut col0(P0_4, 0);
DigitalOut myled(p13);
DigitalOut nSleep(p28, 0); // P28 = Motortreiber enable
PwmOut in1(p29); // P29 = Motortreiber Eingang 1
DigitalOut in2(p30, 1); // P30 = Motortreiber Eingang 2
AnalogIn mic(p3); // P3 = MIC
DigitalIn tasteA(p17);
DigitalIn tasteB(p16);
DigitalOut pin1(p1, 0); // Port als Widerstand benutzen
int main() {
uint16_t len = 6000; // Anzahl Samples, Speicher reicht ohne Waveform-Ausgabe fuer max. 7500
uint16_t interval = 250; // Abtastintervall in us => Abtastrate in Hz = 1/(interval*1.000.000)
// (=> Aufnahmedauer in s = len*interval)
uint8_t buffer[len]; // Aufnahmepuffer
uint16_t n = 0;
in1.period_us(20); // Periodendauer der PWM
while(1) {
if (tasteA.read() == 0) { // Aufnahme
myled = 1;
for (n = 0; n < len; n++) {
buffer[n] = int(mic.read() * 255);
wait_us(interval-101); // gemessene Laufzeit der vorigen Zeile: 101 us
}
myled = 0;
/* optional: Waveform auf serieller Schnittstelle ausgeben
for (n = 0; n < len; n++){
printf("%c", buffer[n]);
}
printf("\n");
*/
}
if (tasteB.read() == 0) { // Wiedergabe
nSleep.write(1);
for (n = 0; n < len; n++) {
in1.write(float(255-buffer[n]) / 255);
wait_us(interval-72); // gemessene Laufzeit der vorigen Zeile: 72 us
}
nSleep.write(0);
}
}
}