Advertisement
skizziks_53

Button with sound v1.0

Feb 27th, 2018
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.85 KB | None | 0 0
  1. /*
  2.    26 February 2018
  3.    Tone with interrupter button
  4.    general example, tested on Uno
  5.  
  6.    Parts required:
  7.    1 normally-open button, wired as INPUT_PULLUP
  8.    1 small speaker
  9. */
  10.  
  11. int buttonPin = 2; // This button is wired as INPUT_PULLUP.
  12. bool button_enabled = true;
  13. int button_debounceTime = 500; // This is the time in milliseconds to debounce the button.
  14. unsigned long buttonPressed_startTime = 0;
  15. unsigned long buttonPressed_currentTime = 0;
  16. int buttonState = 0;
  17.  
  18. 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.
  19. // If you want a LOUD speaker, get an active buzzer (fixed tone, but with its own amp) or use an external amp...
  20. bool tone_enabled = false;
  21. int tone_stage = 0; // This is a counter to control a multi-stage function. Zero == "off".
  22. int tonePinState = 0;
  23.  
  24. // The two variables below are for making the sound. Other values get copied into these before use.
  25. long soundInterval = 0; // The tonePin change interval in microseconds.
  26. // 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.
  27. int soundDuration = 0; // The sound duration in milliseconds.
  28.  
  29. // This example sketch shows how to make (3) different tones if you wanted to.
  30. int tone1_frequency = 3500; // Frequency in Hz
  31. int tone1_duration = 3000; // Length of the tone in milliseconds
  32. int tone2_frequency = 3000; // Frequency in Hz
  33. int tone2_duration = 3100; // Length of the tone in milliseconds
  34. int tone3_frequency = 2600; // Frequency in Hz {also 2600, because capn crunch}
  35. int tone3_duration = 3200; // Length of the tone in milliseconds
  36.  
  37. int delay1_frequency = 0; // For a silent delay, the frequency is set to zero.
  38. int delay1_duration = 1000; // The length of this silent duration in milliseconds.
  39.  
  40. // The two variables below are for timing a single sound pulse (the sound frequency).
  41. unsigned long tonePulse_beginTime_microseconds = 0;
  42. unsigned long tonePulse_currentTime_microseconds = 0;
  43.  
  44. // The two variables below are for timing the length that a single frequency lasts (the sound duration).
  45. unsigned long toneDuration_beginTime_milliseconds = 0;
  46. unsigned long toneDuration_currentTime_milliseconds = 0;
  47.  
  48.  
  49. void myTone(int); // Function prototype
  50. void resetTonePin(); // Function prototype
  51. int setSoundInterval(int, int); // Function prototype
  52.  
  53.  
  54. void setup() {
  55.   Serial.begin(9600);
  56.   // put your setup code here, to run once:
  57.   pinMode(buttonPin, INPUT_PULLUP);
  58.   pinMode(tonePin, OUTPUT);
  59.   digitalWrite(tonePin, LOW);
  60.   Serial.println("Exiting setup()");
  61. }
  62.  
  63. void loop() {
  64.  
  65.   // The section below is what allows the button to toggle on and off.
  66.   if (button_enabled == true) {
  67.     if (digitalRead(buttonPin) == 0) {
  68.       if (buttonState == 0) {
  69.         digitalWrite(13, HIGH);
  70.         Serial.println("Button press = ON");
  71.         buttonState = 1;
  72.         tone_stage = 1;
  73.         myTone(tone_stage);
  74.       }
  75.       else {
  76.         digitalWrite(13, LOW);
  77.         // The below message is what prints if you press the button again while the tone sequence is still playing.
  78.         // Otherwise, pressing the button re-starts the tone sequence from the beginning.
  79.         Serial.println("Button press/sound cutoff = OFF");
  80.         buttonState = 0;
  81.         tone_stage = 0;
  82.         // the tone section won't be active if tone_stage is set to zero
  83.         // and myTone(tone_stage); doesn't do anything if given a zero value, so it doesn't need to be called.
  84.         resetTonePin();
  85.         // resetTonePin() is called here just to make sure that the tone_pin is set back to LOW.
  86.       }
  87.       button_enabled = false;
  88.       buttonPressed_startTime = millis();
  89.     }
  90.   }
  91.  
  92.  
  93.  
  94.   // The section below is what de-bounces the button.
  95.   if (button_enabled == false) {
  96.     buttonPressed_currentTime = millis();
  97.     if (buttonPressed_currentTime > buttonPressed_startTime) {
  98.       if (buttonPressed_currentTime >= (buttonPressed_startTime + button_debounceTime)) {
  99.         button_enabled = true;
  100.       }
  101.     }
  102.     else {
  103.       buttonPressed_startTime = millis(); // millis() rollover condition.
  104.     }
  105.   }
  106.  
  107.  
  108.  
  109.   if (tone_stage != 0) {
  110.     // 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.
  111.     // This is why to make a silent delay period, you can just send a frequency+duration with the frequency set to zero.
  112.     if (soundInterval > 0) {
  113.       tonePulse_currentTime_microseconds = micros();
  114.       if (tonePulse_currentTime_microseconds >= tonePulse_beginTime_microseconds) {
  115.         if (tonePulse_currentTime_microseconds >= (tonePulse_beginTime_microseconds + soundInterval)) {
  116.           if (tonePinState == 1) {
  117.             digitalWrite(tonePin, LOW);
  118.             tonePinState = 0;
  119.           }
  120.           else {
  121.             digitalWrite(tonePin, HIGH);
  122.             tonePinState = 1;
  123.           }
  124.           tonePulse_beginTime_microseconds = micros(); // Reset the pin timer again.
  125.         }
  126.       }
  127.       else {
  128.         tonePulse_beginTime_microseconds = micros(); // micros() rollover condition.
  129.       }
  130.     }
  131.  
  132.  
  133.  
  134.     // The section below times each different part of the tone sequence and advances to the next sequence when necessary.
  135.     toneDuration_currentTime_milliseconds = millis();
  136.     if (toneDuration_currentTime_milliseconds > toneDuration_beginTime_milliseconds) {
  137.       if (toneDuration_currentTime_milliseconds >= (toneDuration_beginTime_milliseconds + soundDuration)) {
  138.         tone_stage++; // This increments the tone stage.
  139.         myTone(tone_stage); // Calling this function resets the tone frequency and duration to the next stage.
  140.       }
  141.     }
  142.     else {
  143.       toneDuration_beginTime_milliseconds = millis(); // Millis() rollover condition.
  144.     }
  145.  
  146.   } // if (tone_stage != 0)
  147.  
  148. } // end of main loop()
  149.  
  150.  
  151.  
  152. // The function below allows sending a series of different-frequency tones, each for a different time length.
  153. // For as many different tones as you want in a series, the switch-case statement has N+1 cases
  154. // (the last case is the one that shuts off the tone and resets the button).
  155. void myTone(int stageNum) {
  156.   switch (tone_stage) {
  157.     case 1:
  158.       soundInterval = setSoundInterval(tone1_frequency, tone1_duration);
  159.       soundDuration = tone1_duration;
  160.       resetTonePin();
  161.       break;
  162.     case 2:
  163.       soundInterval = setSoundInterval(delay1_frequency, delay1_duration);
  164.       soundDuration = delay1_duration;
  165.       resetTonePin();
  166.       break;
  167.     case 3:
  168.       soundInterval = setSoundInterval(tone2_frequency, tone2_duration);
  169.       soundDuration = tone2_duration;
  170.       resetTonePin();
  171.       break;
  172.     case 4:
  173.       soundInterval = setSoundInterval(delay1_frequency, delay1_duration);
  174.       soundDuration = delay1_duration;
  175.       resetTonePin();
  176.       break;
  177.     case 5:
  178.       soundInterval = setSoundInterval(tone3_frequency, tone3_duration);
  179.       soundDuration = tone3_duration;
  180.       resetTonePin();
  181.       break;
  182.     case 6:
  183.       tone_stage = 0; // Setting tone_stage to zero makes the tone section shut off again.
  184.       resetTonePin();
  185.       // When the series of different tones completes,
  186.       // the three lines below also flips the button state back to "off":
  187.       digitalWrite(13, LOW);
  188.       Serial.println("Sound finished: automatic button is reset to (OFF)");
  189.       buttonState = 0;
  190.       break;
  191.     default:
  192.       // nothing here
  193.       break;
  194.   }
  195. }
  196.  
  197. int setSoundInterval(int soundTime, int soundLength) {
  198.   // This function is written to catch the condition of the frequency being set to zero (for a silent delay period).
  199.   // Otherwise a zero-division error would occur when the soundInterval was set.
  200.  
  201.   // Note that this function doesn't really do anything with the sound duration (what is soundLength in this function).
  202.   // The reason that I passed it in anyway is because I wanted to have the option
  203.   // to be able to display the sound duration length over the Serial monitor when any sound tone is called, even silent delays.
  204.   int value1 = 0;
  205.   if (soundTime > 0) {
  206.     value1 = (int) (1000000 / (2 * soundTime)); // If soundTime was zero, this would result in a divide-by-zero error.
  207.     Serial.print("SoundInterval = ");
  208.     Serial.print(value1);
  209.     Serial.print(" for ");
  210.     Serial.print(soundLength);
  211.     Serial.println(" milliseconds.");
  212.   }
  213.   else {
  214.     // This is what happens when you call a silent delay (when the sound frequency is zero).
  215.     value1 = 0; // This skips the division above, that would result in dividing by zero {error}.
  216.     Serial.print("Silent delay = ");
  217.     Serial.print(soundLength);
  218.     Serial.println(" milliseconds.");
  219.   }
  220.   return value1;
  221. }
  222.  
  223. void resetTonePin() {
  224.   tonePulse_beginTime_microseconds = micros();
  225.   toneDuration_beginTime_milliseconds = millis();
  226.   digitalWrite(tonePin, LOW);
  227.   tonePinState = 0;
  228. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement