Pages: [1] 2 3   Go Down
Author Topic: delay funktioniert nicht richtig  (Read 2674 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,
ich versuche zwei Sketche zu verbinden (LCD und Piezo) dabei funktioniert das delay nicht richtig. Es wird immer nur ein delay Wert angenommen. Ich habe schon viel ausprobiert komme aber zu keinem Ergebnis. Deshalb wende ich mich an euch.

Ich hänge den zusammengeführten mal Sketch an.

Im Prinzip soll ein bestimmtes Muster auf dem LCD und zur selben Zeit eine längere Tonabfolge ablaufen.



* Muster_Ton.ino (1.01 KB - downloaded 26 times.)
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 165
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich versuche mal auf Deutsch

Welches 'delay' meinen sie ?

tonePause = 200      das wird nicht andern,  alle Tonen sind gleich in wie lange Sie dauern

Code:
delay(50); //funktioniert nicht in der gewünschten Geschwindigkeit
}

Program wartet 50 milliseconden. Also Ihren Program macht

Piezo Muzik
Warten
LCD sachen
Wartem
---> und wieder

Aber ich glaube was Sie suchen ist: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Sie mochten zwei sachen zu gleich machen, das ist moglich mit dieser Link.
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Im Prinzip soll ein bestimmtes Muster auf dem LCD und zur selben Zeit eine längere Tonabfolge ablaufen.

Sorry, dass ich mir den angehängten Sketch in dem Fall erst gar nicht ansehe: So etwas mußt Du komplett OHNE DELAY programmieren!

Im Prinzip mußt Du Intervalle bilden, nach denen etwas passieren soll.
Und dann laufend die aktuelle Zeit abfragen, z.B. mit millis().
Und wenn das Zeitintervall überschritten ist, passiert was.
Wenn das Intervall zum Setzen eines neuen LCD-Musters abgelaufen ist, kommt ein neues LCD-Muster.
Wenn das Intervall zum Setzen eines neuen Tones abgelaufen ist, kommt ein neuer Ton.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke für die schnellen Antworten.
Gibt es dafür vielleicht einen Beispielsketch. Ich habe das mit millis nicht so richtig verstanden. muss ich dann jede Note (bzw.Ton) einzeln ansprechen und die Pause auch?
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gibt es dafür vielleicht einen Beispielsketch. Ich habe das mit millis nicht so richtig verstanden. muss ich dann jede Note (bzw.Ton) einzeln ansprechen und die Pause auch?

Ja, Du musst für jedes Event jedes einzelnen Tasks einzeln festlegen, wann das Event wieder zuende ist und das nächste Event starten soll.

Wenn Du also einen Task "SpieleNoten()" programmierst, dann mußt Du beim Einschalten einer Note festlegen, wann sie wieder abgeschaltet werden soll, und beim Abschalten der Note mußt Du festlegen, wann die nächste Note wieder starten soll.

Ich habe Dir als Beispiel für Multitasking mit Arduino einen Beispiel-Sketch gemacht, der gleichzeitig drei Tasks abarbeitet:
task_led(); ==> Blinken der Pin-13 LED im Halbsekundentakt
task_tone(); ==> Simulation des Abspielens einer ziemlich atonalen "Melodie" aus verschiedenen Noten
task_serial(); ==> gibt im Sekundentakt ein "H" auf dem seriellen Monitor aus

Statt dass wirklich eine Melodie gespielt wird, habe ich eine Art Simulation gemacht, mit Ausgabe auf dem seriellen Monitor wenn eine Note gespielt und wieder abgeschaltet wird. Das geht dann nicht so auf die Ohren. Damit man die Abspielsimulation per Auge verfogen kann, ist die "Notenlänge" dabei 1, 2, 3, 4, 5 Sekunden lang.

Die "Melodie" habe ich in so eine Datenstruktur gegeben:
char melodie[]="C1D2E4F5A4D2C4";
Immer ein Zeichen benennt die zu spielende Note, ein weiteres Zeichen die Notenlänge in Sekunden.

Wenn Du tatsächlich Noten abspielen möchtest, brauchst Du nur die Ausgaben der Simulation zu ersetzen, also den tone-Befehl statt:
      Serial.print("\r\nNote: ");Serial.print(melodie[notencounter]);
      Serial.print(" Dauer: ");Serial.println(melodie[notencounter+1]);
und den notone-Befehl statt:
      Serial.println("\r\nNote aus");

Wenn die Noten zehnmal schneller gespielt werden sollen, könntest Du die Notendauer als Angabe in Zehntelsekunden interpretieren, dazu muß nur der Faktor der Notenlängendauer von 1000 auf 100 ms herabgesetzt werden:
      nextpause=millis()+(melodie[notencounter+1]-byte('0'))*100;  ==> *100 statt *1000
Dann wird's mit dem Verfolgen der Simulation per Auge aber schwierig, das wäre dann mehr etwas für eine tatsächliche akustische Wiedergabe, vielleicht mit einer etwas gefälligeren Melodie.

Die "Pause" zwischen zwei Noten habe ich fest auf 300 ms eingestellt, das kann man natürlich variieren oder diesen Wert auch in die Melodie-Datenstruktur mit einbinden:
     else nextnote=millis()+300;

Nach Ablauf wiederholt sich die Melodie mit einer Pausenzeit von 10 Sekunden:
       Serial.println("\r\nMelodie startet neu nach 10 Sekunden.");
        nextnote=millis()+10000;

Im ganzen Sketch ist kein einziges delay() drin.

Und auch nur deshalb funktioniert diese Art von Multitasking ("kooperatives Multitasking"), so daß quasi mehrere Aufgaben gleichzeitig ablaufen können, und jeder Task erledigt Aufgaben in einem eigenen Takt, der die Takte der übrigen Tasks nicht beeinträchtigt.

Code:
// Simulation Multitasking by jurs for German Arduino Forum

#define LEDPIN 13

// Nur Simulation, es werden keine Noten gespielt!
// Fiktive Melodie, Note-C 1s, Note-D 2s, Note-E 4s etc.
char melodie[]="C1D2E4F5A4D2C4";

boolean halbSekundenTakt()
// liefert true falls seit dem letzten Aufruf ein neues Halbsekunden-Intervall begonnen hat
{
  static long alterWert;
  if (millis() - alterWert < 500) return(false);
  while (millis() - alterWert >= 500) alterWert+=500;
  return(true); 
}

boolean SekundenTakt()
// liefert true falls seit dem letzten Aufruf ein neues Sekunden-Intervall begonnen hat
{
  static long alterWert;
  if (millis() - alterWert < 1000) return(false);
  while (millis() - alterWert >= 1000) alterWert+=1000;
  return(true); 
}

void task_serial()
{
  // im Sekundentakt ein "H" seriellen Monitor ausgeben
  if (SekundenTakt())
    Serial.print('H');
}


void task_led()
{
  // Im Halbsekundentakt die LED ein- und ausschalten
  if (halbSekundenTakt())
    digitalWrite(LEDPIN,!digitalRead(LEDPIN));
}

void task_tone()
// Simulation: Abspielen einer Melodie,
// die Simulation gibt Notenbeginn und Notenende auf dem seriellen Monitor aus
{
  static byte notencounter;
  static boolean note_an;
  static long nextnote, nextpause;
  if (millis()>nextnote)
  {
    if (!note_an)
    {
      Serial.print("\r\nNote: ");Serial.print(melodie[notencounter]);
      Serial.print(" Dauer: ");Serial.println(melodie[notencounter+1]);
      nextpause=millis()+(melodie[notencounter+1]-byte('0'))*1000;
      note_an=true;
    } 
  }
  if (millis()>nextpause)
  {
    if (note_an)
    {
      Serial.println("\r\nNote aus");
      notencounter+=2; // notencounter weiter
      if (notencounter>=strlen(melodie))
      {
        notencounter=0; // melodie zuende, notencounter reset
        Serial.println("\r\nMelodie startet neu nach 10 Sekunden.");
        nextnote=millis()+10000;
      }
      else nextnote=millis()+300; // Feste Pause von 300 ms zwischen den Noten
      note_an=false; // spielen der Note is abgeschaltet
    } 
  }
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LEDPIN,OUTPUT);
}


