Воспроизведение мелодии с Tone() без использования delay()
Есть ли способ воспроизвести мелодию с помощью Tone() без использования функции delay()?
tone(8, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration;
**delay(pauseBetweenNotes);**
@Zainau, 👍2
Обсуждение4 ответа
Да, используя конечный автомат и некоторое объектно-ориентированное программирование. Я бы рекомендовал прочитать этот учебник, так как он очень хорошо объясняет процесс и содержит множество примеров.
https://learn.adafruit.com/multi-tasking-the-arduino-part-1/ditch-the-delay
Как уже отмечали другие, это можно сделать, используя тот же метод, что и в стандартном примере скетча "BlinkWithoutDelay", и сочетая его с подходом типа конечного автомата. В простом конечном автомате можно предположить, что вы можете находиться в одном из двух состояний: выводить тон и не выводить тон.
Применяя эти идеи к приведенному выше фрагменту кода:
// ПЕРЕД НАСТРОЙКОЙ
const int tonePin = 8;
unsigned long previousMillis = 0;
const long interval = pauseBetweenNotes;
const long interval = noteDuration;
boolean outputTone = false; // Записывает текущее состояние
// В ЦИКЛЕ
unsigned long currentMillis = millis();
if (outputTone) {
// В настоящее время мы выводим тон
// Проверьте, достаточно ли долго это было, и выключите, если да
if (currentMillis - previousMillis >= noteDuration) {
previousMillis = currentMillis;
noTone(tonePin);
outputTone = false;
}
} else {
// В настоящее время мы находимся в паузе
// Проверьте, достаточно ли долго это было, и включите, если это так
if (currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
tone(tonePin, melody[thisNote]);
outputTone = true;
}
}
Работает только для одной задачи. Например, если лента работает параллельно, то возникнет шум., @Andrey Mihalev
Добавим немного к великому примеру кабдуллы, чтобы иметь возможность использовать MelodyArray
// объявление переменных
const int tonePin = 10;
unsigned long previousMillis = 0;
const long pauseBetweenNotes = 250; // интервал между заметками (мс)
const long noteDuration = 400; // (мс)
boolean outputTone = false; // Записывает текущее состояние
const int MelodyLength = 2;
const int Melody[MelodyLength] = {880, 698};
int MelodyIndex = 0;
unsigned long currentMillis;
void setup() {
}
void loop() {
currentMillis = millis();
PlayMelody();
}
void PlayMelody() {
if (outputTone) {
// В настоящее время мы выводим тон
// Проверьте, достаточно ли долго это было, и выключите, если да
if (currentMillis - previousMillis >= noteDuration) {
previousMillis = currentMillis;
noTone(tonePin);
outputTone = false;
}
} else {
// В настоящее время мы находимся в паузе
// Проверьте, достаточно ли долго это было, и включите, если это так
if (currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
tone(tonePin, Melody[MelodyIndex]);
outputTone = true;
// Обновление для воспроизведения следующего тона в следующий раз
MelodyIndex = MelodyIndex + 1;
if (MelodyIndex >= MelodyLength) {
MelodyIndex = 0;
}
}
}
}
это минимальная модификация базового примера Arduino toneMelody в неблокирующую версию
#include "pitches.h"
// ноты в мелодии:
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
// длительность ноты: 4 = четверть ноты, 8 = восьмая нота и т.д.:
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4
};
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes;
int thisNote;
void setup() {
}
void loop() {
// перебирать ноты мелодии:
unsigned long currentMillis = millis();
if (thisNote < 8 && currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
// чтобы рассчитать длительность ноты, возьмите одну секунду, разделенную на тип ноты.
// например, четвертная нота = 1000/4, восьмая нота = 1000/8 и т.д.
int noteDuration = 1000 / noteDurations[thisNote];
tone(8, melody[thisNote], noteDuration);
// чтобы различать ноты, установите минимальное время между ними.
// длительность заметки + 30%, похоже, работает хорошо:
pauseBetweenNotes = noteDuration * 1.30;
thisNote++;
}
}
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
ДА. Тот же метод, что и в примере скетча BlinkWithoutDelay., @Majenko
Это можно сделать с помощью прерывания таймера. http://stackoverflow.com/questions/33051500/arduino-tone-without-delay/33052071#33052071, @Artium