電子積木(4)buzzer 蜂鳴器
就只是一顆台幣兩塊錢的小喇叭有什麼好介紹的?是的。筆者直接貼上驅動程式,及影片。而介紹的部份筆者有空再來增刪修。並且此處的程式部份及所使用的硬體板子都是有專用目的的,故是該再修而筆者當前也沒打算詳述。但就 buzzer 的驅動程式部份,是通用可用的,有興趣的讀者可摘錄使用。
程式碼之控制改為 URI 操作:
/test/alert on/off 交替切換,展示 buzzer
/speed/alert 交替開關轉速警示
/speed 回傳轉速
/relay/on 取代 AC
/relay/off bypass
/ac/on 取代 AC 下,啟動 AC
/ac/off 取代 AC 下,關閉 AC
/speed/error 回傳錯誤超轉的計數
另外由此程式的展示亦可得知,若啟動 WiFi,並且有用戶端連上,將會影響 buzzer 的效能,不論用戶端是否有在收送資料;亦即,client service 將佔用可觀的 CPU 時間。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include"Esp8266MultiPwms.h"
String theSpeedStr="0";
unsigned speed_alert_flag=0, test_alert_flag=0, period5_err=0;
#define AP_MODE_MYSSID "ESP_TESTAP"
#define AP_MODE_MYPW "87654321"
#if 0
#define STA_MODE_SSID "--------"
#define STA_MODE_PW "--------"
#else
#define STA_MODE_SSID AP_MODE_MYSSID
#define STA_MODE_PW AP_MODE_MYPW
#endif
const char *const WIFI_CRED[][2]={ // along with USE_STA_WIFI_MULTI since STA has more than 1 AP to connect to.
{"ESP_TESTAP", "87654321"},
{"Office", "123456"},
{"Xperia X Performance_bc10", "e848acbcfd98"},
};
// use either of one
#define HTTP_SERVER 1
#define HTTP_CLIENT (!HTTP_SERVER)
// use either of one
#define AP_MODE 1
#define STA_MODE (!AP_MODE)
// use either of one
//#define USE_STA_NATIVE
#define USE_STA_WIFI_MULTI
// use either of one
//#define USE_HTTP_HTTP_CLIENT
//#define USE_HTTP_WIFI_CLIENT
#define USE_HTTP_WIFIHTTP_HYBRID
#define HOSTNAME "esp8266-iot" // i.e., http://esp8266-iot.local/
#define UPDFILE "a.bin" // the facility has no version check, so should do it by user.
// the local webpage for updating to local is http://HOSTNAME.local/update
// local updated from remote is http://HOSTNAME.local/upd. when connected to, the UPDFILE will transfer back.
#if defined(USE_STA_WIFI_MULTI)
ESP8266WiFiMulti *WiFiMulti=0;
#endif
Stream &ehConsolePort(Serial);
// for http server
ESP8266WebServer *server_p;
// for remote ip
char remote_ip[16] = {0};
// for url
String web_link;
// for station mode is entered
bool is_station_entered=false;
// webupdater
ESP8266HTTPUpdateServer httpUpdater;
// ==================================================================
const char * const RST_REASONS[] =
{
"REASON_DEFAULT_RST",
"REASON_WDT_RST",
"REASON_EXCEPTION_RST",
"REASON_SOFT_WDT_RST",
"REASON_SOFT_RESTART",
"REASON_DEEP_SLEEP_AWAKE",
"REASON_EXT_SYS_RST"
};
const char * const FLASH_SIZE_MAP_NAMES[] =
{
"FLASH_SIZE_4M_MAP_256_256",
"FLASH_SIZE_2M",
"FLASH_SIZE_8M_MAP_512_512",
"FLASH_SIZE_16M_MAP_512_512",
"FLASH_SIZE_32M_MAP_512_512",
"FLASH_SIZE_16M_MAP_1024_1024",
"FLASH_SIZE_32M_MAP_1024_1024"
};
const char * const OP_MODE_NAMES[]
{
"NULL_MODE",
"STATION_MODE",
"SOFTAP_MODE",
"STATIONAP_MODE"
};
const char * const AUTH_MODE_NAMES[]
{
"AUTH_OPEN",
"AUTH_WEP",
"AUTH_WPA_PSK",
"AUTH_WPA2_PSK",
"AUTH_WPA_WPA2_PSK",
"AUTH_MAX"
};
const char * const PHY_MODE_NAMES[]
{
"",
"PHY_MODE_11B",
"PHY_MODE_11G",
"PHY_MODE_11N"
};
const char * const EVENT_NAMES[]
{
"EVENT_STAMODE_CONNECTED",
"EVENT_STAMODE_DISCONNECTED",
"EVENT_STAMODE_AUTHMODE_CHANGE",
"EVENT_STAMODE_GOT_IP",
"EVENT_SOFTAPMODE_STACONNECTED",
"EVENT_SOFTAPMODE_STADISCONNECTED",
"EVENT_MAX"
};
const char * const EVENT_REASONS[]
{
"",
"REASON_UNSPECIFIED",
"REASON_AUTH_EXPIRE",
"REASON_AUTH_LEAVE",
"REASON_ASSOC_EXPIRE",
"REASON_ASSOC_TOOMANY",
"REASON_NOT_AUTHED",
"REASON_NOT_ASSOCED",
"REASON_ASSOC_LEAVE",
"REASON_ASSOC_NOT_AUTHED",
"REASON_DISASSOC_PWRCAP_BAD",
"REASON_DISASSOC_SUPCHAN_BAD",
"REASON_IE_INVALID",
"REASON_MIC_FAILURE",
"REASON_4WAY_HANDSHAKE_TIMEOUT",
"REASON_GROUP_KEY_UPDATE_TIMEOUT",
"REASON_IE_IN_4WAY_DIFFERS",
"REASON_GROUP_CIPHER_INVALID",
"REASON_PAIRWISE_CIPHER_INVALID",
"REASON_AKMP_INVALID",
"REASON_UNSUPP_RSN_IE_VERSION",
"REASON_INVALID_RSN_IE_CAP",
"REASON_802_1X_AUTH_FAILED",
"REASON_CIPHER_SUITE_REJECTED",
};
void print_system_info(Stream & consolePort)
{
const rst_info * resetInfo = system_get_rst_info();
consolePort.print(F("system_get_rst_info() reset reason: "));
consolePort.println(RST_REASONS[resetInfo->reason]);
consolePort.print(F("system_get_free_heap_size(): "));
consolePort.println(system_get_free_heap_size());
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
system_set_os_print(1);
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
consolePort.print(F("system_print_meminfo(): "));
consolePort.println(system_get_os_print());
system_print_meminfo();
consolePort.print(F("system_get_chip_id(): 0x"));
consolePort.println(system_get_chip_id(), HEX);
consolePort.print(F("system_get_sdk_version(): "));
consolePort.println(system_get_sdk_version());
consolePort.print(F("system_get_boot_version(): "));
consolePort.println(system_get_boot_version());
consolePort.print(F("system_get_userbin_addr(): 0x"));
consolePort.println(system_get_userbin_addr(), HEX);
consolePort.print(F("system_get_boot_mode(): "));
consolePort.println(system_get_boot_mode() == 0 ? F("SYS_BOOT_ENHANCE_MODE") : F("SYS_BOOT_NORMAL_MODE"));
consolePort.print(F("system_get_cpu_freq(): "));
consolePort.println(system_get_cpu_freq());
consolePort.print(F("spi_flash_get_id(): 0x"));
consolePort.println(spi_flash_get_id(), HEX);
consolePort.print(F("system_get_flash_size_map(): "));
consolePort.println(FLASH_SIZE_MAP_NAMES[system_get_flash_size_map()]);
}
void pre_setup(){
print_system_info(Serial);
// Try pushing frequency to 160MHz.
system_update_cpu_freq(SYS_CPU_160MHZ);
// System usually boots up in about 200ms.
Serial.print(F("system_get_time(): "));
Serial.println(system_get_time());
Serial.print(F("system_get_cpu_freq(): "));
Serial.println(system_get_cpu_freq());
Serial.print(F("wifi_get_opmode(): "));
Serial.print(wifi_get_opmode());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode()]);
Serial.print(F("wifi_get_opmode_default(): "));
Serial.print(wifi_get_opmode_default());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode_default()]);
Serial.print(F("wifi_get_broadcast_if(): "));
Serial.println(wifi_get_broadcast_if());
}
void post_setup(){
Serial.printf("getResetReason: %s\r\n", ESP.getResetReason().c_str());
Serial.printf("getFreeHeap: %d\r\n", ESP.getFreeHeap());
Serial.printf("getChipId: %d\r\n", ESP.getChipId());
Serial.printf("getCoreVersion: %s\r\n", ESP.getCoreVersion().c_str());
Serial.printf("getSdkVersion: %s\r\n", ESP.getSdkVersion());
Serial.printf("getCpuFreqMHz: %u\r\n", ESP.getCpuFreqMHz());
Serial.printf("getSketchSize: %u\r\n", ESP.getSketchSize());
Serial.printf("getFreeSketchSpace: %u\r\n", ESP.getFreeSketchSpace());
Serial.printf("getSketchMD5: %s\r\n", ESP.getSketchMD5().c_str());
Serial.printf("getFlashChipId: %d\r\n", ESP.getFlashChipId());
Serial.printf("getFlashChipSize: %u\r\n", ESP.getFlashChipSize());
Serial.printf("getFlashChipRealSize: %u\r\n", ESP.getFlashChipRealSize());
Serial.printf("getFlashChipSpeed: %u\r\n", ESP.getFlashChipSpeed());
Serial.printf("getCycleCount: %u\r\n", ESP.getCycleCount());
////Serial.printf("getVcc: %d\r\n", ESP.getVcc()); // can not be used if ADC is used.
}
// callback function for wifi auto-messages
void wifi_event_handler_cb(System_Event_t * event)
{
if (int(event->event)>=7) return;
if (event->event<sizeof(EVENT_NAMES)/sizeof(EVENT_NAMES[0]))
Serial.print(EVENT_NAMES[event->event]);
Serial.print(" [wifi_auto_info] (");
switch (event->event)
{
case EVENT_STAMODE_CONNECTED:
break;
case EVENT_STAMODE_DISCONNECTED:
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
break;
case EVENT_STAMODE_GOT_IP:
break;
case EVENT_SOFTAPMODE_STACONNECTED:
case EVENT_SOFTAPMODE_STADISCONNECTED:
{
char mac[32] = {0};
snprintf(mac, 32, MACSTR ", aid: %d" , MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
Serial.print(mac);
}
break;
default:
Serial.print(int(event->event));
}
Serial.println(")");
}
void print_softap_config(Stream &consolePort, softap_config const &config)
{
consolePort.println();
consolePort.println(F("SoftAP Configuration"));
consolePort.println(F("--------------------"));
consolePort.print(F("ssid: "));
consolePort.println((char *) config.ssid);
consolePort.print(F("password: "));
consolePort.println((char *) config.password);
consolePort.print(F("ssid_len: "));
consolePort.println(config.ssid_len);
consolePort.print(F("channel: "));
consolePort.println(config.channel);
consolePort.print(F("authmode: "));
consolePort.println(AUTH_MODE_NAMES[config.authmode]);
consolePort.print(F("ssid_hidden: "));
consolePort.println(config.ssid_hidden);
consolePort.print(F("max_connection: "));
consolePort.println(config.max_connection);
consolePort.print(F("beacon_interval: "));
consolePort.print(config.beacon_interval);
consolePort.println("ms");
consolePort.println(F("--------------------"));
consolePort.println();
}
void print_wifi_general(Stream &consolePort)
{
consolePort.print(F("wifi_get_channel(): "));
consolePort.println(wifi_get_channel());
consolePort.print(F("wifi_get_phy_mode(): "));
consolePort.println(PHY_MODE_NAMES[wifi_get_phy_mode()]);
}
void secure_softap_config(softap_config *config, const char *ssid, const char *password)
{ // hidden mode
// it tests if new data size over the storage and truncates.
size_t ssidLen = strlen(ssid) < sizeof(config->ssid) ? strlen(ssid) : sizeof(config->ssid);
size_t passwordLen = strlen(password) < sizeof(config->password) ? strlen(password) : sizeof(config->password);
memset(config->ssid, 0, sizeof(config->ssid));
memcpy(config->ssid, ssid, ssidLen);
memset(config->password, 0, sizeof(config->password));
memcpy(config->password, password, passwordLen);
config->ssid_len = ssidLen;
config->channel = 1;
config->authmode = AUTH_WPA2_PSK;
config->ssid_hidden = 1;
config->max_connection = 4;
config->beacon_interval = 1000;
}
void enter_ap_mode(){
WiFi.softAP(AP_MODE_MYSSID, AP_MODE_MYPW);
IPAddress myIP = WiFi.softAPIP();
Serial.println("");
Serial.println("[-= Enter AP Mode =-]");
Serial.print("AP IP ADDR: ");
Serial.println(myIP);
// get the default config and print it.
softap_config config;
wifi_softap_get_config(&config);
/// if want to be more secure(hidden), modify the configurations.
/// secure_softap_config(&config, AP_MODE_MYSSID, AP_MODE_MYPW);
/// after config is arranged, set it in.
/// wifi_softap_set_config(&config);
print_softap_config(Serial, config);
print_wifi_general(Serial);
// start dhcps
wifi_softap_dhcps_start();
if (wifi_softap_dhcps_status()==DHCP_STARTED) Serial.println(F("DHCP started"));
else Serial.println(F("DHCP stopped"));
// get the AP basic info and print it.
ip_info info;
wifi_get_ip_info(SOFTAP_IF, &info);
/// method 1
/// Serial.printf("AP IP ADDR: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.ip), ip4_addr2(&info.ip), ip4_addr3(&info.ip), ip4_addr4(&info.ip));
/// Serial.printf("AP GATEWAY: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.gw), ip4_addr2(&info.gw), ip4_addr3(&info.gw), ip4_addr4(&info.gw));
/// Serial.printf("AP NETMASK: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.netmask), ip4_addr2(&info.netmask), ip4_addr3(&info.netmask), ip4_addr4(&info.netmask));
// method2
Serial.printf("AP IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("AP GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("AP NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// This doesn't work on an ESP-01.
// wifi_set_sleep_type(LIGHT_SLEEP_T);
// Try this dirty little thing.
// Doesn't work because ESP-01 module doesn't link XPD_DCDC -> RST.
// ESP.deepSleep(15000);
}
int connected_station_status(){
///// this function for count couldn't sync the number of stat_infos retrieved at realtime.
unsigned char number_client=wifi_softap_get_station_num(); // Count of stations
struct station_info *stat_info;
IPAddress address;
int i;
Serial.print("Total connected clients: ");
Serial.println(number_client);
for (i=0, stat_info=wifi_softap_get_station_info(); stat_info!=NULL && i<number_client; i++){
address=(stat_info->ip).addr;
snprintf(remote_ip, 16, "" IPSTR, IP2STR(&(stat_info->ip)));
Serial.printf("Station %d. ", i+1);
Serial.print("IP= ");
Serial.print(address);
Serial.print(" with MAC= ");
Serial.print(stat_info->bssid[0],HEX);
Serial.print(stat_info->bssid[1],HEX);
Serial.print(stat_info->bssid[2],HEX);
Serial.print(stat_info->bssid[3],HEX);
Serial.print(stat_info->bssid[4],HEX);
Serial.print(stat_info->bssid[5],HEX);
Serial.println();
stat_info = STAILQ_NEXT(stat_info, next);
}
wifi_softap_free_station_info();
delay(100);
return i; // not the number_client
}
#if defined(USE_STA_NATIVE) // --------------------------
// 12 seconds waiting
bool enter_station_mode(){
unsigned char u=0;
// Connect to WiFi network
Serial.println("");
Serial.println("[-= Enter Station Mode =-]");
Serial.print("Connecting to ");
Serial.print(STA_MODE_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(STA_MODE_SSID, STA_MODE_PW);
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
if (u++>60) break; // 12 seconds, might not enough
}
Serial.println("");
if (WiFi.status() != WL_CONNECTED){
Serial.println(" WiFi connection failed...");
return false;
}
Serial.println("WiFi connected");
// Print the remote MAC address
uint8_t macAddr[6];
WiFi.macAddress(macAddr);
Serial.printf("Remote MAC adr: %02X:%02X:%02X:%02X:%02X:%02X\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
ip_info info;
wifi_get_ip_info(STATION_IF, &info);
Serial.printf("IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// resolve the remote ip
uint32 x=*(uint32*)(&info.ip)&*(uint32*)(&info.netmask);
ip_addr y=*(ip_addr*)(&x);
snprintf(remote_ip, 16, "%d.%d.%d.%d",\
ip4_addr1(&y)? ip4_addr1(&y): 1,\
ip4_addr2(&y)? ip4_addr2(&y): 1,\
ip4_addr3(&y)? ip4_addr3(&y): 1,\
ip4_addr4(&y)? ip4_addr4(&y): 1
);
Serial.print(F("Remote AP IP: "));
Serial.println(remote_ip);
Serial.printf("Default local hostname: %s\r\n", WiFi.hostname().c_str());
Serial.print("DNS #1, #2 IP: ");
WiFi.dnsIP().printTo(Serial);
Serial.print(", ");
WiFi.dnsIP(1).printTo(Serial);
Serial.println();
Serial.printf("RSSI: %d dBm\r\n", WiFi.RSSI());
WiFi.printDiag(Serial);
// Print the local IP address
Serial.println("");
Serial.print("IP is assigned: ");
Serial.println(WiFi.localIP());
return true;
}
#elif defined(USE_STA_WIFI_MULTI) // --------------------------
// 12 seconds waiting
bool enter_station_mode(){
unsigned char u=0;
// Connect to WiFi network
Serial.println("");
Serial.println("[-= Enter Station Mode =-]");
Serial.print("WiFi Connecting...");
WiFi.mode(WIFI_STA);
if (!WiFiMulti){
WiFiMulti=new ESP8266WiFiMulti;
if (!WiFiMulti) return false;
for (int i=0; i<(sizeof(WIFI_CRED)/sizeof(WIFI_CRED[0])); i++)
WiFiMulti->addAP(WIFI_CRED[i][0], WIFI_CRED[i][1]);
}
while (WiFiMulti->run() != WL_CONNECTED) {
delay(200);
Serial.print(".");
if (u++>60){ // 12 seconds, might not enough
Serial.println(" WiFi connection failed...");
return false;
}
}
Serial.println("WiFi connected");
// Print the remote MAC address
uint8_t macAddr[6];
WiFi.macAddress(macAddr);
Serial.printf("Remote MAC adr: %02X:%02X:%02X:%02X:%02X:%02X\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
ip_info info;
wifi_get_ip_info(STATION_IF, &info);
Serial.printf("IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// resolve the remote ip
uint32 x=*(uint32*)(&info.ip)&*(uint32*)(&info.netmask);
ip_addr y=*(ip_addr*)(&x);
snprintf(remote_ip, 16, "%d.%d.%d.%d",\
ip4_addr1(&y)? ip4_addr1(&y): 1,\
ip4_addr2(&y)? ip4_addr2(&y): 1,\
ip4_addr3(&y)? ip4_addr3(&y): 1,\
ip4_addr4(&y)? ip4_addr4(&y): 1
);
Serial.print(F("Remote AP IP: "));
Serial.println(remote_ip);
Serial.printf("Default local hostname: %s\r\n", WiFi.hostname().c_str());
Serial.print("DNS #1, #2 IP: ");
WiFi.dnsIP().printTo(Serial);
Serial.print(", ");
WiFi.dnsIP(1).printTo(Serial);
Serial.println();
Serial.printf("RSSI: %d dBm\r\n", WiFi.RSSI());
WiFi.printDiag(Serial);
// Print the local IP address
Serial.println("");
Serial.print("IP is assigned: ");
Serial.println(WiFi.localIP());
return true;
}
#endif // USE_STA_x // --------------------------
// The certificate is stored in PMEM
static const uint8_t x509[] PROGMEM = {
0x30, 0x82, 0x01, 0x3d, 0x30, 0x81, 0xe8, 0x02, 0x09, 0x00, 0xfe, 0x56,
0x46, 0xf2, 0x78, 0xc6, 0x51, 0x17, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x38, 0x31,
0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x31,
0x32, 0x35, 0x31, 0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02,
0x41, 0x00, 0xc6, 0x72, 0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7,
0x3a, 0x2a, 0x5a, 0x49, 0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6,
0xbb, 0xa3, 0xd6, 0x6f, 0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33,
0x50, 0x80, 0xec, 0x49, 0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d,
0x81, 0x85, 0x23, 0x24, 0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3,
0x3c, 0x10, 0x40, 0x05, 0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
0x05, 0x00, 0x03, 0x41, 0x00, 0x69, 0xdc, 0x6c, 0x9b, 0xa7, 0x62, 0x57,
0x7e, 0x03, 0x01, 0x45, 0xad, 0x9a, 0x83, 0x90, 0x3a, 0xe7, 0xdf, 0xe8,
0x8f, 0x46, 0x00, 0xd3, 0x5f, 0x2b, 0x0a, 0xde, 0x92, 0x1b, 0xc5, 0x04,
0xc5, 0xc0, 0x76, 0xf4, 0xf6, 0x08, 0x36, 0x97, 0x27, 0x82, 0xf1, 0x60,
0x76, 0xc2, 0xcd, 0x67, 0x6c, 0x4b, 0x6c, 0xca, 0xfd, 0x97, 0xfd, 0x33,
0x9e, 0x12, 0x67, 0x6b, 0x98, 0x7e, 0xd5, 0x80, 0x8f
};
// And so is the key. These could also be in DRAM
static const uint8_t rsakey[] PROGMEM = {
0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xc6, 0x72,
0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7, 0x3a, 0x2a, 0x5a, 0x49,
0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6, 0xbb, 0xa3, 0xd6, 0x6f,
0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33, 0x50, 0x80, 0xec, 0x49,
0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d, 0x81, 0x85, 0x23, 0x24,
0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3, 0x3c, 0x10, 0x40, 0x05,
0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x35, 0x0b, 0x74,
0xd3, 0xff, 0x15, 0x51, 0x44, 0x0f, 0x13, 0x2e, 0x9b, 0x0f, 0x93, 0x5c,
0x3f, 0xfc, 0xf1, 0x17, 0xf9, 0x72, 0x94, 0x5e, 0xa7, 0xc6, 0xb3, 0xf0,
0xfe, 0xc9, 0x6c, 0xb1, 0x1e, 0x83, 0xb3, 0xc6, 0x45, 0x3a, 0x25, 0x60,
0x7c, 0x3d, 0x92, 0x7d, 0x53, 0xec, 0x49, 0x8d, 0xb5, 0x45, 0x10, 0x99,
0x9b, 0xc6, 0x22, 0x3a, 0x68, 0xc7, 0x13, 0x4e, 0xb6, 0x04, 0x61, 0x21,
0x01, 0x02, 0x21, 0x00, 0xea, 0x8c, 0x21, 0xd4, 0x7f, 0x3f, 0xb6, 0x91,
0xfa, 0xf8, 0xb9, 0x2d, 0xcb, 0x36, 0x36, 0x02, 0x5f, 0xf0, 0x0c, 0x6e,
0x87, 0xaa, 0x5c, 0x14, 0xf6, 0x56, 0x8e, 0x12, 0x92, 0x25, 0xde, 0xb3,
0x02, 0x21, 0x00, 0xd8, 0x99, 0x01, 0xf1, 0x04, 0x0b, 0x98, 0xa3, 0x71,
0x56, 0x1d, 0xea, 0x6f, 0x45, 0xd1, 0x36, 0x70, 0x76, 0x8b, 0xab, 0x69,
0x30, 0x58, 0x9c, 0xe0, 0x45, 0x97, 0xe7, 0xb6, 0xb5, 0xef, 0xc1, 0x02,
0x21, 0x00, 0xa2, 0x01, 0x06, 0xc0, 0xf2, 0xdf, 0xbc, 0x28, 0x1a, 0xb4,
0xbf, 0x9b, 0x5c, 0xd8, 0x65, 0xf7, 0xbf, 0xf2, 0x5b, 0x73, 0xe0, 0xeb,
0x0f, 0xcd, 0x3e, 0xd5, 0x4c, 0x2e, 0x91, 0x99, 0xec, 0xb7, 0x02, 0x20,
0x4b, 0x9d, 0x46, 0xd7, 0x3c, 0x01, 0x4c, 0x5d, 0x2a, 0xb0, 0xd4, 0xaa,
0xc6, 0x03, 0xca, 0xa0, 0xc5, 0xac, 0x2c, 0xe0, 0x3f, 0x4d, 0x98, 0x71,
0xd3, 0xbd, 0x97, 0xe5, 0x55, 0x9c, 0xb8, 0x41, 0x02, 0x20, 0x02, 0x42,
0x9f, 0xd1, 0x06, 0x35, 0x3b, 0x42, 0xf5, 0x64, 0xaf, 0x6d, 0xbf, 0xcd,
0x2c, 0x3a, 0xcd, 0x0a, 0x9a, 0x4d, 0x7c, 0xad, 0x29, 0xd6, 0x36, 0x57,
0xd5, 0xdf, 0x34, 0xeb, 0x26, 0x03
};
#if 0
WiFiServer* create_http_server(){
// Create an instance of the server
// specify the 80 port to listen on as an argument
WiFiServer *a=new WiFiServer(80);
/// WiFiServerSecure *a=new WiFiServerSecure(443);
/// a->setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
/// a->begin();
// Start the server
a->begin();
Serial.println("HTTP Server started");
return a;
}
#endif
ESP8266WebServer* create_http_server(){ // ESP8266WebServer & MDNS & Updater facilities
// Create an instance of the server
// specify the 80 port to listen on as an argument
ESP8266WebServer *a=new ESP8266WebServer(80);
MDNS.begin(HOSTNAME);
httpUpdater.setup(a); // will be http://HOSTNAME.local/update
// Start the http server
a->begin();
MDNS.addService("http", "tcp", 80);
Serial.println("HTTP Server started");
return a;
}
#if defined(USE_HTTP_HTTP_CLIENT) // faster but always got nothing // --------------------------
void http_client_connect(const char *url){
/// #include <ESP8266HTTPClient.h>
HTTPClient http;
Serial.print("\r\n[HTTP begin...]\r\n");
// configure traged server and url
/// http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); // HTTPS
http.begin(url); // HTTP
Serial.print("[HTTP GET...]\r\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0){
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP GET... code: %d]\r\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK){ // the connection may be broken and stuck here
Serial.println(" -= data =- ---------");
Serial.println(http.getString()); // usually has no data return, so failed.
Serial.println(" ===================");
}
else Serial.printf("[HTTP GET... failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
}
else Serial.printf("[HTTP Protocol failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
http.end();
delay(150);
}
#elif defined(USE_HTTP_WIFI_CLIENT) // slower but usually failed connection // --------------------------
void http_client_connect(const char *url){
// Use WiFiClient class to create TCP connections
WiFiClient client;
int httpPort = 80;
if (!client.connect(remote_ip, httpPort)) {
Serial.println("");
Serial.println("[HTTP Protocol failed, error: 0]");
Serial.println("");
return;
}
Serial.print("[Requesting URL: [");
Serial.print(url);
Serial.println("]");
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +\
"Host: " + remote_ip + "\r\n" +\
"Connection: close\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 4000) {
Serial.println("[Client Timeout !]");
client.stop();
return;
}
delay(50);
}
// Read all the lines of the reply from server and print them to Serial
Serial.println(" -= data =- ---------");
while(client.available()){
String line = client.readStringUntil('\r');
Serial.println(line);
}
Serial.println(" ===================");
delay(50);
}
#elif defined(USE_HTTP_WIFIHTTP_HYBRID) // --------------------------
void http_client_connect(const char *url){
WiFiClient client;
HTTPClient http; //must be declared after WiFiClient for correct destruction order, because used by http.begin(client,...)
Serial.print("[HTTP begin...]\r\n");
// configure server and url
http.begin(client, url);
/// http.begin(client, remote_ip, 80, url);
Serial.print("[HTTP GET...]\r\n");
// start connection and send HTTP header
int httpCode = http.GET();
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP GET... code: %d]\r\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
// get lenght of document (is -1 when Server sends no Content-Length header)
int len = http.getSize();
// create buffer for read
uint8_t buff[128] = { 0 };
#if 0 // with API
Serial.println(http.getString());
#else // or "by hand"
// get tcp stream
WiFiClient * stream = &client;
Serial.println(" -= data =- ===================");
// read all data from server
while (http.connected() && (len > 0 || len == -1)) {
// read up to 128 byte
int c = stream->readBytes(buff, std::min((size_t)len, sizeof(buff)));
Serial.printf("\r\n[readBytes: %d]", c);
if (!c) {
Serial.println("[read timeout]");
break; // must have or it will stuck here! and then if stuck at GET(), set timeout
}
// write it to Serial
//////////Serial.write(buff, c);
buff[c]=0;
theSpeedStr=(char*)buff;
Serial.println(theSpeedStr);
if (len > 0) len -= c;
}
Serial.println(" ===================");
}
#endif
Serial.println();
Serial.print("[HTTP connection closed or file end.]\r\n");
}
else Serial.printf("[HTTP GET... failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
http.end();
}
#endif // USE_HTTP_x // --------------------------
void gbl_update_started() {
Serial.println("CALLBACK: HTTP update process started");
}
void gbl_update_finished() {
Serial.println("CALLBACK: HTTP update process finished");
}
void gbl_update_progress(int cur, int total) {
Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total);
}
void gbl_update_error(int err) {
Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err);
}
void gbl_updater(const char *url) {
// wait for WiFi connection
WiFiClient client;
// The line below is optional. It can be used to blink the LED on the board during flashing
// The LED will be on during download of one buffer of data from the network. The LED will
// be off during writing that buffer to flash
// On a good connection the LED should flash regularly. On a bad connection the LED will be
// on much longer than it will be off. Other pins than LED_BUILTIN may be used. The second
// value is used to put the LED on. If the LED is on with HIGH, that value should be passed
ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW);
// Add optional callback notifiers
ESPhttpUpdate.onStart(gbl_update_started);
ESPhttpUpdate.onEnd(gbl_update_finished);
ESPhttpUpdate.onProgress(gbl_update_progress);
ESPhttpUpdate.onError(gbl_update_error);
t_httpUpdate_return ret = ESPhttpUpdate.update(client, url);
// Or:
// t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 80, "file.bin");
switch (ret) {
case HTTP_UPDATE_FAILED:
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\r\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("HTTP_UPDATE_NO_UPDATES");
break;
case HTTP_UPDATE_OK:
Serial.println("HTTP_UPDATE_OK");
break;
}
}
bool Timeout_60s(){
static int current_time = millis();
int new_time = millis();
if (new_time < (current_time + 60000)) return false;
current_time = new_time;
return true;
}
bool Timeout_10s(){
static int current_time = millis();
int new_time = millis();
if (new_time < (current_time + 10000)) return false;
current_time = new_time;
return true;
}
bool Timeout_4s(){
static int current_time = millis();
int new_time = millis();
if (new_time < (current_time + 4000)) return false;
current_time = new_time;
return true;
}
void page_gpio_low_cb(){
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nLED is now ";
s += "ON";
s += "</html>\r\n";
// Send the response to the client
server_p->send(200, "text/plain", s.c_str());
beepON();
digitalWrite(2, LOW);
}
void page_gpio_high_cb(){
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nLED is now ";
s += "OFF";
s += "</html>\r\n";
// Send the response to the client
server_p->send(200, "text/plain", s.c_str());
beepOFF();
digitalWrite(2, HIGH);
}
void page_led_onoff_inst(){
/// http://<ip address>/led?state=on will turn the led ON
/// http://<ip address>/led?state=off will turn the led OFF
server_p->on("/led", []() {
String state=server_p->arg("state");
if (state == "on") {beepON(); digitalWrite(2, LOW);}
else if (state == "off") {beepOFF(); digitalWrite(2, HIGH);}
server_p->send(200, "text/plain", "Led is now " + state);
});
}
void page_a_bin_cb(){
SPIFFS.begin();
File file = SPIFFS.open((String("/")+UPDFILE).c_str(), "r");
if (!file) Serial.println((String("/")+UPDFILE+" opened failed").c_str());
server_p->streamFile(file, "application/octet-stream");
file.close();
}
void setup_updater(){
pre_setup();
post_setup();
#if AP_MODE
enter_ap_mode();
wifi_set_event_handler_cb(wifi_event_handler_cb);
#endif
#if HTTP_SERVER
pinMode(2, OUTPUT); // D4
server_p=create_http_server();
server_p->on("/gpio/0", page_gpio_low_cb);
server_p->on("/gpio/1", page_gpio_high_cb);
server_p->on("/", [](){server_p->send(200, "text/plain", "This is an index page.");});
page_led_onoff_inst();
server_p->on("/upd", page_a_bin_cb);
server_p->on("/reset", []() {
server_p->send(200, "text/plain", "now reset...");
//// do something before wdt-reset
delay(1);
while (1);
});
server_p->on("/relay/on", []() {
server_p->send(200, "text/plain", "relay is now on");
beepON();
digitalWrite(14, HIGH);
digitalWrite(2, LOW);
});
server_p->on("/relay/off", []() {
server_p->send(200, "text/plain", "relay is now off");
beepOFF();
digitalWrite(14, LOW);
digitalWrite(2, HIGH);
});
server_p->on("/ac/on", []() {
server_p->send(200, "text/plain", "ac is now on");
beepON();
digitalWrite(16, HIGH);
digitalWrite(2, LOW);
});
server_p->on("/ac/off", []() {
server_p->send(200, "text/plain", "ac is now off");
beepOFF();
digitalWrite(16, LOW);
digitalWrite(2, HIGH);
});
extern unsigned period5_err;
server_p->on("/speed/error", []() {
server_p->send(200, "text/plain", (String("error count ")+period5_err).c_str());
period5_err=0;
});
extern unsigned speed_alert_flag;
server_p->on("/speed/alert", []() {
speed_alert_flag^=1;
if (speed_alert_flag){
server_p->send(200, "text/plain", "speed alert on");
beepON();
digitalWrite(2, LOW);
}
else {
server_p->send(200, "text/plain", "speed alert off");
beepOFF();
digitalWrite(2, HIGH);
}
});
extern unsigned test_alert_flag;
server_p->on("/test/alert", []() {
test_alert_flag^=1;
if (test_alert_flag){
server_p->send(200, "text/plain", "test alert on");
beepON();
digitalWrite(2, LOW);
}
else {
server_p->send(200, "text/plain", "test alert off");
beepOFF();
digitalWrite(2, HIGH);
}
});
extern unsigned freq5;
extern String theSpeedStr;
server_p->on("/speed", []() {
server_p->send(200, "text/plain", theSpeedStr.c_str());
});
#endif
}
void loop_updater() {
//static unsigned tmo=micros();
//if (!cMultiPwms::Timeout(750, tmo)) return;
if (0 && Timeout_60s()){
Serial.printf("\r\n\r\n\r\n\r\nUpdating...\r\n\r\n\r\n\r\n");
gbl_updater((String("http://")+HOSTNAME+".local"+"/upd").c_str());
}
#if AP_MODE
static int has_conns=0;
if (Timeout_10s())
Serial.printf("Current STA connections: %d\r\n", (has_conns=connected_station_status()));
if (has_conns<=0) return;
#elif STA_MODE
if (!is_station_entered){
if (Timeout_4s()){
is_station_entered=enter_station_mode();
}
return;
}
#endif
#if HTTP_SERVER
server_p->handleClient();
MDNS.update();
delay(20);
#elif HTTP_CLIENT
static int x=0;
web_link="http://";
web_link+=remote_ip;
web_link+="/speed";
http_client_connect(web_link.c_str());
delay(80);
#endif
}
//////////////////////////////////////// main function /////////////////////////////////////
// use MultiPwms Lib v.0.9. gpio parking is changed to GPIO3.
// use "ESP-07"
// 2021.02.21.
// configuration/used:
// IDE: generic ESP8266 module, 115200bps, 160MHz, 26MHz crystal, 1MB flash/80MHz
// pins: GND/TX/RX
// pins: Open/GPIO0/Pull-low
// pins: GND/speed signal with 10K resistor to input half voltage(to level shifter)
// raw speed signal > 15V, duty-cycle=90, freq==2xrpm.
// GPIO13, speed signal input from level shifter output/3.3v. capable of max sensing 5kHz signal.
// GPIO12, buzzer, max 1kHz base.
// GPIO14, control relay to bypass or disable AC.
// GPIO16, control AC on/off when AC was disabled.
// connector: power
// connector: USB jack. left to right are bypass high-side, bypass low-side and pull-it-low, raw speed signal, gnd.
// level shifter, max 36v to 3.3v.
// 3 ss8050 used: control relay on, buzzer and GPIO16 sink.
// power board: 3.3V. max input source 24V
#define NEW_PARKING_GPIO 3
#define LED_GPIO 2
void SetLedOn(){digitalWrite(LED_GPIO, LOW);}
void SetLedOff(){digitalWrite(LED_GPIO, HIGH);}
cHwTimer timer_prob_freq(50, isr_prob_freq);
cMultiPwms pwm_buzzer(12, 1000, 20, 0, 0);
void setup_cmultipwms() {
//ADC_MODE(ADC_TOUT);
pinMode(NEW_PARKING_GPIO, INPUT); // by the RX0. set it as the parking pin.
pinMode(LED_GPIO, OUTPUT); // led
pinMode(13, INPUT); // speed
pinMode(12, OUTPUT); digitalWrite(12, LOW); // buzzer
pinMode(14, OUTPUT); digitalWrite(14, LOW); // relay
pinMode(16, OUTPUT); digitalWrite(16, LOW); // ac
}
struct sPwmSound{ // if delay_ms==0, means pause, uses lower_bound for pause-ms.
int lower_bound;
int upper_bound;
int inc;
unsigned delay_ms;
};
sPwmSound buzzer_melody1[]={
// (pos=0, size=3), single beep.
{1000, 1000, 0, 20},
{1800, 1800, 0, 5},
{600, 600, 0, 30},
// (0, 7), 2 beeps.
{3, 0, 0, 0},
{1000, 1000, 0, 20},
{1800, 1800, 0, 5},
{600, 600, 0, 30},
// (0, 11), 3 beeps.
{6, 0, 0, 0},
{1000, 1000, 0, 20},
{1800, 1800, 0, 5},
{600, 600, 0, 30},
// (0, 15), 4 beeps.
{4, 0, 0, 0},
{1000, 1000, 0, 20},
{1800, 1800, 0, 5},
{600, 600, 0, 30},
// (0, 19), 5 beeps.
{7, 0, 0, 0},
{1000, 1000, 0, 20},
{1800, 1800, 0, 5},
{600, 600, 0, 30},
// (19, 1), single lasting 1.5 second beep.
{600, 600, 0, 1500},
// (20, 29), short continuing 15 beeps.
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
{120, 0, 0, 0},
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
{120, 0, 0, 0},
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
// (49, 5), for "on" sound.
{3000, 3000, 0, 15},
{800, 800, 0, 40},
{3000, 3000, 0, 80},
{15, 0, 0, 0},
{2000, 2000, 0, 30},
// (54, 5), for "off" sound.
{2000, 2000, 0, 30},
{15, 0, 0, 0},
{3000, 3000, 0, 15},
{800, 800, 0, 40},
{3000, 3000, 0, 80},
// (59, 6), mid gi gi gi.
{80, 0, 0, 0},
{800, 800, 0, 2},
{4, 0, 0, 0},
{800, 800, 0, 2},
{4, 0, 0, 0},
{800, 800, 0, 2},
// (65, 6), low gi gi gi.
{80, 0, 0, 0},
{9000, 9000, 0, 2},
{4, 0, 0, 0},
{9000, 9000, 0, 2},
{4, 0, 0, 0},
{9000, 9000, 0, 2},
// (71, 6), high gi gi gi.
{80, 0, 0, 0},
{200, 200, 0, 2},
{4, 0, 0, 0},
{200, 200, 0, 2},
{4, 0, 0, 0},
{200, 200, 0, 2},
#if 0 // it works well however, wifi-loop if enabled would affect the buzzer-loop. so, single tone could be ok.
/*static unsigned tmo_sta=micros(), tt=0;
if (cMultiPwms::Timeout(4000, tmo_sta)){
if (tt==0) config_buzzer_sound(buzzer_melody1, 2); // 1
else if (tt==1) config_buzzer_sound(buzzer_melody1, 5); // 2
else if (tt==2) config_buzzer_sound(buzzer_melody1, 8); // 3
else if (tt==3) config_buzzer_sound(buzzer_melody1, 11); // 4
else if (tt==4) config_buzzer_sound(buzzer_melody1, 14); // 5
else if (tt==5) config_buzzer_sound(buzzer_melody1+14, 1); // long beep
else if (tt==6) config_buzzer_sound(buzzer_melody1+15, 29); // beep beep ...
else if (tt==7) config_buzzer_sound(buzzer_melody1+44, 7); // on
else if (tt==8) config_buzzer_sound(buzzer_melody1+51, 8); // off
if (++tt>8) tt=0;
}*/
// (pos=0, size=2), single beep.
{4000, 200, -200, 6},
{6000, 400, -200, 2},
// (0, 5), 2 beeps.
{3, 0, 0, 0},
{3000, 400, -200, 6},
{7000, 200, -200, 2},
// (0, 8), 3 beeps.
{6, 0, 0, 0},
{4000, 200, -200, 6},
{6000, 400, -200, 2},
// (0, 11), 4 beeps.
{4, 0, 0, 0},
{3000, 400, -200, 6},
{7000, 200, -200, 2},
// (0, 14), 5 beeps.
{7, 0, 0, 0},
{4000, 200, -200, 6},
{6000, 400, -200, 2},
// (14, 1), single lasting 1.5 second beep.
{500, 500, 0, 1500},
// (15, 29), short continuing 15 beeps.
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
{120, 0, 0, 0},
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
{120, 0, 0, 0},
{400, 400, 0, 30},
{95, 0, 0, 0},
{400, 400, 0, 40},
{60, 0, 0, 0},
{400, 400, 0, 50},
{80, 0, 0, 0},
{400, 400, 0, 40},
{50, 0, 0, 0},
{400, 400, 0, 30},
// (44, 7), for "on" sound.
{1000, 4000, 200, 10},
{4000, 4000, 0, 200},
{2000, 2000, 0, 50},
{2000, 200, -200, 2},
{200, 200, 0, 50},
{2000, 2000, 0, 50},
{2000, 200, -200, 4},
// (51, 8), for "off" sound.
{2000, 200, -200, 2},
{200, 200, 0, 50},
{2000, 2000, 0, 50},
{2000, 200, -200, 4},
{1000, 4000, 200, 10},
{4000, 4000, 0, 200},
{100, 0, 0, 0},
{4000, 4000, 0, 200},
#endif
};
unsigned buzzer_issued1=0, buzzer_melody_sz1=0;
const sPwmSound *buzzer_melody_ptr=0;
void buzzer_sound(const struct sPwmSound *buzzer_melody, const unsigned buzzer_melody_sz, unsigned &buzzer_issued){ // only for 1 instance.
static int x;
static unsigned x_sz, current_time;
switch (buzzer_issued){
case 0: return;
case 1:
x_sz=0;
buzzer_issued=2;
case 2:
if (++x_sz>buzzer_melody_sz){buzzer_issued=0; pwm_buzzer.Pause(); SetLedOff(); return;}
x=buzzer_melody[x_sz-1].lower_bound;
if (!buzzer_melody[x_sz-1].delay_ms){
pwm_buzzer.Pause();
current_time=micros();
buzzer_issued=5;
return;
}
buzzer_issued=3;
case 3:
if (buzzer_melody[x_sz-1].inc>0 && x>buzzer_melody[x_sz-1].upper_bound){buzzer_issued=2; return;}
else if (buzzer_melody[x_sz-1].inc<0 && x<buzzer_melody[x_sz-1].upper_bound){buzzer_issued=2; return;}
current_time=micros();
pwm_buzzer.setPeriod(x, 2, 50);
pwm_buzzer.Resume();
SetLedOn();
buzzer_issued=4;
case 4:
if (!cMultiPwms::Timeout(buzzer_melody[x_sz-1].delay_ms, current_time, true, true)) return;
if (buzzer_melody[x_sz-1].inc) x+=buzzer_melody[x_sz-1].inc;
else {buzzer_issued=2; return;}
buzzer_issued=3;
return;
case 5:
if (!cMultiPwms::Timeout(x, current_time, true, true)) return;
buzzer_issued=2;
return;
default: buzzer_issued=0; pwm_buzzer.Pause(); return;
}
}
void config_buzzer_sound(const struct sPwmSound *ptr, const unsigned sz){
buzzer_melody_ptr=ptr;
buzzer_melody_sz1=sz;
buzzer_issued1=1;
}
void poll_buzzer_sound(){
if (buzzer_melody_ptr) buzzer_sound(buzzer_melody_ptr, buzzer_melody_sz1, buzzer_issued1);
}
unsigned freq5=0;
IRAM_ATTR unsigned pre_state5=0, cur_state5=0, tmcnt5=0, period5=0;
IRAM_ATTR void isr_prob_freq(){
cur_state5=!digitalRead(13);
if (pre_state5^cur_state5){
if (cur_state5){
period5=micros()-tmcnt5;
tmcnt5=micros();
}
pre_state5=cur_state5;
}
}
void speed_average(){
static unsigned older=0, oldest=0, i=0;
if (period5>100 && period5<1000000){
if (period5<=4580){period5=4285; period5_err++;}////////////////////////////////////////////////////
oldest=older;
older=freq5;
freq5=(((30000000/period5)*8+older*5+oldest*3)>>4);
i=0;
}
else if (i++>5){oldest=older=freq5=i=0;}
}
void speed_alert(){
// if want to continue alert at a specific stage, set its falling as the next rising stage (A+1).
const unsigned rising[]= {0, 999, 1999, 2999, 3999, 4999, 5799, 6299, 6999, 7499, 7999, unsigned(-1)};
const unsigned falling[]= {0, 750, 1750, 2750, 3750, 4750, 5550, 7000, 7500, 8000, unsigned(-1)};
const int snd_offset[]= {-1, -1, 0, 0, 0, 0, 19, 19, 59, 65, 71}; // -1 desig not use.
const int snd_size[]= {-1, -1, 7, 11, 15, 19, 1, 1, 6, 6, 6};
static unsigned pivot=0;
unsigned i=pivot;
while (freq5>rising[i+1]) i++;
if ((pivot<i) && (snd_offset[i]>=0)){
if (!buzzer_issued1) config_buzzer_sound(buzzer_melody1+snd_offset[i], snd_size[i]);
}
while (freq5<falling[i]) i--;
pivot=i;
}
void setup(){
setup_cmultipwms();
Serial.begin(115200);
delay(5000);
setup_updater();
pwm_buzzer.setDC(5);
pwm_buzzer.Pause();
config_buzzer_sound(buzzer_melody1+20, 29); // beep beep ...
}
void beepON(){config_buzzer_sound(buzzer_melody1+49, 5);}
void beepOFF(){config_buzzer_sound(buzzer_melody1+54, 5);}
void beepBEEP(){config_buzzer_sound(buzzer_melody1+20, 29);}
void loop(){
loop_updater();
speed_average();
theSpeedStr=freq5;
if (speed_alert_flag) speed_alert();
poll_buzzer_sound();
static unsigned tmo_sta=micros(), tt=0;
if (test_alert_flag && cMultiPwms::Timeout(4000, tmo_sta)){
if (tt==0) config_buzzer_sound(buzzer_melody1, 3); // 1
else if (tt==1) config_buzzer_sound(buzzer_melody1, 7); // 2
else if (tt==2) config_buzzer_sound(buzzer_melody1, 11); // 3
else if (tt==3) config_buzzer_sound(buzzer_melody1, 15); // 4
else if (tt==4) config_buzzer_sound(buzzer_melody1, 19); // 5
else if (tt==5) config_buzzer_sound(buzzer_melody1+19, 1); // long beep
else if (tt==6) config_buzzer_sound(buzzer_melody1+20, 29); // beep beep ...
else if (tt==7) config_buzzer_sound(buzzer_melody1+49, 5); // on
else if (tt==8) config_buzzer_sound(buzzer_melody1+54, 5); // off
else if (tt==9) config_buzzer_sound(buzzer_melody1+59, 6); // mid gi gi gi
else if (tt==10) config_buzzer_sound(buzzer_melody1+65, 6); // low gi gi gi
else if (tt==11) config_buzzer_sound(buzzer_melody1+71, 6); // high gi gi gi
if (++tt>11) tt=0;
}
}
20210222 新版程式碼更新
20210405 新版程式碼 v.0.1 更新
幾近完善。配合筆者新版的 WiFi code base 及 var2file lib。所以三者的功能整合在一起,有相當多的操作。不過主功能就是只有會鳴叫及傳送轉速數值,就是這張板子的用途。。。