void loop() {
  // put your main code here, to run repeatedly:
  task_led();
  task_tone();
  task_serial();
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke für die umfassende sehr hilfreiche Antwort!!!
Das probiere ich jetzt aus...
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke für die umfassende sehr hilfreiche Antwort!!!
Das probiere ich jetzt aus...

Das Timing für die Noten kannst Du natürlich auch anders machen, als jedesmal mit millis() zu rechnen.

Insbesondere wenn Du Melodien mit unterschiedlichem Tempo / BPM abspielen möchtest, bietet es sich vielleicht an, sich vorher die Dauern von Viertelnote, Halbenote, Sechzehntelnote nur einmal vor dem Start der Melodie anhand der BPM-Angabe auszuechnen (also nicht vor jeder Note), und die Notendauer in der Melodie als Vielfaches der kürzesten Note anzugeben.

Für diese kürzeste Notendauer (z.B. Sechzehntelnote) machst Du Dir dann einen Takt, so wie in den Funktionen für das Blinken der LED und der "H" Ausgabe vorgemacht in den Funktionen halbSekundenTakt(), SekundenTakt(), nur mit kleinerem Millisekundenwert. Vielleicht als Funktion "SechzehntelNotenTakt()".

Und in der Abspielfunktion setzt Du bei Start einer Note oder einer Pause einen Zähler auf den notwendigen Wert, also für eine Sechzehntelnote/-pause auf 1, bei einer Achtelnote/-pause auf 2, bei einer Viertelnote/-pause auf 4 etc. Und bei jedem auftretenden Sechzehntelnoten-Takt wird der Zähler um 1 heruntergezählt. Ist der Zähler bei 0 wird bei Abspielen einer Note die nächste Pause gestartet, beim Abspielen einer Pause die nächste Note. So daß Du beim Abspielen selbst gar nicht mehr mit millis() hantierst, sondern nur noch mit einem Zähler, der Vielfache der kürzesten Notenlänge zählt.

Es gibt ja immer beliebig viele Möglichkeiten, wenn man Programme schreibt.

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ja, das ist eine gute Idee.

Wie kann ich char melodie[]="C1D2E4F5A4D2C4"; in int melodie[] = {55,78,1109, 659,4978,4978} umwandeln, damit ich die Notenwerte in Zahlen angeben kann?
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wie kann ich char melodie[]="C1D2E4F5A4D2C4"; in int melodie[] = {55,78,1109, 659,4978,4978} umwandeln, damit ich die Notenwerte in Zahlen angeben kann?

Wie ist denn "int melodie[] = {55,78,1109, 659,4978,4978} " zu interpretieren?

Wo sind die Noten? Wo sind die Notenlängen in den Zahlen?

Mal kurz in Deinen Quellcode geschaut: Sind das nur Tonhöhen und Du möchtest eine Melodie nur mit immer derselben Notenlänge und Pausenlänge spielen? Das dürfte dann ja ein ziemlich monotones Gepiepe werden!

Warum möchtest Du Notenwerte in Zahlen angeben, Noten sind doch normalerweise Buchstaben (c, d, e, f, g, a, h, c), da würde sich doch eher eine Codierung der Melodie als String anbieten? Wenn ein Tonumfang von vielen Oktaven notwendig wird, codiert man die Oktave mit 2 Zeichen, dann ist "1c" das c aus der ersten Oktave, "2c" das c aus der zweiten Oktave, "3c" das c aus der dritten Oktave. Und dahinter dann die Länge, z.B.
0 - ganze Note
1 - ganze Note punktiert
2 - halbe Note
3 - halbe Note punktiert
4 - viertel Note
5 - viertel Note punktiert
6 - achtel Note
7 - achtel Note punktiert
9 - sechzehntel Note
a - sechzehntel Note punktiert
b - zweiunddreißigstel Note
c - zweiunddreißigstel Note punktiert

Dann wäre eine Folge wie "1c23e5"
1c2 = spiele aus der ersten Oktave, Note C, mit Dauer einer halben Note
3e5 = spiele aus der dritten Oktave, Note E, mit der Dauer einer Viertelnote punktiert

Wenn Du jetzt die Melodie sagen wir mal auf einem Notenblatt vorliegen hast, müßtest Du sie ja irgendwie in eine computergerechte Form bringen, ohne dass das Umschreiben auf die Controller-Melodie Datenstruktur zu aufwändig wird.

Und die grundlegende Datenstruktur müßtest Du Dir zu Anfang überlegen und nicht erst zum Schluß. Wie das dann aus der Datenstruktur heraus gespielt wird, ist einfach, Du schaust einfach die Oktave und Note nach und schlägst in einem Array nach, welche Tonhöhe es ist. Dadurch ergibt sich, was die tone() Funktion als Parameter übergeben bekommt.


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich wollte, wenn ich mit den Tonhöhen arbeiten könnte, eine andere "musikalische" Struktur aufbauen und so z.B. die Fibonacci Zahlenreihe oder andere mathematische Verhältnisse vertonen (verpiepsen) oder einfach auch nur Zufallszahlen.

Das Konvertieren von char zu int sieht ja etwas kompliziert aus (atoi?).
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich wollte, wenn ich mit den Tonhöhen arbeiten könnte, eine andere "musikalische" Struktur aufbauen und so z.B. die Fibonacci Zahlenreihe oder andere mathematische Verhältnisse vertonen (verpiepsen) oder einfach auch nur Zufallszahlen.

Das stelle ich mir schwierig zu vertonen vor, da der mathematische Zahlenbereich von minus Unendlich bis plus Unendlich reicht, das menschliche Hörvermögen allenfalls von 20 bis 20000 Hertz. Kling recht experimentell. Ich habe ehrlich gesagt nur eine recht schwache Vorstellung davon, was Dir dabei vorschwebt.

Das Konvertieren von char zu int sieht ja etwas kompliziert aus (atoi?).

Überhaupt nicht. Anbei mal die Logik zum Dekodieren eines Strings, in dem Oktave und Ton zu einer int-Tonhöhe dekodiert werden.

Code:
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  char melodie[]="1C2E3F4G5A6H4C3C4E3F3G5A6H3D4E3C";
  int tonhoehe;
  for (int i=0;i<strlen(melodie)/2;i++)
  {
    switch (melodie[i*2+1])
    {
    case 'C': tonhoehe=330;break;
    case 'D': tonhoehe=349;break;
    case 'E': tonhoehe=370;break;
    case 'F': tonhoehe=392;break;
    case 'G': tonhoehe=415;break;
    case 'A': tonhoehe=440;break;
    case 'H': tonhoehe=466;break;
    default: Serial.println("Error Ton");
    }
    switch (melodie[i*2])
    {
    case '1': break;
    case '2': tonhoehe*=2;break;
    case '3': tonhoehe*=4;break;
    case '4': tonhoehe*=8;break;
    case '5': tonhoehe*=16;break;
    case '6': tonhoehe*=32;break;
    default: Serial.println("Error Oktave");
    }
    Serial.println(tonhoehe);
  } 

}

void loop() {
  // put your main code here, to run repeatedly:
 
}
[code]
[/code]
Logged

Munich/Germany
Offline Offline
God Member
*****
Karma: 11
Posts: 643
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nimm aber anstelle
Code:
static long alterWert
unbedingt
Code:
static unsigned long alterWert;

Merke:
Variablen für millis() und micros() Werte IMMER als unsigned long deklarieren. Zusammen mit der richtigen Abfrage gibt es dann auch kein Problem mit dem Überlauf.
Logged

_______
Manfred

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Erst mal vielen Dank für die Antworten. In der Tat ist dieses kleine Arduinoprojekt sehr experimentell.

Ich habe jetzt versucht den Code so umzuschreiben, dass man die Töne hören kann. Allerdings kommt nur ein ganz leises "Gefiepse" aus dem Piezo, ganz anders als in meinem obigen Code. (Die Funktionen task_led und task_serial habe ich vorerst ausgeschaltet.) Was habe ich falsch gemacht?
Code:
#define piezoPin A5
char melodie[]="C1D2E4F5A4D2C4";

boolean halbSekundenTakt()
// liefert true falls seit dem letzten Aufruf ein neues Halbsekunden-Intervall begonnen hat
{
  static long alterWert;
  if (millis() - alterWert < 500) return(false);
  while (millis() - alterWert >= 500) alterWert+=500;
  return(true); 
}

