diff --git a/LICENSE.md b/LICENSE.md index 0470928..a7b933f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Robert Gallup +Copyright (c) 2015-2022 Robert Gallup Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3f83695..96b6221 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,52 @@ # BobaBlox Library Documentation -Version: 2.0 -Author: Robert Gallup -Date: 7/19/2015 +**Version: 2.1.0** +**Author: Robert Gallup** +**Date: 1/11/2022** -BobaBlox is an Arduino library that makes it easier to sketch code for basic hardware components. I've found that in teaching introductory Arduino workshops, that the repetitiveness of typing numerous commands just to make an LED blink can get in the way of learning overall programming concepts. So, I developed BobaBlox. It was initially designed to work with the Adafruit Trinket, but works equally well on standard Arduino models. -Here's an example of using BobaBlox in the standard blink example. First, standard blink: + +- - - +# BobaBlox Overview + +BobaBlox is an Arduino library that makes it easier to sketch code for basic hardware components. I've found while teaching Arduino workshops, the repetitiveness of typing multiple commands just to make an LED blink can get in the way of learning overall programming concepts. So, I developed BobaBlox. It should work with all standard Arduino boards, including variants such as the Adafruit Trinket. + +Here's an example using BobaBlox in the standard blink example. First, standard blink from Arduino examples: void setup() { - pinMode (13, OUTPUT); + pinMode (13, OUTPUT); // Define pin 13 as an output pin } void loop() { - digitalWrite (13, HIGH); - delay (500); - digitalWrite (13, LOW); - delay (500); + digitalWrite (13, HIGH); // Turn the LED on + delay (500); // Delay for 500 milliseconds + digitalWrite (13, LOW); // Turn the LED off + delay (500); // Delay for 500 milliseconds } - -When this is written using BobaBlox, it becomes: - #include - LED light(13); - - void loop () { - light.blink(); - } +When this is written using BobaBlox, it becomes: -In this case, setup() isn't required (though it has to be placed in the code). In addition, there are different versions of the blink method for changing the pin, number of blinks, the on-time, and off-time. + #include // Include the BobaBlox library + + LED light(13); // Define the LED on pin 13 + + void setup() {} // No extra setup statements required + void loop () { + light.blink(); // Each time through the loop, blink the LED on/off + } -The same holds true for the other elements in BobaBlox: Button, Knob, Photocell, and Speaker. In addition to the list, below, documentation for methods implemented for each element is in the associated example application when the library is installed. +Notice that there's no need to type digitalWrite/Delay twice. Also, setup() is empty. The only statement needed, is a "blink" command in loop(). -In addition to the documentation, below, see the example BobaBlox sketches when the library is installed. +The same pattern holds true for the other elements in BobaBlox: Button, Knob, Photocell, Speaker and Timer. You can find out more in the following documentation. Also, see the example BobaBlox sketches for working samples. -## Installation +##Installation The library is installed like other Arduino libraries. You can download a zip of the library and install it using Sketch > Include Library > Add .ZIP Library ... . BobaBlox should also be available in the Arduino Library Manager. Install using the Library Manger by choosing: Sketch > Include Library > Manage Libraries ... . Then, search for and select BobaBlox. + +- - - +# BobaBlox Object Reference + ## LED LED's are connected between an Arduino pin and ground, typically with a resistor in series. @@ -45,7 +54,7 @@ LED's are connected between an Arduino pin and ground, typically with a resistor #### Declaration LED led_name(pin); - + *led_name* is the name of the LED variable being declared. *pin* is the number of the pin being used for the LED. @@ -54,83 +63,95 @@ LED's are connected between an Arduino pin and ground, typically with a resistor void on (); // Turns the LED off void off (); // Turns the LED on void set (state); // Sets LED on if state is greater than zero - void blink (); // Blinks LED once with default 250ms on and off - void blink (n); // Blinks n times with default blink delay - void blink (n, delay); // Blinks n times with specific delay - void blink (n, delayON, delayOFF); // Blinks n times with delayON and delayOFF - void setBrightness (brightness); // On a PWM pin, sets LED brightness (0-255) - + void toggle(); // Toggles the LED on and off + void blink (); // Blinks LED once with default 250ms on and off + void blink (n); // Blinks n times with default blink delay + void blink (n, delay); // Blinks n times with specific delay + void blink (n, delayON, delayOFF); // Blinks n times with delayON and delayOFF + void setBrightness (brightness); // On a PWM pin, sets LED brightness (0-255) + +- - - ## Button -Buttons are connected between a pin and ground. The internal pullup resistor is used, so no other external components are required. +Buttons are connected between a pin and ground. The internal pull-up resistor is used, so no other external components are required. #### Declaration Button button_name(pin); - + *button_name* is name of the button variable being declared. *pin* is the number of the pin being used for the button. Its mode will be set to *input_pullup*. #### Methods - int state () // Returns 0 for up, 1 for down - boolean isDown () // Returns true is button is down, false otherwise - boolean isUp () // Returns true if button is up, false otherwise - boolean wasPressed () // Returns true when a button is pressed - boolean wasReleased () // Returns true when a button is released + int state () // Returns 0 for up, 1 for down + boolean isDown () // Returns true is button is down, false otherwise + boolean isUp () // Returns true if button is up, false otherwise + boolean wasPressed () // Returns true when a button is pressed + boolean wasReleased () // Returns true when a button is released + ***Notes:*** The Button methods use basic debouncing, but may have difficulties with "noisy" buttons. Also, *wasPressed()* and *wasReleased()* are more responsive the more frequently they are called. In a simple loop without a lot of *delay()* calls, it should be reasonably responsive. + + +- - - ## Knob -Knobs are potentiometers. This element assumes that the "outside" leads of the Knob are connected to *ground* and *VCC*, respectively. The center lead is connected to an Analog Input pin. +Knobs are potentiometers. This element assumes that the "outside" leads of the Knob are connected to *ground* and *V+*, respectively. The center lead is connected to an analog Input pin. #### Declaration Knob knob_name(pin); - + *knob_name* is name of the knob variable being declared. -*pin* is the number of the pin being used to connect the Knob. +*pin* is the number of the analog pin being used to connect to the center lead of the Knob. #### Methods - int value (); // Returns the current value (0-1023) - int value (int rangeStart, int rangeEnd) // Returns value mapped to specified range + int value (); // Returns the current value (0-1023) + int value (int rangeStart, int rangeEnd) // Returns value mapped to specified range ***Notes:*** -Potentiometers return values from 0 to 1023 on the 10-bit Arduino ADC. However, the range for setting the brightness of an LED, for example, is 0-255. Often, this is change in range is accomplished by using the *map()* function. However *map()* can be a bit complicated to understand. The version of *value()* that allows you to specify the range to return does the mapping automatically and is more straightforward. +Potentiometers return values from 0 to 1023 on the 10-bit Arduino analog to digital convertor (ADC). However, the range for setting the brightness of an LED, for example, is 0-255. Often, this is change in range is accomplished by using the *map()* function. However *map()* can be a bit complicated to understand. The version of *value()* that allows you to specify the range, does the mapping automatically and is more straightforward. + + +- - - ## Photocell -Photocells are identical to Knobs in implementation. This element assumes that the one lead from the photocell is connected to *VCC*. The other lead is connected to *ground* through a series resistor. The point where the photocell and series resistor are joined is connected to an Analog Input pin. +Photocells are identical to Knobs in implementation. This element assumes that the one lead from the photocell is connected to *V+*. The other lead is connected to *ground* through a series resistor. The point where the photocell and series resistor are joined is connected to an Analog Input pin. #### Declaration Photocell photocell_name(pin); - + *photocell_name* is name of the Photocell variable being declared. *pin* is the number of the pin being used for the photocell. #### Methods - int value (); // Returns the current value (0-1023) - int value (int rangeStart, int rangeEnd) // Returns value mapped to specified range + int value (); // Returns the current value (0-1023) + int value (int rangeStart, int rangeEnd) // Returns value mapped to specified range ***Notes:*** * The notes from the Knob section apply here. + + +- - - ## Speaker In standard Arduino, speakers can be controlled using the tone() method. This is not available on the Trinket. So, the Speaker object implements related ways to make sound using one or two pins (see notes, below). #### Declaration - Speaker mySpeaker(pin) // One speaker is pin, the other is ground - Speaker mySpeaker(pin1,pin2) // Speaker is connected between Pin1 and Pin2 + Speaker speaker_name(pin); // One speaker is pin, the other is ground + Speaker speaker_name(pin1,pin2); // Speaker is connected between Pin1 and Pin2 ***Notes:*** @@ -138,12 +159,12 @@ Often, a speaker is connected between one Arduino pin and ground. However, in th #### Methods - void beep (frequency, length, color); // Beeps at frequency for length with color - void tone (frequency, color); // Continuous tone at frequency and color - void start (); // Starts tone (if it's been stopped) - void stop (); // Stops the tone (if its running) - void frequency (); // Returns the last set frequency - void color (); // Returns the last color + void beep (frequency, length, color); // Beeps at frequency for length with color + void tone (frequency, color); // Continuous tone at frequency and color + void start (); // Starts tone (if it's been stopped) + void stop (); // Stops the tone (if its running) + void frequency (); // Returns the last set frequency + void color (); // Returns the last color ***Notes:*** @@ -153,3 +174,40 @@ Often, a speaker is connected between one Arduino pin and ground. However, in th *beep()* is just like the tone() Arduino function. It will pause the loop while the sound is playing. *tone()* plays a tone continuously, monitoring it as the function is called repeatedly in *loop()*. In order for tone() to be effective, it must be called frequently at the top level of *loop()*. + + + +- - - +## Timer + +Sometimes in programming, you want to have timed actions that do not delay the main loop between actions. This is so you can continue checking a button, or blinking an LED, etc. The simple Timer object helps implement these "non-blocking" actions. + +#### Declaration + + Timer timer_name(); // Timer preset to 1 second + Timer timer_name(interval); // Timer preset to specified interval (milliseconds) + +***Notes:*** + +To use a Timer, you can declare it with an interval, or use the setTime() or setTimeMicros() methods (below), then you use the start() method to begin the timer. Finally, the isExpired() method can be used to check when the timer has ended. + +There are two versions of most routines, the "default" one that uses milliseconds, and a "micros" version that uses microseconds for higher resolution. + +#### Methods + + void setTime (time); // Sets the time (milliseconds) + void setTimeMicros (time); // Sets the time (microseconds) + void getTime (); // Returns the interval (milliseconds) + void getTimeMicros (); // Returns the interval (microseconds) + void getTimeRemaining (); // Returns the timer's remaining time (milliseconds) + void getTimeRemainingMicros (); // Returns the timer's remaining time (microseconds) + void start (); // Starts the timer + void restart (); // Same as start () + void isExpired (); // Returns true if the timer has expired, false if not + + + + + +- - - +Copyright 2015-2022 Robert Gallup diff --git a/examples/Button/Button.ino b/examples/Button/Button.ino index f772ab5..c796e68 100644 --- a/examples/Button/Button.ino +++ b/examples/Button/Button.ino @@ -1,26 +1,26 @@ //////////////////////////////////////////// // -// BobaBlox Example Sketch: Button +// EZBlox Example Sketch: Button // // DECLARATION: // -// Button myButton(pin) // pin = the pin connecting to the button +// Button myButton(pin); // pin = the pin connecting to the button // // METHODS: // -// int state () // Returns 0 for up, 1 for down -// boolean isDown () // Returns true is button is down, false otherwise -// boolean isUp () // Returns true if button is up, false otherwise -// boolean wasPressed () // Returns true when a button is pressed -// boolean wasReleased () // Returns true when a button is released +// int state () // Returns 0 for up, 1 for down +// boolean isDown () // Returns true is button is down, false otherwise +// boolean isUp () // Returns true if button is up, false otherwise +// boolean wasPressed () // Returns true when a button is pressed +// boolean wasReleased () // Returns true when a button is released // //////////////////////////////////////////// #include // Declarations -LED boardLED(1); // Use on-board LED -Button myButton(2); // Button is connected between pin #2 and Ground +LED boardLED; // Use on-board LED +Button myButton(2); // Button is connected between pin #2 and Ground // Setup runs once void setup() { @@ -29,25 +29,11 @@ void setup() { // Loop repeats forever void loop() { + // If the button is down, turn LED on if (myButton.isDown()) { boardLED.on(); } else { boardLED.off(); } - -// To reverse the logic (light is on with up): -// Uncomment the following lines (and comment the lines above) - -// if (myButton.isUp()) { -// boardLED.on(); -// } else { -// boardLED.off(); -// } - -// Blink when button is pressed: - -// if (myButton.isDown()) { -// boardLED.blink(1, 30, 70); -// } - + } diff --git a/examples/Knob/Knob.ino b/examples/Knob/Knob.ino index 49cc6de..82179cf 100644 --- a/examples/Knob/Knob.ino +++ b/examples/Knob/Knob.ino @@ -13,28 +13,27 @@ // | | | // | | | // -// 5V PIN GND +// Vcc PIN GND // // // DECLARATION: // -// Knob myKnob(pin) // pin is LED pin +// Knob myKnob(pin); // pin is LED pin // -// METHOD: +// METHODS: // -// int value (); // Returns the current value (0-1023) -// int value (int rangeStart, int rangeEnd) // Returns the current value mapped to range specified +// int value (); // Returns the current value (0-1023) +// int value (rangeStart, rangeEnd); // Returns the current value mapped to the specified range // //////////////////////////////////////////// #include // Declarations -LED boardLED(1); // Declare an LED on pin #1 -Knob myKnob(1); // Knob is connected to Analog pin #1 (digital pin #2) +LED boardLED; // Use the builtin LED +Knob myKnob(1); // Knob is connected to Analog pin #1 -int knobValue; // The knob value -int blinkDelay; // The blink delay +int blinkDelay; // The blink delay // Setup runs once void setup() { @@ -44,11 +43,8 @@ void setup() { // Loop repeats forever void loop() { - // Check the knob value - // Convert the value (0-1023) to a 0-1 second delay (0-1000). - // Note: see the Map command reference - knobValue = myKnob.value(); - blinkDelay = map(knobValue, 0, 1023, 0, 1000); + // Check the knob value (converted to 0-1000) and use it for the blink delay + blinkDelay = myKnob.value(0, 1000); boardLED.blink(1, blinkDelay); -} \ No newline at end of file +} diff --git a/examples/LED/LED.ino b/examples/LED/LED.ino index b9da864..3027dd9 100644 --- a/examples/LED/LED.ino +++ b/examples/LED/LED.ino @@ -4,38 +4,35 @@ // // DECLARATION: // -// LED myLED(pin) // pin is LED pin +// LED myLED; // Uses LED_BUILTIN pin +// LED myLED(pin); // Set LED on specific pin // // METHODS: // // void on (); // void off (); -// void set (state); // Sets LED on if state is greater than zero -// void blink (); // Blinks LED once with default 250ms on and off -// void blink (n); // Blinks n times with default blink delay -// void blink (n, delay); // Blinks n times with specific delay -// void blink (n, delayON, delayOFF); // Blinks n times with delayON and delayOFF -// void setBrightness (brightness); // On an Analog Output (PWM) pin, sets LED brightness (0-255) +// void set (state); // Sets LED on if state is greater than zero +// void blink (); // Blinks LED once with default 250ms on and off +// void blink (n); // Blinks n times with default blink interval +// void blink (n, time); // Blinks n times with specific interval +// void blink (n, timeON, timeOFF); // Blinks n times with intervalON and intervalOFF +// void setBrightness (brightness); // On an Analog Output (PWM) pin, sets LED brightness (0-255) // //////////////////////////////////////////// #include // Declarations -LED boardLED(1); +LED boardLED; // Use the builtin LED // Setup runs once -void setup() { +void setup() { } // Loop repeats forever void loop() { - // Blinks LED. Uncomment one of the blinks below - // Uncomment one of the lines below for it's effect - boardLED.blink(); - // boardLED.blink(1, 100); - // boardLED.blink(1, 20, 250); - + // Blink the LED on/off + boardLED.blink(); } diff --git a/examples/Photocell/Photocell.ino b/examples/Photocell/Photocell.ino index 2765db3..2d13430 100644 --- a/examples/Photocell/Photocell.ino +++ b/examples/Photocell/Photocell.ino @@ -7,47 +7,42 @@ // [Photocell] [10K OHMS] // // // -// o---[==]---o---/\/\/---o +// o---[==]---o---[~~~]---o // | | | // | | | // -// 5V PIN GND +// Vcc PIN GND // // Note: Resistor value depends on your Photocell // // DECLARATION: // -// Photocell cell(pin) // Middle pin in above circuit +// Photocell cell(pin); // Middle pin in above circuit // -// METHOD: +// METHODS: // -// int value (); // Returns the current value (0-1023) -// int value (int rangeStart, int rangeEnd) // Returns the current value mapped to range specified +// int value (); // Returns the current value (0-1023) +// int value (rangeStart, rangeEnd); // Returns the current value mapped to the specified range // //////////////////////////////////////////// #include // Declarations -LED boardLED(1); // Declare an LED on pin #1 -Photocell cell(1); // Knob is connected to Analog pin #1 (digital pin #2) +LED boardLED; // Use the builtin LED +Photocell cell(1); // Photocell "pin" is connected to Analog pin #1 -int cellValue; // This will hold the knob value -int blinkDelay; // This will hold the blink delay +int blinkDelay; // This will hold the blink delay // Setup runs once void setup() { - } // Loop repeats forever void loop() { - // Check the photocell value - // Convert the value (0-1023) to a 0-1 second delay (0-1000). - // Note: see the Map command reference - cellValue = cell.value(); - blinkDelay = map(cellValue, 0, 1023, 0, 1000); + // Check the photocell value (converted to 0-1000) and use it for the blink delay + blinkDelay = cell.value(0, 1000); boardLED.blink(1, blinkDelay); -} \ No newline at end of file +} diff --git a/examples/Speaker/Speaker.ino b/examples/Speaker/Speaker.ino index 56eff83..47c25ec 100644 --- a/examples/Speaker/Speaker.ino +++ b/examples/Speaker/Speaker.ino @@ -4,24 +4,24 @@ // // DECLARATIONS: // -// Speaker mySpeaker(pin) // One speaker is pin, the other is ground -// Speaker mySpeaker(pin1,pin2) // Speaker is connected between Pin1 and Pin2 (doubles the volume) +// Speaker mySpeaker(pin); // One speaker is pin, the other is ground +// Speaker mySpeaker(pin1,pin2); // Speaker is connected between Pin1 and Pin2 (doubles the volume) // // METHODS: // -// void beep (frequency, length, color); // Beeps speaker at frequency (positive int) for length (millis). Color is 0.0 - 1.0 -// void tone (frequency, color); // Runs tone continuously at frequency and color (must be called at top level of loop) -// void start (); // Starts tone (if it's been stopped) -// void stop (); // Stops the tone -// void frequency (); // Returns the last set frequency -// void color (); // Returns the last color +// void beep (frequency, length, color); // Beeps speaker at frequency (positive int) for length (millis). Color is 0.0 - 1.0 +// void tone (frequency, color); // Runs tone continuously at frequency and color (must be called at top level of loop) +// void start (); // Starts tone (if it's been stopped) +// void stop (); // Stops the tone +// void getFrequency (); // Returns the last set frequency +// void getColor (); // Returns the last color // //////////////////////////////////////////// #include // Declarations -Speaker piezo(2); // Declare a speaker using digital pin #2 +Speaker piezo(2); // Speaker uses digital pin #2 // Setup runs once void setup() { @@ -34,7 +34,7 @@ void loop() { int freq; for (freq=50; freq<=6000; freq=freq+50) { piezo.beep(freq, 200); - delay (100); + delay (50); } } diff --git a/keywords.txt b/keywords.txt index b84b9cc..0934014 100644 --- a/keywords.txt +++ b/keywords.txt @@ -11,6 +11,7 @@ Knob KEYWORD1 Button KEYWORD1 Speaker KEYWORD1 Photocell KEYWORD1 +Timer KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -21,8 +22,9 @@ Photocell KEYWORD1 on KEYWORD2 off KEYWORD2 set KEYWORD2 +toggle KEYWORD2 blink KEYWORD2 -fade KEYWORD2 +setBrightness KEYWORD2 # KNOB + PHOTOCELL @@ -42,9 +44,22 @@ beep KEYWORD2 tone KEYWORD2 start KEYWORD2 stop KEYWORD2 +mute KEYWORD2 frequency KEYWORD2 color KEYWORD2 -####################################### +# TIMER + +setTime KEYWORD2 +setTimeMicros KEYWORD2 +getTime KEYWORD2 +getTimeMicros KEYWORD2 +getTimeRemaining KEYWORD2 +getTimeRemainingMicros KEYWORD2 +start KEYWORD2 +restart KEYWORD2 +isExpired KEYWORD2 + +##################################### # Constants (LITERAL1) ####################################### diff --git a/library.properties b/library.properties index b436438..a72ac7f 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=BobaBlox -version=2.0.1 +version=2.1.0 author=Robert Gallup maintainer=Robert Gallup sentence=A library that makes it easy to code simple hardware interactions with the Arduino. -paragraph=Buttons, LEDs, knobs (potentiometers), speakers, and photocells are currently supported. +paragraph=Buttons, LEDs, knobs (potentiometers), speakers, photocells, and timers are currently supported. url=https://github.com/robertgallup/BobaBlox category=Other -architectures=* \ No newline at end of file +architectures=* diff --git a/src/BobaBlox.h b/src/BobaBlox.h index cc00228..2050561 100644 --- a/src/BobaBlox.h +++ b/src/BobaBlox.h @@ -1,16 +1,41 @@ /////////////////////////////////////////////////////////////// // -// BobaBlocks Library Master Include +// BobaBlox Library Master Include +// +// The MIT License (MIT) +// +// Copyright (c) 2014-2022 Robert Gallup +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // /////////////////////////////////////////////////////////////// -#ifndef BOBABLOX_h -#define BOBABLOX_h +#ifndef BOBABLOX_H +#define BOBABLOX_H #include "utility/Button.h" #include "utility/Knob.h" #include "utility/LED.h" -#include "utility/Photocell.h" #include "utility/Speaker.h" +#include "utility/Timer.h" + +// Alias the Photocell type with Knob +typedef Knob Photocell; #endif diff --git a/src/utility/Button.cpp b/src/utility/Button.cpp index 16208fb..e63a5f1 100644 --- a/src/utility/Button.cpp +++ b/src/utility/Button.cpp @@ -6,9 +6,9 @@ // BobaBlox Library // // The MIT License (MIT) -// -// Copyright (c) 2014-2015 Robert Gallup -// +// +// Copyright (c) 2014-2022 Robert Gallup +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights @@ -29,16 +29,17 @@ // /////////////////////////////////////////////////////////////// -#include "Button.h" - -#define DEBOUNCE_INTERVAL 14 +#include "button.h" // Constructor : Button Button::Button (byte p) { _pin = p; pinMode (_pin, INPUT_PULLUP); - _lastState = digitalRead(_pin); + + _lastSample = digitalRead(_pin); + _sampleTime = millis(); + _reading = _lastSample; } // Return button state (0=down, 1=up) @@ -62,27 +63,50 @@ boolean Button::isUp () // Check button was pressed boolean Button::wasPressed () { - return detectEdge (HIGH, LOW); + // Update edge detection + _checkEdge(); + + // Save and reset edge state (_wasPressed) + boolean edge = _wasPressed; + _wasPressed = false; + + // Return _wasPressed state + return edge; } // Check button was released boolean Button::wasReleased () { - return detectEdge (LOW, HIGH); + // Update edge detection + _checkEdge(); + // Save and reset edge state (_wasReleased) + boolean edge = _wasReleased; + _wasReleased = false; + + // Return edge state + return edge; } -boolean Button::detectEdge (int from, int to) { +void Button::_checkEdge () { - boolean e = false; - if ((_lastState == from) && (digitalRead(_pin) == to)) { - delay (DEBOUNCE_INTERVAL); - if (digitalRead(_pin) == to) { - e = true; + // Take samples only on debounce intervals + if ((millis()-_sampleTime) > DEBOUNCE_INTERVAL) { + // Sample pin + _thisSample = digitalRead(_pin); + // If it's the same as the last sample then we have a valid reading + if (_thisSample == _lastSample) { + // If there's a change, then set pressed/release states (inverse of each other) + if (_thisSample != _reading) { + _wasPressed = (_reading == HIGH) && (_thisSample == LOW); + _wasReleased = !_wasPressed; + } + // Save this sample as a reading + _reading = _thisSample; } + // Use this sample/time as reference for the next detection + _lastSample = _thisSample; + _sampleTime = millis(); } - _lastState = digitalRead(_pin); - return e; - } diff --git a/src/utility/Button.h b/src/utility/Button.h index 39bbd29..21d1bc0 100644 --- a/src/utility/Button.h +++ b/src/utility/Button.h @@ -7,7 +7,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2014-2015 Robert Gallup +// Copyright (c) 2014-2022 Robert Gallup // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -29,11 +29,13 @@ // /////////////////////////////////////////////////////////////// -#ifndef BB_BUTTON_h -#define BB_BUTTON_h +#ifndef BUTTON_H +#define BUTTON_H #include "Arduino.h" +#define DEBOUNCE_INTERVAL 14 + // CLASS class Button { @@ -48,10 +50,20 @@ class Button private: - int _lastState; + // Button Pin byte _pin; - boolean detectEdge(int, int); - + + // Checks for press/release event + void _checkEdge(); + + // Associated with _checkEdge(); + unsigned long _sampleTime; + int _lastSample; + int _thisSample; + int _reading; + boolean _wasPressed = false; + boolean _wasReleased = false; + }; #endif diff --git a/src/utility/Knob.cpp b/src/utility/Knob.cpp index d653496..d190d27 100644 --- a/src/utility/Knob.cpp +++ b/src/utility/Knob.cpp @@ -7,7 +7,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2014-2015 Robert Gallup +// Copyright (c) 2014-2022 Robert Gallup // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -42,7 +42,7 @@ Knob::Knob (byte p) int Knob::value () { _lastValue = analogRead(_pin); - return (_lastValue); + return _lastValue; } // Read potentiometer value and map to specified range diff --git a/src/utility/Knob.h b/src/utility/Knob.h index 2fad924..ebfc8bd 100644 --- a/src/utility/Knob.h +++ b/src/utility/Knob.h @@ -7,7 +7,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2014-2015 Robert Gallup +// Copyright (c) 2014-2022 Robert Gallup // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -29,8 +29,8 @@ // /////////////////////////////////////////////////////////////// -#ifndef BB_Knob_h -#define BB_Knob_h +#ifndef KNOB_H +#define KNOB_H #include "Arduino.h" diff --git a/src/utility/LED.cpp b/src/utility/LED.cpp index c7205ba..b2c0f36 100644 --- a/src/utility/LED.cpp +++ b/src/utility/LED.cpp @@ -7,7 +7,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2014 Robert W. Gallup +// Copyright (c) 2014-2022 Robert Gallup // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -32,13 +32,25 @@ #include "LED.h" #define DEFAULT_DURATION 250 +#define _initPin(p) pinMode(p,OUTPUT);digitalWrite(p, LOW) -// Constructor +// Constructor: Built-in LED +LED::LED () +{ + _pin = LED_BUILTIN; + _initPin(_pin); +} + +// Constructor: Specify LED pin +// LED::LED (byte p, boolean analog) +// { +// _pin = p; +// if (!analog) _initPin(_pin); +// } LED::LED (byte p) { _pin = p; - pinMode (_pin, OUTPUT); - digitalWrite (_pin, LOW); + _initPin(_pin); } // Set LED to ON @@ -59,9 +71,15 @@ void LED::set (int ledState) digitalWrite (_pin, ledState & 1); } +// Toggle LED +void LED::toggle() +{ + digitalWrite(_pin, !digitalRead(_pin)); +} + // A single default blink void LED::blink () { - aBlink (DEFAULT_DURATION, DEFAULT_DURATION); + _blink (DEFAULT_DURATION, DEFAULT_DURATION); } // Blink a number of default blinks @@ -74,14 +92,14 @@ void LED::blink (int times) { // Blink a number of times with symetrical on/off durations void LED::blink (int times, int duration) { for (int i=0; i _cycleLength[_halfCycle]) { - _cycleTimer += _cycleLength[_halfCycle]; + if ((micros() - _cycleTimer) > _cycleTime[_halfCycle]) { + _cycleTimer += _cycleTime[_halfCycle]; _halfCycle = 1-_halfCycle; _cycleSpeaker(_halfCycle); } @@ -134,22 +134,30 @@ void Speaker::stop() { _soundON = false; } +// Mute/unmute sound +void Speaker::mute(boolean mute) { + + if (mute) {stop();} else {start();} + +} + // Return current frequency -unsigned int Speaker::frequency() { +unsigned int Speaker::getFrequency() { return (_frequency); } // Return current tone color (pulse width) -float Speaker::color() { +float Speaker::getColor() { return (_color); } // Private method to calculate wave components void Speaker::_calculateWave () { - unsigned long cycleLengthTotal = (1.0 / float(_frequency)) * MICROS_PER_SECOND; - _cycleLength[POSITIVE_HALFCYCLE] = _color * cycleLengthTotal; - _cycleLength[NEGATIVE_HALFCYCLE] = cycleLengthTotal - _cycleLength[POSITIVE_HALFCYCLE]; + // Cycle time in micro seconds + unsigned long fullCycleTime = (1.0 / float(_frequency)) * MICROS_PER_SECOND; + _cycleTime[POSITIVE_HALFCYCLE] = _color * fullCycleTime; + _cycleTime[NEGATIVE_HALFCYCLE] = fullCycleTime - _cycleTime[POSITIVE_HALFCYCLE]; } diff --git a/src/utility/Speaker.h b/src/utility/Speaker.h index b9bcb10..4a85e09 100644 --- a/src/utility/Speaker.h +++ b/src/utility/Speaker.h @@ -7,7 +7,7 @@ // // The MIT License (MIT) // -// Copyright (c) 2014-2015 Robert Gallup +// Copyright (c) 2014-2022 Robert Gallup // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -29,8 +29,8 @@ // /////////////////////////////////////////////////////////////// -#ifndef BB_SPEAKER_h -#define BB_SPEAKER_h +#ifndef SPEAKER_H +#define SPEAKER_H #include "Arduino.h" @@ -48,10 +48,11 @@ class Speaker void tone (unsigned int, float color=0.5); void start(); void stop(); + void mute(boolean); // Returns current frequency and color - unsigned int frequency(); - float color(); + unsigned int getFrequency(); + float getColor(); private: @@ -66,9 +67,9 @@ class Speaker float _color; // Tone color (pulse width) // Waveform definition - unsigned long _cycleLength[2]; // Lengths for the two halfcycles + unsigned long _cycleTime[2]; // Lengths for the two halfcycles unsigned long _cycleTimer; // For timing the half cycles - byte _halfCycle; // 0=positive halfcycle, 1=-halfcycle + byte _halfCycle; // 0 = positive halfcycle, 1 = negative halfcycle // Utility methods void _calculateWave(); // Calculates positive/negative halfcycle lengths given current frequency/color