Go Down

Topic: Melodien Soundsequenzen mit dem arduino wieder geben (Read 2673 times) previous topic - next topic

DennisD

Hallo
Vorweg ich bin ein Neuling auf dem gebiet der Microcontrollern
ich möchte mit dem Arduino Einen soundgenerator machen um ein LKW Dieselgeräusch zu erzeugen und in der Drehzahl zu regeln
Ist das Möglich ?

Danke im Voraus

DennisD

Ist hier Niemand der mir helfen will oder kann ?

Addi

Du kannst Melodien abspielen, wenn du die Frequenzen des LKW kennst.
Wenn ich mich nicht irre heiß die Funktion tone().

Addi
/ \    _|  _| o
 /--\ (_| (_| |

uwefed


Du kannst Melodien abspielen, wenn du die Frequenzen des LKW kennst.
Wenn ich mich nicht irre heiß die Funktion tone().
Addi

Das klingt dann aber gar nicht nach einem Dieselmotor.
DennisD hast Du dich mal bei Modellbaubedarf informiert oder auf solche Seiten über Modellbauprojekte.

Du kannst auf einer SD-Karte ein Musikfile aufzeichnen und dieses mit einem Shield, von Arduino gesteuert abspielen.

Grüße Uwe

qualidat

Doch, das geht. Zuerst brauchst du eine Originalaufnahme. Die bearbeitest du am PC mit einem Soundeditor (z.B. Audacity) so, dass eine "nahtlose" Soundschleife von ca. 1 Sekunde Länge entsteht. Mit "nahtlos" meine ich, dass beim ständig wiederholten Abspielen kein Knacksen  beim Übergang Ende zu Anfang zu hören ist. Da musst du mit dem grafischen Wellenbild etwas experimentieren ...

Der nächste Schritt ist das Abspeichern als unkomprimiertes WAVE-File, mono, 8 Bit, Samplingrate ca. 6..8 kHz. Du kannst den Klang dann schon mal am PC testen, indem du auch den zukünftig zu verwendenden Lautsprecher anschliesst (wahtscheinlich irgend einen Mini-Speaker?). Je geringer die Samplingrate ist, mit der du dich zufrieden gibst, um so besser - desto gringer die Datenmenge. Erwarte kein Hifi, guter "Telefonsound" ist aber durchaus zu ereichen.

Als nächstes musst du mit einem Hex-Editor die Haeder-Daten vom Wave-File abschneiden. Wie lang der Haeder ist, steht z.B. bei Wikipedia. Würdest du diese Daten vom Arduino mit abspielen lassen, kämen die als Knacken und Kratzen 'rüber. Der übriggebliebene Datenblock kommt als Byte-Array mit in den Programmtext oder auf die SD-Karte (falls du öfters mal tauschen willst).

Zum Abspielen liest du im Arduino-Programm Byte für Byte und schiebst das per PWM aus einem Ausgangs-Pin, wo dann der Lautspecher oder ein Verstärker angeschlossen ist. Dazu musst du noch die Frequenz der PWM auf 32 kHz erhöhen (steht u.a. hier: http://arduino.cc/forum/index.php/topic,45094.0.html), damit die sicher aus dem Bereich der hörbaren Frequenzen raus ist. Das hat noch Nichts mit der Abspielgeschwindigkeit zu tun, die bestimmst du damit, wie schnell du jeweils ein neues Byte aus den Sunddaten "nachlädtst". Das sollten so 5000 ... 8000 pro Sekunde sein - Nichts, was den Arduino wirklich ins Schwitzen bringt, es ist also noch genügend Kapazität für irgend eine Empfangsroutine (seriell, Ethernet) oder das Auslesen des AD-Wandlers zur Beeinflussung der Abspielgeschwindigkeit ...

DennisD

vielen dank für die antworten setzte mich gleich hin und versuche es mal
das einzige was ich nicht verstanden habe ist das mit dem hochsetzten des PWM Signals wie hoch ist dieses den normalerweise ?

DennisD

so hab jetzt schon mal die daten geschnitten und umgewandelt.
Macht es was aus ob die byts hex oder ascii sind?

und verstehe immer noch nicht (weil mein englisch anscheinend dafür zu schlecht ist) wie ich die PWM Frequenz auf 32KHz bekomme
das programm siet bis jetzt so aus:

int Speaker = 10;

int myArray[]={
00,00,0x93,0x7b,0x72,0x76,0x67,0x94,0x85,...............................};

void setup ()
{  pinMode(Speaker,OUTPUT);  }

void loop ()
{
for (int i=0; i<2280; i++){
  analogWrite(Speaker,myArray);
}
}

qualidat

#7
Dec 31, 2012, 01:17 pm Last Edit: Dec 31, 2012, 01:26 pm by qualidat Reason: 1
Wie die Bytes notiert sind, ist unerheblich, das wandelt die IDE beim Compilieren sowieso in binär um.
Wie du die Frequenz hoch bekommst steht hier:

http://books.google.de/books?id=YSsj2b2h37kC&pg=PA253&lpg=PA253&dq=arduino+audio+pwm&source=bl&ots=bsOKLhzR_p&sig=OCDKMQCYwm0tVHuVOlPPLyr2zZE&hl=de&sa=X&ei=S4DhUKjyFI_Nsgb0-oGwBQ&ved=0CDEQ6AEwAA#v=onepage&q=arduino%20audio%20pwm&f=false

DIe PWM ist quasi die "Trägerfrequenz" für das Ausgangssignal und muss mindestens um den Faktor 2..3 höher sein als das höchste "getragene" Signal (lt. Abtasttheorem) und ausserdem natürlich (bei Audio) selber nicht mehr im Hörbereich (>20kHz). In deine Ausgabeschleife musst du ausserdem noch ein DelayMicroseconds einbauen und so dimensionieren, dass zunächst bei der Ausgabegeschwindigkeit wieder die ursprüngliche Samplingrate rauskommt. Verkürzt du das Delay, dann wird der Sound höher, verlängerst du es, tiefer ...

Code: [Select]

for (int i=0; i<2280; i++)
{
 analogWrite(Speaker,myArray[i]);
 DelayMicroseconds(125); //so ungefähr bei 6k Sampling, genauen Wert ausprobieren
}


Hörst du denn schon irgendwas?

DennisD

Der verweis was schon mal sehr hilfreich danke nur auch trotz des hochsetztens omt bei meinem programm kein ton raus daher würde iches gern auf basis des im verweis verwendeten programmes versuchen :

int Speaker = 9;

void writeAudio(uint8_t val) {
  OCR1A = (val);
}

void setup ()
{

  pinMode(Speaker,OUTPUT);
  TCCR1A = _BV(WGM10) | _BV(COM1A1);
  TCCR1B = _BV(CS10)| _BV(WGM12);
}

void loop ()
{
  int inc =20;
  for ( int j=0; j<1024; j++){
  writeAudio(j/4);
  delayMicroseconds(10);
  }

}

welche variabele muss ich nun zu meinem myArray ändern damit die daten wiedergegeben werden ?

qualidat

Also Eines ist schon mal klar - Arrays, deren Inhalt im Programmtext definiert wird - so wie du das gemacht hast (und ich zur Überprüfung auch), haben eine Begrenzung in der Größe. Den genauen Wert habe ich noch nicht gefunden, Tests haben ergeben, dass bei ca. 1750 Werten Schluss ist. Danach macht der Arduino nur noch Unsinn ...

Das ist bestimmt auch ein Grund, warum du Nichts hörst, das Programm läuft nicht richtig, auch wenn es in Ordnung ist. Ich teste das morgen mal weiter ...

DennisD

ok danke schon mal für die info ich kurze es mal noch mehr und versuche es dann auch nochmal

mkl0815


Also Eines ist schon mal klar - Arrays, deren Inhalt im Programmtext definiert wird - so wie du das gemacht hast (und ich zur Überprüfung auch), haben eine Begrenzung in der Größe. Den genauen Wert habe ich noch nicht gefunden, Tests haben ergeben, dass bei ca. 1750 Werten Schluss ist. Danach macht der Arduino nur noch Unsinn ...

Das liegt daran, das eine Variable immer Speicher im SRAM belegt und davon hat der Uno gerade mal 2kB. Mit einem char-Array (oder Byte-Array) mit 1750 Werten verbräts Du schon mal 85% der verfügbaren Speichers. Verwendest Du nun zusätzlich noch die Serial-Ausgabe, braucht die noch RAM für Ihren Puffer. Dazu kommen sämtliche andere Variablen die Dein Programm so benötigt. Der µC verwendet auch noch das untere Ende vom RAM als Stack, der gegen den Anfang des Speichers wächst, z.B. bei Funktionsaufrufen.
Mario.

qualidat

#12
Jan 01, 2013, 09:48 pm Last Edit: Jan 01, 2013, 09:54 pm by qualidat Reason: 1
Quote
Das liegt daran, das eine Variable immer Speicher im SRAM belegt und davon hat der Uno gerade mal 2kB. Mit einem char-Array (oder Byte-Array) mit 1750 Werten verbräts Du schon mal 85% der verfügbaren Speichers. Verwendest Du nun zusätzlich noch die Serial-Ausgabe, braucht die noch RAM für Ihren Puffer. Dazu kommen sämtliche andere Variablen die Dein Programm so benötigt. Der µC verwendet auch noch das untere Ende vom RAM als Stack, der gegen den Anfang des Speichers wächst, z.B. bei Funktionsaufrufen.
Mario.


Ja, das klingt logisch. Die Lösung steht hier, habe ich aber selber noch nicht gemacht, muss ich erstmal ausprobieren:

http://arduino.cc/en/Reference/PROGMEM

Hier noch ein Beispiel:

http://stackoverflow.com/questions/12169374/arduino-progmem-byte-array

DennisD

so hab jetzt die daten menge auf die hälfte reduziert uns es kommt auch was aus dem Lautsprecher zwar verzerrt und leicht unsauber aber es kommt schon mal was

qualidat

#14
Jan 02, 2013, 03:27 am Last Edit: Jan 02, 2013, 03:29 am by qualidat Reason: 1
Ich habe nochmal in meinen Verzeichnissen gewühlt und ein Beispiel wiedegefunden. Mit dem folgenden Code habe ich Musik (8k Samplingrate) per serieller Schnittstelle an den Arduino gesendet und per Lautsprecher in erstaunlich guter Qualität ausgegeben. Du musst nur noch das Problem mit der Datenmenge lösen (PROGMEM). Im Programmspeicher ist so viel Platz, da könntest du durchaus besser gesampelte oder gar verschiedene Sounds hinterlegen. In diesem Beispiel bestimmt das Tempo der Seriellen die Ausgabegeschwindgkeit - bei Dir ist es das Delay in der For-Schleife ...

Code: [Select]
//------------------------ DEFINE --------------------------
#define PWM_Pin 11
byte buf;
//------------------------- SETUP --------------------------
void setup()
{
 Serial.begin(57600);
 int pwm_freq=1;
 TCCR2B = (TCCR2B & 0xF8) | pwm_freq;
 pinMode(PWM_Pin, OUTPUT);
}
//------------------------ LOOP -----------------------------
void loop()
{
   //...................... serial input .....................
 if (Serial.available() > 0)
   {
     buf = Serial.read();
   }  
   analogWrite(PWMPin,buf); 
}

Go Up