使用 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();
}