Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 26 February 2018
- Tone with interrupter button
- general example, tested on Uno
- Parts required:
- 1 normally-open button, wired as INPUT_PULLUP
- 1 small speaker
- */
- int buttonPin = 2; // This button is wired as INPUT_PULLUP.
- bool button_enabled = true;
- int button_debounceTime = 500; // This is the time in milliseconds to debounce the button.
- unsigned long buttonPressed_startTime = 0;
- unsigned long buttonPressed_currentTime = 0;
- int buttonState = 0;
- int tonePin = 3; // For the sound I used a small (30mm) 8-ohm speaker in series with a 700-ohm resistor. ~500 to 700+ ohms is good.
- // If you want a LOUD speaker, get an active buzzer (fixed tone, but with its own amp) or use an external amp...
- bool tone_enabled = false;
- int tone_stage = 0; // This is a counter to control a multi-stage function. Zero == "off".
- int tonePinState = 0;
- // The two variables below are for making the sound. Other values get copied into these before use.
- long soundInterval = 0; // The tonePin change interval in microseconds.
- // The soundInterval is not the same thing as frequency, since the pin has to change at a rate that is twice as high as the frequency.
- int soundDuration = 0; // The sound duration in milliseconds.
- // This example sketch shows how to make (3) different tones if you wanted to.
- int tone1_frequency = 3500; // Frequency in Hz
- int tone1_duration = 3000; // Length of the tone in milliseconds
- int tone2_frequency = 3000; // Frequency in Hz
- int tone2_duration = 3100; // Length of the tone in milliseconds
- int tone3_frequency = 2600; // Frequency in Hz {also 2600, because capn crunch}
- int tone3_duration = 3200; // Length of the tone in milliseconds
- int delay1_frequency = 0; // For a silent delay, the frequency is set to zero.
- int delay1_duration = 1000; // The length of this silent duration in milliseconds.
- // The two variables below are for timing a single sound pulse (the sound frequency).
- unsigned long tonePulse_beginTime_microseconds = 0;
- unsigned long tonePulse_currentTime_microseconds = 0;
- // The two variables below are for timing the length that a single frequency lasts (the sound duration).
- unsigned long toneDuration_beginTime_milliseconds = 0;
- unsigned long toneDuration_currentTime_milliseconds = 0;
- void myTone(int); // Function prototype
- void resetTonePin(); // Function prototype
- int setSoundInterval(int, int); // Function prototype
- void setup() {
- Serial.begin(9600);
- // put your setup code here, to run once:
- pinMode(buttonPin, INPUT_PULLUP);
- pinMode(tonePin, OUTPUT);
- digitalWrite(tonePin, LOW);
- Serial.println("Exiting setup()");
- }
- void loop() {
- // The section below is what allows the button to toggle on and off.
- if (button_enabled == true) {
- if (digitalRead(buttonPin) == 0) {
- if (buttonState == 0) {
- digitalWrite(13, HIGH);
- Serial.println("Button press = ON");
- buttonState = 1;
- tone_stage = 1;
- myTone(tone_stage);
- }
- else {
- digitalWrite(13, LOW);
- // The below message is what prints if you press the button again while the tone sequence is still playing.
- // Otherwise, pressing the button re-starts the tone sequence from the beginning.
- Serial.println("Button press/sound cutoff = OFF");
- buttonState = 0;
- tone_stage = 0;
- // the tone section won't be active if tone_stage is set to zero
- // and myTone(tone_stage); doesn't do anything if given a zero value, so it doesn't need to be called.
- resetTonePin();
- // resetTonePin() is called here just to make sure that the tone_pin is set back to LOW.
- }
- button_enabled = false;
- buttonPressed_startTime = millis();
- }
- }
- // The section below is what de-bounces the button.
- if (button_enabled == false) {
- buttonPressed_currentTime = millis();
- if (buttonPressed_currentTime > buttonPressed_startTime) {
- if (buttonPressed_currentTime >= (buttonPressed_startTime + button_debounceTime)) {
- button_enabled = true;
- }
- }
- else {
- buttonPressed_startTime = millis(); // millis() rollover condition.
- }
- }
- if (tone_stage != 0) {
- // The section below is what blinks the sound pin on and off rapidly to make the frequency requested, unless the frequency is set to zero.
- // This is why to make a silent delay period, you can just send a frequency+duration with the frequency set to zero.
- if (soundInterval > 0) {
- tonePulse_currentTime_microseconds = micros();
- if (tonePulse_currentTime_microseconds >= tonePulse_beginTime_microseconds) {
- if (tonePulse_currentTime_microseconds >= (tonePulse_beginTime_microseconds + soundInterval)) {
- if (tonePinState == 1) {
- digitalWrite(tonePin, LOW);
- tonePinState = 0;
- }
- else {
- digitalWrite(tonePin, HIGH);
- tonePinState = 1;
- }
- tonePulse_beginTime_microseconds = micros(); // Reset the pin timer again.
- }
- }
- else {
- tonePulse_beginTime_microseconds = micros(); // micros() rollover condition.
- }
- }
- // The section below times each different part of the tone sequence and advances to the next sequence when necessary.
- toneDuration_currentTime_milliseconds = millis();
- if (toneDuration_currentTime_milliseconds > toneDuration_beginTime_milliseconds) {
- if (toneDuration_currentTime_milliseconds >= (toneDuration_beginTime_milliseconds + soundDuration)) {
- tone_stage++; // This increments the tone stage.
- myTone(tone_stage); // Calling this function resets the tone frequency and duration to the next stage.
- }
- }
- else {
- toneDuration_beginTime_milliseconds = millis(); // Millis() rollover condition.
- }
- } // if (tone_stage != 0)
- } // end of main loop()
- // The function below allows sending a series of different-frequency tones, each for a different time length.
- // For as many different tones as you want in a series, the switch-case statement has N+1 cases
- // (the last case is the one that shuts off the tone and resets the button).
- void myTone(int stageNum) {
- switch (tone_stage) {
- case 1:
- soundInterval = setSoundInterval(tone1_frequency, tone1_duration);
- soundDuration = tone1_duration;
- resetTonePin();
- break;
- case 2:
- soundInterval = setSoundInterval(delay1_frequency, delay1_duration);
- soundDuration = delay1_duration;
- resetTonePin();
- break;
- case 3:
- soundInterval = setSoundInterval(tone2_frequency, tone2_duration);
- soundDuration = tone2_duration;
- resetTonePin();
- break;
- case 4:
- soundInterval = setSoundInterval(delay1_frequency, delay1_duration);
- soundDuration = delay1_duration;
- resetTonePin();
- break;
- case 5:
- soundInterval = setSoundInterval(tone3_frequency, tone3_duration);
- soundDuration = tone3_duration;
- resetTonePin();
- break;
- case 6:
- tone_stage = 0; // Setting tone_stage to zero makes the tone section shut off again.
- resetTonePin();
- // When the series of different tones completes,
- // the three lines below also flips the button state back to "off":
- digitalWrite(13, LOW);
- Serial.println("Sound finished: automatic button is reset to (OFF)");
- buttonState = 0;
- break;
- default:
- // nothing here
- break;
- }
- }
- int setSoundInterval(int soundTime, int soundLength) {
- // This function is written to catch the condition of the frequency being set to zero (for a silent delay period).
- // Otherwise a zero-division error would occur when the soundInterval was set.
- // Note that this function doesn't really do anything with the sound duration (what is soundLength in this function).
- // The reason that I passed it in anyway is because I wanted to have the option
- // to be able to display the sound duration length over the Serial monitor when any sound tone is called, even silent delays.
- int value1 = 0;
- if (soundTime > 0) {
- value1 = (int) (1000000 / (2 * soundTime)); // If soundTime was zero, this would result in a divide-by-zero error.
- Serial.print("SoundInterval = ");
- Serial.print(value1);
- Serial.print(" for ");
- Serial.print(soundLength);
- Serial.println(" milliseconds.");
- }
- else {
- // This is what happens when you call a silent delay (when the sound frequency is zero).
- value1 = 0; // This skips the division above, that would result in dividing by zero {error}.
- Serial.print("Silent delay = ");
- Serial.print(soundLength);
- Serial.println(" milliseconds.");
- }
- return value1;
- }
- void resetTonePin() {
- tonePulse_beginTime_microseconds = micros();
- toneDuration_beginTime_milliseconds = millis();
- digitalWrite(tonePin, LOW);
- tonePinState = 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement