Tone ohne Delay

Hallo,

mit Bezug auf: https://forum.arduino.cc/index.php?topic=208171.0
habe ich folgendes vor:

Eine Tonleiter abspielen, ohne das Programm zu blockieren.

Bisher versucht:

Quote from: jurs on Jan 02, 2014, 10:59 pm aus dem oben genannten Beitrag
Du schreibst einfach ein Programm, das genau das macht.

Zum Beispiel:

#define LEDPIN 13

void blinkWithoutDelay(int pin, int off, int on)
{
  int blinkPhase=millis()%(off+on);
  if (blinkPhase<off) digitalWrite(pin, LOW);
  else digitalWrite(pin, HIGH);
}

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

void loop(){
  blinkWithoutDelay(LEDPIN, 1000, 100);
}

Auf der Suche nach einer Lösung, Töne auszugeben, ohne das Programm zu blockieren bin ich auf den oben benannten Beitrag gestoßen.
Die Funktion habe ich etwas umgeschrieben:

const int BuzzerPin = 6;
int frequenz = 0;

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

void Buzzer(int TonAn, int TonAus, int Freq)
{
  int blinkPhase=millis()%(TonAn+TonAus);
  if (blinkPhase<TonAn) tone(BuzzerPin, Freq);
  else noTone(BuzzerPin);
}

void loop() {
//Serial.println(millis());
//Buzzer(300, 4000, 450);

  for (int i = 0; i < 7; i++){
  Serial.println(i);
  frequenz = (200 + (100 * i));
  Serial.println(frequenz);
  Buzzer(1000, 1000, frequenz);
  }
delay(2000);
}

Das auskommentierte Buzzer(300, 4000, 450); funktioniert wie es soll.
Das auskommentierte Serial.println(millis()); zeigt dabei auch, dass das Programm weiter läuft.

Jetzt wollte ich aber eine “Tonleiter” erzeugen.
Der Code mit der Schleife funktionierte ursprünglich mit delay() und noTone

Jetzt wird aber “nur” ein 800Hz-Tone erzeugt. Nach etwas nachdenken wurde mir klar, die Schleife läuft ja weiter, es kann also nicht anders sein.
Diese Tonleiter (in ihrer ursprünglichen Funktion) blockiert den Arduino für einige Zeit.

Bis jetzt läuft es so:

for (int i = 0; i < 7; i++){
tone(BuzzerPin, 200 + (100 * i));
delay(100);
noTone(BuzzerPin);
}

Die Funktion umgeschrieben zu:

void BuzzerLeiter(int TonAn, int TonAus)
{
  while (i << 7){
  frequenz = (200 + (100 * i));
  Serial.println(frequenz);
  int blinkPhase=millis()%(TonAn+TonAus);
  if (blinkPhase<TonAn) tone(BuzzerPin, frequenz);
  if (blinkPhase<TonAn) i++;
  else noTone(BuzzerPin);
  }
}

Funktioniert auch nicht.

Kann mir jemand helfen, einen anderen Lösungsansatz zu finden?

Vielen Dank

marco_78:
Kann mir jemand helfen, einen anderen Lösungsansatz zu finden?

Ich würde die Frequenzen der Töne in ein Array schreiben und bei jedem Umlauf den Zähler des Arrays um eins erhöhen, den ton holen, der sich dahinter verbirgt, abspielen, und wieder den Zähler um eins erhöhen.

Vielleicht gehts auch einfacher. Probier mal den umgeschriebenen Code von Dir:

const int BuzzerPin = 6;
int frequenz = 0;
int tonzaehler = 1;
void setup()
  {
  Serial.begin(9600);
  }

bool Buzzer(const int TonAn, const int TonAus, const int Freq)
  {
  bool status = false;
  int blinkPhase = millis() % (TonAn + TonAus);
  if (blinkPhase < TonAn) tone(BuzzerPin, Freq);
  else
    {
    noTone(BuzzerPin);
    status = true;
    }
  return status;
  }

void loop()
  {
  //Serial.println(millis());
  //Buzzer(300, 4000, 450);
    {
    Serial.println(tonzaehler);
    frequenz = (200 + (100 * tonzaehler));
    Serial.println(frequenz);
    if (Buzzer(1000, 1000, frequenz))
      {
      tonzaehler++;
      if (tonzaehler > 7) tonzaehler = 1;
      }
    }
  }

Hallo,

und vielen Dank!

Das funktioniert so.
Was ich (noch) nicht geschafft habe, ist das abspielen von unterschiedlichen Tonhöhen nacheinander.
Aber da klingt das mit den Arrys ganz sinnvoll.
Werde ich bei Zeiten mal ausprobieren.