Мне показалось, что это было открыто на моем экране в рамках другого проекта, когда я прочитал ваш вопрос. Я обычно не просто раздаю код, но сегодня я чувствую себя щедрым, и все, что мне нужно было сделать, это скопировать, вставить и добавить пару комментариев для вас.
Не забудьте оставить неблокирующим весь ваш другой код (без задержек или циклов, ожидающих чего-то в физическом мире), иначе это не сработает.
Как написано, он не тестировался, но был извлечен из проверенного кода и лишь слегка отредактирован для ясности. Если я не сделал опечатку где-нибудь, это должно сработать.
byte sirenPin = 8; // or whatever pin
byte startPin = 7; // a button to start the siren wired between pin and ground.
byte stopPin = 6; // a cancel button
byte heartbeatPin = 5; // a blinking light
boolean sirenOn = false;
unsigned int totalSirenTime = 1000; // one second siren
unsigned int startFreq = 100;
unsigned int stopFreq = 800;
unsigned int stepSize = 10; // lets take 10Hz steps
unsigned int currentFreq;
void playSiren(){
static boolean midWhoop = false;
static unsigned long lastStep = millis();
unsigned long elapsedTime = millis() - lastStep;
unsigned int numberOfSteps = (stopFreq-startFreq)/stepSize;
unsigned int timePerStep = totalSirenTime/numberOfSteps;
if(!midWhoop){
// new round, reset our variables
lastStep = millis();
currentFreq = startFreq;
midWhoop = true;
}
if(elapsedTime >= timePerStep){
currentFreq += stepSize;
lastStep = millis();
if(currentFreq > stopFreq){
stopSiren();
midWhoop = false;
return;
}
}
tone(sirenPin, currentFreq);
}
void startSiren(){
sirenOn = true;
}
void stopSiren(){
sirenOn = false;
noTone(sirenPin);
}
void heartbeat(){
static unsigned long lastBlink = millis();
unsigned long elapsedTime = millis() - lastBlink;
if(elapsedTime >= 250){ // 0.5 hz blinking)
digitalWrite(heartbeatPin, !digitalRead(heartbeatPin));
lastBlink = millis();
}
}
void setup() {
pinMode(sirenPin, OUTPUT);
pinMode(startPin, INPUT_PULLUP);
pinMode(stopPin, INPUT_PULLUP);
pinMode(heartbeatPin, OUTPUT);
}
void loop() {
// whatever other code that can call startSiren() to make it start
// keep all the code in loop non-blocking.
if((digitalRead(startPin) == LOW) && !sirenOn){
startSiren();
}
if(digitalRead(stopPin) == LOW){
stopSiren();
}
if(sirenOn){
playSiren();
}
heartbeat();
}