diff --git a/README.md b/README.md index 17097e4..37369ca 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ The library declares these Arduino dependencies: [claws/BH1750](https://github.com/claws/BH1750) - `Adafruit NeoPixel` - `ESP32Servo` for ESP32-based RadioCore boards +- `NonBlockingRTTTL` version 1.4.0 or newer for non-blocking buzzer melodies Dependency-aware Arduino tools can install these libraries automatically. RadioCore_Kit does not copy, wrap, or re-export them. @@ -61,6 +62,7 @@ compile time. | `Soil_Moisture_Read` | Read and calibrate an analog soil moisture sensor | [Guide](examples/Soil_Moisture_Read/README.md) | | `NV3001B_Display` | Exercise the 128-by-220 color TFT | [Guide](examples/NV3001B_Display/README.md) | | `WS2812` | Run a three-color breathing animation | [Sketch](examples/WS2812/WS2812.ino) | +| `Buzzer_Control` | Play and repeat an RTTTL melody through the board-designated buzzer output | [Sketch](examples/Buzzer_Control/Buzzer_Control.ino) | | `Motor_Control` | Drive two direction inputs on an external motor driver | [Sketch](examples/Motor_Control/Motor_Control.ino) | | `Relay_Control` | Toggle an active-high relay module | [Sketch](examples/Relay_Control/Relay_Control.ino) | | `Servo_Control` | Control both channels of an RS-SV01 servo driver | [Sketch](examples/Servo_Control/Servo_Control.ino) | @@ -83,9 +85,10 @@ A new board declares only the capabilities it supports: `CO01_Read`, and `Soil_Moisture_Read`; CO01 also requires its control pin. - NV3001B pins, active levels, SPI frequency, and one supported display transport for `NV3001B_Display`. -- A data pin for `WS2812`, two motor-driver inputs for `Motor_Control`, a relay - output and active level for `Relay_Control`, and two PWM pins plus driver - enable facts for `Servo_Control`. +- A data pin for `WS2812`, a buzzer output pin and any shared peripheral power + control required by `Buzzer_Control`, two motor-driver inputs for + `Motor_Control`, a relay output and active level for `Relay_Control`, and two + PWM pins plus driver enable facts for `Servo_Control`. The shared examples currently support the ESP32/WiFi Kit Series and Heltec nRF52 peripheral APIs used by RC32, RCC6, and RC52. A board with a different diff --git a/docs/CONTEXT.md b/docs/CONTEXT.md index 748d122..aa3fba0 100644 --- a/docs/CONTEXT.md +++ b/docs/CONTEXT.md @@ -76,6 +76,10 @@ An external chain of individually addressable RGB pixels controlled by a single data signal. _Avoid_: generic RGB LED, onboard LED +**Buzzer output**: +The board-designated PWM output connected to a piezo buzzer or buzzer module. +_Avoid_: tone pin, speaker output + **Motor control input**: One of a pair of digital direction signals connected to an external motor driver; together the pair selects a stopped state or a drive direction. diff --git a/examples/Buzzer_Control/Buzzer_Control.ino b/examples/Buzzer_Control/Buzzer_Control.ino new file mode 100644 index 0000000..52b4c05 --- /dev/null +++ b/examples/Buzzer_Control/Buzzer_Control.ino @@ -0,0 +1,86 @@ +/* + * Plays the Meshtastic default RTTTL notification melody through the + * board-designated buzzer output: RC32 GPIO48 or RC52 P0.05. RCC6 has no + * supported buzzer output. + * + * Playback is non-blocking. The melody repeats five seconds after it finishes. + * Define BUZZER_RTTTL or BUZZER_REPLAY_INTERVAL_MS before this sketch content + * to use a different melody or replay interval. + */ +#ifndef BUZZER_RTTTL +#define BUZZER_RTTTL \ + "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p," \ + "b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p" +#endif + +#ifndef BUZZER_REPLAY_INTERVAL_MS +#define BUZZER_REPLAY_INTERVAL_MS 5000UL +#endif + +#include +#include + +#if !RADIOCORE_HAS_BUZZER +#error "Buzzer_Control requires a RadioCore board with a supported buzzer output." +#else + +#include + +namespace { + +constexpr char kRingtone[] = BUZZER_RTTTL; + +uint32_t playbackFinishedAt = 0; +bool replayPending = false; + +void startPlayback(bool replay) +{ + rtttl::begin(RADIOCORE_BUZZER_PIN, kRingtone); + replayPending = false; + Serial.println( + replay ? F("Buzzer replay started") : F("Buzzer playback started")); +} + +} // namespace + +void setup() +{ + Serial.begin(115200); + + pinMode(RADIOCORE_BUZZER_PIN, OUTPUT); + digitalWrite(RADIOCORE_BUZZER_PIN, LOW); + +#if RADIOCORE_HAS_SENSOR_POWER_CTRL + pinMode(RADIOCORE_SENSOR_POWER_CTRL_PIN, OUTPUT); + digitalWrite( + RADIOCORE_SENSOR_POWER_CTRL_PIN, + RADIOCORE_SENSOR_POWER_ON); + delay(RADIOCORE_SENSOR_POWER_WARMUP_MS); +#endif + + Serial.println(); + Serial.println(F("RadioCore buzzer control example")); + startPlayback(false); +} + +void loop() +{ + if (rtttl::isPlaying()) { + rtttl::play(); + + if (!rtttl::isPlaying()) { + playbackFinishedAt = millis(); + replayPending = true; + Serial.println(F("Buzzer playback finished")); + } + + return; + } + + if (replayPending && + millis() - playbackFinishedAt >= BUZZER_REPLAY_INTERVAL_MS) { + startPlayback(true); + } +} + +#endif // RADIOCORE_HAS_BUZZER diff --git a/library.properties b/library.properties index 6a68bc6..411457a 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Device Control url=https://github.com/HelTecAutomation/RadioCore_Library architectures=* includes=RadioCore_Kit.h -depends=Adafruit BME280 Library, BH1750 (>=1.3.0), Adafruit NeoPixel, ESP32Servo +depends=Adafruit BME280 Library, BH1750 (>=1.3.0), Adafruit NeoPixel, ESP32Servo, NonBlockingRTTTL (>=1.4.0) diff --git a/src/RadioCoreBoardConfig.h b/src/RadioCoreBoardConfig.h index 272d2ac..35300f7 100644 --- a/src/RadioCoreBoardConfig.h +++ b/src/RadioCoreBoardConfig.h @@ -23,6 +23,7 @@ #define RADIOCORE_NV3001B_USE_HARDWARE_SPI 0 #define RADIOCORE_NV3001B_USE_SOFTWARE_SPI 0 #define RADIOCORE_HAS_WS2812 0 +#define RADIOCORE_HAS_BUZZER 0 #define RADIOCORE_HAS_MOTOR_CONTROL 0 #define RADIOCORE_HAS_RELAY_CONTROL 0 #define RADIOCORE_HAS_SERVO_CONTROL 0 diff --git a/src/boards/heltec_rc32.h b/src/boards/heltec_rc32.h index 4a33290..5f01046 100644 --- a/src/boards/heltec_rc32.h +++ b/src/boards/heltec_rc32.h @@ -66,6 +66,9 @@ #define RADIOCORE_HAS_WS2812 1 #define RADIOCORE_WS2812_DATA_PIN 5 +#define RADIOCORE_HAS_BUZZER 1 +#define RADIOCORE_BUZZER_PIN 48 + #define RADIOCORE_HAS_MOTOR_CONTROL 1 #define RADIOCORE_MOTOR_IN1_PIN 41 #define RADIOCORE_MOTOR_IN2_PIN 42 diff --git a/src/boards/heltec_rc52.h b/src/boards/heltec_rc52.h index 14c7fa4..d4a5b55 100644 --- a/src/boards/heltec_rc52.h +++ b/src/boards/heltec_rc52.h @@ -57,6 +57,9 @@ #define RADIOCORE_HAS_WS2812 1 #define RADIOCORE_WS2812_DATA_PIN (0 + 9) // P0.09 +#define RADIOCORE_HAS_BUZZER 1 +#define RADIOCORE_BUZZER_PIN (0 + 5) // P0.05 + #define RADIOCORE_HAS_MOTOR_CONTROL 1 #define RADIOCORE_MOTOR_IN1_PIN (32 + 1) // P1.01 #define RADIOCORE_MOTOR_IN2_PIN (0 + 20) // P0.20 diff --git a/src/boards/heltec_rcc6.h b/src/boards/heltec_rcc6.h index 429389b..401ead5 100644 --- a/src/boards/heltec_rcc6.h +++ b/src/boards/heltec_rcc6.h @@ -46,6 +46,8 @@ #define RADIOCORE_HAS_WS2812 1 #define RADIOCORE_WS2812_DATA_PIN 2 +#define RADIOCORE_HAS_BUZZER 0 + #define RADIOCORE_HAS_MOTOR_CONTROL 1 #define RADIOCORE_MOTOR_IN1_PIN 3 #define RADIOCORE_MOTOR_IN2_PIN 4