mirror of https://github.com/arendst/Tasmota.git
Merge pull request #9437 from arendst/dev-gpio16
Redesign internal 8-bit GPIO to 16-bit GPIO
This commit is contained in:
commit
e1620d62b0
|
@ -17,7 +17,11 @@ See [migration path](https://tasmota.github.io/docs/Upgrading#migration-path) fo
|
|||
6. Migrate to **Tasmota 8.1**
|
||||
7. Migrate to **Tasmota 8.x**
|
||||
|
||||
While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v8.1.0 Doris** the Settings are re-allocated in such a way that fallback is only allowed and possible to release **v7.2.0 Constance**. Once at v7.2.0 you're on your own when downgrading even further.
|
||||
--- Major change in GPIO function representation ---
|
||||
|
||||
8. Migrate to **Tasmota 9.x**
|
||||
|
||||
While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v9.1.0 Imogen** the internal GPIO function representation has changed in such a way that fallback is only possible to the latest GPIO configuration before installing **v9.1.0**.
|
||||
|
||||
## Supported Core versions
|
||||
|
||||
|
@ -57,4 +61,5 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
|||
|
||||
### Version 9.0.0.1
|
||||
|
||||
- New dev release
|
||||
- Remove auto config update for all Friendlynames and Switchtopic from versions before 8.x
|
||||
- Change redesigning ESP8266 GPIO internal representation in line with ESP32
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
### 9.0.0.1 20201002
|
||||
|
||||
- New dev release
|
||||
- Remove auto config update for all Friendlynames and Switchtopic from versions before 8.x
|
||||
- Change redesigning ESP8266 GPIO internal representation in line with ESP32
|
||||
|
||||
### 8.5.1 20201002
|
||||
|
||||
|
|
|
@ -424,12 +424,18 @@ struct {
|
|||
SysBitfield3 flag3; // 3A0
|
||||
uint8_t switchmode[MAX_SWITCHES]; // 3A4 (6.0.0b - moved from 0x4CA)
|
||||
|
||||
// char ex_friendlyname[4][33]; // 3AC
|
||||
// char ex_switch_topic[33]; // 430
|
||||
|
||||
myio my_gp; // 3AC - 2 x 18 bytes (ESP8266) / 2 x 40 bytes (ESP32)
|
||||
#ifdef ESP8266
|
||||
char ex_friendlyname[4][33]; // 3AC
|
||||
char ex_switch_topic[33]; // 430
|
||||
uint16_t gpio16_converted; // 3D0
|
||||
uint8_t free_esp8266_3D2[42]; // 3D2
|
||||
#endif
|
||||
mytmplt user_template; // 3FC - 2 x 15 bytes (ESP8266) / 2 x 37 bytes (ESP32)
|
||||
#ifdef ESP8266
|
||||
uint8_t free_esp8266_41A[55]; // 41A
|
||||
#else // ESP32
|
||||
myio my_gp; // 3AC - 2 x 40 bytes (ESP32)
|
||||
mytmplt user_template; // 3FC - 2 x 37 bytes (ESP32)
|
||||
uint8_t eth_type; // 446
|
||||
uint8_t eth_clk_mode; // 447
|
||||
|
||||
|
@ -449,12 +455,12 @@ struct {
|
|||
uint8_t ws_width[3]; // 481
|
||||
|
||||
#ifdef ESP8266
|
||||
myio my_gp; // 484 - 17 bytes (ESP8266)
|
||||
myio8 ex_my_gp8; // 484 - 17 bytes (ESP8266) - free once gpio16 is active
|
||||
#else // ESP32
|
||||
uint8_t free_esp32_484[17]; // 484
|
||||
#endif // ESP8266 - ESP32
|
||||
uint8_t ex_my_adc0; // 495 free once gpio16 is active
|
||||
|
||||
uint8_t my_adc0; // 495
|
||||
uint16_t light_pixels; // 496
|
||||
uint8_t light_color[5]; // 498
|
||||
uint8_t light_correction; // 49D
|
||||
|
@ -508,7 +514,7 @@ struct {
|
|||
char user_template_name[15]; // 720 15 bytes - Backward compatibility since v8.2.0.3
|
||||
|
||||
#ifdef ESP8266
|
||||
mytmplt user_template; // 72F 14 bytes (ESP8266)
|
||||
mytmplt8285 ex_user_template8; // 72F 14 bytes (ESP8266) - free once gpio16 is active
|
||||
#else // ESP32
|
||||
uint8_t free_esp32_72f[14]; // 72F
|
||||
#endif // ESP8266 - ESP32
|
||||
|
|
|
@ -1193,8 +1193,8 @@ void SettingsDelta(void)
|
|||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
if (Settings.my_gp.io[i] >= GPIO_SWT5) { // Move up from GPIO_SWT5 to GPIO_KEY1
|
||||
Settings.my_gp.io[i] += 4;
|
||||
if (Settings.ex_my_gp8.io[i] >= GPI8_SWT5) { // Move up from GPI8_SWT5 to GPI8_KEY1
|
||||
Settings.ex_my_gp8.io[i] += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1259,7 +1259,7 @@ void SettingsDelta(void)
|
|||
Settings.ledmask = APP_LEDMASK;
|
||||
}
|
||||
if (Settings.version < 0x0605000A) {
|
||||
Settings.my_adc0 = ADC0_NONE;
|
||||
Settings.ex_my_adc0 = GPIO_NONE;
|
||||
}
|
||||
if (Settings.version < 0x0605000D) {
|
||||
Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE;
|
||||
|
@ -1450,7 +1450,7 @@ void SettingsDelta(void)
|
|||
SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password);
|
||||
SettingsUpdateText(SET_CORS, Settings.ex_cors_domain);
|
||||
SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic);
|
||||
SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic);
|
||||
// SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic);
|
||||
SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]);
|
||||
SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]);
|
||||
SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]);
|
||||
|
@ -1463,10 +1463,10 @@ void SettingsDelta(void)
|
|||
SettingsUpdateText(SET_MEM3, Settings.script_pram[2]);
|
||||
SettingsUpdateText(SET_MEM4, Settings.script_pram[3]);
|
||||
SettingsUpdateText(SET_MEM5, Settings.script_pram[4]);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]);
|
||||
// SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]);
|
||||
// SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]);
|
||||
// SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]);
|
||||
// SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]);
|
||||
}
|
||||
if (Settings.version < 0x08020003) {
|
||||
SettingsUpdateText(SET_TEMPLATE_NAME, Settings.user_template_name);
|
||||
|
|
|
@ -1131,13 +1131,94 @@ int ResponseJsonEndEnd(void)
|
|||
* GPIO Module and Template management
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef ESP8266
|
||||
uint16_t GpioConvert(uint8_t gpio) {
|
||||
if (gpio > ARRAY_SIZE(kGpioConvert)) {
|
||||
return AGPIO(GPIO_USER);
|
||||
}
|
||||
return pgm_read_word(kGpioConvert + gpio);
|
||||
}
|
||||
|
||||
uint16_t Adc0Convert(uint8_t adc0) {
|
||||
if (adc0 > 7) {
|
||||
return AGPIO(GPIO_USER);
|
||||
}
|
||||
else if (0 == adc0) {
|
||||
return GPIO_NONE;
|
||||
}
|
||||
return AGPIO(GPIO_ADC_INPUT + adc0 -1);
|
||||
}
|
||||
|
||||
void TemplateConvert(uint8_t template8[], uint16_t template16[]) {
|
||||
for (uint32_t i = 0; i < (sizeof(mytmplt) / 2) -2; i++) {
|
||||
template16[i] = GpioConvert(template8[i]);
|
||||
}
|
||||
template16[(sizeof(mytmplt) / 2) -2] = Adc0Convert(template8[sizeof(mytmplt8285) -1]);
|
||||
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FNC: TemplateConvert"));
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, template8, sizeof(mytmplt8285));
|
||||
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)template16, sizeof(mytmplt) / 2, 2);
|
||||
}
|
||||
|
||||
void ConvertGpios(void) {
|
||||
if (Settings.gpio16_converted != 0xF5A0) {
|
||||
// Convert 8-bit user template
|
||||
TemplateConvert((uint8_t*)&Settings.ex_user_template8, (uint16_t*)&Settings.user_template);
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(Settings.ex_my_gp8.io); i++) {
|
||||
Settings.my_gp.io[i] = GpioConvert(Settings.ex_my_gp8.io[i]);
|
||||
}
|
||||
Settings.my_gp.io[(sizeof(myio) / 2) -1] = Adc0Convert(Settings.ex_my_adc0);
|
||||
Settings.gpio16_converted = 0xF5A0;
|
||||
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FNC: ConvertGpios"));
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&Settings.ex_my_gp8.io, sizeof(myio8));
|
||||
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t *)&Settings.my_gp.io, sizeof(myio) / 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void DumpConvertTable(void) {
|
||||
bool jsflg = false;
|
||||
uint32_t lines = 1;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioConvert); i++) {
|
||||
uint32_t data = pgm_read_word(kGpioConvert + i);
|
||||
if (!jsflg) {
|
||||
Response_P(PSTR("{\"GPIOConversion%d\":{"), lines);
|
||||
} else {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
jsflg = true;
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kGpioConvert) -1)) {
|
||||
ResponseJsonEndEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command);
|
||||
jsflg = false;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) {
|
||||
uint32_t data = pgm_read_word(kAdcNiceList + i);
|
||||
if (!jsflg) {
|
||||
Response_P(PSTR("{\"ADC0Conversion%d\":{"), lines);
|
||||
} else {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
jsflg = true;
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kAdcNiceList) -1)) {
|
||||
ResponseJsonEndEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command);
|
||||
jsflg = false;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
mqtt_data[0] = '\0';
|
||||
}
|
||||
*/
|
||||
#endif // ESP8266
|
||||
|
||||
uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index = 0);
|
||||
uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) {
|
||||
#ifdef ESP8266
|
||||
uint16_t real_gpio = gpio + index;
|
||||
#else // ESP32
|
||||
uint16_t real_gpio = (gpio << 5) + index;
|
||||
#endif // ESP8266 - ESP32
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(gpio_pin); i++) {
|
||||
if (gpio_pin[i] == real_gpio) {
|
||||
return i; // Pin number configured for gpio
|
||||
|
@ -1224,44 +1305,45 @@ void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option) {
|
|||
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Template %d, Option %d"), module_template, option);
|
||||
|
||||
uint8_t internal_template[sizeof(mytmplt)] = { GPIO_NONE };
|
||||
// template8 = GPIO 0,1,2,3,4,5,9,10,12,13,14,15,16,Adc
|
||||
uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE };
|
||||
if (module_template < TMP_WEMOS) {
|
||||
memcpy_P(&internal_template, &kModules8266[module_template], 6);
|
||||
memcpy_P(&internal_template[8], &kModules8266[module_template].gp.io[6], 6);
|
||||
memcpy_P(&template8, &kModules8266[module_template], 6);
|
||||
memcpy_P(&template8[8], &kModules8266[module_template].gp.io[6], 6);
|
||||
} else {
|
||||
memcpy_P(&internal_template, &kModules8285[module_template - TMP_WEMOS], sizeof(mytmplt));
|
||||
memcpy_P(&template8, &kModules8285[module_template - TMP_WEMOS], sizeof(template8));
|
||||
}
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&internal_template, sizeof(mytmplt));
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&template8, sizeof(mytmplt8285));
|
||||
|
||||
// template16 = GPIO 0,1,2,3,4,5,9,10,12,13,14,15,16,Adc,Flg
|
||||
uint16_t template16[(sizeof(mytmplt) / 2)] = { GPIO_NONE };
|
||||
TemplateConvert(template8, template16);
|
||||
|
||||
uint32_t index = 0;
|
||||
uint32_t size = sizeof(mycfgio); // kmodules[module_template].gp
|
||||
uint32_t size = sizeof(mycfgio); // template16[module_template].gp
|
||||
switch (option) {
|
||||
case 2: {
|
||||
index = sizeof(internal_template) -1; // kModules[module_template].flag
|
||||
size = 1;
|
||||
index = (sizeof(mytmplt) / 2) -1; // template16[module_template].flag
|
||||
size = 2;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
size = sizeof(internal_template); // kmodules[module_template]
|
||||
size = sizeof(mytmplt); // template16[module_template]
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(ptr, &internal_template[index], size);
|
||||
memcpy(ptr, &template16[index], size);
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)ptr, size);
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FNC: GetInternalTemplate option %d"), option);
|
||||
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t *)ptr, size / 2, 2);
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
void ModuleGpios(myio *gp)
|
||||
{
|
||||
#ifdef ESP8266
|
||||
uint8_t *dest = (uint8_t *)gp;
|
||||
uint8_t src[ARRAY_SIZE(Settings.user_template.gp.io)];
|
||||
#else // ESP32
|
||||
uint16_t *dest = (uint16_t *)gp;
|
||||
uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)];
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
memset(dest, GPIO_NONE, sizeof(myio));
|
||||
if (USER_MODULE == Settings.module) {
|
||||
|
@ -1337,7 +1419,7 @@ uint32_t ValidPin(uint32_t pin, uint32_t gpio)
|
|||
|
||||
// if (!is_8285 && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's
|
||||
if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's
|
||||
if ((pin == 9) || (pin == 10)) {
|
||||
if ((9 == pin) || (10 == pin)) {
|
||||
return GPIO_NONE; // Disable possible flash GPIO9 and GPIO10
|
||||
}
|
||||
}
|
||||
|
@ -1347,23 +1429,15 @@ uint32_t ValidPin(uint32_t pin, uint32_t gpio)
|
|||
|
||||
bool ValidGPIO(uint32_t pin, uint32_t gpio)
|
||||
{
|
||||
#ifdef ESP8266
|
||||
#ifdef USE_ADC_VCC
|
||||
if (ADC0_PIN == pin) { return false; } // ADC0 = GPIO17
|
||||
#endif
|
||||
#endif
|
||||
return (GPIO_USER == ValidPin(pin, BGPIO(gpio))); // Only allow GPIO_USER pins
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
bool ValidAdc(void)
|
||||
{
|
||||
gpio_flag flag = ModuleFlag();
|
||||
uint32_t template_adc0 = flag.data &15;
|
||||
return (ADC0_USER == template_adc0);
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
#ifdef ESP8266
|
||||
bool GetUsedInModule(uint32_t val, uint8_t *arr)
|
||||
#else // ESP32
|
||||
bool GetUsedInModule(uint32_t val, uint16_t *arr)
|
||||
#endif // ESP8266 - ESP32
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
|
@ -1426,7 +1500,8 @@ bool GetUsedInModule(uint32_t val, uint16_t *arr)
|
|||
|
||||
bool JsonTemplate(char* dataBuf)
|
||||
{
|
||||
// {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255}
|
||||
// Old: {"NAME":"Shelly 2.5","GPIO":[56,0,17,0,21,83,0,0,6,82,5,22,156],"FLAG":2,"BASE":18}
|
||||
// New: {"NAME":"Shelly 2.5","GPIO":[320,0,32,0,224,193,0,0,640,192,608,225,3456,4736],"FLAG":0,"BASE":18}
|
||||
|
||||
if (strlen(dataBuf) < 9) { return false; } // Workaround exception if empty JSON like {} - Needs checks
|
||||
|
||||
|
@ -1441,23 +1516,38 @@ bool JsonTemplate(char* dataBuf)
|
|||
}
|
||||
JsonParserArray arr = root[PSTR(D_JSON_GPIO)];
|
||||
if (arr) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
|
||||
#ifdef ESP8266
|
||||
Settings.user_template.gp.io[i] = arr[i].getUInt();
|
||||
#else // ESP32
|
||||
uint16_t gpio = arr[i].getUInt();
|
||||
if (gpio == (AGPIO(GPIO_NONE) +1)) {
|
||||
gpio = AGPIO(GPIO_USER);
|
||||
if (!arr[13].getUInt()) { // Old template
|
||||
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TPL: Converting template ..."));
|
||||
|
||||
uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE };
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(template8) -1; i++) {
|
||||
template8[i] = arr[i].getUInt();
|
||||
}
|
||||
Settings.user_template.gp.io[i] = gpio;
|
||||
val = root[PSTR(D_JSON_FLAG)];
|
||||
if (val) {
|
||||
template8[ARRAY_SIZE(template8) -1] = val.getUInt() & 0x0F;
|
||||
}
|
||||
TemplateConvert(template8, Settings.user_template.gp.io);
|
||||
Settings.user_template.flag.data = 0;
|
||||
} else {
|
||||
#endif
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
|
||||
uint16_t gpio = arr[i].getUInt();
|
||||
if (gpio == (AGPIO(GPIO_NONE) +1)) {
|
||||
gpio = AGPIO(GPIO_USER);
|
||||
}
|
||||
Settings.user_template.gp.io[i] = gpio;
|
||||
}
|
||||
val = root[PSTR(D_JSON_FLAG)];
|
||||
if (val) {
|
||||
Settings.user_template.flag.data = val.getUInt();
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
}
|
||||
val = root[PSTR(D_JSON_FLAG)];
|
||||
if (val) {
|
||||
uint32_t flag = val.getUInt();
|
||||
memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag));
|
||||
}
|
||||
#endif
|
||||
val = root[PSTR(D_JSON_BASE)];
|
||||
if (val) {
|
||||
uint32_t base = val.getUInt();
|
||||
|
@ -1471,15 +1561,11 @@ void TemplateJson(void)
|
|||
{
|
||||
Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME));
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
|
||||
#ifdef ESP8266
|
||||
ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]);
|
||||
#else // ESP32
|
||||
uint16_t gpio = Settings.user_template.gp.io[i];
|
||||
if (gpio == AGPIO(GPIO_USER)) {
|
||||
gpio = AGPIO(GPIO_NONE) +1;
|
||||
}
|
||||
ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", gpio);
|
||||
#endif
|
||||
}
|
||||
ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ void ButtonInit(void)
|
|||
}
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) {
|
||||
else if ((99 == Button.adc) && AdcButtonPresent(0)) {
|
||||
Button.present++;
|
||||
Button.adc = i;
|
||||
}
|
||||
|
@ -167,12 +167,7 @@ void ButtonHandler(void)
|
|||
#ifndef USE_ADC_VCC
|
||||
if (Button.adc == button_index) {
|
||||
button_present = 1;
|
||||
if (ADC0_BUTTON_INV == my_adc0) {
|
||||
button = (AdcRead(1) < 128);
|
||||
}
|
||||
else if (ADC0_BUTTON == my_adc0) {
|
||||
button = (AdcRead(1) > 128);
|
||||
}
|
||||
button = AdcGetButton(0);
|
||||
}
|
||||
#endif // USE_ADC_VCC
|
||||
#else // ESP32
|
||||
|
|
|
@ -1120,19 +1120,11 @@ void CmndGpio(void)
|
|||
if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) {
|
||||
bool present = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
if (midx == XdrvMailbox.payload) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
#else // ESP32
|
||||
uint32_t midx = pgm_read_word(kGpioNiceList + i);
|
||||
if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < midx)) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
if (present) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
|
@ -1147,7 +1139,7 @@ void CmndGpio(void)
|
|||
Response_P(PSTR("{"));
|
||||
bool jsflg = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
if (ValidGPIO(i, cmodule.io[i]) || ((AGPIO(GPIO_USER) == XdrvMailbox.payload) && !FlashPin(i))) {
|
||||
if (ValidGPIO(i, cmodule.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) {
|
||||
if (jsflg) { ResponseAppend_P(PSTR(",")); }
|
||||
jsflg = true;
|
||||
uint32_t sensor_type = Settings.my_gp.io[i];
|
||||
|
@ -1159,7 +1151,6 @@ void CmndGpio(void)
|
|||
}
|
||||
char sindex[4] = { 0 };
|
||||
uint32_t sensor_name_idx = BGPIO(sensor_type);
|
||||
#ifdef ESP32
|
||||
uint32_t nice_list_search = sensor_type & 0xFFE0;
|
||||
for (uint32_t j = 0; j < ARRAY_SIZE(kGpioNiceList); j++) {
|
||||
uint32_t nls_idx = pgm_read_word(kGpioNiceList + j);
|
||||
|
@ -1168,7 +1159,6 @@ void CmndGpio(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif // ESP32
|
||||
const char *sensor_names = kSensorNames;
|
||||
if (sensor_name_idx > GPIO_FIX_START) {
|
||||
sensor_name_idx = sensor_name_idx - GPIO_FIX_START -1;
|
||||
|
@ -1187,20 +1177,13 @@ void CmndGpio(void)
|
|||
}
|
||||
}
|
||||
|
||||
void CmndGpios(void)
|
||||
{
|
||||
void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines) {
|
||||
myio cmodule;
|
||||
ModuleGpios(&cmodule);
|
||||
uint32_t lines = 1;
|
||||
bool jsflg = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
uint32_t ridx = midx;
|
||||
#else // ESP32
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
for (uint32_t i = offset; i < size; i++) { // Skip ADC_NONE
|
||||
uint32_t ridx = pgm_read_word(NiceList + i) & 0xFFE0;
|
||||
uint32_t midx = BGPIO(ridx);
|
||||
#endif // ESP8266 - ESP32
|
||||
if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; }
|
||||
if (!jsflg) {
|
||||
Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines);
|
||||
|
@ -1209,19 +1192,37 @@ void CmndGpios(void)
|
|||
}
|
||||
jsflg = true;
|
||||
char stemp1[TOPSZ];
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), ridx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kGpioNiceList) -1)) {
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), ridx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == size -1)) {
|
||||
ResponseJsonEndEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command);
|
||||
jsflg = false;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmndGpios(void)
|
||||
{
|
||||
/*
|
||||
if (XdrvMailbox.payload == 17) {
|
||||
DumpConvertTable();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
uint32_t lines = 1;
|
||||
ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines);
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines);
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266
|
||||
mqtt_data[0] = '\0';
|
||||
}
|
||||
|
||||
void CmndTemplate(void)
|
||||
{
|
||||
// {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255}
|
||||
// {"NAME":"Shelly 2.5","GPIO":[320,0,32,0,224,193,0,0,640,192,608,225,3456,4736],"FLAG":0,"BASE":18}
|
||||
|
||||
bool error = false;
|
||||
|
||||
if (strstr(XdrvMailbox.data, "{") == nullptr) { // If no JSON it must be parameter
|
||||
|
|
|
@ -1476,6 +1476,10 @@ void GpioInit(void)
|
|||
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Used GPIOs %d"), GPIO_SENSOR_END);
|
||||
|
||||
#ifdef ESP8266
|
||||
ConvertGpios();
|
||||
#endif // ESP8266
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
|
||||
if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) {
|
||||
Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); // Fix not supported sensor ids in template
|
||||
|
@ -1495,19 +1499,6 @@ void GpioInit(void)
|
|||
my_module.io[i] = def_gp.io[i]; // Force Template override
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) {
|
||||
Settings.my_adc0 = ADC0_NONE; // Fix not supported sensor ids in module
|
||||
}
|
||||
else if (Settings.my_adc0 > ADC0_NONE) {
|
||||
my_adc0 = Settings.my_adc0; // Set User selected Module sensors
|
||||
}
|
||||
my_module_flag = ModuleFlag();
|
||||
uint32_t template_adc0 = my_module_flag.data &15;
|
||||
if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) {
|
||||
my_adc0 = template_adc0; // Force Template override
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) {
|
||||
uint32_t mpin = ValidPin(i, my_module.io[i]);
|
||||
|
|
|
@ -82,7 +82,11 @@ const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names
|
|||
const uint8_t MAX_BUTTON_TEXT = 16; // Max number of GUI button labels
|
||||
const uint8_t MAX_GROUP_TOPICS = 4; // Max number of Group Topics
|
||||
const uint8_t MAX_DEV_GROUP_NAMES = 4; // Max number of Device Group names
|
||||
#ifdef ESP8266
|
||||
const uint8_t MAX_ADCS = 1; // Max number of ESP8266 ADC pins
|
||||
#else
|
||||
const uint8_t MAX_ADCS = 8; // Max number of ESP32 ADC pins (ADC2 pins are unusable with Wifi enabled)
|
||||
#endif
|
||||
|
||||
const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation
|
||||
const uint8_t MAX_ROTARIES = 2; // Max number of Rotary Encoders
|
||||
|
@ -297,7 +301,9 @@ enum SettingsTextIndex { SET_OTAURL,
|
|||
SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4, // MAX_DEV_GROUP_NAMES
|
||||
SET_DEVICENAME,
|
||||
SET_TELEGRAM_TOKEN, SET_TELEGRAM_CHATID,
|
||||
#ifdef ESP32
|
||||
#ifdef ESP8266
|
||||
SET_ADC_PARAM1,
|
||||
#else // ESP32
|
||||
SET_ADC_PARAM1, SET_ADC_PARAM2, SET_ADC_PARAM3, SET_ADC_PARAM4, SET_ADC_PARAM5, SET_ADC_PARAM6, SET_ADC_PARAM7, SET_ADC_PARAM8, // MAX_ADCS
|
||||
#endif
|
||||
SET_MAX };
|
||||
|
|
|
@ -116,11 +116,7 @@ uint16_t tele_period = 9999; // Tele period timer
|
|||
uint16_t blink_counter = 0; // Number of blink cycles
|
||||
uint16_t seriallog_timer = 0; // Timer to disable Seriallog
|
||||
uint16_t syslog_timer = 0; // Timer to re-enable syslog_level
|
||||
|
||||
#ifdef ESP32
|
||||
uint16_t gpio_pin[MAX_GPIO_PIN] = { 0 }; // GPIO functions indexed by pin number
|
||||
#endif // ESP32
|
||||
|
||||
int16_t save_data_counter; // Counter and flag for config save to Flash
|
||||
RulesBitfield rules_flag; // Rule state flags (16 bits)
|
||||
uint8_t mqtt_cmnd_blocked = 0; // Ignore flag for publish command
|
||||
|
@ -129,11 +125,6 @@ uint8_t state_250mS = 0; // State 250msecond per second flag
|
|||
uint8_t latching_relay_pulse = 0; // Latching relay pulse timer
|
||||
uint8_t ssleep; // Current copy of Settings.sleep
|
||||
uint8_t blinkspeed = 1; // LED blink rate
|
||||
|
||||
#ifdef ESP8266
|
||||
uint8_t gpio_pin[MAX_GPIO_PIN] = { 0 }; // GPIO functions indexed by pin number
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
uint8_t active_device = 1; // Active device in ExecuteCommandPower
|
||||
uint8_t leds_present = 0; // Max number of LED supported
|
||||
uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off))
|
||||
|
@ -150,7 +141,6 @@ uint8_t masterlog_level = 0; // Master log level used to override
|
|||
uint8_t seriallog_level; // Current copy of Settings.seriallog_level
|
||||
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 = 0; // Active copy of Module ADC0
|
||||
uint8_t last_source = 0; // Last command source
|
||||
uint8_t shutters_present = 0; // Number of actual define shutters
|
||||
uint8_t prepped_loglevel = 0; // Delayed log level message
|
||||
|
@ -172,7 +162,6 @@ bool is_8285 = false; // Hardware device ESP8266EX (0) or
|
|||
bool skip_light_fade; // Temporarily skip light fading
|
||||
bool restart_halt = false; // Do not restart but stay in wait loop
|
||||
myio my_module; // Active copy of Module GPIOs (17 x 8 bits)
|
||||
gpio_flag my_module_flag; // Active copy of Template GPIO flags
|
||||
StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits)
|
||||
char my_version[33]; // Composed version string
|
||||
char my_image[33]; // Code image and/or commit
|
||||
|
@ -277,9 +266,6 @@ void setup(void) {
|
|||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors
|
||||
}
|
||||
#ifdef ESP8266
|
||||
Settings.my_adc0 = ADC0_NONE; // Reset user defined ADC0 disabling sensors
|
||||
#endif
|
||||
}
|
||||
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
|
||||
Settings.module = Settings.fallback_module; // Reset module to fallback module
|
||||
|
|
|
@ -333,6 +333,12 @@ const char kWebColors[] PROGMEM =
|
|||
#define ARDUINO_CORE_RELEASE ARDUINO_ESP8266_RELEASE
|
||||
#endif // ARDUINO_ESP8266_RELEASE
|
||||
|
||||
#ifndef USE_ADC_VCC
|
||||
#define USE_ADC
|
||||
#else
|
||||
#undef USE_ADC
|
||||
#endif
|
||||
|
||||
#endif // ESP8266
|
||||
|
||||
#ifdef ESP32
|
||||
|
@ -378,13 +384,8 @@ const char kWebColors[] PROGMEM =
|
|||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
#define AGPIO(x) (x)
|
||||
#define BGPIO(x) (x)
|
||||
#else // ESP32
|
||||
#define AGPIO(x) (x<<5)
|
||||
#define BGPIO(x) (x>>5)
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,729 +0,0 @@
|
|||
/*
|
||||
tasmota_template_ESP32.h - ESP32 template settings for Tasmota
|
||||
|
||||
Copyright (C) 2020 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _TASMOTA_TEMPLATE_ESP32_H_
|
||||
#define _TASMOTA_TEMPLATE_ESP32_H_
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
// Hardware has no ESP32
|
||||
#undef USE_TUYA_DIMMER
|
||||
#undef USE_PWM_DIMMER
|
||||
#undef USE_EXS_DIMMER
|
||||
#undef USE_ARMTRONIX_DIMMERS
|
||||
#undef USE_SONOFF_RF
|
||||
#undef USE_SONOFF_SC
|
||||
#undef USE_SONOFF_IFAN
|
||||
#undef USE_SONOFF_L1
|
||||
#undef USE_SONOFF_D1
|
||||
#undef USE_RF_FLASH
|
||||
|
||||
// Not ported (yet)
|
||||
#undef USE_DISCOVERY
|
||||
#undef USE_MY92X1
|
||||
#undef USE_TUYA_MCU
|
||||
#undef USE_PS_16_DZ
|
||||
|
||||
enum UserSelectablePins {
|
||||
GPIO_NONE, // Not used
|
||||
GPIO_KEY1, GPIO_KEY1_NP, GPIO_KEY1_INV, GPIO_KEY1_INV_NP, // 4 x Button
|
||||
GPIO_SWT1, GPIO_SWT1_NP, // 8 x User connected external switches
|
||||
GPIO_REL1, GPIO_REL1_INV, // 8 x Relays
|
||||
GPIO_LED1, GPIO_LED1_INV, // 4 x Leds
|
||||
GPIO_CNTR1, GPIO_CNTR1_NP, // 4 x Counter
|
||||
GPIO_PWM1, GPIO_PWM1_INV, // 5 x PWM
|
||||
GPIO_BUZZER, GPIO_BUZZER_INV, // Buzzer
|
||||
GPIO_LEDLNK, GPIO_LEDLNK_INV, // Link led
|
||||
GPIO_I2C_SCL, GPIO_I2C_SDA, // Software I2C
|
||||
GPIO_SPI_MISO, GPIO_SPI_MOSI, GPIO_SPI_CLK, GPIO_SPI_CS, GPIO_SPI_DC, // Hardware SPI
|
||||
GPIO_SSPI_MISO, GPIO_SSPI_MOSI, GPIO_SSPI_SCLK, GPIO_SSPI_CS, GPIO_SSPI_DC, // Software SPI
|
||||
GPIO_BACKLIGHT, // Display backlight control
|
||||
GPIO_OLED_RESET, // OLED Display Reset
|
||||
GPIO_IRSEND, GPIO_IRRECV, // IR interface
|
||||
GPIO_RFSEND, GPIO_RFRECV, // RF interface
|
||||
GPIO_DHT11, GPIO_DHT22, GPIO_SI7021, GPIO_DHT11_OUT, // DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
GPIO_DSB, GPIO_DSB_OUT, // DS18B20 or DS18S20
|
||||
GPIO_WS2812, // WS2812 Led string
|
||||
GPIO_MHZ_TXD, GPIO_MHZ_RXD, // MH-Z19 Serial interface
|
||||
GPIO_PZEM0XX_TX, GPIO_PZEM004_RX, GPIO_PZEM016_RX, GPIO_PZEM017_RX, // PZEM Serial Modbus interface
|
||||
GPIO_SAIR_TX, GPIO_SAIR_RX, // SenseAir Serial interface
|
||||
GPIO_PMS5003_TX, GPIO_PMS5003_RX, // Plantower PMS5003 Serial interface
|
||||
GPIO_SDS0X1_TX, GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
|
||||
GPIO_SBR_TX, GPIO_SBR_RX, // Serial Bridge Serial interface
|
||||
GPIO_SR04_TRIG, GPIO_SR04_ECHO, // SR04 interface
|
||||
GPIO_SDM120_TX, GPIO_SDM120_RX, // SDM120 Serial interface
|
||||
GPIO_SDM630_TX, GPIO_SDM630_RX, // SDM630 Serial interface
|
||||
GPIO_TM16CLK, GPIO_TM16DIO, GPIO_TM16STB, // TM1638 interface
|
||||
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
|
||||
GPIO_HX711_SCK, GPIO_HX711_DAT, // HX711 Load Cell interface
|
||||
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
|
||||
GPIO_TUYA_TX, GPIO_TUYA_RX, // Tuya Serial interface
|
||||
GPIO_MGC3130_XFER, GPIO_MGC3130_RESET, // MGC3130 interface
|
||||
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
|
||||
GPIO_AZ_TXD, GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface
|
||||
GPIO_MAX31855CS, GPIO_MAX31855CLK, GPIO_MAX31855DO, // MAX31855 Serial interface
|
||||
GPIO_NRG_SEL, GPIO_NRG_SEL_INV, GPIO_NRG_CF1, GPIO_HLW_CF, GPIO_HJL_CF, // HLW8012/HJL-01/BL0937 energy monitoring
|
||||
GPIO_MCP39F5_TX, GPIO_MCP39F5_RX, GPIO_MCP39F5_RST, // MCP39F501 Energy monitoring (Shelly2)
|
||||
GPIO_PN532_TXD, GPIO_PN532_RXD, // PN532 NFC Serial interface
|
||||
GPIO_SM16716_CLK, GPIO_SM16716_DAT, GPIO_SM16716_SEL, // SM16716 SELECT
|
||||
GPIO_DI, GPIO_DCKI, // my92x1 PWM controller
|
||||
GPIO_CSE7766_TX, GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
|
||||
GPIO_ARIRFRCV, GPIO_ARIRFSEL, // Arilux RF Receive input
|
||||
GPIO_TXD, GPIO_RXD, // Serial interface
|
||||
GPIO_ROT1A, GPIO_ROT1B, // Rotary switch
|
||||
GPIO_ADC_JOY, // Analog joystick
|
||||
GPIO_SSPI_MAX31865_CS1, // MAX31865 Chip Select
|
||||
GPIO_HRE_CLOCK, GPIO_HRE_DATA, // HR-E Water Meter
|
||||
GPIO_ADE7953_IRQ, // ADE7953 IRQ
|
||||
GPIO_SOLAXX1_TX, GPIO_SOLAXX1_RX, // Solax Inverter Serial interface
|
||||
GPIO_ZIGBEE_TX, GPIO_ZIGBEE_RX, // Zigbee Serial interface
|
||||
GPIO_RDM6300_RX, // RDM6300 RX
|
||||
GPIO_IBEACON_TX, GPIO_IBEACON_RX, // HM17 IBEACON Serial interface
|
||||
GPIO_A4988_DIR, GPIO_A4988_STP, GPIO_A4988_ENA, // A4988 interface
|
||||
GPIO_A4988_MS1, GPIO_A4988_MS2, GPIO_A4988_MS3, // A4988 microstep
|
||||
GPIO_DDS2382_TX, GPIO_DDS2382_RX, // DDS2382 Serial interface
|
||||
GPIO_DDSU666_TX, GPIO_DDSU666_RX, // DDSU666 Serial interface
|
||||
GPIO_SM2135_CLK, GPIO_SM2135_DAT, // SM2135 PWM controller
|
||||
GPIO_DEEPSLEEP, // Kill switch for deepsleep
|
||||
GPIO_EXS_ENABLE, // EXS MCU Enable
|
||||
GPIO_TASMOTACLIENT_TXD, GPIO_TASMOTACLIENT_RXD, // Client Serial interface
|
||||
GPIO_TASMOTACLIENT_RST, GPIO_TASMOTACLIENT_RST_INV, // Client Reset
|
||||
GPIO_HPMA_RX, GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
|
||||
GPIO_GPS_RX, GPIO_GPS_TX, // GPS Serial interface
|
||||
GPIO_HM10_RX, GPIO_HM10_TX, // HM10-BLE-Mijia-bridge Serial interface
|
||||
GPIO_LE01MR_RX, GPIO_LE01MR_TX, // F&F LE-01MR energy meter
|
||||
GPIO_CC1101_GDO0, GPIO_CC1101_GDO2, // CC1101 Serial interface
|
||||
GPIO_HRXL_RX, // Data from MaxBotix HRXL sonar range sensor
|
||||
GPIO_ELECTRIQ_MOODL_TX, // ElectriQ iQ-wifiMOODL Serial TX
|
||||
GPIO_AS3935, // Franklin Lightning Sensor
|
||||
GPIO_ADC_INPUT, // Analog input
|
||||
GPIO_ADC_TEMP, // Analog Thermistor
|
||||
GPIO_ADC_LIGHT, // Analog Light sensor
|
||||
GPIO_ADC_BUTTON, GPIO_ADC_BUTTON_INV, // Analog Button
|
||||
GPIO_ADC_RANGE, // Analog Range
|
||||
GPIO_ADC_CT_POWER, // ANalog Current
|
||||
GPIO_WEBCAM_PWDN, GPIO_WEBCAM_RESET, GPIO_WEBCAM_XCLK, // Webcam
|
||||
GPIO_WEBCAM_SIOD, GPIO_WEBCAM_SIOC, // Webcam I2C
|
||||
GPIO_WEBCAM_DATA,
|
||||
GPIO_WEBCAM_VSYNC, GPIO_WEBCAM_HREF, GPIO_WEBCAM_PCLK,
|
||||
GPIO_WEBCAM_PSCLK,
|
||||
GPIO_WEBCAM_HSD,
|
||||
GPIO_WEBCAM_PSRCS,
|
||||
GPIO_BOILER_OT_RX, GPIO_BOILER_OT_TX, // OpenTherm Boiler TX pin
|
||||
GPIO_WINDMETER_SPEED, // WindMeter speed counter pin
|
||||
GPIO_KEY1_TC, // Touch pin as button
|
||||
GPIO_BL0940_RX, // BL0940 serial interface
|
||||
GPIO_TCP_TX, GPIO_TCP_RX, // TCP to serial bridge
|
||||
GPIO_ETH_PHY_POWER, GPIO_ETH_PHY_MDC, GPIO_ETH_PHY_MDIO, // Ethernet
|
||||
GPIO_TELEINFO_RX, // Teleinfo telemetry data receive pin
|
||||
GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin
|
||||
GPIO_LMT01, // LMT01 input counting pin
|
||||
GPIO_IEM3000_TX, GPIO_IEM3000_RX, // IEM3000 Serial interface
|
||||
GPIO_ZIGBEE_RST, // Zigbee reset
|
||||
GPIO_DYP_RX,
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
// GPIO_FIX_START = 254,
|
||||
GPIO_FIX_START = 2046,
|
||||
GPIO_USER, // User configurable needs to be 2047
|
||||
GPIO_MAX };
|
||||
|
||||
// Text in webpage Module Parameters and commands GPIOS and GPIO
|
||||
const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_NONE "|"
|
||||
D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "_n|" D_SENSOR_BUTTON "_i|" D_SENSOR_BUTTON "_in|"
|
||||
D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "_n|"
|
||||
D_SENSOR_RELAY "|" D_SENSOR_RELAY "_i|"
|
||||
D_SENSOR_LED "|" D_SENSOR_LED "_i|"
|
||||
D_SENSOR_COUNTER "|" D_SENSOR_COUNTER "_n|"
|
||||
D_SENSOR_PWM "|" D_SENSOR_PWM "_i|"
|
||||
D_SENSOR_BUZZER "|" D_SENSOR_BUZZER "_i|"
|
||||
D_SENSOR_LED_LINK "|" D_SENSOR_LED_LINK "_i|"
|
||||
D_SENSOR_I2C_SCL "|" D_SENSOR_I2C_SDA "|"
|
||||
D_SENSOR_SPI_MISO "|" D_SENSOR_SPI_MOSI "|" D_SENSOR_SPI_CLK "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|"
|
||||
D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|"
|
||||
D_SENSOR_BACKLIGHT "|" D_SENSOR_OLED_RESET "|"
|
||||
D_SENSOR_IRSEND "|" D_SENSOR_IRRECV "|"
|
||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
|
||||
D_SENSOR_DHT11 "|" D_SENSOR_AM2301 "|" D_SENSOR_SI7021 "|" D_SENSOR_DHT11 "_o|"
|
||||
D_SENSOR_DS18X20 "|" D_SENSOR_DS18X20 "_o|"
|
||||
D_SENSOR_WS2812 "|"
|
||||
D_SENSOR_MHZ_TX "|" D_SENSOR_MHZ_RX "|"
|
||||
D_SENSOR_PZEM0XX_TX "|" D_SENSOR_PZEM004_RX "|" D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|"
|
||||
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
|
||||
D_SENSOR_PMS5003_TX "|" D_SENSOR_PMS5003_RX "|"
|
||||
D_SENSOR_SDS0X1_TX "|" D_SENSOR_SDS0X1_RX "|"
|
||||
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
|
||||
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
|
||||
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|"
|
||||
D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX "|"
|
||||
D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB "|"
|
||||
D_SENSOR_DFR562 "|"
|
||||
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
||||
D_SENSOR_TX2X_TX "|"
|
||||
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
|
||||
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|"
|
||||
D_SENSOR_RF_SENSOR "|"
|
||||
D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|"
|
||||
D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|"
|
||||
D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "_i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|"
|
||||
D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|"
|
||||
D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX "|"
|
||||
D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER "|"
|
||||
D_SENSOR_MY92X1_DI "|" D_SENSOR_MY92X1_DCKI "|"
|
||||
D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|"
|
||||
D_SENSOR_ARIRFRCV "|" D_SENSOR_ARIRFSEL "|"
|
||||
D_SENSOR_TXD "|" D_SENSOR_RXD "|"
|
||||
D_SENSOR_ROTARY "_a|" D_SENSOR_ROTARY "_b|"
|
||||
D_SENSOR_ADC_JOYSTICK "|"
|
||||
D_SENSOR_MAX31865_CS "|"
|
||||
D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|"
|
||||
D_SENSOR_ADE7953_IRQ "|"
|
||||
D_SENSOR_SOLAXX1_TX "|" D_SENSOR_SOLAXX1_RX "|"
|
||||
D_SENSOR_ZIGBEE_TXD "|" D_SENSOR_ZIGBEE_RXD "|"
|
||||
D_SENSOR_RDM6300_RX "|"
|
||||
D_SENSOR_IBEACON_TX "|" D_SENSOR_IBEACON_RX "|"
|
||||
D_SENSOR_A4988_DIR "|" D_SENSOR_A4988_STP "|" D_SENSOR_A4988_ENA "|" D_SENSOR_A4988_MS1 "|" D_SENSOR_A4988_MS2 "|" D_SENSOR_A4988_MS3 "|"
|
||||
D_SENSOR_DDS2382_TX "|" D_SENSOR_DDS2382_RX "|"
|
||||
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
|
||||
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
|
||||
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
|
||||
D_SENSOR_CLIENT_TX "|" D_SENSOR_CLIENT_RX "|" D_SENSOR_CLIENT_RESET "|" D_SENSOR_CLIENT_RESET "_i|"
|
||||
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
|
||||
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|"
|
||||
D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|"
|
||||
D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX "|"
|
||||
D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 "|"
|
||||
D_SENSOR_HRXL_RX "|"
|
||||
D_SENSOR_ELECTRIQ_MOODL "|"
|
||||
D_SENSOR_AS3935 "|"
|
||||
D_SENSOR_ADC_INPUT "|"
|
||||
D_SENSOR_ADC_TEMP "|"
|
||||
D_SENSOR_ADC_LIGHT "|"
|
||||
D_SENSOR_ADC_BUTTON "|" D_SENSOR_ADC_BUTTON "_i|"
|
||||
D_SENSOR_ADC_RANGE "|"
|
||||
D_SENSOR_ADC_CT_POWER "|"
|
||||
D_GPIO_WEBCAM_PWDN "|" D_GPIO_WEBCAM_RESET "|" D_GPIO_WEBCAM_XCLK "|"
|
||||
D_GPIO_WEBCAM_SIOD "|" D_GPIO_WEBCAM_SIOC "|"
|
||||
D_GPIO_WEBCAM_DATA "|"
|
||||
D_GPIO_WEBCAM_VSYNC "|" D_GPIO_WEBCAM_HREF "|" D_GPIO_WEBCAM_PCLK "|"
|
||||
D_GPIO_WEBCAM_PSCLK "|"
|
||||
D_GPIO_WEBCAM_HSD "|"
|
||||
D_GPIO_WEBCAM_PSRCS "|"
|
||||
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
|
||||
D_SENSOR_WINDMETER_SPEED "|" D_SENSOR_BUTTON "_tc|"
|
||||
D_SENSOR_BL0940_RX "|"
|
||||
D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|"
|
||||
D_SENSOR_ETH_PHY_POWER "|" D_SENSOR_ETH_PHY_MDC "|" D_SENSOR_ETH_PHY_MDIO "|"
|
||||
D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
|
||||
D_SENSOR_LMT01_PULSE "|"
|
||||
D_SENSOR_IEM3000_TX "|" D_SENSOR_IEM3000_RX "|"
|
||||
D_SENSOR_ZIGBEE_RST "|"
|
||||
D_SENSOR_DYP_RX
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
D_SENSOR_USER;
|
||||
|
||||
#define MAX_MAX31865_CS 6
|
||||
#define MAX_WEBCAM_DATA 8
|
||||
#define MAX_WEBCAM_HSD 3
|
||||
|
||||
const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_NONE, // Not used
|
||||
AGPIO(GPIO_KEY1) + MAX_KEYS, // Buttons
|
||||
AGPIO(GPIO_KEY1_NP) + MAX_KEYS,
|
||||
AGPIO(GPIO_KEY1_INV) + MAX_KEYS,
|
||||
AGPIO(GPIO_KEY1_INV_NP) + MAX_KEYS,
|
||||
AGPIO(GPIO_KEY1_TC) + MAX_KEYS, // Touch button
|
||||
AGPIO(GPIO_SWT1) + MAX_SWITCHES, // User connected external switches
|
||||
AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES,
|
||||
#ifdef ROTARY_V1
|
||||
AGPIO(GPIO_ROT1A) + MAX_ROTARIES, // Rotary A Pin
|
||||
AGPIO(GPIO_ROT1B) + MAX_ROTARIES, // Rotary B Pin
|
||||
#endif
|
||||
AGPIO(GPIO_REL1) + MAX_RELAYS, // Relays
|
||||
AGPIO(GPIO_REL1_INV) + MAX_RELAYS,
|
||||
AGPIO(GPIO_LED1) + MAX_LEDS, // Leds
|
||||
AGPIO(GPIO_LED1_INV) + MAX_LEDS,
|
||||
#ifdef USE_COUNTER
|
||||
AGPIO(GPIO_CNTR1) + MAX_COUNTERS, // Counters
|
||||
AGPIO(GPIO_CNTR1_NP) + MAX_COUNTERS,
|
||||
#endif
|
||||
AGPIO(GPIO_PWM1) + MAX_PWMS, // RGB Red or C Cold White
|
||||
AGPIO(GPIO_PWM1_INV) + MAX_PWMS,
|
||||
#ifdef USE_BUZZER
|
||||
AGPIO(GPIO_BUZZER), // Buzzer
|
||||
AGPIO(GPIO_BUZZER_INV), // Inverted buzzer
|
||||
#endif
|
||||
AGPIO(GPIO_LEDLNK), // Link led
|
||||
AGPIO(GPIO_LEDLNK_INV), // Inverted link led
|
||||
#ifdef USE_I2C
|
||||
AGPIO(GPIO_I2C_SCL), // I2C SCL
|
||||
AGPIO(GPIO_I2C_SDA), // I2C SDA
|
||||
#endif
|
||||
#ifdef USE_SPI
|
||||
AGPIO(GPIO_SPI_MISO), // SPI MISO
|
||||
AGPIO(GPIO_SPI_MOSI), // SPI MOSI
|
||||
AGPIO(GPIO_SPI_CLK), // SPI Clk
|
||||
AGPIO(GPIO_SPI_CS), // SPI Chip Select
|
||||
AGPIO(GPIO_SPI_DC), // SPI Data Direction
|
||||
#endif
|
||||
AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Client Output
|
||||
AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Client Input
|
||||
AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock
|
||||
AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select
|
||||
AGPIO(GPIO_SSPI_DC), // Software SPI Data or Command
|
||||
#ifdef USE_DISPLAY
|
||||
AGPIO(GPIO_BACKLIGHT), // Display backlight control
|
||||
AGPIO(GPIO_OLED_RESET), // OLED Display Reset
|
||||
#endif
|
||||
|
||||
AGPIO(GPIO_TXD), // Serial interface
|
||||
AGPIO(GPIO_RXD), // Serial interface
|
||||
|
||||
#ifdef USE_DHT
|
||||
AGPIO(GPIO_DHT11), // DHT11
|
||||
AGPIO(GPIO_DHT22), // DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
AGPIO(GPIO_SI7021), // iTead SI7021
|
||||
AGPIO(GPIO_DHT11_OUT), // Pseudo Single wire DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
#endif
|
||||
#ifdef USE_DS18x20
|
||||
AGPIO(GPIO_DSB), // Single wire DS18B20 or DS18S20
|
||||
AGPIO(GPIO_DSB_OUT), // Pseudo Single wire DS18B20 or DS18S20
|
||||
#endif
|
||||
#ifdef USE_LMT01
|
||||
AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO
|
||||
#endif
|
||||
|
||||
// Light
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_WS2812
|
||||
AGPIO(GPIO_WS2812), // WS2812 Led string
|
||||
#endif
|
||||
#ifdef USE_ARILUX_RF
|
||||
AGPIO(GPIO_ARIRFRCV), // AriLux RF Receive input
|
||||
AGPIO(GPIO_ARIRFSEL), // Arilux RF Receive input selected
|
||||
#endif
|
||||
#ifdef USE_MY92X1
|
||||
AGPIO(GPIO_DI), // my92x1 PWM input
|
||||
AGPIO(GPIO_DCKI), // my92x1 CLK input
|
||||
#endif // USE_MY92X1
|
||||
#ifdef USE_SM16716
|
||||
AGPIO(GPIO_SM16716_CLK), // SM16716 CLOCK
|
||||
AGPIO(GPIO_SM16716_DAT), // SM16716 DATA
|
||||
AGPIO(GPIO_SM16716_SEL), // SM16716 SELECT
|
||||
#endif // USE_SM16716
|
||||
#ifdef USE_SM2135
|
||||
AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK
|
||||
AGPIO(GPIO_SM2135_DAT), // SM2135 DATA
|
||||
#endif // USE_SM2135
|
||||
#ifdef USE_TUYA_MCU
|
||||
AGPIO(GPIO_TUYA_TX), // Tuya Serial interface
|
||||
AGPIO(GPIO_TUYA_RX), // Tuya Serial interface
|
||||
#endif
|
||||
#ifdef USE_EXS_DIMMER
|
||||
AGPIO(GPIO_EXS_ENABLE), // EXS MCU Enable
|
||||
#endif
|
||||
#ifdef USE_ELECTRIQ_MOODL
|
||||
AGPIO(GPIO_ELECTRIQ_MOODL_TX),
|
||||
#endif
|
||||
#endif // USE_LIGHT
|
||||
|
||||
#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL)
|
||||
AGPIO(GPIO_IRSEND), // IR remote
|
||||
#if defined(USE_IR_RECEIVE) || defined(USE_IR_REMOTE_FULL)
|
||||
AGPIO(GPIO_IRRECV), // IR receiver
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_RC_SWITCH
|
||||
AGPIO(GPIO_RFSEND), // RF transmitter
|
||||
AGPIO(GPIO_RFRECV), // RF receiver
|
||||
#endif
|
||||
#ifdef USE_RF_SENSOR
|
||||
AGPIO(GPIO_RF_SENSOR), // Rf receiver with sensor decoding
|
||||
#endif
|
||||
#ifdef USE_SR04
|
||||
AGPIO(GPIO_SR04_TRIG), // SR04 Tri/TXgger pin
|
||||
AGPIO(GPIO_SR04_ECHO), // SR04 Ech/RXo pin
|
||||
#endif
|
||||
#ifdef USE_TM1638
|
||||
AGPIO(GPIO_TM16CLK), // TM1638 Clock
|
||||
AGPIO(GPIO_TM16DIO), // TM1638 Data I/O
|
||||
AGPIO(GPIO_TM16STB), // TM1638 Strobe
|
||||
#endif
|
||||
#ifdef USE_HX711
|
||||
AGPIO(GPIO_HX711_SCK), // HX711 Load Cell clock
|
||||
AGPIO(GPIO_HX711_DAT), // HX711 Load Cell data
|
||||
#endif
|
||||
|
||||
// Energy sensors
|
||||
#ifdef USE_ENERGY_SENSOR
|
||||
#ifdef USE_HLW8012
|
||||
AGPIO(GPIO_NRG_SEL), // HLW8012/HLJ-01 Sel output (1 = Voltage)
|
||||
AGPIO(GPIO_NRG_SEL_INV), // HLW8012/HLJ-01 Sel output (0 = Voltage)
|
||||
AGPIO(GPIO_NRG_CF1), // HLW8012/HLJ-01 CF1 voltage / current
|
||||
AGPIO(GPIO_HLW_CF), // HLW8012 CF power
|
||||
AGPIO(GPIO_HJL_CF), // HJL-01/BL0937 CF power
|
||||
#endif
|
||||
#if defined(USE_I2C) && defined(USE_ADE7953)
|
||||
AGPIO(GPIO_ADE7953_IRQ), // ADE7953 IRQ
|
||||
#endif
|
||||
#ifdef USE_CSE7766
|
||||
AGPIO(GPIO_CSE7766_TX), // CSE7766 Serial interface (S31 and Pow R2)
|
||||
AGPIO(GPIO_CSE7766_RX), // CSE7766 Serial interface (S31 and Pow R2)
|
||||
#endif
|
||||
#ifdef USE_MCP39F501
|
||||
AGPIO(GPIO_MCP39F5_TX), // MCP39F501 Serial interface (Shelly2)
|
||||
AGPIO(GPIO_MCP39F5_RX), // MCP39F501 Serial interface (Shelly2)
|
||||
AGPIO(GPIO_MCP39F5_RST), // MCP39F501 Reset (Shelly2)
|
||||
#endif
|
||||
#if defined(USE_PZEM004T) || defined(USE_PZEM_AC) || defined(USE_PZEM_DC)
|
||||
AGPIO(GPIO_PZEM0XX_TX), // PZEM0XX Serial interface
|
||||
#endif
|
||||
#ifdef USE_PZEM004T
|
||||
AGPIO(GPIO_PZEM004_RX), // PZEM004T Serial interface
|
||||
#endif
|
||||
#ifdef USE_PZEM_AC
|
||||
AGPIO(GPIO_PZEM016_RX), // PZEM-014,016 Serial Modbus interface
|
||||
#endif
|
||||
#ifdef USE_PZEM_DC
|
||||
AGPIO(GPIO_PZEM017_RX), // PZEM-003,017 Serial Modbus interface
|
||||
#endif
|
||||
#ifdef USE_SDM120
|
||||
AGPIO(GPIO_SDM120_TX), // SDM120 Serial interface
|
||||
AGPIO(GPIO_SDM120_RX), // SDM120 Serial interface
|
||||
#endif
|
||||
#ifdef USE_SDM630
|
||||
AGPIO(GPIO_SDM630_TX), // SDM630 Serial interface
|
||||
AGPIO(GPIO_SDM630_RX), // SDM630 Serial interface
|
||||
#endif
|
||||
#ifdef USE_DDS2382
|
||||
AGPIO(GPIO_DDS2382_TX), // DDS2382 Serial interface
|
||||
AGPIO(GPIO_DDS2382_RX), // DDS2382 Serial interface
|
||||
#endif
|
||||
#ifdef USE_DDSU666
|
||||
AGPIO(GPIO_DDSU666_TX), // DDSU666 Serial interface
|
||||
AGPIO(GPIO_DDSU666_RX), // DDSU666 Serial interface
|
||||
#endif // USE_DDSU666
|
||||
#ifdef USE_SOLAX_X1
|
||||
AGPIO(GPIO_SOLAXX1_TX), // Solax Inverter tx pin
|
||||
AGPIO(GPIO_SOLAXX1_RX), // Solax Inverter rx pin
|
||||
#endif // USE_SOLAX_X1
|
||||
#ifdef USE_LE01MR
|
||||
AGPIO(GPIO_LE01MR_TX), // F7F LE-01MR energy meter tx pin
|
||||
AGPIO(GPIO_LE01MR_RX), // F7F LE-01MR energy meter rx pin
|
||||
#endif // IFDEF:USE_LE01MR
|
||||
#ifdef USE_BL0940
|
||||
AGPIO(GPIO_BL0940_RX), // BL0940 Serial interface
|
||||
#endif
|
||||
#ifdef USE_IEM3000
|
||||
AGPIO(GPIO_IEM3000_TX), // IEM3000 Serial interface
|
||||
AGPIO(GPIO_IEM3000_RX), // IEM3000 Serial interface
|
||||
#endif
|
||||
#endif // USE_ENERGY_SENSOR
|
||||
|
||||
// Serial
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
AGPIO(GPIO_SBR_TX), // Serial Bridge Serial interface
|
||||
AGPIO(GPIO_SBR_RX), // Serial Bridge Serial interface
|
||||
#endif
|
||||
#ifdef USE_TCP_BRIDGE
|
||||
AGPIO(GPIO_TCP_TX), // TCP Serial bridge
|
||||
AGPIO(GPIO_TCP_RX), // TCP Serial bridge
|
||||
#endif
|
||||
#ifdef USE_ZIGBEE
|
||||
AGPIO(GPIO_ZIGBEE_TX), // Zigbee Serial interface
|
||||
AGPIO(GPIO_ZIGBEE_RX), // Zigbee Serial interface
|
||||
AGPIO(GPIO_ZIGBEE_RST), // Zigbee reset
|
||||
#endif
|
||||
#ifdef USE_MHZ19
|
||||
AGPIO(GPIO_MHZ_TXD), // MH-Z19 Serial interface
|
||||
AGPIO(GPIO_MHZ_RXD), // MH-Z19 Serial interface
|
||||
#endif
|
||||
#ifdef USE_SENSEAIR
|
||||
AGPIO(GPIO_SAIR_TX), // SenseAir Serial interface
|
||||
AGPIO(GPIO_SAIR_RX), // SenseAir Serial interface
|
||||
#endif
|
||||
#ifdef USE_NOVA_SDS
|
||||
AGPIO(GPIO_SDS0X1_TX), // Nova Fitness SDS011 Serial interface
|
||||
AGPIO(GPIO_SDS0X1_RX), // Nova Fitness SDS011 Serial interface
|
||||
#endif
|
||||
#ifdef USE_HPMA
|
||||
AGPIO(GPIO_HPMA_TX), // Honeywell HPMA115S0 Serial interface
|
||||
AGPIO(GPIO_HPMA_RX), // Honeywell HPMA115S0 Serial interface
|
||||
#endif
|
||||
#ifdef USE_PMS5003
|
||||
AGPIO(GPIO_PMS5003_TX), // Plantower PMS5003 Serial interface
|
||||
AGPIO(GPIO_PMS5003_RX), // Plantower PMS5003 Serial interface
|
||||
#endif
|
||||
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
|
||||
AGPIO(GPIO_TX2X_TXD_BLACK), // TX20/TX23 Transmission Pin
|
||||
#endif
|
||||
#ifdef USE_WINDMETER
|
||||
AGPIO(GPIO_WINDMETER_SPEED),
|
||||
#endif
|
||||
#ifdef USE_MP3_PLAYER
|
||||
AGPIO(GPIO_MP3_DFR562), // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
|
||||
#endif
|
||||
#ifdef USE_AZ7798
|
||||
AGPIO(GPIO_AZ_TXD), // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
AGPIO(GPIO_AZ_RXD), // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
#endif
|
||||
#ifdef USE_PN532_HSU
|
||||
AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx
|
||||
AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
AGPIO(GPIO_TASMOTACLIENT_TXD), // Tasmota Client TX
|
||||
AGPIO(GPIO_TASMOTACLIENT_RXD), // Tasmota Client RX
|
||||
AGPIO(GPIO_TASMOTACLIENT_RST), // Tasmota Client Reset
|
||||
AGPIO(GPIO_TASMOTACLIENT_RST_INV), // Tasmota Client Reset Inverted
|
||||
#endif
|
||||
#ifdef USE_RDM6300
|
||||
AGPIO(GPIO_RDM6300_RX),
|
||||
#endif
|
||||
#ifdef USE_IBEACON
|
||||
AGPIO(GPIO_IBEACON_TX),
|
||||
AGPIO(GPIO_IBEACON_RX),
|
||||
#endif
|
||||
#ifdef USE_GPS
|
||||
AGPIO(GPIO_GPS_TX), // GPS serial interface
|
||||
AGPIO(GPIO_GPS_RX), // GPS serial interface
|
||||
#endif
|
||||
#ifdef USE_HM10
|
||||
AGPIO(GPIO_HM10_TX), // GPS serial interface
|
||||
AGPIO(GPIO_HM10_RX), // GPS serial interface
|
||||
#endif
|
||||
#ifdef USE_OPENTHERM
|
||||
AGPIO(GPIO_BOILER_OT_TX),
|
||||
AGPIO(GPIO_BOILER_OT_RX),
|
||||
#endif
|
||||
|
||||
#ifdef USE_MGC3130
|
||||
AGPIO(GPIO_MGC3130_XFER),
|
||||
AGPIO(GPIO_MGC3130_RESET),
|
||||
#endif
|
||||
#ifdef USE_MAX31855
|
||||
AGPIO(GPIO_MAX31855CS), // MAX31855 Serial interface
|
||||
AGPIO(GPIO_MAX31855CLK), // MAX31855 Serial interface
|
||||
AGPIO(GPIO_MAX31855DO), // MAX31855 Serial interface
|
||||
#endif
|
||||
#ifdef USE_MAX31855
|
||||
AGPIO(GPIO_SSPI_MAX31865_CS1) + MAX_MAX31865_CS,
|
||||
#endif
|
||||
#ifdef USE_HRE
|
||||
AGPIO(GPIO_HRE_CLOCK),
|
||||
AGPIO(GPIO_HRE_DATA),
|
||||
#endif
|
||||
#ifdef USE_A4988_STEPPER
|
||||
AGPIO(GPIO_A4988_DIR), // A4988 direction pin
|
||||
AGPIO(GPIO_A4988_STP), // A4988 step pin
|
||||
// folowing are not mandatory
|
||||
AGPIO(GPIO_A4988_ENA), // A4988 enabled pin
|
||||
AGPIO(GPIO_A4988_MS1), // A4988 microstep pin1
|
||||
AGPIO(GPIO_A4988_MS2), // A4988 microstep pin2
|
||||
AGPIO(GPIO_A4988_MS3), // A4988 microstep pin3
|
||||
#endif
|
||||
#ifdef USE_DEEPSLEEP
|
||||
AGPIO(GPIO_DEEPSLEEP),
|
||||
#endif
|
||||
#ifdef USE_KEELOQ
|
||||
AGPIO(GPIO_CC1101_GDO0), // CC1101 pin for RX
|
||||
AGPIO(GPIO_CC1101_GDO2), // CC1101 pin for RX
|
||||
#endif
|
||||
#ifdef USE_HRXL
|
||||
AGPIO(GPIO_HRXL_RX),
|
||||
#endif
|
||||
#ifdef USE_DYP
|
||||
AGPIO(GPIO_DYP_RX),
|
||||
#endif
|
||||
#ifdef USE_AS3935
|
||||
AGPIO(GPIO_AS3935), // AS3935 IRQ Pin
|
||||
#endif
|
||||
#ifdef USE_TELEINFO
|
||||
AGPIO(GPIO_TELEINFO_RX),
|
||||
AGPIO(GPIO_TELEINFO_ENABLE),
|
||||
#endif
|
||||
#ifdef USE_ADC
|
||||
AGPIO(GPIO_ADC_INPUT) + MAX_ADCS, // Analog inputs
|
||||
AGPIO(GPIO_ADC_TEMP) + MAX_ADCS, // Thermistor
|
||||
AGPIO(GPIO_ADC_LIGHT) + MAX_ADCS, // Light sensor
|
||||
AGPIO(GPIO_ADC_BUTTON) + MAX_ADCS, // Button
|
||||
AGPIO(GPIO_ADC_BUTTON_INV) + MAX_ADCS,
|
||||
AGPIO(GPIO_ADC_RANGE) + MAX_ADCS, // Range
|
||||
AGPIO(GPIO_ADC_CT_POWER) + MAX_ADCS, // Current
|
||||
AGPIO(GPIO_ADC_JOY) + MAX_ADCS, // Joystick
|
||||
#endif
|
||||
#ifdef USE_WEBCAM
|
||||
AGPIO(GPIO_WEBCAM_PWDN),
|
||||
AGPIO(GPIO_WEBCAM_RESET),
|
||||
AGPIO(GPIO_WEBCAM_XCLK),
|
||||
AGPIO(GPIO_WEBCAM_SIOD),
|
||||
AGPIO(GPIO_WEBCAM_SIOC),
|
||||
AGPIO(GPIO_WEBCAM_DATA) + MAX_WEBCAM_DATA,
|
||||
AGPIO(GPIO_WEBCAM_VSYNC),
|
||||
AGPIO(GPIO_WEBCAM_HREF),
|
||||
AGPIO(GPIO_WEBCAM_PCLK),
|
||||
AGPIO(GPIO_WEBCAM_PSCLK),
|
||||
AGPIO(GPIO_WEBCAM_HSD) + MAX_WEBCAM_HSD,
|
||||
AGPIO(GPIO_WEBCAM_PSRCS),
|
||||
#endif
|
||||
#ifdef USE_ETHERNET
|
||||
AGPIO(GPIO_ETH_PHY_POWER),
|
||||
AGPIO(GPIO_ETH_PHY_MDC),
|
||||
AGPIO(GPIO_ETH_PHY_MDIO), // Ethernet
|
||||
#endif
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
// User selectable ADC functionality
|
||||
enum UserSelectableAdc {
|
||||
ADC_NONE, // Not used
|
||||
ADC_INPUT, // Analog input
|
||||
ADC_TEMP, // Thermistor
|
||||
ADC_LIGHT, // Light sensor
|
||||
ADC_BUTTON, // Button
|
||||
ADC_BUTTON_INV,
|
||||
ADC_RANGE, // Range
|
||||
ADC_CT_POWER, // Current
|
||||
ADC_JOY, // Joystick
|
||||
// ADC_SWITCH, // Switch
|
||||
// ADC_SWITCH_INV,
|
||||
ADC_END };
|
||||
|
||||
#define MAX_GPIO_PIN 40 // Number of supported GPIO
|
||||
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
|
||||
#define MAX_USER_PINS 36 // MAX_GPIO_PIN - MIN_FLASH_PINS
|
||||
#define WEMOS_MODULE 0 // Wemos module
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839
|
||||
const char PINS_WEMOS[] PROGMEM = "IOTXIORXIOIOflashcFLFLolIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOAOAOIAIAIAIAIAIA";
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
typedef struct MYIO {
|
||||
uint16_t io[MAX_GPIO_PIN];
|
||||
} myio; // 40 * 2 = 80 bytes
|
||||
|
||||
typedef struct MYCFGIO {
|
||||
uint16_t io[MAX_USER_PINS];
|
||||
} mycfgio; // 36 * 2 = 72 bytes
|
||||
|
||||
#define GPIO_FLAG_USED 0 // Currently no flags used
|
||||
|
||||
typedef union {
|
||||
uint16_t data;
|
||||
struct {
|
||||
uint16_t spare00 : 1;
|
||||
uint16_t spare01 : 1;
|
||||
uint16_t spare02 : 1;
|
||||
uint16_t spare03 : 1;
|
||||
uint16_t spare04 : 1;
|
||||
uint16_t spare05 : 1;
|
||||
uint16_t spare06 : 1;
|
||||
uint16_t spare07 : 1;
|
||||
uint16_t spare08 : 1;
|
||||
uint16_t spare09 : 1;
|
||||
uint16_t spare10 : 1;
|
||||
uint16_t spare11 : 1;
|
||||
uint16_t spare12 : 1;
|
||||
uint16_t spare13 : 1;
|
||||
uint16_t spare14 : 1;
|
||||
uint16_t spare15 : 1;
|
||||
};
|
||||
} gpio_flag; // 2 bytes
|
||||
|
||||
typedef struct MYTMPLT {
|
||||
mycfgio gp; // 72 bytes
|
||||
gpio_flag flag; // 2 bytes
|
||||
} mytmplt; // 74 bytes
|
||||
|
||||
/********************************************************************************************/
|
||||
// Supported hardware modules
|
||||
enum SupportedModules { WEMOS, ESP32_CAM_AITHINKER, MAXMODULE };
|
||||
|
||||
#define USER_MODULE 255
|
||||
|
||||
const char kModuleNames[] PROGMEM = "ESP32-DevKit|ESP32 Cam AiThinker";
|
||||
|
||||
// Default module settings
|
||||
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WEMOS, ESP32_CAM_AITHINKER };
|
||||
|
||||
const mytmplt kModules PROGMEM =
|
||||
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
|
||||
AGPIO(GPIO_USER), // 0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
|
||||
AGPIO(GPIO_USER), // 1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
|
||||
AGPIO(GPIO_USER), // 2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
|
||||
AGPIO(GPIO_USER), // 3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
|
||||
AGPIO(GPIO_USER), // 4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
|
||||
AGPIO(GPIO_USER), // 5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
|
||||
// 6 IO GPIO6, Flash CLK
|
||||
// 7 IO GPIO7, Flash D0
|
||||
// 8 IO GPIO8, Flash D1
|
||||
AGPIO(GPIO_USER), // 9 IO GPIO9, Flash D2, U1RXD
|
||||
AGPIO(GPIO_USER), // 10 IO GPIO10, Flash D3, U1TXD
|
||||
// 11 IO GPIO11, Flash CMD
|
||||
AGPIO(GPIO_USER), // 12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
|
||||
AGPIO(GPIO_USER), // 13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
|
||||
AGPIO(GPIO_USER), // 14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
|
||||
AGPIO(GPIO_USER), // 15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
|
||||
AGPIO(GPIO_USER), // 16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
|
||||
AGPIO(GPIO_USER), // 17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
|
||||
AGPIO(GPIO_USER), // 18 IO GPIO18, VSPICLK, HS1_DATA7
|
||||
AGPIO(GPIO_USER), // 19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
|
||||
0, // 20
|
||||
AGPIO(GPIO_USER), // 21 IO GPIO21, VSPIHD, EMAC_TX_EN
|
||||
AGPIO(GPIO_USER), // 22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
|
||||
AGPIO(GPIO_USER), // 23 IO GPIO23, VSPID, HS1_STROBE
|
||||
0, // 24
|
||||
AGPIO(GPIO_USER), // 25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
|
||||
AGPIO(GPIO_USER), // 26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
|
||||
AGPIO(GPIO_USER), // 27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
|
||||
0, // 28
|
||||
0, // 29
|
||||
0, // 30
|
||||
0, // 31
|
||||
AGPIO(GPIO_USER), // 32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
|
||||
AGPIO(GPIO_USER), // 33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
|
||||
AGPIO(GPIO_USER), // 34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
|
||||
AGPIO(GPIO_USER), // 35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
|
||||
AGPIO(GPIO_USER), // 36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
|
||||
0, // 37 NO PULLUP
|
||||
0, // 38 NO PULLUP
|
||||
AGPIO(GPIO_USER), // 39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
|
||||
0 // Flag
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
Known templates
|
||||
|
||||
{"NAME":"AITHINKER CAM","GPIO":[4992,1,1,1,1,5088,1,1,1,1,1,1,1,1,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,1,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1}
|
||||
{"NAME":"Olimex ESP32-PoE","GPIO":[1,1,1,1,1,1,0,0,5536,1,1,1,1,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
{"NAME":"wESP32","GPIO":[1,1,1,1,1,1,0,0,0,1,1,1,5568,5600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
{"NAME":"Denky (Teleinfo)","GPIO":[1,1,1,1,5664,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1376,1,1,0,0,0,0,1,5632,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
|
||||
\*********************************************************************************************/
|
||||
|
||||
#endif // ESP32
|
||||
|
||||
#endif // _TASMOTA_TEMPLATE_ESP32_H_
|
|
@ -368,16 +368,12 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM =
|
|||
"wl(h);"; // Add console command key eventlistener after name has been synced with id (= wl(jd))
|
||||
#endif //USE_UNISHOX_COMPRESSION
|
||||
|
||||
const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM =
|
||||
"}2%d'>%s (%d}3"; // }2 and }3 are used in below os.replace
|
||||
|
||||
const char HTTP_MODULE_TEMPLATE_REPLACE_INDEX[] PROGMEM =
|
||||
"}2%d'>%s (%d)}3"; // }2 and }3 are used in below os.replace
|
||||
const char HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX[] PROGMEM =
|
||||
"}2%d'>%s}3"; // }2 and }3 are used in below os.replace
|
||||
|
||||
#if defined(USE_UNISHOX_COMPRESSION) && defined(ESP32)
|
||||
// no compression on ESP8266, we would lose 16 bytes
|
||||
#if defined(USE_UNISHOX_COMPRESSION)
|
||||
const size_t HTTP_SCRIPT_MODULE_TEMPLATE_SIZE = 602;
|
||||
const char HTTP_SCRIPT_MODULE_TEMPLATE_COMPRESSED[] PROGMEM = "\x33\xBF\xAC\xF1\xD4\x2B\xC7\x83\x02\xF8\x3A\xDC\xE4\x1B\x3B\xBA\x75\x1A\x8E\xF1"
|
||||
"\xED\x33\xBF\xAC\x3E\x09\x81\x8B\x1A\xFA\x8E\x81\xFD\xDD\x32\x61\x31\xAF\xA8\xEE"
|
||||
|
@ -405,14 +401,6 @@ const char HTTP_SCRIPT_MODULE_TEMPLATE_COMPRESSED[] PROGMEM = "\x33\xBF\xAC\xF1\
|
|||
#define HTTP_SCRIPT_MODULE_TEMPLATE Decompress(HTTP_SCRIPT_MODULE_TEMPLATE_COMPRESSED,HTTP_SCRIPT_MODULE_TEMPLATE_SIZE).c_str()
|
||||
#else
|
||||
const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM =
|
||||
#ifdef ESP8266
|
||||
"var os;"
|
||||
"function sk(s,g){" // s = value, g = id and name
|
||||
"var o=os.replace(/}2/g,\"<option value='\").replace(/}3/g,\")</option>\");"
|
||||
"eb('g'+g).innerHTML=o;"
|
||||
"eb('g'+g).value=s;"
|
||||
"}";
|
||||
#else // ESP32
|
||||
"var os,hs;"
|
||||
"function ce(i,q){" // Create index select
|
||||
"var o=document.createElement('option');"
|
||||
|
@ -436,7 +424,6 @@ const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM =
|
|||
"eb('g'+g).value=(g<99)?s&0xffe0:s;"
|
||||
"if(g<99){ot(g,s);}"
|
||||
"}";
|
||||
#endif // ESP8266 - ESP32
|
||||
#endif //USE_UNISHOX_COMPRESSION
|
||||
|
||||
#ifdef USE_UNISHOX_COMPRESSION
|
||||
|
@ -486,13 +473,12 @@ const char HTTP_SCRIPT_TEMPLATE2[] PROGMEM =
|
|||
"if(8==i){j=12;}"
|
||||
"sk(g[i],j);" // Set GPIO
|
||||
"j++;"
|
||||
"}"
|
||||
"g=o.shift();"; // FLAG
|
||||
"}";
|
||||
const char HTTP_SCRIPT_TEMPLATE3[] PROGMEM =
|
||||
"\";"
|
||||
"sk(g&15," STR(ADC0_PIN) ");" // Set ADC0
|
||||
"g>>=4;";
|
||||
"sk(g[13]," STR(ADC0_PIN) ");"; // Set ADC0
|
||||
const char HTTP_SCRIPT_TEMPLATE4[] PROGMEM =
|
||||
"g=o.shift();" // FLAG
|
||||
"for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){"
|
||||
"p=(g>>i)&1;"
|
||||
"eb('c'+i).checked=p;" // Set FLAG checkboxes
|
||||
|
@ -1795,25 +1781,15 @@ void HandleTemplateConfiguration(void)
|
|||
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3...
|
||||
#ifdef ESP8266
|
||||
if (1 == i) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, AGPIO(GPIO_USER), D_SENSOR_USER, AGPIO(GPIO_USER)); // }2'255'>User (255)}3
|
||||
}
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
uint32_t ridx = midx;
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), ridx);
|
||||
#else // ESP32
|
||||
if (1 == i) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); // }2'255'>User}3
|
||||
}
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
uint32_t midx = BGPIO(ridx);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames));
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
WSContentSend_P(PSTR("\";"));
|
||||
|
||||
#ifdef ESP32
|
||||
WSContentSend_P(PSTR("hs=["));
|
||||
bool first_done = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453];
|
||||
|
@ -1825,17 +1801,18 @@ void HandleTemplateConfiguration(void)
|
|||
}
|
||||
}
|
||||
WSContentSend_P(PSTR("];"));
|
||||
#endif // ESP32
|
||||
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE2);
|
||||
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("os=\""));
|
||||
for (uint32_t i = 0; i < ADC0_END; i++) { // FLAG: }2'0'>None (0)}3}2'17'>Analog (17)}3...
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { // FLAG: }2'0'>None}3}2'17'>Analog}3...
|
||||
if (1 == i) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); // }2'15'>User (15)}3
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), D_SENSOR_USER); // }2'15'>User}3
|
||||
}
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i);
|
||||
uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0;
|
||||
uint32_t midx = BGPIO(ridx);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames));
|
||||
}
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE3);
|
||||
#endif // ESP8266
|
||||
|
@ -1843,11 +1820,7 @@ void HandleTemplateConfiguration(void)
|
|||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE4);
|
||||
for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3"
|
||||
uint32_t midx = pgm_read_byte(kModuleNiceList + i);
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1);
|
||||
#else // ESP32
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), midx +1);
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE5);
|
||||
|
||||
|
@ -1861,27 +1834,22 @@ void HandleTemplateConfiguration(void)
|
|||
WSContentSend_P(HTTP_TABLE100);
|
||||
for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (!FlashPin(i)) {
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_GPIO "%d</font></b></td><td%s><select id='g%d'></select></td></tr>"),
|
||||
((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i);
|
||||
#else // ESP32
|
||||
//#ifdef ESP8266
|
||||
// WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>%s%d</font></b></td><td%s><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
// ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT),
|
||||
// (ADC0_PIN==i) ? PSTR(D_ADC) : PSTR(D_GPIO), (ADC0_PIN==i) ? 0 : i,
|
||||
// (0==i) ? " style='width:150px'" : "", i, i);
|
||||
//#else // ESP32
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_GPIO "%d</font></b></td><td%s><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:150px'" : "", i, i);
|
||||
//#endif // ESP8266
|
||||
WSContentSend_P(PSTR("<td style='width:50px'><select id='h%d'></select></td></tr>"), i);
|
||||
#endif // ESP8266
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_ADC "0</font></b></td><td><select id='g17'></select></td></tr>"), WebColor(COL_TEXT));
|
||||
#endif
|
||||
WSContentSend_P(PSTR("</table>"));
|
||||
|
||||
gpio_flag flag = ModuleFlag();
|
||||
#ifdef ESP8266
|
||||
if (flag.data > ADC0_USER) {
|
||||
#else // ESP32
|
||||
if (flag.data) {
|
||||
#endif // ESP32
|
||||
WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG);
|
||||
}
|
||||
|
||||
|
@ -1906,27 +1874,20 @@ void TemplateSaveSettings(void)
|
|||
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO
|
||||
uint32_t gpio = atoi(tmp);
|
||||
#ifdef ESP32
|
||||
char tmp2[8]; // WebGetArg numbers only
|
||||
char webindex2[5]; // WebGetArg name
|
||||
snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), j);
|
||||
WebGetArg(webindex2, tmp2, sizeof(tmp2));
|
||||
uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1;
|
||||
gpio += value2;
|
||||
#endif // ESP32
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio);
|
||||
j++;
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp)); // FLAG - ADC0
|
||||
uint32_t flag = atoi(tmp);
|
||||
#else // ESP32
|
||||
uint32_t flag = 0;
|
||||
#endif // ESP32
|
||||
for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) {
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i);
|
||||
uint32_t state = Webserver->hasArg(webindex) << i +4; // FLAG
|
||||
uint32_t state = Webserver->hasArg(webindex) << i; // FLAG
|
||||
flag += state;
|
||||
}
|
||||
WebGetArg("g99", tmp, sizeof(tmp)); // BASE
|
||||
|
@ -1968,31 +1929,18 @@ void HandleModuleConfiguration(void)
|
|||
midx = pgm_read_byte(kModuleNiceList + i -1);
|
||||
vidx = midx +1;
|
||||
}
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx);
|
||||
#else // ESP32
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), vidx);
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings.module);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
midx = pgm_read_byte(kGpioNiceList + i);
|
||||
uint32_t ridx = midx;
|
||||
if (!GetUsedInModule(midx, cmodule.io)) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), ridx);
|
||||
}
|
||||
#else // ESP32
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
midx = BGPIO(ridx);
|
||||
if (!GetUsedInModule(midx, cmodule.io)) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames));
|
||||
}
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
WSContentSend_P(PSTR("\";"));
|
||||
|
||||
#ifdef ESP32
|
||||
WSContentSend_P(PSTR("hs=["));
|
||||
bool first_done = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453];
|
||||
|
@ -2004,7 +1952,6 @@ void HandleModuleConfiguration(void)
|
|||
}
|
||||
}
|
||||
WSContentSend_P(PSTR("];"));
|
||||
#endif // ESP32
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) {
|
||||
if (ValidGPIO(i, cmodule.io[i])) {
|
||||
|
@ -2015,10 +1962,12 @@ void HandleModuleConfiguration(void)
|
|||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
WSContentSend_P(PSTR("os=\""));
|
||||
for (uint32_t j = 0; j < ADC0_END; j++) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { // FLAG: }2'0'>None}3}2'17'>Analog}3...
|
||||
uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0;
|
||||
uint32_t midx = BGPIO(ridx);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames));
|
||||
}
|
||||
WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_adc0);
|
||||
WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_gp.io[(sizeof(myio) / 2) -1]);
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266
|
||||
|
||||
|
@ -2029,25 +1978,18 @@ void HandleModuleConfiguration(void)
|
|||
for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) {
|
||||
if (ValidGPIO(i, cmodule.io[i])) {
|
||||
snprintf_P(stemp, 3, PINS_WEMOS +i*2);
|
||||
#ifdef ESP8266
|
||||
char sesp8285[40];
|
||||
snprintf_P(sesp8285, sizeof(sesp8285), PSTR("<font color='#%06x'>ESP8285</font>"), WebColor(COL_TEXT_WARNING));
|
||||
WSContentSend_P(PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:176px'><select id='g%d'></select></td></tr>"),
|
||||
(WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i);
|
||||
#else // ESP32
|
||||
//#ifdef ESP8266
|
||||
// WSContentSend_P(PSTR("<tr><td style='width:116px'>%s <b>%s%d</b></td><td style='width:150px'><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
// (WEMOS==my_module_type)?stemp:"",
|
||||
// (ADC0_PIN==i) ? PSTR(D_ADC) : PSTR(D_GPIO), (ADC0_PIN==i) ? 0 : i,
|
||||
// i, i);
|
||||
//#else // ESP32
|
||||
WSContentSend_P(PSTR("<tr><td style='width:116px'>%s <b>" D_GPIO "%d</b></td><td style='width:150px'><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
(WEMOS==my_module_type)?stemp:"", i, i, i);
|
||||
//#endif
|
||||
WSContentSend_P(PSTR("<td style='width:50px'><select id='h%d'></select></td></tr>"), i);
|
||||
#endif // ESP8266
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
if (ValidAdc()) {
|
||||
WSContentSend_P(PSTR("<tr><td>%s <b>" D_ADC "0</b></td><td style='width:176px'><select id='g17'></select></td></tr>"), (WEMOS==my_module_type)?"A0":"");
|
||||
}
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266
|
||||
WSContentSend_P(PSTR("</table>"));
|
||||
WSContentSend_P(HTTP_FORM_END);
|
||||
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
||||
|
@ -2075,26 +2017,17 @@ void ModuleSaveSettings(void)
|
|||
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp));
|
||||
uint32_t value = (!strlen(tmp)) ? 0 : atoi(tmp);
|
||||
#ifdef ESP32
|
||||
char tmp2[8]; // WebGetArg numbers only
|
||||
char webindex2[5]; // WebGetArg name
|
||||
snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), i);
|
||||
WebGetArg(webindex2, tmp2, sizeof(tmp2));
|
||||
uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1;
|
||||
value += value2;
|
||||
#endif // ESP8266 - ESP32
|
||||
Settings.my_gp.io[i] = value;
|
||||
gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp));
|
||||
Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp);
|
||||
gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0);
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266
|
||||
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
xsns_02_analog.ino - ESP8266 ADC support for Tasmota
|
||||
xsns_02_analog.ino - ADC support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Theo Arends
|
||||
|
||||
|
@ -17,14 +17,16 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
#ifdef USE_ADC
|
||||
/*********************************************************************************************\
|
||||
* ADC support
|
||||
* ADC support for up to 8 channels on GPIO32 to GPIO39
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_02 2
|
||||
|
||||
#define ANALOG_RESOLUTION 12 // 12 = 4095, 11 = 2047, 10 = 1023
|
||||
#define ANALOG_RANGE 4095 // 4095 = 12, 2047 = 11, 1023 = 10
|
||||
|
||||
#define TO_CELSIUS(x) ((x) - 273.15)
|
||||
#define TO_KELVIN(x) ((x) + 273.15)
|
||||
|
||||
|
@ -57,62 +59,161 @@
|
|||
// Default settings for a 20A/1V Current Transformer.
|
||||
// Analog peak to peak range is measured and converted to RMS current using ANALOG_CT_MULTIPLIER
|
||||
#define ANALOG_CT_FLAGS 0 // (uint32_t) reserved for possible future use
|
||||
#define ANALOG_CT_MULTIPLIER 2146 // (uint32_t) Multiplier*100000 to convert raw ADC peak to peak range 0..1023 to RMS current in Amps. Value of 100000 corresponds to 1
|
||||
#define ANALOG_CT_MULTIPLIER 2146 // (uint32_t) Multiplier*100000 to convert raw ADC peak to peak range 0..ANALOG_RANGE to RMS current in Amps. Value of 100000 corresponds to 1
|
||||
#define ANALOG_CT_VOLTAGE 2300 // (int) Convert current in Amps to apparrent power in Watts using voltage in Volts*10. Value of 2200 corresponds to 220V
|
||||
|
||||
#define CT_FLAG_ENERGY_RESET (1 << 0) // Reset energy total
|
||||
|
||||
// Odroid joysticks
|
||||
// ---- Up
|
||||
// 3V3 ---| |------------
|
||||
// |
|
||||
// ---- Dn |--- R10k --- Gnd
|
||||
// 3V3 ---| |--- R10k ---|
|
||||
// |
|
||||
// ADC
|
||||
// Press "Up" will raise ADC to ANALOG_RANGE, Press "Dn" will raise ADC to ANALOG_RANGE/2
|
||||
#define ANALOG_JOYSTICK (ANALOG_RANGE / 3) +100 // Add resistor tolerance
|
||||
|
||||
struct {
|
||||
uint8_t present = 0;
|
||||
uint8_t type = 0;
|
||||
} Adcs;
|
||||
|
||||
struct {
|
||||
float temperature = 0;
|
||||
float current = 0;
|
||||
float energy = 0;
|
||||
uint32_t param1 = 0;
|
||||
uint32_t param2 = 0;
|
||||
int param3 = 0;
|
||||
int param4 = 0;
|
||||
uint32_t previous_millis = 0;
|
||||
uint16_t last_value = 0;
|
||||
} Adc;
|
||||
uint8_t type = 0;
|
||||
uint8_t pin = 0;
|
||||
} Adc[MAX_ADCS];
|
||||
|
||||
void AdcInit(void)
|
||||
{
|
||||
if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) {
|
||||
if (ADC0_TEMP == my_adc0) {
|
||||
#ifdef ESP8266
|
||||
bool adcAttachPin(uint8_t pin) {
|
||||
return (ADC0_PIN == pin);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AdcSaveSettings(uint32_t idx) {
|
||||
char parameters[32];
|
||||
snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"),
|
||||
Adc[idx].type, Adc[idx].param1, Adc[idx].param2, Adc[idx].param3, Adc[idx].param4);
|
||||
SettingsUpdateText(SET_ADC_PARAM1 + idx, parameters);
|
||||
}
|
||||
|
||||
void AdcGetSettings(uint32_t idx) {
|
||||
char parameters[32];
|
||||
Adcs.type = 0;
|
||||
Adc[idx].param1 = 0;
|
||||
Adc[idx].param2 = 0;
|
||||
Adc[idx].param3 = 0;
|
||||
Adc[idx].param4 = 0;
|
||||
if (strstr(SettingsText(SET_ADC_PARAM1 + idx), ",") != nullptr) {
|
||||
Adcs.type = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 1));
|
||||
Adc[idx].param1 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 2));
|
||||
Adc[idx].param2 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 3));
|
||||
Adc[idx].param3 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 4));
|
||||
Adc[idx].param4 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 5));
|
||||
}
|
||||
}
|
||||
|
||||
void AdcInitParams(uint8_t idx) {
|
||||
if ((Adcs.type != Adc[idx].type) || (Adc[idx].param1 > 1000000)) {
|
||||
if (ADC_TEMP == Adc[idx].type) {
|
||||
// Default Shelly 2.5 and 1PM parameters
|
||||
Settings.adc_param_type = ADC0_TEMP;
|
||||
Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE;
|
||||
Settings.adc_param2 = ANALOG_NTC_RESISTANCE;
|
||||
Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000;
|
||||
Adc[idx].param1 = ANALOG_NTC_BRIDGE_RESISTANCE;
|
||||
Adc[idx].param2 = ANALOG_NTC_RESISTANCE;
|
||||
Adc[idx].param3 = ANALOG_NTC_B_COEFFICIENT * 10000;
|
||||
}
|
||||
else if (ADC0_LIGHT == my_adc0) {
|
||||
Settings.adc_param_type = ADC0_LIGHT;
|
||||
Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE;
|
||||
Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR;
|
||||
Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000;
|
||||
else if (ADC_LIGHT == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_LDR_BRIDGE_RESISTANCE;
|
||||
Adc[idx].param2 = ANALOG_LDR_LUX_CALC_SCALAR;
|
||||
Adc[idx].param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000;
|
||||
}
|
||||
else if (ADC0_RANGE == my_adc0) {
|
||||
Settings.adc_param_type = ADC0_RANGE;
|
||||
Settings.adc_param1 = 0;
|
||||
Settings.adc_param2 = 1023;
|
||||
Settings.adc_param3 = 0;
|
||||
Settings.adc_param4 = 100;
|
||||
else if (ADC_RANGE == Adc[idx].type) {
|
||||
Adc[idx].param1 = 0;
|
||||
Adc[idx].param2 = ANALOG_RANGE;
|
||||
Adc[idx].param3 = 0;
|
||||
Adc[idx].param4 = 100;
|
||||
}
|
||||
else if (ADC0_CT_POWER == my_adc0) {
|
||||
Settings.adc_param_type = ADC0_CT_POWER;
|
||||
Settings.adc_param1 = ANALOG_CT_FLAGS; //(uint32_t) 0
|
||||
Settings.adc_param2 = ANALOG_CT_MULTIPLIER; //(uint32_t) 100000
|
||||
Settings.adc_param3 = ANALOG_CT_VOLTAGE; //(int) 10
|
||||
else if (ADC_CT_POWER == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_CT_FLAGS; // (uint32_t) 0
|
||||
Adc[idx].param2 = ANALOG_CT_MULTIPLIER; // (uint32_t) 100000
|
||||
Adc[idx].param3 = ANALOG_CT_VOLTAGE; // (int) 10
|
||||
}
|
||||
else if (ADC_JOY == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_JOYSTICK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AdcRead(uint8_t factor)
|
||||
{
|
||||
void AdcAttach(uint8_t pin, uint8_t type) {
|
||||
Adc[Adcs.present].pin = pin;
|
||||
if (adcAttachPin(Adc[Adcs.present].pin)) {
|
||||
Adc[Adcs.present].type = type;
|
||||
// analogSetPinAttenuation(Adc[Adcs.present].pin, ADC_11db); // Default
|
||||
Adcs.present++;
|
||||
}
|
||||
}
|
||||
|
||||
void AdcInit(void) {
|
||||
Adcs.present = 0;
|
||||
for (uint32_t i = 0; i < MAX_ADCS; i++) {
|
||||
if (PinUsed(GPIO_ADC_INPUT, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_INPUT, i), ADC_INPUT);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_TEMP, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_TEMP, i), ADC_TEMP);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_LIGHT, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_LIGHT, i), ADC_LIGHT);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_BUTTON, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_BUTTON, i), ADC_BUTTON);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_BUTTON_INV, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_BUTTON_INV, i), ADC_BUTTON_INV);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_RANGE, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_RANGE, i), ADC_RANGE);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_CT_POWER, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_CT_POWER, i), ADC_CT_POWER);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_JOY, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_JOY, i), ADC_JOY);
|
||||
}
|
||||
}
|
||||
if (Adcs.present) {
|
||||
#ifdef ESP32
|
||||
analogSetClockDiv(1); // Default 1
|
||||
analogSetWidth(ANALOG_RESOLUTION); // Default 12 bits (0 - 4095)
|
||||
analogSetAttenuation(ADC_11db); // Default 11db
|
||||
#endif
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
AdcGetSettings(idx);
|
||||
AdcInitParams(idx);
|
||||
AdcSaveSettings(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AdcRead(uint32_t pin, uint32_t factor) {
|
||||
// factor 1 = 2 samples
|
||||
// factor 2 = 4 samples
|
||||
// factor 3 = 8 samples
|
||||
// factor 4 = 16 samples
|
||||
// factor 5 = 32 samples
|
||||
uint8_t samples = 1 << factor;
|
||||
uint16_t analog = 0;
|
||||
uint32_t samples = 1 << factor;
|
||||
uint32_t analog = 0;
|
||||
for (uint32_t i = 0; i < samples; i++) {
|
||||
analog += analogRead(A0);
|
||||
analog += analogRead(pin);
|
||||
delay(1);
|
||||
}
|
||||
analog >>= factor;
|
||||
|
@ -120,44 +221,72 @@ uint16_t AdcRead(uint8_t factor)
|
|||
}
|
||||
|
||||
#ifdef USE_RULES
|
||||
void AdcEvery250ms(void)
|
||||
{
|
||||
if (ADC0_INPUT == my_adc0) {
|
||||
uint16_t new_value = AdcRead(5);
|
||||
if ((new_value < Adc.last_value -10) || (new_value > Adc.last_value +10)) {
|
||||
Adc.last_value = new_value;
|
||||
uint16_t value = Adc.last_value / 10;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value);
|
||||
XdrvRulesProcess();
|
||||
void AdcEvery250ms(void) {
|
||||
char adc_idx[3] = { 0 };
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
#ifdef ESP32
|
||||
snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1);
|
||||
offset = 1;
|
||||
#endif
|
||||
if (ADC_INPUT == Adc[idx].type) {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 5);
|
||||
if ((new_value < Adc[idx].last_value -10) || (new_value > Adc[idx].last_value +10)) {
|
||||
Adc[idx].last_value = new_value;
|
||||
uint16_t value = Adc[idx].last_value / 10;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"A%ddiv10\":%d}}"), idx + offset, (value > 99) ? 100 : value);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
}
|
||||
else if (ADC_JOY == Adc[idx].type) {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 1);
|
||||
if (new_value && (new_value != Adc[idx].last_value)) {
|
||||
Adc[idx].last_value = new_value;
|
||||
uint16_t value = new_value / Adc[idx].param1;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"Joy%s\":%d}}"), adc_idx, value);
|
||||
XdrvRulesProcess();
|
||||
} else {
|
||||
Adc[idx].last_value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_RULES
|
||||
|
||||
uint16_t AdcGetLux(void)
|
||||
{
|
||||
int adc = AdcRead(2);
|
||||
bool AdcButtonPresent(uint32_t idx) {
|
||||
return ((ADC_BUTTON == Adc[idx].type) || (ADC_BUTTON_INV == Adc[idx].type));
|
||||
}
|
||||
|
||||
uint8_t AdcGetButton(uint32_t idx) {
|
||||
if (ADC_BUTTON_INV == Adc[idx].type) {
|
||||
return (AdcRead(Adc[idx].pin, 1) < 128);
|
||||
}
|
||||
else if (ADC_BUTTON == Adc[idx].type) {
|
||||
return (AdcRead(Adc[idx].pin, 1) > 128);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AdcGetLux(uint32_t idx) {
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
// Source: https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/
|
||||
double resistorVoltage = ((double)adc / 1023) * ANALOG_V33;
|
||||
double resistorVoltage = ((double)adc / ANALOG_RANGE) * ANALOG_V33;
|
||||
double ldrVoltage = ANALOG_V33 - resistorVoltage;
|
||||
double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1;
|
||||
double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000);
|
||||
double ldrResistance = ldrVoltage / resistorVoltage * (double)Adc[idx].param1;
|
||||
double ldrLux = (double)Adc[idx].param2 * FastPrecisePow(ldrResistance, (double)Adc[idx].param3 / 10000);
|
||||
|
||||
return (uint16_t)ldrLux;
|
||||
}
|
||||
|
||||
uint16_t AdcGetRange(void)
|
||||
{
|
||||
uint16_t AdcGetRange(uint32_t idx) {
|
||||
// formula for calibration: value, fromLow, fromHigh, toLow, toHigh
|
||||
// Example: 514, 632, 236, 0, 100
|
||||
// int( ((<param2> - <analog-value>) / (<param2> - <param1>) ) * (<param3> - <param4>) ) + <param4> )
|
||||
int adc = AdcRead(2);
|
||||
double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 );
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
double adcrange = ( ((double)Adc[idx].param2 - (double)adc) / ( ((double)Adc[idx].param2 - (double)Adc[idx].param1)) * ((double)Adc[idx].param3 - (double)Adc[idx].param4) + (double)Adc[idx].param4 );
|
||||
return (uint16_t)adcrange;
|
||||
}
|
||||
|
||||
void AdcGetCurrentPower(uint8_t factor)
|
||||
{
|
||||
void AdcGetCurrentPower(uint8_t idx, uint8_t factor) {
|
||||
// factor 1 = 2 samples
|
||||
// factor 2 = 4 samples
|
||||
// factor 3 = 8 samples
|
||||
|
@ -165,12 +294,12 @@ void AdcGetCurrentPower(uint8_t factor)
|
|||
// factor 5 = 32 samples
|
||||
uint8_t samples = 1 << factor;
|
||||
uint16_t analog = 0;
|
||||
uint16_t analog_min = 1023;
|
||||
uint16_t analog_min = ANALOG_RANGE;
|
||||
uint16_t analog_max = 0;
|
||||
|
||||
if (0 == Settings.adc_param1) {
|
||||
if (0 == Adc[idx].param1) {
|
||||
for (uint32_t i = 0; i < samples; i++) {
|
||||
analog = analogRead(A0);
|
||||
analog = analogRead(Adc[idx].pin);
|
||||
if (analog < analog_min) {
|
||||
analog_min = analog;
|
||||
}
|
||||
|
@ -179,138 +308,181 @@ void AdcGetCurrentPower(uint8_t factor)
|
|||
}
|
||||
delay(1);
|
||||
}
|
||||
Adc.current = (float)(analog_max-analog_min) * ((float)(Settings.adc_param2) / 100000);
|
||||
Adc[idx].current = (float)(analog_max-analog_min) * ((float)(Adc[idx].param2) / 100000);
|
||||
}
|
||||
else {
|
||||
analog = AdcRead(5);
|
||||
if (analog > Settings.adc_param1) {
|
||||
Adc.current = ((float)(analog) - (float)Settings.adc_param1) * ((float)(Settings.adc_param2) / 100000);
|
||||
analog = AdcRead(Adc[idx].pin, 5);
|
||||
if (analog > Adc[idx].param1) {
|
||||
Adc[idx].current = ((float)(analog) - (float)Adc[idx].param1) * ((float)(Adc[idx].param2) / 100000);
|
||||
}
|
||||
else {
|
||||
Adc.current = 0;
|
||||
Adc[idx].current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float power = Adc.current * (float)(Settings.adc_param3) / 10;
|
||||
float power = Adc[idx].current * (float)(Adc[idx].param3) / 10;
|
||||
uint32_t current_millis = millis();
|
||||
Adc.energy = Adc.energy + ((power * (current_millis - Adc.previous_millis)) / 3600000000);
|
||||
Adc.previous_millis = current_millis;
|
||||
Adc[idx].energy = Adc[idx].energy + ((power * (current_millis - Adc[idx].previous_millis)) / 3600000000);
|
||||
Adc[idx].previous_millis = current_millis;
|
||||
}
|
||||
|
||||
void AdcEverySecond(void)
|
||||
{
|
||||
if (ADC0_TEMP == my_adc0) {
|
||||
int adc = AdcRead(2);
|
||||
// Steinhart-Hart equation for thermistor as temperature sensor
|
||||
double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc);
|
||||
double BC = (double)Settings.adc_param3 / 10000;
|
||||
double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2));
|
||||
Adc.temperature = ConvertTemp(TO_CELSIUS(T));
|
||||
}
|
||||
else if (ADC0_CT_POWER == my_adc0) {
|
||||
AdcGetCurrentPower(5);
|
||||
}
|
||||
}
|
||||
|
||||
void AdcShow(bool json)
|
||||
{
|
||||
if (ADC0_INPUT == my_adc0) {
|
||||
uint16_t analog = AdcRead(5);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog);
|
||||
#endif // USE_WEBSERVER
|
||||
void AdcEverySecond(void) {
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
if (ADC_TEMP == Adc[idx].type) {
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
// Steinhart-Hart equation for thermistor as temperature sensor
|
||||
double Rt = (adc * Adc[idx].param1) / (1024.0 * ANALOG_V33 - (double)adc);
|
||||
double BC = (double)Adc[idx].param3 / 10000;
|
||||
double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2));
|
||||
Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T));
|
||||
}
|
||||
else if (ADC_CT_POWER == Adc[idx].type) {
|
||||
AdcGetCurrentPower(idx, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (ADC0_TEMP == my_adc0) {
|
||||
char temperature[33];
|
||||
dtostrfd(Adc.temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
void AdcShowContinuation(bool *jsonflg) {
|
||||
if (*jsonflg) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
} else {
|
||||
ResponseAppend_P(PSTR(",\"ANALOG\":{"));
|
||||
*jsonflg = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) {
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
void AdcShow(bool json) {
|
||||
bool domo_flag[ADC_END] = { false };
|
||||
char adc_name[10] = { 0 }; // ANALOG8
|
||||
char adc_idx[3] = { 0 };
|
||||
uint32_t offset = 0;
|
||||
|
||||
bool jsonflg = false;
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
#ifdef ESP32
|
||||
snprintf_P(adc_name, sizeof(adc_name), PSTR("Analog%d"), idx +1);
|
||||
snprintf_P(adc_idx, sizeof(adc_idx), PSTR("%d"), idx +1);
|
||||
offset = 1;
|
||||
#endif
|
||||
|
||||
switch (Adc[idx].type) {
|
||||
case ADC_INPUT: {
|
||||
uint16_t analog = AdcRead(Adc[idx].pin, 5);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"A%d\":%d"), idx + offset, analog);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ANALOG, "", idx + offset, analog);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_TEMP: {
|
||||
char temperature[33];
|
||||
dtostrfd(Adc[idx].temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "%s\":%s"), adc_idx, temperature);
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_TEMP])) {
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
domo_flag[ADC_TEMP] = true;
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
if (0 == tele_period) {
|
||||
KnxSensor(KNX_TEMPERATURE, Adc.temperature);
|
||||
}
|
||||
KnxSensor(KNX_TEMPERATURE, Adc[idx].temperature);
|
||||
#endif // USE_KNX
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit());
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_TEMP, adc_name, temperature, TempUnit());
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
else if (ADC0_LIGHT == my_adc0) {
|
||||
uint16_t adc_light = AdcGetLux();
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) {
|
||||
DomoticzSensor(DZ_ILLUMINANCE, adc_light);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_LIGHT: {
|
||||
uint16_t adc_light = AdcGetLux(idx);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_ILLUMINANCE "%s\":%d"), adc_idx, adc_light);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_LIGHT])) {
|
||||
DomoticzSensor(DZ_ILLUMINANCE, adc_light);
|
||||
domo_flag[ADC_LIGHT] = true;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light);
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, adc_name, adc_light);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
else if (ADC0_RANGE == my_adc0) {
|
||||
uint16_t adc_range = AdcGetRange();
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
else if (ADC0_CT_POWER == my_adc0) {
|
||||
AdcGetCurrentPower(5);
|
||||
|
||||
float voltage = (float)(Settings.adc_param3) / 10;
|
||||
char voltage_chr[FLOATSZ];
|
||||
dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
||||
char current_chr[FLOATSZ];
|
||||
dtostrfd(Adc.current, Settings.flag2.current_resolution, current_chr);
|
||||
char power_chr[FLOATSZ];
|
||||
dtostrfd(voltage * Adc.current, Settings.flag2.wattage_resolution, power_chr);
|
||||
char energy_chr[FLOATSZ];
|
||||
dtostrfd(Adc.energy, Settings.flag2.energy_resolution, energy_chr);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"ANALOG\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"),
|
||||
energy_chr, power_chr, voltage_chr, current_chr);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) {
|
||||
DomoticzSensor(DZ_POWER_ENERGY, power_chr);
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr);
|
||||
DomoticzSensor(DZ_CURRENT, current_chr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_RANGE: {
|
||||
uint16_t adc_range = AdcGetRange(idx);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_RANGE "%s\":%d"), adc_idx, adc_range);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_RANGE, adc_name, adc_range);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_CT_POWER: {
|
||||
AdcGetCurrentPower(idx, 5);
|
||||
|
||||
float voltage = (float)(Adc[idx].param3) / 10;
|
||||
char voltage_chr[FLOATSZ];
|
||||
dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
||||
char current_chr[FLOATSZ];
|
||||
dtostrfd(Adc[idx].current, Settings.flag2.current_resolution, current_chr);
|
||||
char power_chr[FLOATSZ];
|
||||
dtostrfd(voltage * Adc[idx].current, Settings.flag2.wattage_resolution, power_chr);
|
||||
char energy_chr[FLOATSZ];
|
||||
dtostrfd(Adc[idx].energy, Settings.flag2.energy_resolution, energy_chr);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"CTEnergy%s\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"),
|
||||
adc_idx, energy_chr, power_chr, voltage_chr, current_chr);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_CT_POWER])) {
|
||||
DomoticzSensor(DZ_POWER_ENERGY, power_chr);
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr);
|
||||
DomoticzSensor(DZ_CURRENT, current_chr);
|
||||
domo_flag[ADC_CT_POWER] = true;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr);
|
||||
WSContentSend_PD(HTTP_SNS_CURRENT, current_chr);
|
||||
WSContentSend_PD(HTTP_SNS_POWER, power_chr);
|
||||
WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr);
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr);
|
||||
WSContentSend_PD(HTTP_SNS_CURRENT, current_chr);
|
||||
WSContentSend_PD(HTTP_SNS_POWER, power_chr);
|
||||
WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_JOY: {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 1);
|
||||
uint16_t value = new_value / Adc[idx].param1;
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"Joy%s\":%d"), adc_idx, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonflg) {
|
||||
ResponseJsonEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -318,118 +490,94 @@ void AdcShow(bool json)
|
|||
\*********************************************************************************************/
|
||||
|
||||
const char kAdcCommands[] PROGMEM = "|" // No prefix
|
||||
#ifdef ESP8266
|
||||
D_CMND_ADC "|" D_CMND_ADCS "|"
|
||||
#endif // ESP8266
|
||||
D_CMND_ADCPARAM;
|
||||
|
||||
void (* const AdcCommand[])(void) PROGMEM = {
|
||||
#ifdef ESP8266
|
||||
&CmndAdc, &CmndAdcs,
|
||||
#endif // ESP8266
|
||||
&CmndAdcParam };
|
||||
|
||||
#ifdef ESP8266
|
||||
void CmndAdc(void)
|
||||
{
|
||||
if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) {
|
||||
Settings.my_adc0 = XdrvMailbox.payload;
|
||||
restart_flag = 2;
|
||||
}
|
||||
char stemp1[TOPSZ];
|
||||
Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names));
|
||||
}
|
||||
|
||||
void CmndAdcs(void)
|
||||
{
|
||||
Response_P(PSTR("{\"" D_CMND_ADCS "\":{"));
|
||||
bool jsflg = false;
|
||||
char stemp1[TOPSZ];
|
||||
for (uint32_t i = 0; i < ADC0_END; i++) {
|
||||
if (jsflg) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
jsflg = true;
|
||||
ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names));
|
||||
}
|
||||
ResponseJsonEndEnd();
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
void CmndAdcParam(void)
|
||||
{
|
||||
if (XdrvMailbox.data_len) {
|
||||
if ((ADC0_TEMP == XdrvMailbox.payload) ||
|
||||
(ADC0_LIGHT == XdrvMailbox.payload) ||
|
||||
(ADC0_RANGE == XdrvMailbox.payload) ||
|
||||
(ADC0_CT_POWER == XdrvMailbox.payload)) {
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
// AdcParam 2, 32000, 10000, 3350
|
||||
// AdcParam 3, 10000, 12518931, -1.405
|
||||
// AdcParam 6, 0, 1023, 0, 100
|
||||
Settings.adc_param_type = XdrvMailbox.payload;
|
||||
Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10);
|
||||
if (ADC0_RANGE == XdrvMailbox.payload) {
|
||||
Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10));
|
||||
Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10));
|
||||
} else {
|
||||
Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000);
|
||||
}
|
||||
if (ADC0_CT_POWER == XdrvMailbox.payload) {
|
||||
if (((1 == Settings.adc_param1) & CT_FLAG_ENERGY_RESET) > 0) {
|
||||
Adc.energy = 0;
|
||||
Settings.adc_param1 ^= CT_FLAG_ENERGY_RESET; // Cancel energy reset flag
|
||||
void CmndAdcParam(void) {
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_ADCS)) {
|
||||
uint8_t idx = XdrvMailbox.index -1;
|
||||
if (XdrvMailbox.data_len) {
|
||||
if ((ADC_TEMP == XdrvMailbox.payload) ||
|
||||
(ADC_LIGHT == XdrvMailbox.payload) ||
|
||||
(ADC_RANGE == XdrvMailbox.payload) ||
|
||||
(ADC_CT_POWER == XdrvMailbox.payload) ||
|
||||
(ADC_JOY == XdrvMailbox.payload)) {
|
||||
AdcGetSettings(idx);
|
||||
if (ChrCount(XdrvMailbox.data, ",") > 2) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
// AdcParam 2, 32000, 10000, 3350
|
||||
// AdcParam 3, 10000, 12518931, -1.405
|
||||
// AdcParam 6, 0, ANALOG_RANGE, 0, 100
|
||||
// AdcParam 7, 0, 2146, 0.23
|
||||
// AdcParam 8, 1000, 0, 0
|
||||
Adc[idx].type = XdrvMailbox.payload;
|
||||
Adc[idx].param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
Adc[idx].param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10);
|
||||
if (ADC_RANGE == XdrvMailbox.payload) {
|
||||
Adc[idx].param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10));
|
||||
Adc[idx].param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10));
|
||||
} else {
|
||||
Adc[idx].param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000);
|
||||
}
|
||||
if (ADC_CT_POWER == XdrvMailbox.payload) {
|
||||
if (((1 == Adc[idx].param1) & CT_FLAG_ENERGY_RESET) > 0) {
|
||||
for (uint32_t idx = 0; idx < MAX_ADCS; idx++) {
|
||||
Adc[idx].energy = 0;
|
||||
}
|
||||
Adc[idx].param1 ^= CT_FLAG_ENERGY_RESET; // Cancel energy reset flag
|
||||
}
|
||||
}
|
||||
} else { // Set default values based on current adc type
|
||||
// AdcParam 2
|
||||
// AdcParam 3
|
||||
// AdcParam 6
|
||||
// AdcParam 7
|
||||
// AdcParam 8
|
||||
Adcs.type = 0;
|
||||
AdcInitParams(idx);
|
||||
}
|
||||
} else { // Set default values based on current adc type
|
||||
// AdcParam 2
|
||||
// AdcParam 3
|
||||
// AdcParam 6
|
||||
// AdcParam 7
|
||||
Settings.adc_param_type = 0;
|
||||
AdcInit();
|
||||
AdcSaveSettings(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AdcParam
|
||||
Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2);
|
||||
if (ADC0_RANGE == my_adc0) {
|
||||
ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4);
|
||||
} else {
|
||||
int value = Settings.adc_param3;
|
||||
uint8_t precision;
|
||||
for (precision = 4; precision > 0; precision--) {
|
||||
if (value % 10) { break; }
|
||||
value /= 10;
|
||||
// AdcParam
|
||||
AdcGetSettings(idx);
|
||||
Response_P(PSTR("{\"" D_CMND_ADCPARAM "%d\":[%d,%d,%d"), idx +1, Adcs.type, Adc[idx].param1, Adc[idx].param2);
|
||||
if (ADC_RANGE == Adc[idx].type) {
|
||||
ResponseAppend_P(PSTR(",%d,%d"), Adc[idx].param3, Adc[idx].param4);
|
||||
} else {
|
||||
int value = Adc[idx].param3;
|
||||
uint8_t precision;
|
||||
for (precision = 4; precision > 0; precision--) {
|
||||
if (value % 10) { break; }
|
||||
value /= 10;
|
||||
}
|
||||
char param3[33];
|
||||
dtostrfd(((double)Adc[idx].param3)/10000, precision, param3);
|
||||
ResponseAppend_P(PSTR(",%s"), param3);
|
||||
}
|
||||
char param3[33];
|
||||
dtostrfd(((double)Settings.adc_param3)/10000, precision, param3);
|
||||
ResponseAppend_P(PSTR(",%s"), param3);
|
||||
ResponseAppend_P(PSTR("]}"));
|
||||
}
|
||||
ResponseAppend_P(PSTR("]}"));
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns02(uint8_t function)
|
||||
{
|
||||
bool Xsns02(uint8_t function) {
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kAdcCommands, AdcCommand);
|
||||
break;
|
||||
case FUNC_INIT:
|
||||
AdcInit();
|
||||
break;
|
||||
default:
|
||||
if ((ADC0_INPUT == my_adc0) ||
|
||||
(ADC0_TEMP == my_adc0) ||
|
||||
(ADC0_LIGHT == my_adc0) ||
|
||||
(ADC0_RANGE == my_adc0) ||
|
||||
(ADC0_CT_POWER == my_adc0)) {
|
||||
if (Adcs.present) {
|
||||
switch (function) {
|
||||
#ifdef USE_RULES
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
|
@ -439,9 +587,6 @@ bool Xsns02(uint8_t function)
|
|||
case FUNC_EVERY_SECOND:
|
||||
AdcEverySecond();
|
||||
break;
|
||||
case FUNC_INIT:
|
||||
AdcInit();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
AdcShow(1);
|
||||
break;
|
||||
|
@ -456,5 +601,4 @@ bool Xsns02(uint8_t function)
|
|||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266
|
||||
#endif // USE_ADC
|
||||
|
|
|
@ -1,573 +0,0 @@
|
|||
/*
|
||||
xsns_02_analog_esp32.ino - ESP32 ADC support for Tasmota
|
||||
|
||||
Copyright (C) 2020 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 ESP32
|
||||
#ifdef USE_ADC
|
||||
/*********************************************************************************************\
|
||||
* ADC support for up to 8 channels on GPIO32 to GPIO39
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_02 2
|
||||
|
||||
#define ANALOG_RESOLUTION 12 // 12 = 4095, 11 = 2047, 10 = 1023
|
||||
#define ANALOG_RANGE 4095 // 4095 = 12, 2047 = 11, 1023 = 10
|
||||
|
||||
#define TO_CELSIUS(x) ((x) - 273.15)
|
||||
#define TO_KELVIN(x) ((x) + 273.15)
|
||||
|
||||
// Parameters for equation
|
||||
#define ANALOG_V33 3.3 // ESP8266 Analog voltage
|
||||
#define ANALOG_T0 TO_KELVIN(25.0) // 25 degrees Celcius in Kelvin (= 298.15)
|
||||
|
||||
// Shelly 2.5 NTC Thermistor
|
||||
// 3V3 --- ANALOG_NTC_BRIDGE_RESISTANCE ---v--- NTC --- Gnd
|
||||
// |
|
||||
// ADC0
|
||||
#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 // NTC Voltage bridge resistor
|
||||
#define ANALOG_NTC_RESISTANCE 10000 // NTC Resistance
|
||||
#define ANALOG_NTC_B_COEFFICIENT 3350 // NTC Beta Coefficient
|
||||
|
||||
// LDR parameters
|
||||
// 3V3 --- LDR ---v--- ANALOG_LDR_BRIDGE_RESISTANCE --- Gnd
|
||||
// |
|
||||
// ADC0
|
||||
#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 // LDR Voltage bridge resistor
|
||||
#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 // Experimental
|
||||
#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 // Experimental
|
||||
|
||||
// CT Based Apparrent Power Measurement Parameters
|
||||
// 3V3 --- R1 ----v--- R1 --- Gnd
|
||||
// |
|
||||
// CT+ CT-
|
||||
// |
|
||||
// ADC0
|
||||
// Default settings for a 20A/1V Current Transformer.
|
||||
// Analog peak to peak range is measured and converted to RMS current using ANALOG_CT_MULTIPLIER
|
||||
#define ANALOG_CT_FLAGS 0 // (uint32_t) reserved for possible future use
|
||||
#define ANALOG_CT_MULTIPLIER 2146 // (uint32_t) Multiplier*100000 to convert raw ADC peak to peak range 0..ANALOG_RANGE to RMS current in Amps. Value of 100000 corresponds to 1
|
||||
#define ANALOG_CT_VOLTAGE 2300 // (int) Convert current in Amps to apparrent power in Watts using voltage in Volts*10. Value of 2200 corresponds to 220V
|
||||
|
||||
#define CT_FLAG_ENERGY_RESET (1 << 0) // Reset energy total
|
||||
|
||||
// Odroid joysticks
|
||||
// ---- Up
|
||||
// 3V3 ---| |------------
|
||||
// |
|
||||
// ---- Dn |--- R10k --- Gnd
|
||||
// 3V3 ---| |--- R10k ---|
|
||||
// |
|
||||
// ADC
|
||||
// Press "Up" will raise ADC to ANALOG_RANGE, Press "Dn" will raise ADC to ANALOG_RANGE/2
|
||||
#define ANALOG_JOYSTICK (ANALOG_RANGE / 3) +100 // Add resistor tolerance
|
||||
|
||||
struct {
|
||||
uint8_t present = 0;
|
||||
uint8_t type = 0;
|
||||
} Adcs;
|
||||
|
||||
struct {
|
||||
float temperature = 0;
|
||||
float current = 0;
|
||||
float energy = 0;
|
||||
uint32_t param1 = 0;
|
||||
uint32_t param2 = 0;
|
||||
int param3 = 0;
|
||||
int param4 = 0;
|
||||
uint32_t previous_millis = 0;
|
||||
uint16_t last_value = 0;
|
||||
uint8_t type = 0;
|
||||
uint8_t pin = 0;
|
||||
} Adc[MAX_ADCS];
|
||||
|
||||
void AdcSaveSettings(uint32_t idx) {
|
||||
char parameters[32];
|
||||
snprintf_P(parameters, sizeof(parameters), PSTR("%d,%d,%d,%d,%d"),
|
||||
Adc[idx].type, Adc[idx].param1, Adc[idx].param2, Adc[idx].param3, Adc[idx].param4);
|
||||
SettingsUpdateText(SET_ADC_PARAM1 + idx, parameters);
|
||||
}
|
||||
|
||||
void AdcGetSettings(uint32_t idx) {
|
||||
char parameters[32];
|
||||
Adcs.type = 0;
|
||||
Adc[idx].param1 = 0;
|
||||
Adc[idx].param2 = 0;
|
||||
Adc[idx].param3 = 0;
|
||||
Adc[idx].param4 = 0;
|
||||
if (strstr(SettingsText(SET_ADC_PARAM1 + idx), ",") != nullptr) {
|
||||
Adcs.type = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 1));
|
||||
Adc[idx].param1 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 2));
|
||||
Adc[idx].param2 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 3));
|
||||
Adc[idx].param3 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 4));
|
||||
Adc[idx].param4 = atoi(subStr(parameters, SettingsText(SET_ADC_PARAM1 + idx), ",", 5));
|
||||
}
|
||||
}
|
||||
|
||||
void AdcInitParams(uint8_t idx) {
|
||||
if ((Adcs.type != Adc[idx].type) || (Adc[idx].param1 > 1000000)) {
|
||||
if (ADC_TEMP == Adc[idx].type) {
|
||||
// Default Shelly 2.5 and 1PM parameters
|
||||
Adc[idx].param1 = ANALOG_NTC_BRIDGE_RESISTANCE;
|
||||
Adc[idx].param2 = ANALOG_NTC_RESISTANCE;
|
||||
Adc[idx].param3 = ANALOG_NTC_B_COEFFICIENT * 10000;
|
||||
}
|
||||
else if (ADC_LIGHT == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_LDR_BRIDGE_RESISTANCE;
|
||||
Adc[idx].param2 = ANALOG_LDR_LUX_CALC_SCALAR;
|
||||
Adc[idx].param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000;
|
||||
}
|
||||
else if (ADC_RANGE == Adc[idx].type) {
|
||||
Adc[idx].param1 = 0;
|
||||
Adc[idx].param2 = ANALOG_RANGE;
|
||||
Adc[idx].param3 = 0;
|
||||
Adc[idx].param4 = 100;
|
||||
}
|
||||
else if (ADC_CT_POWER == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_CT_FLAGS; // (uint32_t) 0
|
||||
Adc[idx].param2 = ANALOG_CT_MULTIPLIER; // (uint32_t) 100000
|
||||
Adc[idx].param3 = ANALOG_CT_VOLTAGE; // (int) 10
|
||||
}
|
||||
else if (ADC_JOY == Adc[idx].type) {
|
||||
Adc[idx].param1 = ANALOG_JOYSTICK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdcAttach(uint8_t pin, uint8_t type) {
|
||||
Adc[Adcs.present].pin = pin;
|
||||
if (adcAttachPin(Adc[Adcs.present].pin)) {
|
||||
Adc[Adcs.present].type = type;
|
||||
// analogSetPinAttenuation(Adc[Adcs.present].pin, ADC_11db); // Default
|
||||
Adcs.present++;
|
||||
}
|
||||
}
|
||||
|
||||
void AdcInit(void) {
|
||||
Adcs.present = 0;
|
||||
for (uint32_t i = 0; i < MAX_ADCS; i++) {
|
||||
if (PinUsed(GPIO_ADC_INPUT, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_INPUT, i), ADC_INPUT);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_TEMP, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_TEMP, i), ADC_TEMP);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_LIGHT, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_LIGHT, i), ADC_LIGHT);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_BUTTON, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_BUTTON, i), ADC_BUTTON);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_BUTTON_INV, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_BUTTON_INV, i), ADC_BUTTON_INV);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_RANGE, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_RANGE, i), ADC_RANGE);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_CT_POWER, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_CT_POWER, i), ADC_CT_POWER);
|
||||
}
|
||||
if (PinUsed(GPIO_ADC_JOY, i)) {
|
||||
AdcAttach(Pin(GPIO_ADC_JOY, i), ADC_JOY);
|
||||
}
|
||||
}
|
||||
if (Adcs.present) {
|
||||
analogSetClockDiv(1); // Default 1
|
||||
analogSetWidth(ANALOG_RESOLUTION); // Default 12 bits (0 - 4095)
|
||||
analogSetAttenuation(ADC_11db); // Default 11db
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
AdcGetSettings(idx);
|
||||
AdcInitParams(idx);
|
||||
AdcSaveSettings(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t AdcRead(uint32_t pin, uint32_t factor) {
|
||||
// factor 1 = 2 samples
|
||||
// factor 2 = 4 samples
|
||||
// factor 3 = 8 samples
|
||||
// factor 4 = 16 samples
|
||||
// factor 5 = 32 samples
|
||||
uint32_t samples = 1 << factor;
|
||||
uint32_t analog = 0;
|
||||
for (uint32_t i = 0; i < samples; i++) {
|
||||
analog += analogRead(pin);
|
||||
delay(1);
|
||||
}
|
||||
analog >>= factor;
|
||||
return analog;
|
||||
}
|
||||
|
||||
#ifdef USE_RULES
|
||||
void AdcEvery250ms(void) {
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
if (ADC_INPUT == Adc[idx].type) {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 5);
|
||||
if ((new_value < Adc[idx].last_value -10) || (new_value > Adc[idx].last_value +10)) {
|
||||
Adc[idx].last_value = new_value;
|
||||
uint16_t value = Adc[idx].last_value / 10;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"A%ddiv10\":%d}}"), idx +1, (value > 99) ? 100 : value);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
}
|
||||
else if (ADC_JOY == Adc[idx].type) {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 1);
|
||||
if (new_value && (new_value != Adc[idx].last_value)) {
|
||||
Adc[idx].last_value = new_value;
|
||||
uint16_t value = new_value / Adc[idx].param1;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"Joy%d\":%d}}"), idx +1, value);
|
||||
XdrvRulesProcess();
|
||||
} else {
|
||||
Adc[idx].last_value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_RULES
|
||||
|
||||
uint16_t AdcGetLux(uint32_t idx) {
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
// Source: https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/
|
||||
double resistorVoltage = ((double)adc / ANALOG_RANGE) * ANALOG_V33;
|
||||
double ldrVoltage = ANALOG_V33 - resistorVoltage;
|
||||
double ldrResistance = ldrVoltage / resistorVoltage * (double)Adc[idx].param1;
|
||||
double ldrLux = (double)Adc[idx].param2 * FastPrecisePow(ldrResistance, (double)Adc[idx].param3 / 10000);
|
||||
|
||||
return (uint16_t)ldrLux;
|
||||
}
|
||||
|
||||
uint16_t AdcGetRange(uint32_t idx) {
|
||||
// formula for calibration: value, fromLow, fromHigh, toLow, toHigh
|
||||
// Example: 514, 632, 236, 0, 100
|
||||
// int( ((<param2> - <analog-value>) / (<param2> - <param1>) ) * (<param3> - <param4>) ) + <param4> )
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
double adcrange = ( ((double)Adc[idx].param2 - (double)adc) / ( ((double)Adc[idx].param2 - (double)Adc[idx].param1)) * ((double)Adc[idx].param3 - (double)Adc[idx].param4) + (double)Adc[idx].param4 );
|
||||
return (uint16_t)adcrange;
|
||||
}
|
||||
|
||||
void AdcGetCurrentPower(uint8_t idx, uint8_t factor) {
|
||||
// factor 1 = 2 samples
|
||||
// factor 2 = 4 samples
|
||||
// factor 3 = 8 samples
|
||||
// factor 4 = 16 samples
|
||||
// factor 5 = 32 samples
|
||||
uint8_t samples = 1 << factor;
|
||||
uint16_t analog = 0;
|
||||
uint16_t analog_min = ANALOG_RANGE;
|
||||
uint16_t analog_max = 0;
|
||||
|
||||
if (0 == Adc[idx].param1) {
|
||||
for (uint32_t i = 0; i < samples; i++) {
|
||||
analog = analogRead(Adc[idx].pin);
|
||||
if (analog < analog_min) {
|
||||
analog_min = analog;
|
||||
}
|
||||
if (analog > analog_max) {
|
||||
analog_max = analog;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
Adc[idx].current = (float)(analog_max-analog_min) * ((float)(Adc[idx].param2) / 100000);
|
||||
}
|
||||
else {
|
||||
analog = AdcRead(Adc[idx].pin, 5);
|
||||
if (analog > Adc[idx].param1) {
|
||||
Adc[idx].current = ((float)(analog) - (float)Adc[idx].param1) * ((float)(Adc[idx].param2) / 100000);
|
||||
}
|
||||
else {
|
||||
Adc[idx].current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float power = Adc[idx].current * (float)(Adc[idx].param3) / 10;
|
||||
uint32_t current_millis = millis();
|
||||
Adc[idx].energy = Adc[idx].energy + ((power * (current_millis - Adc[idx].previous_millis)) / 3600000000);
|
||||
Adc[idx].previous_millis = current_millis;
|
||||
}
|
||||
|
||||
void AdcEverySecond(void) {
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
if (ADC_TEMP == Adc[idx].type) {
|
||||
int adc = AdcRead(Adc[idx].pin, 2);
|
||||
// Steinhart-Hart equation for thermistor as temperature sensor
|
||||
double Rt = (adc * Adc[idx].param1) / (1024.0 * ANALOG_V33 - (double)adc);
|
||||
double BC = (double)Adc[idx].param3 / 10000;
|
||||
double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Adc[idx].param2));
|
||||
Adc[idx].temperature = ConvertTemp(TO_CELSIUS(T));
|
||||
}
|
||||
else if (ADC_CT_POWER == Adc[idx].type) {
|
||||
AdcGetCurrentPower(idx, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdcShowContinuation(bool *jsonflg) {
|
||||
if (*jsonflg) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
} else {
|
||||
ResponseAppend_P(PSTR(",\"ANALOG\":{"));
|
||||
*jsonflg = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AdcShow(bool json) {
|
||||
bool domo_flag[ADC_END] = { false };
|
||||
char adc_name[10]; // ANALOG8
|
||||
|
||||
bool jsonflg = false;
|
||||
for (uint32_t idx = 0; idx < Adcs.present; idx++) {
|
||||
snprintf_P(adc_name, sizeof(adc_name), PSTR("Analog%d"), idx +1);
|
||||
|
||||
switch (Adc[idx].type) {
|
||||
case ADC_INPUT: {
|
||||
uint16_t analog = AdcRead(Adc[idx].pin, 5);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"A%d\":%d"), idx +1, analog);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ANALOG, "", idx +1, analog);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_TEMP: {
|
||||
char temperature[33];
|
||||
dtostrfd(Adc[idx].temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "%d\":%s"), idx +1, temperature);
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_TEMP])) {
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
domo_flag[ADC_TEMP] = true;
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
KnxSensor(KNX_TEMPERATURE, Adc[idx].temperature);
|
||||
#endif // USE_KNX
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_TEMP, adc_name, temperature, TempUnit());
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_LIGHT: {
|
||||
uint16_t adc_light = AdcGetLux(idx);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_ILLUMINANCE "%d\":%d"), idx +1, adc_light);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_LIGHT])) {
|
||||
DomoticzSensor(DZ_ILLUMINANCE, adc_light);
|
||||
domo_flag[ADC_LIGHT] = true;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, adc_name, adc_light);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_RANGE: {
|
||||
uint16_t adc_range = AdcGetRange(idx);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"" D_JSON_RANGE "%d\":%d"), idx +1, adc_range);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_RANGE, adc_name, adc_range);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_CT_POWER: {
|
||||
AdcGetCurrentPower(idx, 5);
|
||||
|
||||
float voltage = (float)(Adc[idx].param3) / 10;
|
||||
char voltage_chr[FLOATSZ];
|
||||
dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
||||
char current_chr[FLOATSZ];
|
||||
dtostrfd(Adc[idx].current, Settings.flag2.current_resolution, current_chr);
|
||||
char power_chr[FLOATSZ];
|
||||
dtostrfd(voltage * Adc[idx].current, Settings.flag2.wattage_resolution, power_chr);
|
||||
char energy_chr[FLOATSZ];
|
||||
dtostrfd(Adc[idx].energy, Settings.flag2.energy_resolution, energy_chr);
|
||||
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"CTEnergy%d\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"),
|
||||
idx +1, energy_chr, power_chr, voltage_chr, current_chr);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && (!domo_flag[ADC_CT_POWER])) {
|
||||
DomoticzSensor(DZ_POWER_ENERGY, power_chr);
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr);
|
||||
DomoticzSensor(DZ_CURRENT, current_chr);
|
||||
domo_flag[ADC_CT_POWER] = true;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr);
|
||||
WSContentSend_PD(HTTP_SNS_CURRENT, current_chr);
|
||||
WSContentSend_PD(HTTP_SNS_POWER, power_chr);
|
||||
WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_JOY: {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 1);
|
||||
uint16_t value = new_value / Adc[idx].param1;
|
||||
if (json) {
|
||||
AdcShowContinuation(&jsonflg);
|
||||
ResponseAppend_P(PSTR("\"Joy%d\":%d"), idx +1, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsonflg) {
|
||||
ResponseJsonEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
const char kAdcCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_ADCPARAM;
|
||||
|
||||
void (* const AdcCommand[])(void) PROGMEM = {
|
||||
&CmndAdcParam };
|
||||
|
||||
void CmndAdcParam(void) {
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_ADCS)) {
|
||||
uint8_t idx = XdrvMailbox.index -1;
|
||||
if (XdrvMailbox.data_len) {
|
||||
if ((ADC_TEMP == XdrvMailbox.payload) ||
|
||||
(ADC_LIGHT == XdrvMailbox.payload) ||
|
||||
(ADC_RANGE == XdrvMailbox.payload) ||
|
||||
(ADC_CT_POWER == XdrvMailbox.payload) ||
|
||||
(ADC_JOY == XdrvMailbox.payload)) {
|
||||
AdcGetSettings(idx);
|
||||
if (ChrCount(XdrvMailbox.data, ",") > 2) { // Process parameter entry
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
// AdcParam 2, 32000, 10000, 3350
|
||||
// AdcParam 3, 10000, 12518931, -1.405
|
||||
// AdcParam 6, 0, ANALOG_RANGE, 0, 100
|
||||
// AdcParam 7, 0, 2146, 0.23
|
||||
// AdcParam 8, 1000, 0, 0
|
||||
Adc[idx].type = XdrvMailbox.payload;
|
||||
Adc[idx].param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
Adc[idx].param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10);
|
||||
if (ADC_RANGE == XdrvMailbox.payload) {
|
||||
Adc[idx].param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10));
|
||||
Adc[idx].param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10));
|
||||
} else {
|
||||
Adc[idx].param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000);
|
||||
}
|
||||
if (ADC_CT_POWER == XdrvMailbox.payload) {
|
||||
if (((1 == Adc[idx].param1) & CT_FLAG_ENERGY_RESET) > 0) {
|
||||
for (uint32_t idx = 0; idx < MAX_ADCS; idx++) {
|
||||
Adc[idx].energy = 0;
|
||||
}
|
||||
Adc[idx].param1 ^= CT_FLAG_ENERGY_RESET; // Cancel energy reset flag
|
||||
}
|
||||
}
|
||||
} else { // Set default values based on current adc type
|
||||
// AdcParam 2
|
||||
// AdcParam 3
|
||||
// AdcParam 6
|
||||
// AdcParam 7
|
||||
// AdcParam 8
|
||||
Adcs.type = 0;
|
||||
AdcInitParams(idx);
|
||||
}
|
||||
AdcSaveSettings(idx);
|
||||
}
|
||||
}
|
||||
|
||||
// AdcParam
|
||||
AdcGetSettings(idx);
|
||||
Response_P(PSTR("{\"" D_CMND_ADCPARAM "%d\":[%d,%d,%d"), idx +1, Adcs.type, Adc[idx].param1, Adc[idx].param2);
|
||||
if (ADC_RANGE == Adc[idx].type) {
|
||||
ResponseAppend_P(PSTR(",%d,%d"), Adc[idx].param3, Adc[idx].param4);
|
||||
} else {
|
||||
int value = Adc[idx].param3;
|
||||
uint8_t precision;
|
||||
for (precision = 4; precision > 0; precision--) {
|
||||
if (value % 10) { break; }
|
||||
value /= 10;
|
||||
}
|
||||
char param3[33];
|
||||
dtostrfd(((double)Adc[idx].param3)/10000, precision, param3);
|
||||
ResponseAppend_P(PSTR(",%s"), param3);
|
||||
}
|
||||
ResponseAppend_P(PSTR("]}"));
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns02(uint8_t function) {
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kAdcCommands, AdcCommand);
|
||||
break;
|
||||
case FUNC_INIT:
|
||||
AdcInit();
|
||||
break;
|
||||
default:
|
||||
if (Adcs.present) {
|
||||
switch (function) {
|
||||
#ifdef USE_RULES
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
AdcEvery250ms();
|
||||
break;
|
||||
#endif // USE_RULES
|
||||
case FUNC_EVERY_SECOND:
|
||||
AdcEverySecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
AdcShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
AdcShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_ADC
|
||||
#endif // ESP32
|
Loading…
Reference in New Issue