Add command Buzzer

Add command Buzzer with optional parameters <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps> enabled when a buzzer is configured (#5988)
This commit is contained in:
Theo Arends 2019-08-12 17:18:08 +02:00
parent 9152aad6f2
commit 23ec00a452
9 changed files with 196 additions and 23 deletions

View File

@ -5,6 +5,7 @@
* See DEBUG_CORE_LOG example in sonoff.ino and DEBUG_DRIVER_LOG example in xdrv_09_timers.ino
* Add support for Solax X1 inverter by Pablo Zerón
* Add ZigBee support phase 1 - low level MQTT ZNP messages for CC2530 devices
* Add command Buzzer with optional parameters <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps> enabled when a buzzer is configured (#5988)
*
* 6.6.0.3 20190725
* Change filename of configuration backup from using FriendlyName1 to Hostname solving diacritic issues (#2422)

View File

@ -304,6 +304,7 @@
// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code)
// -- Optional modules ----------------------------
#define USE_BUZZER // Add support for a buzzer (+0k6 code)
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer
#define TUYA_DIMMER_ID 0 // Default dimmer Id

View File

@ -246,7 +246,7 @@ enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT
enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND,
FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART,
FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,

View File

@ -132,7 +132,6 @@ uint8_t leds_present = 0; // Max number of LED supported
uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off))
uint8_t led_power = 0; // LED power state
uint8_t ledlnk_inverted = 0; // Link LED inverted flag (1 = (0 = On, 1 = Off))
uint8_t buzzer_inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off))
uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted)
uint8_t counter_no_pullup = 0; // Counter input pullup flag (1 = No pullup)
uint8_t energy_flg = 0; // Energy monitor configured
@ -144,7 +143,6 @@ uint8_t seriallog_level; // Current copy of Settings.seriallo
uint8_t syslog_level; // Current copy of Settings.syslog_level
uint8_t my_module_type; // Current copy of Settings.module or user template type
uint8_t my_adc0; // Active copy of Module ADC0
uint8_t buzzer_count = 0; // Number of buzzes
//uint8_t mdns_delayed_start = 0; // mDNS delayed start
bool serial_local = false; // Handle serial locally;
bool fallback_topic_flag = false; // Use Topic or FallbackTopic
@ -816,16 +814,6 @@ void Every100mSeconds(void)
if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; }
}
}
if ((pin[GPIO_BUZZER] < 99) && (Settings.flag3.buzzer_enable)) {
if (buzzer_count) {
buzzer_count--;
uint8_t state = buzzer_count & 1;
digitalWrite(pin[GPIO_BUZZER], (buzzer_inverted) ? !state : state);
}
} else {
buzzer_count = 0;
}
}
/*-------------------------------------------------------------------------------------------*\
@ -1256,6 +1244,8 @@ void GpioInit(void)
DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin);
if (mpin) {
XdrvMailbox.index = mpin;
if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) {
SwitchPullupFlag(mpin - GPIO_SWT1_NP);
mpin -= (GPIO_SWT1_NP - GPIO_SWT1);
@ -1285,10 +1275,6 @@ void GpioInit(void)
ledlnk_inverted = 1;
mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK);
}
else if (mpin == GPIO_BUZZER_INV) {
buzzer_inverted = 1;
mpin -= (GPIO_BUZZER_INV - GPIO_BUZZER);
}
else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) {
bitSet(pwm_inverted, mpin - GPIO_PWM1_INV);
mpin -= (GPIO_PWM1_INV - GPIO_PWM1);
@ -1307,6 +1293,12 @@ void GpioInit(void)
}
}
#endif // USE_DHT
else if (XdrvCall(FUNC_PIN_STATE)) {
mpin = XdrvMailbox.index;
}
else if (XsnsCall(FUNC_PIN_STATE)) {
mpin = XdrvMailbox.index;
};
}
if (mpin) pin[mpin] = i;
}
@ -1422,10 +1414,6 @@ void GpioInit(void)
pinMode(pin[GPIO_LEDLNK], OUTPUT);
digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted);
}
if (pin[GPIO_BUZZER] < 99) {
pinMode(pin[GPIO_BUZZER], OUTPUT);
digitalWrite(pin[GPIO_BUZZER], buzzer_inverted); // Buzzer Off
}
ButtonInit();
SwitchInit();

View File

@ -488,8 +488,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_CNTR4,
GPIO_CNTR4_NP,
#endif
#ifdef USE_BUZZER
GPIO_BUZZER, // Buzzer
GPIO_BUZZER_INV, // Inverted buzzer
#endif
GPIO_TXD, // Serial interface
GPIO_RXD, // Serial interface
#ifdef USE_I2C

View File

@ -124,7 +124,9 @@ void SonoffIfanReceived(void)
if (action != GetFanspeed()) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action);
ExecuteCommand(svalue, SRC_REMOTE);
buzzer_count = 2; // Beep once
#ifdef USE_BUZZER
BuzzerEnabledBeep(1); // Beep once
#endif
}
} else {
// AA 55 01 04 00 01 04 0A - Light
@ -137,7 +139,9 @@ void SonoffIfanReceived(void)
}
if (7 == mode) {
// AA 55 01 07 00 01 01 0A - Rf long press - forget RF codes
buzzer_count = 6; // Beep three times
#ifdef USE_BUZZER
BuzzerEnabledBeep(3); // Beep three times
#endif
}
// Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7

175
sonoff/xdrv_24_buzzer.ino Normal file
View File

@ -0,0 +1,175 @@
/*
xdrv_24_buzzer.ino - buzzer support for Sonoff-Tasmota
Copyright (C) 2019 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_BUZZER
/*********************************************************************************************\
* Buzzer support
\*********************************************************************************************/
#define XDRV_24 24
struct BUZZER {
uint32_t tune = 0;
bool active = true;
bool enable = false;
uint8_t inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off))
uint8_t count = 0; // Number of buzzes
uint8_t set[2];
uint8_t duration;
uint8_t state = 0;
} buzzer;
/*********************************************************************************************/
//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0);
void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune)
{
buzzer.set[0] = off;
buzzer.set[1] = on;
buzzer.duration = 1; // Start buzzer on first step
buzzer.tune = tune;
buzzer.count = count * 2; // Start buzzer
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d,%d,%d,0x%08X"), count, on, off, tune);
buzzer.enable = true;
}
void BuzzerBeep(uint32_t count) {
BuzzerBeep(count, 1, 1, 0);
}
void BuzzerEnabledBeep(uint32_t count)
{
if (Settings.flag3.buzzer_enable) { // SetOption67
BuzzerBeep(count);
}
}
/*********************************************************************************************/
bool BuzzerPinState()
{
if (XdrvMailbox.index == GPIO_BUZZER_INV) {
buzzer.inverted = 1;
XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER);
return true;
}
return false;
}
void BuzzerInit(void)
{
if (pin[GPIO_BUZZER] < 99) {
pinMode(pin[GPIO_BUZZER], OUTPUT);
digitalWrite(pin[GPIO_BUZZER], buzzer.inverted); // Buzzer Off
} else {
buzzer.active = false;
}
}
void BuzzerEvery100mSec(void)
{
if (buzzer.enable) {
if (buzzer.count) {
uint8_t state = buzzer.count & 1;
if (buzzer.duration) {
buzzer.duration--;
if (!buzzer.duration) {
buzzer.count--;
state = buzzer.count & 1;
buzzer.duration = buzzer.set[state];
}
}
digitalWrite(pin[GPIO_BUZZER], (buzzer.inverted) ? !state : state);
} else {
buzzer.enable = false;
}
}
}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
const char kBuzzerCommands[] PROGMEM = "|" // No prefix
"Buzzer" ;
void (* const BuzzerCommand[])(void) PROGMEM = {
&CmndBuzzer };
void CmndBuzzer(void)
{
// Buzzer <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps>
// All parameters are optional
//
// Buzzer = Buzzer 1,1,1 = Beep once with both duration and pause set to 100mS
// Buzzer 2 = Beep twice with duration 200mS and pause 100mS
// Buzzer 2,3 = Beep twice with duration 300mS and pause 100mS
// Buzzer 2,3,4 = Beep twice with duration 300mS and pause 400mS
if (XdrvMailbox.data_len > 0) {
char *p;
uint32_t i = 0;
uint32_t parm[4] = { 0 };
for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) {
parm[i] = strtol(str, nullptr, 0);
i++;
}
for (uint32_t i = 0; i < 4; i++) {
if (i < 3) {
if (parm[i] < 1) { parm[i] = 1; } // Default Count, On time, Off time
} else {
if (parm[3] < 0) { parm[3] = 0; } // Default Tune bitmap
}
}
BuzzerBeep(parm[0], parm[1], parm[2], parm[3]);
} else {
BuzzerBeep(1);
}
ResponseCmndDone();
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv24(uint8_t function)
{
bool result = false;
if (buzzer.active) {
switch (function) {
case FUNC_EVERY_100_MSECOND:
BuzzerEvery100mSec();
break;
case FUNC_COMMAND:
result = DecodeCommand(kBuzzerCommands, BuzzerCommand);
break;
case FUNC_PRE_INIT:
BuzzerInit();
break;
case FUNC_PIN_STATE:
result = BuzzerPinState();
break;
}
}
return result;
}
#endif // USE_BUZZER

View File

@ -237,6 +237,7 @@ bool XdrvCall(uint8_t Function)
(FUNC_SERIAL == Function) ||
(FUNC_MODULE_INIT == Function) ||
(FUNC_SET_CHANNELS == Function) ||
(FUNC_PIN_STATE == Function) ||
(FUNC_SET_DEVICE_POWER == Function)
)) {
break;

View File

@ -469,6 +469,7 @@ bool XsnsCall(uint8_t Function)
#endif // PROFILE_XSNS_SENSOR_EVERY_SECOND
if (result && ((FUNC_COMMAND == Function) ||
(FUNC_PIN_STATE == Function) ||
(FUNC_COMMAND_SENSOR == Function)
)) {
break;