boolean SekundenTakt()
{
  static unsigned long alterWert;
  if (millis() - alterWert < 1000) return(false);
  while (millis() - alterWert >= 1000) alterWert+=1000;
  return(true); 
}
void task_tone()
{
  static byte notencounter;
  static boolean note_an;
  static long nextnote, nextpause;
  if (millis()>nextnote)
  {
    if (!note_an)
    {
      tone(piezoPin,melodie[notencounter]);
      tone(piezoPin,melodie[notencounter+1]);
      nextpause=millis()+(melodie[notencounter+1]-byte('0'))*1000;
      note_an=true;
    } 
  }
  if (millis()>nextpause)
  {
    if (note_an)
    {
      noTone(piezoPin);
      notencounter+=2; // notencounter weiter
      if (notencounter>=strlen(melodie))
      {
        notencounter=0; // melodie zuende, notencounter reset
        Serial.println("\r\nMelodie startet neu nach 10 Sekunden.");
        nextnote=millis()+10000;
      }
      else nextnote=millis()+300; // Feste Pause von 300 ms zwischen den Noten
      note_an=false; // spielen der Note is abgeschaltet
    } 
  }
}


void setup() {
}


void loop() {
  task_tone();
}
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3071
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ich habe jetzt versucht den Code so umzuschreiben, dass man die Töne hören kann. Allerdings kommt nur ein ganz leises "Gefiepse" aus dem Piezo, ganz anders als in meinem obigen Code... Was habe ich falsch gemacht?

In dem was du im ersten Post angehängt hast, benutzt du tone(pin, freq, duration), hier die mit 2 Parametern...
Kommt jetzt das noTone() zu früh ???

Sonst ist es eher Hardware ...
Logged

Germany S-H
Offline Offline
Faraday Member
**
Karma: 160
Posts: 3166
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe jetzt versucht den Code so umzuschreiben, dass man die Töne hören kann. Allerdings kommt nur ein ganz leises "Gefiepse" aus dem Piezo, ganz anders als in meinem obigen Code.

Du darfst natürlich nicht einfach die ASCII-Codes der Buchstaben als Tonhöhe nehmen:
      tone(piezoPin,melodie[notencounter]);
      tone(piezoPin,melodie[notencounter+1]);
sondern mußt Angaben wie "2C" (2. Oktave , Note C) schon erst noch in eine Tonhöhe umrechnen.

Ich hab's jetzt mal auf das Abspielen von einfachen Melodien umgeschrieben. Jeder Ton der Melodie wird jetzt mit vier Bytes in einem String definiert:
- Oktave
- Note
- Notendauer
- Komma
Leerzeichen dürfen nicht vorkommen.

Falls statt einer Note eine Pause gespielt werden soll, für Oktave und Note einfach "P" setzen.

Wenn die Melodie schneller oder langsamer abgespielt werden soll, kann der Wert für BPM (Beats per Minute) verändert werden.

Die zweite, auskommentierte Melodie ist übrigens eine Tonleiter aus Viertelnoten.

Code:
#define piezoPin A5
char melodie[]="2d5,2d6,2c4,2d6,2d6,2g6,2a4,2a6,2g6,2a6,2a6,2d6,2f2,PP4,2f4,2e6,2d6,2e6,2f6,2a6,2c5,2h6,2a6,2h6,2c6,2g5";
// char melodie[]="1c4,1d4,1e4,1f4,1g4,1a4,1h4,2c4,2d4,2e4,2f4,2g4,2a4,2h4,3c4,3d4,3e4,3f4,3g4,3a4,3h4,4c4,4d4,4e4,4f4,4g4,4a4,4h4,5c4,5d4,5e4,5f4,5g4,5a4,5h4,6c4,6d4,6e4,6f4,6g4,6a4,6h4";

