Malted_Wheaties
Malted_Wheaties

Reputation: 143

Generating a smooth tone sweep with Arduino

I am trying to make a whooping alarm using a piezo buzzer that rises linearly from a frequency of approximately 100Hz to 800Hz, over the course of one second. How do I do this?

I do not need exact measurements or timings, just something that will grab attention.

I believe tone()is the only way to go about this?

Upvotes: 2

Views: 1250

Answers (1)

Delta_G
Delta_G

Reputation: 3243

I just happened to have this open on my screen in part of another project when I read your question. I usually don't just hand out code but I'm feeling generous today and all I had to do was copy and paste and add a couple of comments for you.

Remember to keep all your other code non-blocking (no delays or long for or while loops waiting for things in the physical world) or this won't work.

As written it's untested but it was pulled out of tested code and only slightly edited for clarity. Unless I made a typo somewhere this should work out just fine.

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

Upvotes: 3

Related Questions