使用 Arduino 生成平滑的音调扫描
Generating a smooth tone sweep with Arduino
我正在尝试使用压电蜂鸣器发出警报声,该蜂鸣器在一秒钟内从大约 100Hz 的频率线性上升到 800Hz。我该怎么做?
我不需要精确的测量值或时间,只要能引起注意的东西即可。
我相信tone()
是解决这个问题的唯一方法吗?
当我读到你的问题时,我刚好在另一个项目的一部分的屏幕上打开了这个。我通常不只是分发代码,但我今天感觉很慷慨,我所要做的就是复制粘贴并为您添加一些评论。
记住让所有其他代码保持非阻塞(没有延迟或 long for 或 while 循环等待物理世界中的事物),否则这将不起作用。
正如所写的那样,它未经测试,但它是从经过测试的代码中提取出来的,并且为了清晰起见只进行了轻微的编辑。除非我在某处打错了字,否则应该没问题。
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();
}
我正在尝试使用压电蜂鸣器发出警报声,该蜂鸣器在一秒钟内从大约 100Hz 的频率线性上升到 800Hz。我该怎么做?
我不需要精确的测量值或时间,只要能引起注意的东西即可。
我相信tone()
是解决这个问题的唯一方法吗?
当我读到你的问题时,我刚好在另一个项目的一部分的屏幕上打开了这个。我通常不只是分发代码,但我今天感觉很慷慨,我所要做的就是复制粘贴并为您添加一些评论。
记住让所有其他代码保持非阻塞(没有延迟或 long for 或 while 循环等待物理世界中的事物),否则这将不起作用。
正如所写的那样,它未经测试,但它是从经过测试的代码中提取出来的,并且为了清晰起见只进行了轻微的编辑。除非我在某处打错了字,否则应该没问题。
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();
}