#define BPM 120
#define SECONDS_PER_MINUTE 60
int getNotenDauer(int beatsPerMinute, char notendauer)
{
  long factor;
  switch (notendauer)
  {
    case '0': factor=1024;break; // ganze Note
    case '1': factor=1536;break; // ganze Note punktiert
    case '2': factor=512;break; // halbe Note
    case '3': factor=768;break; // halbe Note punktiert
    case '4': factor=256;break; // viertel Note
    case '5': factor=384;break; // viertel Note punktiet
    case '6': factor=128;break; // achtel Note
    case '7': factor=192;break; // achtel Note punktiert
    case '8': factor=64;break;  // sechzehntel Note
    case '9': factor=96;break;  // sechzehntel Note punktiert
    case 'a': factor=32;break;  // 32stel Note
    case 'b': factor=48;break;  // 32stel Note punktiert
    default: {Serial.print("Error Tondauer ");Serial.println(notendauer);}
  }  
  return (4*factor*SECONDS_PER_MINUTE/beatsPerMinute);
}


int getTonHoehe(char oktave, char note)
{
  int tonhoehe;
  switch (note)
  {
    case 'c': tonhoehe=330;break;
    case 'd': tonhoehe=349;break;
    case 'e': tonhoehe=370;break;
    case 'f': tonhoehe=392;break;
    case 'g': tonhoehe=415;break;
    case 'a': tonhoehe=440;break;
    case 'h': tonhoehe=466;break;
    default: {Serial.print("Error Ton ");Serial.println(note);}
  }
  switch (oktave)
  {
    case '1': break;
    case '2': tonhoehe*=2;break;
    case '3': tonhoehe*=4;break;
    case '4': tonhoehe*=8;break;
    case '5': tonhoehe*=16;break;
    case '6': tonhoehe*=32;break;
    default: {Serial.print("Error Oktave ");Serial.println(oktave);}
  }
 return(tonhoehe);
}  


boolean halbSekundenTakt()
// liefert true falls seit dem letzten Aufruf ein neues Halbsekunden-Intervall begonnen hat
{
  static long alterWert;
  if (millis() - alterWert < 500) return(false);
  while (millis() - alterWert >= 500) alterWert+=500;
  return(true);  
}

boolean SekundenTakt()
{
  static unsigned long alterWert;
  if (millis() - alterWert < 1000) return(false);
  while (millis() - alterWert >= 1000) alterWert+=1000;
  return(true);  
}
void task_tone()
{
  static int notencounter;
  static boolean note_an;
  static long nextnote, nextpause;
  if (millis()>nextnote)
  {
    if (!note_an)
    {
      if (melodie[notencounter]!='P')
      {
        tone (piezoPin,getTonHoehe(melodie[notencounter], melodie[notencounter+1]));
//        Serial.println(getTonHoehe(melodie[notencounter], melodie[notencounter+1]));
      }
      else
      {
        noTone(piezoPin); // Pause statt Note  
//        Serial.println("Pause");
      }
      nextpause=millis()+getNotenDauer(BPM,melodie[notencounter+2]);
//      Serial.println(getNotenDauer(BPM,melodie[notencounter+2]));
      Serial.println();
      note_an=true;
    }  
  }
  if (millis()>nextpause)
  {
    if (note_an)
    {
      noTone(piezoPin);
      notencounter+=4; // notencounter weiter
      if (notencounter>=strlen(melodie))
      {
        notencounter=0; // melodie zuende, notencounter reset
        Serial.println("\r\nMelodie startet neu nach 10 Sekunden.");
        nextnote=millis()+10000;
      }
      else nextnote=millis()+100; // Feste Pause von 100 ms zwischen den Noten
      note_an=false; // spielen der Note is abgeschaltet
    }  
  }
}


void setup() {
  Serial.begin(9600);
}


void loop() {
  task_tone();
}

Das ist natürlich ein selbsterfundenes Datenformat für die Melodie, und Halbtöne sind auch nicht dabei. Wenn Du fertige Melodien per Download ziehen oder Software erzeugen möchtest, wäre natürlich ein Standardformat wie MIDI oder RTTTL (Nokia Klingeltonformat aus alten Handy-Zeiten) besser geeignet. Aber rein für das Spielen von Zufallstönen und computergenerierten Tönen ist es ja egal, ob das Datenformat auch von irgendeiner anderen Software unterstützt wird oder nicht.
« Last Edit: February 28, 2013, 06:56:54 am by jurs » Logged

Pages: [1] 2 3   Go Up
Jump to: