diff --git a/code/espurna/config/all.h b/code/espurna/config/all.h index c1c08c54..843288c9 100644 --- a/code/espurna/config/all.h +++ b/code/espurna/config/all.h @@ -37,6 +37,6 @@ #include "general.h" #include "defaults.h" #include "deprecated.h" -#include "dependencies.h" #include "sensors.h" +#include "dependencies.h" #include "webui.h" diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index f5e92627..d0c9fdbb 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -191,39 +191,40 @@ // Features (values below are non-default values) //-------------------------------------------------------------------------------- -//#define ALEXA_SUPPORT 0 -//#define API_SUPPORT 0 -//#define BUTTON_SUPPORT 0 -//#define DEBUG_SERIAL_SUPPORT 0 -//#define DEBUG_TELNET_SUPPORT 0 -//#define DEBUG_UDP_SUPPORT 1 -//#define DEBUG_WEB_SUPPORT 0 -//#define DOMOTICZ_SUPPORT 0 -//#define ENCODER_SUPPORT 1 -//#define HOMEASSISTANT_SUPPORT 0 -//#define I2C_SUPPORT 1 -//#define INFLUXDB_SUPPORT 1 -//#define IR_SUPPORT 1 -//#define LED_SUPPORT 0 -//#define LLMNR_SUPPORT 1 -//#define MDNS_SERVER_SUPPORT 0 -//#define MQTT_SUPPORT 0 -//#define NETBIOS_SUPPORT 1 -//#define NOFUSS_SUPPORT 1 -//#define NTP_SUPPORT 0 -//#define OTA_ARDUINOOTA_SUPPORT 1 -//#define RFM69_SUPPORT 1 -//#define RFB_SUPPORT 1 -//#define RPN_RULES_SUPPORT 0 -//#define SCHEDULER_SUPPORT 0 -//#define SPIFFS_SUPPORT 1 -//#define SSDP_SUPPORT 1 -//#define TELNET_SUPPORT 0 -//#define TERMINAL_SUPPORT 0 -//#define THINGSPEAK_SUPPORT 0 -//#define TUYA_SUPPORT 0 -//#define UART_MQTT_SUPPORT 1 -//#define WEB_SUPPORT 0 +//#define ALEXA_SUPPORT 0 +//#define API_SUPPORT 0 +//#define BUTTON_SUPPORT 0 +//#define DEBUG_SERIAL_SUPPORT 0 +//#define DEBUG_TELNET_SUPPORT 0 +//#define DEBUG_UDP_SUPPORT 1 +//#define DEBUG_WEB_SUPPORT 0 +//#define DOMOTICZ_SUPPORT 0 +//#define ENCODER_SUPPORT 1 +//#define HOMEASSISTANT_SUPPORT 0 +//#define I2C_SUPPORT 1 +//#define INFLUXDB_SUPPORT 1 +//#define IR_SUPPORT 1 +//#define LED_SUPPORT 0 +//#define LLMNR_SUPPORT 1 +//#define MDNS_SERVER_SUPPORT 0 +//#define MQTT_SUPPORT 0 +//#define NETBIOS_SUPPORT 1 +//#define NOFUSS_SUPPORT 1 +//#define NTP_SUPPORT 0 +//#define OTA_ARDUINOOTA_SUPPORT 1 +//#define RFM69_SUPPORT 1 +//#define RFB_SUPPORT 1 +//#define RPN_RULES_SUPPORT 0 +//#define SCHEDULER_SUPPORT 0 +//#define SPIFFS_SUPPORT 1 +//#define SSDP_SUPPORT 1 +//#define TELNET_SUPPORT 0 +//#define TERMINAL_SUPPORT 0 +//#define TERMINAL_SERIAL_SUPPORT 0 +//#define THINGSPEAK_SUPPORT 0 +//#define TUYA_SUPPORT 0 +//#define UART_MQTT_SUPPORT 1 +//#define WEB_SUPPORT 0 //-------------------------------------------------------------------------------- // Sensors (values below are non-default values) diff --git a/code/espurna/config/defaults.h b/code/espurna/config/defaults.h index 7555a41e..b24aaf20 100644 --- a/code/espurna/config/defaults.h +++ b/code/espurna/config/defaults.h @@ -1400,6 +1400,94 @@ #define TUYA_SW8_DPID 0 #endif +// ----------------------------------------------------------------------------- +// UART +// ----------------------------------------------------------------------------- + +#ifndef UART1_BAUDRATE +#define UART1_BAUDRATE 115200 +#endif + +#ifndef UART1_TX_PIN +#define UART1_TX_PIN 1 +#endif + +#ifndef UART1_RX_PIN +#define UART1_RX_PIN 3 +#endif + +#ifndef UART1_DATA_BITS +#define UART1_DATA_BITS 8 +#endif + +#ifndef UART1_PARITY +#define UART1_PARITY None +#endif + +#ifndef UART1_STOP_BITS +#define UART1_STOP_BITS 1 +#endif + +#ifndef UART1_INVERT +#define UART1_INVERT 0 +#endif + +#ifndef UART2_BAUDRATE +#define UART2_BAUDRATE 115200 +#endif + +#ifndef UART2_TX_PIN +#define UART2_TX_PIN GPIO_NONE +#endif + +#ifndef UART2_RX_PIN +#define UART2_RX_PIN GPIO_NONE +#endif + +#ifndef UART2_DATA_BITS +#define UART2_DATA_BITS 8 +#endif + +#ifndef UART2_PARITY +#define UART2_PARITY None +#endif + +#ifndef UART2_STOP_BITS +#define UART2_STOP_BITS 1 +#endif + +#ifndef UART2_INVERT +#define UART2_INVERT 0 +#endif + +#ifndef UART3_BAUDRATE +#define UART3_BAUDRATE 115200 +#endif + +#ifndef UART3_TX_PIN +#define UART3_TX_PIN GPIO_NONE +#endif + +#ifndef UART3_RX_PIN +#define UART3_RX_PIN GPIO_NONE +#endif + +#ifndef UART3_DATA_BITS +#define UART3_DATA_BITS 8 +#endif + +#ifndef UART3_PARITY +#define UART3_PARITY None +#endif + +#ifndef UART3_STOP_BITS +#define UART3_STOP_BITS 1 +#endif + +#ifndef UART3_INVERT +#define UART3_INVERT 0 +#endif + // ----------------------------------------------------------------------------- // General // ----------------------------------------------------------------------------- diff --git a/code/espurna/config/dependencies.h b/code/espurna/config/dependencies.h index 09c46db8..0c85ede9 100644 --- a/code/espurna/config/dependencies.h +++ b/code/espurna/config/dependencies.h @@ -30,14 +30,34 @@ #if UART_MQTT_SUPPORT #undef MQTT_SUPPORT -#define MQTT_SUPPORT 1 // UART<->MQTT requires MQTT and no serial debug +#define MQTT_SUPPORT 1 // UART<->MQTT requires MQTT and no serial debug & terminal +#undef UART_SUPPORT +#define UART_SUPPORT 1 #undef DEBUG_SERIAL_SUPPORT -#define DEBUG_SERIAL_SUPPORT 0 // TODO: compare UART_MQTT_PORT with DEBUG_PORT? (as strings) +#define DEBUG_SERIAL_SUPPORT 0 +#undef TERMINAL_SERIAL_SUPPORT +#define TERMINAL_SERIAL_SUPPORT 0 +#endif + +#if RELAY_PROVIDER_STM_SUPPORT || RELAY_PROVIDER_DUAL_SUPPORT +#undef UART_SUPPORT +#define UART_SUPPORT 1 +#undef DEBUG_SERIAL_SUPPORT +#define DEBUG_SERIAL_SUPPORT 0 +#undef TERMINAL_SERIAL_SUPPORT +#define TERMINAL_SERIAL_SUPPORT 0 +#endif + +#if not UART_SUPPORT +#undef DEBUG_SERIAL_SUPPORT +#define DEBUG_SERIAL_SUPPORT 0 +#undef TERMINAL_SERIAL_SUPPORT +#define TERMINAL_SERIAL_SUPPORT 0 #endif #if ALEXA_SUPPORT #undef RELAY_SUPPORT -#define RELAY_SUPPORT 1 // and switches +#define RELAY_SUPPORT 1 // alexa needs some switches support to work #endif #if RPN_RULES_SUPPORT @@ -196,3 +216,62 @@ #undef ADC_MODE_VALUE #define ADC_MODE_VALUE ADC_TOUT #endif + +//------------------------------------------------------------------------------ +// RFBRIDGE EFM provider needs serial support +#if RFB_PROVIDER == RFB_PROVIDER_EFM8BB1 +#undef UART_SUPPORT +#define UART_SUPPORT 1 +#endif + +//------------------------------------------------------------------------------ +// Forcibly disable UART logger and terminal, these modules usually +// are expecting to work with the port exclusivelly +// (an so we could more easily describe things in hardware .h) +#if (\ + ((CSE7766_SUPPORT) && (CSE7766_PORT == DEBUG_SERIAL_PORT)) || \ + ((EZOPH_SUPPORT) && (EZOPH_PORT == DEBUG_SERIAL_PORT)) || \ + ((KINGART_CURTAIN_SUPPORT) && (KINGART_CURTAIN_PORT == DEBUG_SERIAL_PORT)) || \ + ((MHZ19_SUPPORT) && (MHZ19_PORT == DEBUG_SERIAL_PORT)) || \ + ((PM1006_SUPPORT) && (PM1006_PORT == DEBUG_SERIAL_PORT)) || \ + ((PMSX003_SUPPORT) && (PMSX003_PORT == DEBUG_SERIAL_PORT)) || \ + ((PZEM004TV30_SUPPORT) && (PZEM004TV30_PORT == DEBUG_SERIAL_PORT)) || \ + ((PZEM004T_SUPPORT) && (PZEM004T_PORT == DEBUG_SERIAL_PORT)) || \ + ((RELAY_PROVIDER_DUAL_SUPPORT) && (RELAY_PROVIDER_DUAL_PORT == DEBUG_SERIAL_PORT)) || \ + ((RELAY_PROVIDER_STM_SUPPORT) && (RELAY_PROVIDER_STM_PORT == DEBUG_SERIAL_PORT)) || \ + ((RFB_PROVIDER == RFB_PROVIDER_EFM8BB1) && (RFB_PORT == DEBUG_SERIAL_PORT)) || \ + ((SDS011_SUPPORT) && (SDS011_PORT == DEBUG_SERIAL_PORT)) || \ + ((SENSEAIR_SUPPORT) && (SENSEAIR_PORT == DEBUG_SERIAL_PORT)) || \ + ((SM300D2_SUPPORT) && (SM300D2_PORT == DEBUG_SERIAL_PORT)) || \ + ((T6613_SUPPORT) && (T6613_PORT == DEBUG_SERIAL_PORT)) || \ + ((TUYA_SUPPORT) && (TUYA_PORT == DEBUG_SERIAL_PORT)) || \ + ((V9261F_SUPPORT) && (V9261F_PORT == DEBUG_SERIAL_PORT)) || \ + (defined(FOXEL_LIGHTFOX_DUAL) && (LIGHTFOX_PORT == DEBUG_SERIAL_PORT)) \ +) +#undef DEBUG_SERIAL_SUPPORT +#define DEBUG_SERIAL_SUPPORT 0 +#endif + +#if (\ + ((CSE7766_SUPPORT) && (CSE7766_PORT == TERMINAL_SERIAL_PORT)) || \ + ((EZOPH_SUPPORT) && (EZOPH_PORT == TERMINAL_SERIAL_PORT)) || \ + ((KINGART_CURTAIN_SUPPORT) && (KINGART_CURTAIN_PORT == TERMINAL_SERIAL_PORT)) || \ + ((MHZ19_SUPPORT) && (MHZ19_PORT == TERMINAL_SERIAL_PORT)) || \ + ((PM1006_SUPPORT) && (PM1006_PORT == TERMINAL_SERIAL_PORT)) || \ + ((PMSX003_SUPPORT) && (PMSX003_PORT == TERMINAL_SERIAL_PORT)) || \ + ((PZEM004TV30_SUPPORT) && (PZEM004TV30_PORT == TERMINAL_SERIAL_PORT)) || \ + ((PZEM004T_SUPPORT) && (PZEM004T_PORT == TERMINAL_SERIAL_PORT)) || \ + ((RELAY_PROVIDER_DUAL_SUPPORT) && (RELAY_PROVIDER_DUAL_PORT == TERMINAL_SERIAL_PORT)) || \ + ((RELAY_PROVIDER_STM_SUPPORT) && (RELAY_PROVIDER_STM_PORT == TERMINAL_SERIAL_PORT)) || \ + ((RFB_PROVIDER == RFB_PROVIDER_EFM8BB1) && (RFB_PORT == TERMINAL_SERIAL_PORT)) || \ + ((SDS011_SUPPORT) && (SDS011_PORT == TERMINAL_SERIAL_PORT)) || \ + ((SENSEAIR_SUPPORT) && (SENSEAIR_PORT == TERMINAL_SERIAL_PORT)) || \ + ((SM300D2_SUPPORT) && (SM300D2_PORT == TERMINAL_SERIAL_PORT)) || \ + ((T6613_SUPPORT) && (T6613_PORT == TERMINAL_SERIAL_PORT)) || \ + ((TUYA_SUPPORT) && (TUYA_PORT == TERMINAL_SERIAL_PORT)) || \ + ((V9261F_SUPPORT) && (V9261F_PORT == TERMINAL_SERIAL_PORT)) || \ + (defined(FOXEL_LIGHTFOX_DUAL) && (LIGHTFOX_PORT == TERMINAL_SERIAL_PORT)) \ +) +#undef TERMINAL_SERIAL_SUPPORT +#define TERMINAL_SERIAL_SUPPORT 0 +#endif diff --git a/code/espurna/config/deprecated.h b/code/espurna/config/deprecated.h index 5a62f05b..01c984e3 100644 --- a/code/espurna/config/deprecated.h +++ b/code/espurna/config/deprecated.h @@ -100,8 +100,8 @@ #endif #ifdef CSE7766_PIN -#warning "CSE7766_PIN is deprecated! Please use CSE7766_RX_PIN instead" -#define CSE7766_RX_PIN CSE7766_PIN +#warning "CSE7766_PIN is deprecated! Please use UART[1-3]_RX_PIN" +#define UART1_RX_PIN CSE7766_PIN #endif #ifdef WIFI_FALLBACK_APMODE @@ -170,3 +170,8 @@ #define SENSOR_REAL_TIME_VALUES API_REAL_TIME_VALUES #warning "API_REAL_TIME_VALUES is deprecated! Please use SENSOR_REAL_TIME_VALUES" #endif + +#ifdef SERIAL_BAUDRATE +#warning "SERIAL_BAUDRATE is deprecated! Please use UART[1-3]_BAUDRATE" +#define UART1_BAUDRATE SERIAL_BAUDRATE +#endif diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 473c9572..785ff829 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -59,12 +59,8 @@ #define DEBUG_SERIAL_SUPPORT 1 // Enable serial debug log #endif -#ifndef DEBUG_PORT -#define DEBUG_PORT Serial // Default debugging port -#endif - -#ifndef SERIAL_BAUDRATE -#define SERIAL_BAUDRATE 115200 // Default baudrate +#ifndef DEBUG_SERIAL_PORT +#define DEBUG_SERIAL_PORT 1 // Default debugging port #endif #ifndef DEBUG_ADD_TIMESTAMP @@ -72,22 +68,6 @@ // (in millis overflowing every 1000 seconds) #endif -// Second serial port (used for RX) - -#ifndef SERIAL_RX_ENABLED -#define SERIAL_RX_ENABLED 0 // Secondary serial port for RX -#endif - -#ifndef SERIAL_RX_PORT -#define SERIAL_RX_PORT Serial // This setting is usually defined - // in the hardware.h file for those - // boards that require it -#endif - -#ifndef SERIAL_RX_BAUDRATE -#define SERIAL_RX_BAUDRATE 115200 // Default baudrate -#endif - //------------------------------------------------------------------------------ // UDP debug log @@ -175,16 +155,16 @@ //------------------------------------------------------------------------------ #ifndef TERMINAL_SUPPORT -#define TERMINAL_SUPPORT 1 // Enable terminal commands (0.97Kb) +#define TERMINAL_SUPPORT 1 // Enable terminal commands (0.97Kb) #endif #ifndef TERMINAL_SERIAL_SUPPORT -#define TERMINAL_SERIAL_SUPPORT 1 // Enable terminal over UART +#define TERMINAL_SERIAL_SUPPORT 1 // Enable terminal over UART #endif #ifndef TERMINAL_SERIAL_PORT -#define TERMINAL_SERIAL_PORT Serial // Use specific 'global' Arduino HardwareSerial object - // (UART0 by default) +#define TERMINAL_SERIAL_PORT 1 // Use specific port configured as UART#_PORT + // (first port by default) #endif #ifndef TERMINAL_SERIAL_BUFFER_SIZE @@ -389,11 +369,19 @@ #define RELAY_PROVIDER_STM_SUPPORT 0 #endif +#ifndef RELAY_PROVIDER_STM_PORT +#define RELAY_PROVIDER_STM_PORT 1 +#endif + // Sonoff Dual, using serial protocol #ifndef RELAY_PROVIDER_DUAL_SUPPORT #define RELAY_PROVIDER_DUAL_SUPPORT 0 #endif +#ifndef RELAY_PROVIDER_DUAL_PORT +#define RELAY_PROVIDER_DUAL_PORT 1 +#endif + // Default boot mode: 0 means OFF, 1 ON and 2 whatever was before #ifndef RELAY_BOOT_MODE #define RELAY_BOOT_MODE RELAY_BOOT_OFF @@ -883,6 +871,20 @@ #define NOFUSS_INTERVAL 3600000 // Check for updates every hour #endif +// ----------------------------------------------------------------------------- +// UART +// ----------------------------------------------------------------------------- + +#ifndef UART_SUPPORT +#define UART_SUPPORT 1 +#endif + +#ifndef UART_SOFTWARE_SUPPORT +#define UART_SOFTWARE_SUPPORT 0 // (optional) allows to set TX and RX pins + // to values other than just 1, 2, 3, 13 or 15 + // which by default use hardware UART +#endif + // ----------------------------------------------------------------------------- // UART <-> MQTT // ----------------------------------------------------------------------------- @@ -891,30 +893,8 @@ #define UART_MQTT_SUPPORT 0 // Not enabled by default #endif -#ifndef UART_MQTT_BAUDRATE -#define UART_MQTT_BAUDRATE 115200 -#endif - -#ifndef UART_MQTT_CONFIG -#define UART_MQTT_CONFIG SERIAL_8N1 // Arduino-specific serial configuration - // 8bit, no parity bit, stop 1bit by default - // (note that software serial config is prefixed with SW) -#endif - -#ifndef UART_MQTT_SOFTWARE_SERIAL -#define UART_MQTT_SOFTWARE_SERIAL 0 // Enable when hardware port needs to be replaced by a software one - // (*not recommended* for full-duplex communication, it is possible - // to lose data due to timing constraints) - // Depends on TX and RX setting below and *will* use hardware - // port when using known pins like 1 and 3, or 13 and 15 -#endif - -#ifndef UART_MQTT_TX_PIN -#define UART_MQTT_TX_PIN 1 -#endif - -#ifndef UART_MQTT_RX_PIN -#define UART_MQTT_RX_PIN 3 +#ifndef UART_MQTT_PORT +#define UART_MQTT_PORT 1 #endif #ifndef UART_MQTT_BUFFER_SIZE @@ -1491,8 +1471,12 @@ #define RFB_PROVIDER RFB_PROVIDER_RCSWITCH #endif +#ifndef RFB_PORT +#define RFB_PORT 1 // If EFM is enabled, use this UART port +#endif + #ifndef RFB_RX_PIN -#define RFB_RX_PIN GPIO_NONE +#define RFB_RX_PIN GPIO_NONE // If RCSWITCH is enabled, use these pins #endif #ifndef RFB_TX_PIN @@ -1712,8 +1696,8 @@ #define TUYA_SUPPORT 0 #endif -#ifndef TUYA_SERIAL -#define TUYA_SERIAL Serial +#ifndef TUYA_PORT +#define TUYA_PORT 1 #endif #ifndef TUYA_FILTER_ENABLED @@ -1777,6 +1761,26 @@ // Clamp duty value, prevent 100% power #endif +// ============================================================================= +// Curtain hardware support +// ============================================================================= + +#ifndef KINGART_CURTAIN_SUPPORT +#define KINGART_CURTAIN_SUPPORT 0 +#endif + +#ifndef KINGART_CURTAIN_PORT +#define KINGART_CURTAIN_PORT 1 +#endif + +#ifndef KINGART_CURTAIN_BUFFER_SIZE +#define KINGART_CURTAIN_BUFFER_SIZE 128 +#endif + +#ifndef KINGART_CURTAIN_TERMINATION +#define KINGART_CURTAIN_TERMINATION '\e' // Termination character after each message +#endif + // ============================================================================= // Configuration helpers to help detect features // ============================================================================= diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 6c26d2fd..f6180d0e 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -72,6 +72,7 @@ #define SENSOR_SUPPORT 0 #define TERMINAL_SERIAL_SUPORT 0 #define THINGSPEAK_SUPPORT 0 + #define UART_SUPPORT 0 #define WEB_SUPPORT 0 #define DEBUG_TELNET_SUPPORT 1 @@ -111,6 +112,7 @@ #define SENSOR_SUPPORT 0 #define TERMINAL_SERIAL_SUPORT 0 #define THINGSPEAK_SUPPORT 0 + #define UART_SUPPORT 0 // Small webpage to upload the .bin #define MDNS_SERVER_SUPPORT 0 @@ -569,14 +571,19 @@ #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 + // Sensor uses UART + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 // CSE7766 #ifndef CSE7766_SUPPORT #define CSE7766_SUPPORT 1 #endif - #define CSE7766_RX_PIN 3 + + #define CSE7766_PORT 1 #elif defined(ITEAD_SONOFF_POW_R3) @@ -597,26 +604,33 @@ #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 + // Sensor uses UART0 + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 // CSE7766 #ifndef CSE7766_SUPPORT #define CSE7766_SUPPORT 1 #endif - #define CSE7766_RX_PIN 3 #elif defined(ITEAD_SONOFF_DUAL) // Info #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_DUAL" - #define SERIAL_BAUDRATE 19230 // LEDs #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 + // Device uses serial port to control relays + #define UART1_BAUDRATE 19230 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 + // Relays #define RELAY_PROVIDER_DUAL_SUPPORT 1 @@ -627,9 +641,6 @@ // "Buttons" are attached to a secondary MCU and RELAY_PROVIDER_DUAL handles that #define BUTTON_PROVIDER_GPIO_SUPPORT 0 - // Conflicts with relay operation - #define DEBUG_SERIAL_SUPPORT 0 - #elif defined(ITEAD_SONOFF_DUAL_R2) #define MANUFACTURER "ITEAD" @@ -852,18 +863,15 @@ #define RFB_SUPPORT 1 - // When using un-modified harware, ESPurna communicates with the secondary - // MCU EFM8BB1 via UART at 19200 bps so we need to change the speed of - // the port and remove UART noise on serial line + // When using un-modified harware, we communicate with EFM8BB1 MCU + // using the UART connection (needs to be configured to 19200 bps) #ifndef RFB_PROVIDER #define RFB_PROVIDER RFB_PROVIDER_EFM8BB1 #endif - #ifndef DEBUG_SERIAL_SUPPORT - #define DEBUG_SERIAL_SUPPORT 0 - #endif - - #define SERIAL_BAUDRATE 19200 + #define UART1_BAUDRATE 19200 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 // Only used when RFB_PROVIDER is RCSWITCH #define RFB_RX_PIN 4 @@ -1038,12 +1046,15 @@ #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 + // Sensor uses UART0 + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 // CSE7766 #define CSE7766_SUPPORT 1 - #define CSE7766_RX_PIN 3 #elif defined(ITEAD_SONOFF_S31_LITE) @@ -1434,7 +1445,7 @@ #define DEVICE "ZJ_WFMN_C_11" #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER - // Buttons + // Buttons #define BUTTON1_PIN 0 #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH #define BUTTON1_RELAY 1 @@ -1493,8 +1504,10 @@ #define MANUFACTURER "HUACANXING" #define DEVICE "H801" #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER - #define DEBUG_PORT Serial1 - #define SERIAL_RX_ENABLED 1 + + // Debug + #define UART1_TX_PIN 2 + #define UART2_RX_PIN GPIO_NONE // LEDs #define LED1_PIN 5 @@ -1513,8 +1526,10 @@ #define MANUFACTURER "HUACANXING" #define DEVICE "H802" #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER - #define DEBUG_PORT Serial1 - #define SERIAL_RX_ENABLED 1 + + // Debug + #define UART1_TX_PIN 2 + #define UART2_RX_PIN GPIO_NONE // Light #define LIGHT_CH1_PIN 12 // RED @@ -1749,8 +1764,16 @@ // V9261F #define V9261F_SUPPORT 1 - #define V9261F_PIN 2 - #define V9261F_PIN_INVERSE 1 + + // UART only reads data + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 + #define UART1_INVERSE 1 + + #define V9261F_PORT 1 // ----------------------------------------------------------------------------- // ECH1560 @@ -1779,10 +1802,23 @@ #define MANUFACTURER "GENERIC" #define DEVICE "PZEM004T" - #define PZEM004T_SUPPORT 1 + #define PZEM004T_SUPPORT 1 - #define ALEXA_SUPPORT 0 - #define DEBUG_SERIAL_SUPPORT 0 + #define ALEXA_SUPPORT 0 + +// ----------------------------------------------------------------------------- +// PZEM004TV30 +// ----------------------------------------------------------------------------- + +#elif defined(GENERIC_PZEM004TV30) + + // Info + #define MANUFACTURER "GENERIC" + #define DEVICE "PZEM004TV30" + + #define PZEM004TV30_SUPPORT 1 + + #define ALEXA_SUPPORT 0 // ----------------------------------------------------------------------------- // ESP-01 generic esp8266 board with 512 kB flash @@ -1839,10 +1875,10 @@ // DS18B20 #ifndef DALLAS_SUPPORT - #define DALLAS_SUPPORT 1 + #define DALLAS_SUPPORT 1 #endif - #define DALLAS_PIN 2 - #define DALLAS_UPDATE_INTERVAL 5000 + #define DALLAS_PIN 2 + #define DALLAS_UPDATE_INTERVAL 5000 #define TEMPERATURE_MIN_CHANGE 1.0 // ----------------------------------------------------------------------------- @@ -2000,7 +2036,7 @@ // LEDs #define LED1_PIN 4 //BLUE #define LED1_PIN_INVERSE 0 - #define LED2_PIN 5 //RED + #define LED2_PIN 5 //RED #define LED2_PIN_INVERSE 1 // ----------------------------------------------------------------------------- @@ -2183,11 +2219,17 @@ #define MANUFACTURER "STM_RELAY" #define DEVICE "2CH" + // UART + #define UART_SUPPORT 1 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 + // Relays #define RELAY_PROVIDER_STM_SUPPORT 1 + #define RELAY_PROVIDER_STM_PORT 1 - #define RELAY1_PROVIDER RELAY_PROVIDER_STM - #define RELAY2_PROVIDER RELAY_PROVIDER_STM + #define RELAY1_PROVIDER RELAY_PROVIDER_STM + #define RELAY2_PROVIDER RELAY_PROVIDER_STM // Make sure we space out serial writes when relays are in sync. ref: // - https://github.com/xoseperez/espurna/issues/1130 @@ -2195,10 +2237,6 @@ // - https://github.com/xoseperez/espurna/pull/1520 #define RELAY_DELAY_INTERLOCK 100 - // Remove UART noise on serial line - // (or use `#define DEBUG_PORT Serial1` instead) - #define DEBUG_SERIAL_SUPPORT 0 - // ----------------------------------------------------------------------------- // Tonbux Powerstrip02 // ----------------------------------------------------------------------------- @@ -2209,6 +2247,9 @@ #define MANUFACTURER "TONBUX" #define DEVICE "POWERSTRIP02" + // Disable UART noise since this board uses GPIO3 + #define UART_SUPPORT 0 + // Buttons #define BUTTON1_PIN 5 #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH @@ -2314,7 +2355,7 @@ #define HLW8012_VOLTAGE_R_UP ( 2 * 1000000 ) // Upstream voltage resistor // LED1 on RX pin - #define DEBUG_SERIAL_SUPPORT 1 + #define UART1_RX_PIN GPIO_NONE // ----------------------------------------------------------------------------- // Maxcio W-DE004 @@ -2417,6 +2458,9 @@ #define MANUFACTURER "YIDIAN" #define DEVICE "XSSSA05" + // Disable UART noise since this board uses GPIO3 + #define UART_SUPPORT 0 + // Buttons #define BUTTON1_PIN 13 #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH @@ -2748,9 +2792,8 @@ #define MANUFACTURER "ZHILDE" #define DEVICE "44EU_W" - // Based on the reporter, this product uses GPIO1 and 3 for the button - // and onboard LED, so hardware serial should be disabled... - #define DEBUG_SERIAL_SUPPORT 0 + // Disable UART noise since this board uses GPIO1 and GPIO3 + #define UART_SUPPORT 0 // Buttons #define BUTTON1_PIN 3 @@ -2784,7 +2827,7 @@ // Based on https://templates.blakadder.com/ZLD64-EU-W.html , // This product uses GPIO1 for LED and 3 for the button, so hardware serial should be disabled... - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 #define BUTTON1_PIN 3 #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_SET_PULLUP | BUTTON_DEFAULT_HIGH @@ -3048,7 +3091,7 @@ #define DEVICE "ZLD_34EU" // Disable UART noise since this board uses GPIO3 - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 // Buttons #define BUTTON1_PIN 16 @@ -3086,7 +3129,6 @@ #define LED3_RELAY 3 #define LED4_RELAY 4 - // ----------------------------------------------------------------------------- // Bruno Horta's OnOfre // https://www.bhonofre.pt/ @@ -3205,7 +3247,7 @@ #define HLW8012_INTERRUPT_ON FALLING // BUTTON1 and LED1 are using Serial pins - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 // ----------------------------------------------------------------------------- // Similar to both devices above but also with switchable USB ports @@ -3240,14 +3282,19 @@ #define LED2_MODE LED_MODE_FINDME #define LED2_RELAY 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 + // Sensor works through serial port + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 // CSE7766 #ifndef CSE7766_SUPPORT - #define CSE7766_SUPPORT 1 + #define CSE7766_SUPPORT 1 #endif - #define CSE7766_RX_PIN 3 + + #define CSE7766_PORT 1 // ----------------------------------------------------------------------------- // Teckin SP21 @@ -3272,7 +3319,6 @@ #define LED1_PIN 2 #define LED1_PIN_INVERSE 1 - // ----------------------------------------------------------------------------- // Teckin SP22 v1.4 - v1.6 // ----------------------------------------------------------------------------- @@ -3315,7 +3361,7 @@ #define HLW8012_INTERRUPT_ON FALLING // BUTTON1 and LED1 are using Serial pins - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 // ----------------------------------------------------------------------------- // Teckin SP22 v1.4 - v1.6 @@ -3432,7 +3478,7 @@ #define LED1_PIN_INVERSE 1 // LED1 is using TX pin - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 // ---------------------------------------------------------------------------------------- // Power socket 16A similar to BLITZWOLF_BWSHPX but button pin differs @@ -3478,8 +3524,8 @@ #define HLW8012_INTERRUPT_ON FALLING // ---------------------------------------------------------------------------------------- -// Power strip 15A - 3 Sockets + 3 USB ports -// This device uses just one digital button (main one). All other three buttons are connected +// Power strip 15A - 3 Sockets + 3 USB ports +// This device uses just one digital button (main one). All other three buttons are connected // to the ADC pin via resistors with different values. This approach is known under the name of // "Resistor Ladder" - https://en.wikipedia.org/wiki/Resistor_ladder // https://www.amazon.de/-/en/gp/product/B085XXCPRD @@ -3491,14 +3537,10 @@ #define MANUFACTURER "GOSUND" #define DEVICE "P1" - //Enable this to view buttons analog level. //Or, use adc terminal command //#define ANALOG_SUPPORT 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 - // Buttons #define BUTTON_PROVIDER_GPIO_SUPPORT 1 #define BUTTON_PROVIDER_ANALOG_SUPPORT 1 @@ -3531,11 +3573,19 @@ // LEDs #define LED1_PIN 2 - #define LED1_PIN_INVERSE 1 + #define LED1_PIN_INVERSE 1 + + // Sensor uses UART0 + #define UART_SUPPORT 1 + + #define UART1_BAUDRATE 4800 + #define UART1_TX_PIN GPIO_NONE + #define UART1_RX_PIN 3 // CSE7766 #define CSE7766_SUPPORT 1 - #define CSE7766_RX_PIN 3 + + #define CSE7766_PORT 1 // ---------------------------------------------------------------------------------------- // Homecube 16A is similar but some pins differ and it also has RGB LEDs @@ -3619,9 +3669,6 @@ #define LED2_MODE LED_MODE_FINDME #define LED2_RELAY 1 - // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 - // HJL01 / BL0937 #ifndef HLW8012_SUPPORT #define HLW8012_SUPPORT 1 @@ -3630,6 +3677,9 @@ #define HLW8012_CF1_PIN 14 #define HLW8012_CF_PIN 5 + // Disable UART noise + #define UART_SUPPORT 0 + #define HLW8012_SEL_CURRENT LOW #define HLW8012_CURRENT_RATIO 25740 #define HLW8012_VOLTAGE_RATIO 313400 @@ -4342,7 +4392,12 @@ // Info #define MANUFACTURER "FOXEL" #define DEVICE "LIGHTFOX_DUAL" - #define SERIAL_BAUDRATE 19200 + + #define UART1_BAUDRATE 19200 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 + + #define LIGHTFOX_PORT 1 // Relays #define LIGHTFOX_RELAYS 2 @@ -4360,9 +4415,6 @@ #define BUTTON3_RELAY 2 #define BUTTON4_RELAY 1 - // Conflicts with relay operation - #define DEBUG_SERIAL_SUPPORT 0 - // ----------------------------------------------------------------------------- // Teckin SP20 // ----------------------------------------------------------------------------- @@ -4522,13 +4574,17 @@ #define TUYA_SUPPORT 1 #define LIGHT_PROVIDER LIGHT_PROVIDER_CUSTOM + #define TUYA_PORT 1 + + #define UART1_BAUDRATE 9600 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 + #define LED1_GPIO 14 #define TUYA_CH_STATE_DPID 1 #define TUYA_CH1_DPID 2 - #define DEBUG_SERIAL_SUPPORT 0 - // ----------------------------------------------------------------------------- // Etekcity ESW01-USA // https://www.amazon.com/Etekcity-Voltson-Outlet-Monitoring-Required/dp/B01M3MYIFS @@ -4583,6 +4639,7 @@ #define DEVICE "UAP1" // Inputs + #define DIGITAL_SUPPORT 1 #define DIGITAL1_PIN 4 #define DIGITAL2_PIN 5 @@ -4601,7 +4658,7 @@ #define LED1_PIN 2 // Disable UART noise - #define DEBUG_SERIAL_SUPPORT 0 + #define UART_SUPPORT 0 // ----------------------------------------------------------------------------- // TFLAG NX-SM100 & NX-SM200 @@ -4764,9 +4821,12 @@ #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 - // KINGART module handles the UART, can't print any debug messages #define KINGART_CURTAIN_SUPPORT 1 - #define DEBUG_SERIAL_SUPPORT 0 + #define KINGART_CURTAIN_PORT 1 + + #define UART1_BAUDRATE 19200 + #define UART1_TX_PIN 1 + #define UART1_RX_PIN 3 // ----------------------------------------------------------------------------- // LSC Smart LED Light Strip (Smart CXonnect Series) available ACTION (Germany) @@ -4862,9 +4922,8 @@ #define MANUFACTURER "NEDIS" #define DEVICE "WIFIP310FWT" - // Based on the reporter, this product uses GPIO1 and 3 for the button - // and onboard LED, so hardware serial should be disabled... - #define DEBUG_SERIAL_SUPPORT 0 + // Disable UART noise since this board uses GPIO1 and GPIO3 + #define UART_SUPPORT 0 // Buttons #define BUTTON1_PIN 3 @@ -4917,6 +4976,9 @@ #define MANUFACTURER "ARLEC" #define DEVICE "PB89HA" + // Disable UART noise since this board uses GPIO1 and GPIO3 + #define UART_SUPPORT 0 + // Buttons #define BUTTON1_PIN 3 #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH @@ -5041,7 +5103,7 @@ // ----------------------------------------------------------------------------- // Mirabella Genio White A60 // https://www.woolworths.com.au/shop/productdetails/877102/mirabella-smart-led-gls-es-9w-cool-white -// Like https://www.mirabellagenio.com.au/product-range/mirabella-genio-wi-fi-dimmable-9w-led-gls-bulb/ +// Like https://www.mirabellagenio.com.au/product-range/mirabella-genio-wi-fi-dimmable-9w-led-gls-bulb/ // but in cardboard box, Item # I002604 // ----------------------------------------------------------------------------- @@ -5073,6 +5135,9 @@ #define MANUFACTURER "YAGUSMART" #define DEVICE "TOUCH_HWMOD_1G" + // Disable UART noise since this board uses GPIO3 + #define UART_SUPPORT 0 + #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH #define BUTTON1_PIN 3 #define BUTTON1_RELAY 1 @@ -5091,12 +5156,13 @@ #define LED1_PIN_INVERSE 1 #define LED1_MODE LED_MODE_WIFI - #define DEBUG_SERIAL_SUPPORT 0 - #elif defined(YAGUSMART_TOUCH_HWMOD_2G) #define MANUFACTURER "YAGUSMART" #define DEVICE "TOUCH_HWMOD_2G" + // Disable UART noise since this board uses GPIO3 + #define UART_SUPPORT 0 + #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH #define BUTTON1_PIN 3 #define BUTTON1_RELAY 1 @@ -5128,12 +5194,13 @@ #define LED1_PIN_INVERSE 1 #define LED1_MODE LED_MODE_WIFI - #define DEBUG_SERIAL_SUPPORT 0 - #elif defined(YAGUSMART_TOUCH_HWMOD_3G) #define MANUFACTURER "YAGUSMART" #define DEVICE "TOUCH_HWMOD_3G" + // Disable UART noise since this board uses GPIO1 and GPIO3 + #define UART_SUPPORT 0 + #define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH | BUTTON_SET_PULLUP #define BUTTON1_PIN 12 #define BUTTON1_PRESS BUTTON_ACTION_TOGGLE @@ -5175,8 +5242,6 @@ #define LED1_PIN_INVERSE 1 #define LED1_MODE LED_MODE_WIFI - #define DEBUG_SERIAL_SUPPORT 0 - #else #error "UNSUPPORTED HARDWARE!!" diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index e94567e8..76578e98 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -264,22 +264,11 @@ #define CSE7766_SUPPORT 0 #endif -#ifndef CSE7766_RX_PIN -#define CSE7766_RX_PIN 3 // RX pin connected to the CSE7766 - // As we never transmit anything, this is the only pin used +#ifndef CSE7766_PORT +#define CSE7766_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 4800`) #endif -#ifndef CSE7766_PIN_INVERSE -#define CSE7766_PIN_INVERSE 0 // Signal is inverted -#endif - -#define CSE7766_SYNC_INTERVAL 300 // Safe time between transmissions (ms) -#define CSE7766_BAUDRATE 4800 // UART baudrate - -#define CSE7766_V1R 1.0 // 1mR current resistor -#define CSE7766_V2R 1.0 // 1M voltage resistor - - //------------------------------------------------------------------------------ // Digital sensor // Enable support by passing DIGITAL_SUPPORT=1 build flag @@ -812,12 +801,9 @@ #define MHZ19_SUPPORT 0 #endif -#ifndef MHZ19_RX_PIN -#define MHZ19_RX_PIN 13 -#endif - -#ifndef MHZ19_TX_PIN -#define MHZ19_TX_PIN 15 +#ifndef MHZ19_PORT +#define MHZ19_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -913,12 +899,9 @@ #define PM1006_SUPPORT 0 #endif -#ifndef PM1006_RX_PIN -#define PM1006_RX_PIN 3 -#endif - -#ifndef PM1006_BAUDRATE -#define PM1006_BAUDRATE 9600 +#ifndef PM1006_PORT +#define PM1006_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -930,6 +913,11 @@ #define PMSX003_SUPPORT 0 #endif +#ifndef PMS_PORT +#define PMS_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) +#endif + #ifndef PMS_TYPE #define PMS_TYPE PMS_TYPE_X003 #endif @@ -941,22 +929,6 @@ #define PMS_SMART_SLEEP 0 #endif -#ifndef PMS_USE_SOFT -#define PMS_USE_SOFT 0 // If PMS_USE_SOFT == 1, DEBUG_SERIAL_SUPPORT must be 0 -#endif - -#ifndef PMS_RX_PIN -#define PMS_RX_PIN 13 // Software serial RX GPIO (if PMS_USE_SOFT == 1) -#endif - -#ifndef PMS_TX_PIN -#define PMS_TX_PIN 15 // Software serial TX GPIO (if PMS_USE_SOFT == 1) -#endif - -#ifndef PMS_HW_PORT -#define PMS_HW_PORT Serial // Hardware serial port (if PMS_USE_SOFT == 0) -#endif - //------------------------------------------------------------------------------ // Pulse Meter Energy monitor // Enable support by passing PULSEMETER_SUPPORT=1 build flag @@ -990,22 +962,9 @@ #define PZEM004T_SUPPORT 0 #endif -#ifndef PZEM004T_USE_SOFT -#define PZEM004T_USE_SOFT 0 // By default, use Hardware serial with GPIO15 (TX) and GPIO13 (RX) - // (but, make sure to change DEBUG_PORT to Serial1 or set DEBUG_SERIAL_SUPPORT to 0) -#endif - -#ifndef PZEM004T_RX_PIN -#define PZEM004T_RX_PIN 13 // Serial RX GPIO (if PZEM004T_USE_SOFT == 1, creates a SoftwareSerial object) -#endif - -#ifndef PZEM004T_TX_PIN -#define PZEM004T_TX_PIN 15 // Serial TX GPIO (if PZEM004T_USE_SOFT == 1, creates a SoftwareSerial object) -#endif - -#ifndef PZEM004T_HW_PORT -#define PZEM004T_HW_PORT Serial // Hardware serial port (if PZEM004T_USE_SOFT == 0) - // ESP8266: Serial1 does not allow receiving data, no point in changing this setting +#ifndef PZEM004T_PORT +#define PZEM004T_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif #ifndef PZEM004T_READ_INTERVAL @@ -1047,22 +1006,9 @@ #define PZEM004TV30_ADDRESS 0xF8 // Default: factory value #endif -#ifndef PZEM004TV30_USE_SOFT -#define PZEM004TV30_USE_SOFT 0 // By default, use Hardware serial with GPIO15 (TX) and GPIO13 (RX) - // (but, make sure to change DEBUG_PORT to Serial1 or set DEBUG_SERIAL_SUPPORT to 0) -#endif - -#ifndef PZEM004TV30_HW_PORT -#define PZEM004TV30_HW_PORT Serial // Hardware serial port (if PZEM004TV30_USE_SOFT == 0) - // ESP8266: Serial1 does not allow receiving data, no point in changing this setting -#endif - -#ifndef PZEM004TV30_RX_PIN -#define PZEM004TV30_RX_PIN 13 // Serial RX GPIO (if PZEM004T_USE_SOFT == 1, creates a SoftwareSerial object) -#endif - -#ifndef PZEM004TV30_TX_PIN -#define PZEM004TV30_TX_PIN 15 // Serial TX GPIO (if PZEM004T_USE_SOFT == 1, creates a SoftwareSerial object) +#ifndef PZEM004TV30_PORT +#define PZEM004TV30_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif #ifndef PZEM004TV30_DEBUG @@ -1078,12 +1024,9 @@ #define SDS011_SUPPORT 0 #endif -#ifndef SDS011_RX_PIN -#define SDS011_RX_PIN 14 -#endif - -#ifndef SDS011_TX_PIN -#define SDS011_TX_PIN 12 +#ifndef SDS011_PORT +#define SDS011_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -1095,12 +1038,9 @@ #define SENSEAIR_SUPPORT 0 #endif -#ifndef SENSEAIR_RX_PIN -#define SENSEAIR_RX_PIN 0 -#endif - -#ifndef SENSEAIR_TX_PIN -#define SENSEAIR_TX_PIN 2 +#ifndef SENSEAIR_PORT +#define SENSEAIR_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -1138,12 +1078,9 @@ #define SM300D2_SUPPORT 0 #endif -#ifndef SM300D2_RX_PIN -#define SM300D2_RX_PIN 13 -#endif - -#ifndef SM300D2_BAUDRATE -#define SM300D2_BAUDRATE 9600 +#ifndef SM300D2_PORT +#define SM300D2_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -1193,12 +1130,9 @@ #define T6613_SUPPORT 0 #endif -#ifndef T6613_RX_PIN -#define T6613_RX_PIN 4 -#endif - -#ifndef T6613_TX_PIN -#define T6613_TX_PIN 5 +#ifndef T6613_PORT +#define T6613_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif //------------------------------------------------------------------------------ @@ -1223,16 +1157,14 @@ #define V9261F_SUPPORT 0 #endif -#ifndef V9261F_PIN -#define V9261F_PIN 2 // TX pin from the V9261F -#endif - -#ifndef V9261F_PIN_INVERSE -#define V9261F_PIN_INVERSE 1 // Signal is inverted +#ifndef V9261F_PORT +#define V9261F_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 4800` and `UART#_INVERSE 1`) #endif +#ifndef V9261F_SYNC_INTERVAL #define V9261F_SYNC_INTERVAL 600 // Sync signal length (ms) -#define V9261F_BAUDRATE 4800 // UART baudrate +#endif // Default ratios #define V9261F_CURRENT_FACTOR 79371434.0 @@ -1320,12 +1252,9 @@ #define EZOPH_SUPPORT 0 #endif -#ifndef EZOPH_RX_PIN -#define EZOPH_RX_PIN 13 // Software serial RX GPIO -#endif - -#ifndef EZOPH_TX_PIN -#define EZOPH_TX_PIN 15 // Software serial TX GPIO +#ifndef EZOPH_PORT +#define EZOPH_PORT 1 // By default, use the first port + // (needs `UART#_BAUDRATE 9600`) #endif #ifndef EZOPH_SYNC_INTERVAL @@ -1477,6 +1406,26 @@ // Configuration helpers // ============================================================================= +// UART support for sensors using serial port +// (notice that baudrate and mode config is set *externally*) +#if (\ + CSE7766_SUPPORT || \ + MHZ19_SUPPORT || \ + PM1006_SUPPORT || \ + PMSX003_SUPPORT || \ + PZEM004T_SUPPORT || \ + SENSEAIR_SUPPORT || \ + SDS011_SUPPORT || \ + SM300D2_SUPPORT || \ + T6613_SUPPORT || \ + V9261F_SUPPORT || \ + EZOPH_SUPPORT || \ + PZEM004TV30_SUPPORT \ +) +#undef UART_SUPPORT +#define UART_SUPPORT 1 +#endif + // I2C support when sensor needs it #if ( ADE7953_SUPPORT || \ AM2320_SUPPORT || \ diff --git a/code/espurna/curtain_kingart.cpp b/code/espurna/curtain_kingart.cpp index a0536f21..4097b4da 100644 --- a/code/espurna/curtain_kingart.cpp +++ b/code/espurna/curtain_kingart.cpp @@ -21,17 +21,6 @@ Copyright (C) 2020 - Eric Chauvet #include "settings.h" #include "ws.h" -#ifndef KINGART_CURTAIN_PORT -#define KINGART_CURTAIN_PORT Serial // Hardware serial port by default -#endif - -#ifndef KINGART_CURTAIN_BUFFER_SIZE -#define KINGART_CURTAIN_BUFFER_SIZE 100 // Local UART buffer size -#endif - -#define KINGART_CURTAIN_TERMINATION '\e' // Termination character after each message -#define KINGART_CURTAIN_BAUDRATE 19200 // Serial speed is fixed for the device - // --> Let see after if we define a curtain generic switch, use these for now #define CURTAIN_BUTTON_UNKNOWN -1 #define CURTAIN_BUTTON_PAUSE 0 @@ -48,6 +37,8 @@ Copyright (C) 2020 - Eric Chauvet #define KINGART_DEBUG_MSG_P(...) do { if (_curtain_debug_flag) { DEBUG_MSG_P(__VA_ARGS__); } } while(0) +Stream* _curtain_port { nullptr }; + char _KACurtainBuffer[KINGART_CURTAIN_BUFFER_SIZE]; bool _KACurtainNewData = false; @@ -117,9 +108,9 @@ void _KASetMoving() { //------------------------------------------------------------------------------ //Send a buffer to serial void _KACurtainSend(const char * tx_buffer) { - KINGART_CURTAIN_PORT.print(tx_buffer); - KINGART_CURTAIN_PORT.print(KINGART_CURTAIN_TERMINATION); - KINGART_CURTAIN_PORT.flush(); + _curtain_port->print(tx_buffer); + _curtain_port->print(KINGART_CURTAIN_TERMINATION); + _curtain_port->flush(); KINGART_DEBUG_MSG_P(PSTR("[KA] UART OUT %s\n"), tx_buffer); } @@ -192,8 +183,8 @@ void _KAStopMoving() { //Receive a buffer from serial bool _KACurtainReceiveUART() { static unsigned char ndx = 0; - while (KINGART_CURTAIN_PORT.available() > 0 && !_KACurtainNewData) { - char rc = KINGART_CURTAIN_PORT.read(); + while (_curtain_port->available() > 0 && !_KACurtainNewData) { + char rc = _curtain_port->read(); if (rc != KINGART_CURTAIN_TERMINATION) { _KACurtainBuffer[ndx] = rc; if (ndx < KINGART_CURTAIN_BUFFER_SIZE - 1) ndx++; @@ -468,9 +459,12 @@ void _KACurtainLoop() { //------------------------------------------------------------------------------ void kingartCurtainSetup() { + const auto port = uartPort(KINGART_CURTAIN_PORT - 1); + if (!port || (!port->tx || !port->rx)) { + return; + } - // Init port to receive and send messages - KINGART_CURTAIN_PORT.begin(KINGART_CURTAIN_BAUDRATE); + _curtain_port = port->stream; #if MQTT_SUPPORT // Register MQTT callback only when supported diff --git a/code/espurna/debug.cpp b/code/espurna/debug.cpp index 2b450e49..cce88fd8 100644 --- a/code/espurna/debug.cpp +++ b/code/espurna/debug.cpp @@ -431,11 +431,58 @@ void dump(Print& out) { #if DEBUG_SERIAL_SUPPORT namespace serial { -void output(Print& out, const char (&prefix)[10], const char* message, size_t len) { +using Output = void(*)(const char (&)[10], const char*, size_t); + +void null_output(const char (&)[10], const char*, size_t) { +} + +namespace internal { + +Print* port { nullptr }; +Output output { null_output }; + +} // namespace + +void output(const char (&prefix)[10], const char* message, size_t len) { + internal::output(prefix, message, len); +} + +void port_output(const char (&prefix)[10], const char* message, size_t len) { if (prefix[0] != '\0') { - out.write(&prefix[0], sizeof(prefix) - 1); + internal::port->write(&prefix[0], sizeof(prefix) - 1); } - out.write(message, len); + internal::port->write(message, len); +} + +void setup() { + // HardwareSerial::begin() will automatically enable this when + // `#if defined(DEBUG_ESP_PORT) && !defined(NDEBUG)` + // Do not interfere when that is the case + const auto port = uartPort(DEBUG_SERIAL_PORT - 1); + if (!port || !port->tx) { + return; + } + + // TODO: notice that SDK accepts anything as putc / printf, + // but we don't really have a good reason to wrire both + // this debug output and the one from SDK + // (and most of the time this is need to grab boot info from a + // physically connected device) + if (!build::coreDebug() && settings::sdkDebug()) { + switch (port->type) { + case driver::uart::Type::Uart0: + uart_set_debug(0); + break; + case driver::uart::Type::Uart1: + uart_set_debug(1); + break; + default: + break; + } + } + + internal::port = port->stream; + internal::output = port_output; } } // namespace serial @@ -511,7 +558,7 @@ void send(const char* message, size_t len, Timestamp timestamp) { bool pause { false }; #if DEBUG_SERIAL_SUPPORT - serial::output(DEBUG_PORT, prefix, message, len); + serial::output(prefix, message, len); #endif #if DEBUG_UDP_SUPPORT @@ -574,13 +621,6 @@ bool status(espurna::heartbeat::Mask mask) { } void configure() { - // HardwareSerial::begin() will automatically enable this when - // `#if defined(DEBUG_ESP_PORT) && !defined(NDEBUG)` - // Do not interfere when that is the case - if (!build::coreDebug()) { - DEBUG_PORT.setDebugOutput(settings::sdkDebug()); - } - #if DEBUG_LOG_BUFFER_SUPPORT if (settings::buffer()) { debug::buffer::enable(settings::bufferSize()); @@ -701,16 +741,14 @@ void debugShowBanner() { void debugSetup() { #if DEBUG_SERIAL_SUPPORT - DEBUG_PORT.begin(SERIAL_BAUDRATE); + espurna::debug::serial::setup(); #endif - #if DEBUG_UDP_SUPPORT if (espurna::debug::syslog::build::enabled()) { espurna::debug::syslog::configure(); espurnaRegisterReload(espurna::debug::syslog::configure); } #endif - #if DEBUG_LOG_BUFFER_SUPPORT #if TERMINAL_SUPPORT espurna::debug::terminal::setup(); diff --git a/code/espurna/espurna.h b/code/espurna/espurna.h index 0f896527..34512060 100644 --- a/code/espurna/espurna.h +++ b/code/espurna/espurna.h @@ -34,6 +34,7 @@ along with this program. If not, see . #include "settings.h" #include "system.h" #include "terminal.h" +#include "uart.h" #include "utils.h" #include "network.h" #include "wifi.h" diff --git a/code/espurna/garland/color.h b/code/espurna/garland/color.h index 96f5225a..fac72f05 100644 --- a/code/espurna/garland/color.h +++ b/code/espurna/garland/color.h @@ -96,15 +96,11 @@ public: return r == 0 && g == 0 && b == 0; } - void println() const { - Serial.print(("r="));Serial.print(r);Serial.print((" ")); - Serial.print(("g="));Serial.print(g);Serial.print( (" ")); - Serial.print(("b="));Serial.println(b); - } - String to_str() { char buf[20]; - sprintf(buf, "r=%hhu, g=%hhu, b=%hhu", r, g, b); + snprintf_P(buf, sizeof(buf), + PSTR("r=%hhu, g=%hhu, b=%hhu"), + r, g, b); return buf; } }; diff --git a/code/espurna/gpio.cpp b/code/espurna/gpio.cpp index 9d866850..c6c79280 100644 --- a/code/espurna/gpio.cpp +++ b/code/espurna/gpio.cpp @@ -19,9 +19,8 @@ Copyright (C) 2017-2019 by Xose Pérez #include "ws.h" namespace espurna { -namespace { - namespace peripherals { +namespace { // TODO: `struct Register { ... }` with additional size params? // e.g. GPIO IN / OUT register is techically u16, and we don't detect writing past the allowed 'mask' @@ -399,8 +398,9 @@ void mode(uint8_t pin, uint8_t mode) { } } // namespace pin -} // namespace peripherals + } // namespace +} // namespace peripherals namespace gpio { namespace { diff --git a/code/espurna/lightfox.cpp b/code/espurna/lightfox.cpp index d6d310d7..27e0ec28 100644 --- a/code/espurna/lightfox.cpp +++ b/code/espurna/lightfox.cpp @@ -38,6 +38,8 @@ constexpr size_t _lightfoxBuildRelays() { return LIGHTFOX_RELAYS; } +static Stream* _lightfox_port { nullptr }; + // ----------------------------------------------------------------------------- // PROTOCOL // ----------------------------------------------------------------------------- @@ -56,8 +58,8 @@ void _lightfoxSend(uint8_t code) { static_cast('\r'), static_cast('\n') }; - Serial.write(data, sizeof(data)); - Serial.flush(); + _lightfox_port->write(data, sizeof(data)); + _lightfox_port->flush(); DEBUG_MSG_P(PSTR("[LIGHTFOX] Code %02X sent\n"), code); } @@ -89,11 +91,6 @@ public: } bool setup() override { - static bool once { false }; - if (!once) { - once = true; - Serial.begin(SERIAL_BAUDRATE); - } return true; } @@ -125,8 +122,8 @@ public: DEBUG_MSG_P(PSTR("[LIGHTFOX] Sending DUAL mask: 0x%02X\n"), mask); uint8_t buffer[4] { 0xa0, 0x04, static_cast(mask), 0xa1 }; - Serial.write(buffer, sizeof(buffer)); - Serial.flush(); + _lightfox_port->write(buffer, sizeof(buffer)); + _lightfox_port->flush(); } private: @@ -193,12 +190,12 @@ void _lightfoxCommandsSetup() { // ----------------------------------------------------------------------------- void _lightfoxInputLoop() { - if (Serial.available() < 4) { + if (_lightfox_port->available() < 4) { return; } unsigned char bytes[4] = {0}; - Serial.readBytes(bytes, 4); + _lightfox_port->readBytes(bytes, 4); if ((bytes[0] != 0xA0) && (bytes[1] != 0x04) && (bytes[3] != 0xA1)) { return; } @@ -218,6 +215,13 @@ void _lightfoxInputLoop() { void lightfoxSetup() { + const auto port = uartPort(LIGHTFOX_PORT - 1); + if (!port || !port.tx) { + return; + } + + _lightfox_port = port->stream; + #if WEB_SUPPORT wsRegister() .onVisible(_lightfoxWebSocketOnVisible) diff --git a/code/espurna/main.cpp b/code/espurna/main.cpp index f3a5e484..1221aba5 100644 --- a/code/espurna/main.cpp +++ b/code/espurna/main.cpp @@ -113,6 +113,9 @@ void setup() { // Init persistance settingsSetup(); + // Init hardware / software UART ports + uartSetup(); + // Configure logger and crash recorder #if DEBUG_SUPPORT debugConfigureBoot(); diff --git a/code/espurna/relay.cpp b/code/espurna/relay.cpp index 75cd0bbc..6dbf5911 100644 --- a/code/espurna/relay.cpp +++ b/code/espurna/relay.cpp @@ -1370,8 +1370,11 @@ public: static bool once { false }; if (!once) { once = true; - Serial.begin(SERIAL_BAUDRATE); - espurnaRegisterLoop(loop); + const auto port = uartPort(RELAY_PROVIDER_DUAL_PORT - 1); + if (port) { + _port = port->stream; + espurnaRegisterLoop(loop); + } } return true; } @@ -1421,17 +1424,17 @@ public: DEBUG_MSG_P(PSTR("[RELAY] Sending DUAL mask: %s\n"), mask.toString().c_str()); uint8_t buffer[4] { 0xa0, 0x04, static_cast(mask.toUnsigned()), 0xa1 }; - Serial.write(buffer, sizeof(buffer)); - Serial.flush(); + _port->write(buffer, sizeof(buffer)); + _port->flush(); } static void loop() { - if (Serial.available() < 4) { + if (_port->available() < 4) { return; } unsigned char bytes[4] = {0}; - Serial.readBytes(bytes, 4); + _port->readBytes(bytes, 4); if ((bytes[0] != 0xA0) && (bytes[1] != 0x04) && (bytes[3] != 0xA1)) { return; } @@ -1453,6 +1456,7 @@ public: } private: + Stream* _port { nullptr }; size_t _id; static std::vector _instances; @@ -1480,7 +1484,10 @@ public: static bool once { false }; if (!once) { once = true; - Serial.begin(SERIAL_BAUDRATE); + const auto port = uartPort(RELAY_PROVIDER_STM_PORT - 1); + if (port) { + _port = port->stream; + } } return true; } @@ -1492,19 +1499,22 @@ public: } void change(bool status) override { - Serial.flush(); - Serial.write(0xA0); - Serial.write(_id + 1); - Serial.write(status); - Serial.write(0xA1 + status + _id); + if (_port) { + _port->flush(); + _port->write(0xA0); + _port->write(_id + 1); + _port->write(status); + _port->write(0xA1 + status + _id); - // TODO: is this really solved via interlock delay, so we don't have to switch contexts here? - //delay(100); + // TODO: is this really solved via interlock delay, so we don't have to switch contexts here? + //delay(100); - Serial.flush(); + _port->flush(); + } } private: + Stream* _port; size_t _id; }; diff --git a/code/espurna/rfbridge.cpp b/code/espurna/rfbridge.cpp index edbc6375..b0566a3d 100644 --- a/code/espurna/rfbridge.cpp +++ b/code/espurna/rfbridge.cpp @@ -39,6 +39,7 @@ bool _rfb_transmit { false }; #else +static Stream* _rfb_port { nullptr }; constexpr bool _rfb_receive { true }; constexpr bool _rfb_transmit { true }; @@ -654,7 +655,7 @@ bool _rfbEnqueue(const char* code, size_t length, unsigned char repeats = 1u) { } void _rfbSendRaw(const uint8_t* message, size_t size) { - Serial.write(message, size); + _rfb_port->write(message, size); } void _rfbAckImpl() { @@ -663,8 +664,8 @@ void _rfbAckImpl() { }; DEBUG_MSG_P(PSTR("[RF] Sending ACK\n")); - Serial.write(message, sizeof(message)); - Serial.flush(); + _rfb_port->write(message, sizeof(message)); + _rfb_port->flush(); } void _rfbLearnImpl() { @@ -673,16 +674,16 @@ void _rfbLearnImpl() { }; DEBUG_MSG_P(PSTR("[RF] Sending LEARN\n")); - Serial.write(message, sizeof(message)); - Serial.flush(); + _rfb_port->write(message, sizeof(message)); + _rfb_port->flush(); } void _rfbSendImpl(const RfbMessage& message) { - Serial.write(CodeStart); - Serial.write(CodeSendBasic); + _rfb_port->write(CodeStart); + _rfb_port->write(CodeSendBasic); _rfbSendRaw(message.code, sizeof(message.code)); - Serial.write(CodeEnd); - Serial.flush(); + _rfb_port->write(CodeEnd); + _rfb_port->flush(); } void _rfbParse(uint8_t code, const std::vector& payload) { @@ -759,8 +760,8 @@ static RfbParser _rfb_parser(_rfbParse); void _rfbReceiveImpl() { - while (Serial.available()) { - auto c = Serial.read(); + while (_rfb_port->available()) { + auto c = _rfb_port->read(); if (c < 0) { continue; } @@ -1350,7 +1351,12 @@ void _rfbSettingsMigrate(int version) { void rfbSetup() { #if RFB_PROVIDER == RFB_PROVIDER_EFM8BB1 - Serial.begin(SERIAL_BAUDRATE); + const auto port = uartPort(RFB_PORT - 1); + if (!port || (!port.tx || !port.rx)) { + return; + } + + _rfb_port = port->stream; _rfb_parser.reserve(RfbParser::MessageSizeBasic); #elif RFB_PROVIDER == RFB_PROVIDER_RCSWITCH diff --git a/code/espurna/rtcmem.cpp b/code/espurna/rtcmem.cpp index 6ab5b861..25d74066 100644 --- a/code/espurna/rtcmem.cpp +++ b/code/espurna/rtcmem.cpp @@ -19,9 +19,9 @@ volatile RtcmemData* Rtcmem = reinterpret_cast(RtcmemBegin namespace espurna { namespace peripherals { -namespace rtc { namespace { +namespace rtc { namespace internal { bool status = false; @@ -134,8 +134,9 @@ void setup() { } -} // namespace } // namespace rtc + +} // namespace } // namespace peripherals } // namespace espurna diff --git a/code/espurna/sensor.cpp b/code/espurna/sensor.cpp index f6236c61..11640218 100644 --- a/code/espurna/sensor.cpp +++ b/code/espurna/sensor.cpp @@ -2066,8 +2066,14 @@ void load() { #if CSE7766_SUPPORT { + const auto port = uartPort(CSE7766_PORT - 1); + if (!port) { + return; + } + auto* sensor = new CSE7766Sensor(); - sensor->setRX(CSE7766_RX_PIN); + sensor->setPort(port->stream); + add(sensor); } #endif @@ -2260,9 +2266,13 @@ void load() { #if MHZ19_SUPPORT { + const auto port = uartPort(MHZ19_PORT - 1); + if (!port) { + return; + } + auto* sensor = new MHZ19Sensor(); - sensor->setRX(MHZ19_RX_PIN); - sensor->setTX(MHZ19_TX_PIN); + sensor->setPort(port->stream); sensor->setCalibrateAuto(getSetting("mhz19CalibrateAuto", false)); add(sensor); } @@ -2306,21 +2316,26 @@ void load() { #if PM1006_SUPPORT { + const auto port = uartPort(PM1006_PORT - 1); + if (!port) { + return; + } + auto* sensor = new PM1006Sensor(); - sensor->setRX(PM1006_RX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif #if PMSX003_SUPPORT { + const auto port = uartPort(PMS_PORT - 1); + if (!port) { + return; + } + auto* sensor = new PMSX003Sensor(); -#if PMS_USE_SOFT - sensor->setRX(PMS_RX_PIN); - sensor->setTX(PMS_TX_PIN); -#else - sensor->setSerial(& PMS_HW_PORT); -#endif + sensor->setPort(port->stream); sensor->setType(PMS_TYPE); add(sensor); } @@ -2340,24 +2355,14 @@ void load() { #if PZEM004T_SUPPORT { - PZEM004TSensor::PortPtr port; - - auto rx = getSetting("pzemRX", PZEM004TSensor::RxPin); - auto tx = getSetting("pzemTX", PZEM004TSensor::TxPin); - - if (getSetting("pzemSoft", PZEM004TSensor::useSoftwareSerial())) { - port = PZEM004TSensor::makeSoftwarePort(rx, tx); - } else { - port = PZEM004TSensor::makeHardwarePort( - PZEM004TSensor::defaultHardwarePort(), rx, tx); - } - + const auto port = uartPort(PZEM004T_PORT - 1); if (!port) { return; } - bool initialized { false }; + auto serial = std::make_shared(port->stream); + bool initialized { false }; #if !defined(PZEM004T_ADDRESSES) for (size_t index = 0; index < PZEM004TSensor::DevicesMax; ++index) { auto address = getSetting({"pzemAddr", index}, PZEM004TSensor::defaultAddress(index)); @@ -2365,7 +2370,7 @@ void load() { break; } - auto* ptr = PZEM004TSensor::make(port, address); + auto* ptr = PZEM004TSensor::make(serial, address); if (ptr) { add(ptr); initialized = true; @@ -2384,7 +2389,7 @@ void load() { size_t device{0}; char* address{strtok(buffer, " ")}; while ((device < PZEM004TSensor::DevicesMax) && (address != nullptr)) { - auto* ptr = PZEM004TSensor::make(port, address); + auto* ptr = PZEM004TSensor::make(serial, IPAddress(address)); if (ptr) { add(ptr); initialized = true; @@ -2400,18 +2405,26 @@ void load() { #if SENSEAIR_SUPPORT { + const auto port = uartPort(SENSEAIR_PORT - 1); + if (!port) { + return; + } + auto* sensor = new SenseAirSensor(); - sensor->setRX(SENSEAIR_RX_PIN); - sensor->setTX(SENSEAIR_TX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif #if SDS011_SUPPORT { + const auto port = uartPort(SDS011_PORT - 1); + if (!port) { + return; + } + auto* sensor = new SDS011Sensor(); - sensor->setRX(SDS011_RX_PIN); - sensor->setTX(SDS011_TX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif @@ -2434,17 +2447,26 @@ void load() { #if SM300D2_SUPPORT { + const auto port = uartPort(SM300D2_PORT - 1); + if (!port) { + return; + } + auto* sensor = new SM300D2Sensor(); - sensor->setRX(SM300D2_RX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif #if T6613_SUPPORT { + const auto port = uartPort(T6613_PORT - 1); + if (!port) { + return; + } + auto* sensor = new T6613Sensor(); - sensor->setRX(T6613_RX_PIN); - sensor->setTX(T6613_TX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif @@ -2459,9 +2481,13 @@ void load() { #if V9261F_SUPPORT { + const auto port = uartPort(V9261F_PORT - 1); + if (!port) { + return; + } + auto* sensor = new V9261FSensor(); - sensor->setRX(V9261F_PIN); - sensor->setInverted(V9261F_PIN_INVERSE); + sensor->setPort(port->stream); add(sensor); } #endif @@ -2499,9 +2525,13 @@ void load() { #if EZOPH_SUPPORT { + const auto port = uartPort(EZOPH_PORT - 1); + if (!port) { + return; + } + auto* sensor = new EZOPHSensor(); - sensor->setRX(EZOPH_RX_PIN); - sensor->setTX(EZOPH_TX_PIN); + sensor->setPort(port->stream); add(sensor); } #endif @@ -2532,31 +2562,18 @@ void load() { #if PZEM004TV30_SUPPORT { - auto rx = getSetting("pzemv30RX", PZEM004TV30Sensor::RxPin); - auto tx = getSetting("pzemv30TX", PZEM004TV30Sensor::TxPin); - - //TODO: getSetting("pzemv30*Cfg", (SW)SERIAL_8N1); ? - //TODO: getSetting("serial*Cfg", ...); and attach index of the port ? - //TODO: more than one sensor on port, like the v1 - PZEM004TV30Sensor::PortPtr port; - if (getSetting("pzemSoft", PZEM004TV30Sensor::useSoftwareSerial())) { - port = PZEM004TV30Sensor::makeSoftwarePort(rx, tx); - } else { - port = PZEM004TV30Sensor::makeHardwarePort( - PZEM004TV30Sensor::defaultHardwarePort(), rx, tx); + const auto port = uartPort(PZEM004TV30_PORT - 1); + if (!port) { + return; } - if (port) { - port->begin(PZEM004TV30Sensor::Baudrate); + auto* sensor = PZEM004TV30Sensor::make(port->stream, + getSetting("pzemv30Addr", PZEM004TV30Sensor::DefaultAddress), + getSetting("pzemv30ReadTimeout", PZEM004TV30Sensor::DefaultReadTimeout)); + sensor->setDebug( + getSetting("pzemv30Debug", PZEM004TV30Sensor::DefaultDebug)); - auto* sensor = PZEM004TV30Sensor::make(std::move(port), - getSetting("pzemv30Addr", PZEM004TV30Sensor::DefaultAddress), - getSetting("pzemv30ReadTimeout", PZEM004TV30Sensor::DefaultReadTimeout)); - sensor->setDebug( - getSetting("pzemv30Debug", PZEM004TV30Sensor::DefaultDebug)); - - add(sensor); - } + add(sensor); } #endif } diff --git a/code/espurna/sensors/CSE7766Sensor.h b/code/espurna/sensors/CSE7766Sensor.h index dd99268c..2c856afe 100644 --- a/code/espurna/sensors/CSE7766Sensor.h +++ b/code/espurna/sensors/CSE7766Sensor.h @@ -8,11 +8,14 @@ #pragma once +#define CSE7766_SYNC_INTERVAL 300 // Safe time between transmissions (ms) + +#define CSE7766_V1R 1.0 // 1mR current resistor +#define CSE7766_V2R 1.0 // 1M voltage resistor + #include "BaseSensor.h" #include "BaseEmonSensor.h" -#include - class CSE7766Sensor : public BaseEmonSensor { public: @@ -49,30 +52,6 @@ class CSE7766Sensor : public BaseEmonSensor { // --------------------------------------------------------------------- - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; - _dirty = true; - } - - void setInverted(bool inverted) { - if (_inverted == inverted) return; - _inverted = inverted; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - bool getInverted() const { - return _inverted; - } - - // --------------------------------------------------------------------- - double getRatio(unsigned char index) const override { switch (index) { case 0: @@ -102,6 +81,13 @@ class CSE7766Sensor : public BaseEmonSensor { } } + // --------------------------------------------------------------------- + + void setPort(Stream* port) { + _dirty = true; + _serial = port; + } + // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -113,22 +99,6 @@ class CSE7766Sensor : public BaseEmonSensor { if (!_dirty) return; - if (_serial) { - _serial.reset(nullptr); - } - - if (3 == _pin_rx) { - Serial.begin(CSE7766_BAUDRATE); - } else if (13 == _pin_rx) { - Serial.begin(CSE7766_BAUDRATE); - Serial.flush(); - Serial.swap(); - } else { - _serial = std::make_unique(_pin_rx, -1, _inverted); - _serial->enableIntTx(false); - _serial->begin(CSE7766_BAUDRATE); - } - _last_index_reset = TimeSource::now(); _ready = true; @@ -138,19 +108,12 @@ class CSE7766Sensor : public BaseEmonSensor { // Descriptive name of the sensor String description() const override { - if (_serial_is_hardware()) { - return F("CSE7766 @ HwSerial"); - } else { - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("CSE7766 @ SwSerial(%u,NULL)"), _pin_rx); - return String(buffer); - } + return F("CSE7766"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - return String(_pin_rx, 10); + return String(CSE7766_PORT, 10); } // Loop-like method, call it in your main loop @@ -305,7 +268,7 @@ class CSE7766Sensor : public BaseEmonSensor { _error = SENSOR_ERROR_OK; - while (_serial_available()) { + while (_serial->available() > 0) { // A 24 bytes message takes ~55ms to go through at 4800 bps // Reset counter if more than 1000ms have passed since last byte. @@ -315,7 +278,7 @@ class CSE7766Sensor : public BaseEmonSensor { _last_index_reset = TimeSource::now(); - uint8_t byte = _serial_read(); + uint8_t byte = _serial->read(); // first byte must be 0x55 or 0xF? if (0 == _data_index) { @@ -333,7 +296,7 @@ class CSE7766Sensor : public BaseEmonSensor { _data[_data_index++] = byte; if (_data_index > 23) { - _serial_flush(); + _serial->flush(); break; } @@ -349,39 +312,7 @@ class CSE7766Sensor : public BaseEmonSensor { // --------------------------------------------------------------------- - bool _serial_is_hardware() const { - return (3 == _pin_rx) || (13 == _pin_rx); - } - - bool _serial_available() const { - if (_serial_is_hardware()) { - return Serial.available(); - } else { - return _serial->available(); - } - } - - void _serial_flush() { - if (_serial_is_hardware()) { - return Serial.flush(); - } else { - return _serial->flush(); - } - } - - uint8_t _serial_read() const { - if (_serial_is_hardware()) { - return Serial.read(); - } else { - return _serial->read(); - } - } - - // --------------------------------------------------------------------- - - unsigned char _pin_rx = CSE7766_RX_PIN; - bool _inverted = CSE7766_PIN_INVERSE; - std::unique_ptr _serial; + Stream* _serial; double _active = 0; double _reactive = 0; diff --git a/code/espurna/sensors/EZOPHSensor.h b/code/espurna/sensors/EZOPHSensor.h index 1aba3a60..25bb3ef6 100644 --- a/code/espurna/sensors/EZOPHSensor.h +++ b/code/espurna/sensors/EZOPHSensor.h @@ -1,7 +1,6 @@ // ----------------------------------------------------------------------------- // EZO™ pH Circuit from Atlas Scientific // -// Uses SoftwareSerial library // Copyright (C) 2018 by Rui Marinho // ----------------------------------------------------------------------------- @@ -9,38 +8,17 @@ #pragma once -#include - #include "BaseSensor.h" class EZOPHSensor : public BaseSensor { public: - // --------------------------------------------------------------------- - - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() { - return _pin_rx; - } - - unsigned char getTX() { - return _pin_tx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -56,33 +34,18 @@ class EZOPHSensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { if (!_dirty) return; - - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, _pin_tx); - _serial->enableIntTx(false); - _serial->begin(9600); - _ready = true; _dirty = false; } // Descriptive name of the sensor String description() const override { - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("EZOPH @ SwSerial(%u,%u)"), _pin_rx, _pin_tx); - return String(buffer); + return F("EZOPH"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char index) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(EZOPH_PORT, 10); } // Type for slot # index @@ -185,9 +148,7 @@ class EZOPHSensor : public BaseSensor { TimeSource::time_point _timestamp; double _ph = 0; - unsigned char _pin_rx; - unsigned char _pin_tx; - std::unique_ptr _serial; + Stream* _serial; }; diff --git a/code/espurna/sensors/MHZ19Sensor.h b/code/espurna/sensors/MHZ19Sensor.h index a1f0da49..3aad1854 100644 --- a/code/espurna/sensors/MHZ19Sensor.h +++ b/code/espurna/sensors/MHZ19Sensor.h @@ -2,7 +2,6 @@ // MHZ19 CO2 sensor // Based on: https://github.com/nara256/mhz19_uart // http://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf -// Uses SoftwareSerial library // Copyright (C) 2017-2019 by Xose Pérez // ----------------------------------------------------------------------------- @@ -10,8 +9,6 @@ #pragma once -#include - #include "BaseSensor.h" #include @@ -45,28 +42,11 @@ class MHZ19Sensor : public BaseSensor { public: - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - unsigned char getTX() const { - return _pin_tx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -81,37 +61,21 @@ class MHZ19Sensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, _pin_tx, false); - _serial->enableIntTx(false); - _serial->begin(9600); calibrateAuto(_calibrateAuto); _ready = true; _dirty = false; - } // Descriptive name of the sensor String description() const override { - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("MHZ19 @ SwSerial(%hhu,%hhu)"), _pin_rx, _pin_tx); - return String(buffer); + return F("MHZ19"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(MHZ19_PORT, 10); } // Type for slot # index @@ -225,10 +189,8 @@ class MHZ19Sensor : public BaseSensor { } double _co2 = 0; - unsigned char _pin_rx; - unsigned char _pin_tx; bool _calibrateAuto = false; - std::unique_ptr _serial; + Stream* _serial { nullptr }; }; diff --git a/code/espurna/sensors/PM1006Sensor.h b/code/espurna/sensors/PM1006Sensor.h index 07433df1..58eb048e 100644 --- a/code/espurna/sensors/PM1006Sensor.h +++ b/code/espurna/sensors/PM1006Sensor.h @@ -1,7 +1,6 @@ // ----------------------------------------------------------------------------- // Wuhan Cubic PM1006 // Used in the IKEA VINDRIKTNING Air Quality Sensor -// Uses SoftwareSerial library // Copyright (C) 2022 by Xose Pérez // ----------------------------------------------------------------------------- @@ -9,24 +8,17 @@ #pragma once -#include - #include "BaseSensor.h" class PM1006Sensor : public BaseSensor { public: - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - unsigned char getRX() const { - return _pin_rx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -41,47 +33,20 @@ class PM1006Sensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - if (_serial) { - _serial.reset(nullptr); - } - - if (3 == _pin_rx) { - Serial.begin(PM1006_BAUDRATE); - } else if (13 == _pin_rx) { - Serial.begin(PM1006_BAUDRATE); - Serial.flush(); - Serial.swap(); - } else { - _serial = std::make_unique(_pin_rx, -1, false); - _serial->enableIntTx(false); - _serial->begin(PM1006_BAUDRATE); - } - _ready = true; _dirty = false; - } // Descriptive name of the sensor String description() const override { - if (_serial_is_hardware()) { - return F("PM1006 @ HwSerial"); - } - - char buffer[32]; - snprintf_P(buffer, sizeof(buffer), - PSTR("PM1006 @ SwSerial(%hhu,NULL)"), _pin_rx); - return String(buffer); + return F("PM1006"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char index) const override { - char buffer[4]; - snprintf_P(buffer, sizeof(buffer), PSTR("%hhu"), _pin_rx); - return String(buffer); + return String(PM1006_PORT, 10); } // Type for slot # index @@ -107,36 +72,6 @@ class PM1006Sensor : public BaseSensor { // Protected // --------------------------------------------------------------------- - bool _serial_is_hardware() const { - return (3 == _pin_rx) || (13 == _pin_rx); - } - - bool _serial_available() const { - if (_serial_is_hardware()) { - return Serial.available(); - } else { - return _serial->available(); - } - } - - void _serial_flush() { - if (_serial_is_hardware()) { - return Serial.flush(); - } else { - return _serial->flush(); - } - } - - uint8_t _serial_read() { - if (_serial_is_hardware()) { - return Serial.read(); - } else { - return _serial->read(); - } - } - - // --------------------------------------------------------------------- - void _parse() { #if SENSOR_DEBUG DEBUG_MSG_P(PSTR("[SENSOR] PM1006: %s\n"), hexEncode(_buffer).c_str()); @@ -167,9 +102,9 @@ class PM1006Sensor : public BaseSensor { void _read() { - while(_serial_available()) { + while(_serial->available()) { - unsigned char ch = _serial_read(); + unsigned char ch = _serial->read(); if ((_position > 0) || (ch == 0x16)) { _buffer[_position] = ch; _position++; @@ -191,9 +126,7 @@ class PM1006Sensor : public BaseSensor { unsigned char _position = 0; double _pm25 = 0; - - unsigned char _pin_rx = PM1006_RX_PIN; - std::unique_ptr _serial; + Stream* _serial { nullptr }; }; diff --git a/code/espurna/sensors/PMSX003Sensor.h b/code/espurna/sensors/PMSX003Sensor.h index e5784159..9cae350d 100644 --- a/code/espurna/sensors/PMSX003Sensor.h +++ b/code/espurna/sensors/PMSX003Sensor.h @@ -1,6 +1,5 @@ // ----------------------------------------------------------------------------- // PMS Dust Sensor -// Uses SoftwareSerial library // Contribution by Òscar Rovira López // Refine to support PMS5003T/PMS5003ST by Yonsm Guo // ----------------------------------------------------------------------------- @@ -11,11 +10,6 @@ #include "BaseSensor.h" -#include - -// Generic data -#define PMS_BAUD_RATE 9600 - // Type of sensor #define PMS_TYPE_X003 0 #define PMS_TYPE_X003_9 1 @@ -163,26 +157,8 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { }; public: - - ~PMSX003Sensor() { - removeSerial(); - } - - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; - _dirty = true; - } - - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - void setSerial(HardwareSerial * serial) { - _soft = false; - _serial = serial; + void setPort(Stream* port) { + _serial = port; _dirty = true; } @@ -191,16 +167,6 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { _type = type; } - // --------------------------------------------------------------------- - - unsigned char getRX() { - return _pin_rx; - } - - unsigned char getTX() { - return _pin_tx; - } - unsigned char getType() { return _type; } @@ -219,21 +185,8 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - if (_soft) { - if (_serial) removeSerial(); - _serial = new SoftwareSerial(_pin_rx, _pin_tx, false); - static_cast(_serial)->enableIntTx(false); - } - - if (_soft) { - static_cast(_serial)->begin(PMS_BAUD_RATE); - } else { - static_cast(_serial)->begin(PMS_BAUD_RATE); - } - passiveMode(); _startTime = TimeSource::now(); @@ -244,40 +197,21 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { // Descriptive name of the sensor String description() const override { - char buffer[28]; - if (_soft) { - snprintf_P(buffer, sizeof(buffer), - PSTR("%s @ SwSerial(%u,%u)"), - Specs[_type].name, _pin_rx, _pin_tx); - } else { - snprintf_P(buffer, sizeof(buffer), - PSTR("%s @ HwSerial"), Specs[_type].name); - } - - return String(buffer); + return String(Specs[_type].name); } // Descriptive name of the slot # index String description(unsigned char index) const override { - char buffer[36] = {0}; - if (_soft) { - snprintf_P(buffer, sizeof(buffer), - PSTR("%d @ %s @ SwSerial(%u,%u)"), - int(index + 1), Specs[_type].name, _pin_rx, _pin_tx); - } else { - snprintf_P(buffer, sizeof(buffer), - PSTR("%d @ %s @ HwSerial"), - int(index + 1), Specs[_type].name); - } - return String(buffer); + String out; + out += String(index + 1, 10); + out += " @ "; + out += description(); + return out; } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char index) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(PMS_PORT, 10); } // Type for slot # index @@ -381,18 +315,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 { return _slot_values[index]; } - private: - void removeSerial() { - if (_serial && _soft) { - delete static_cast(_serial); - } - } - protected: - bool _soft = true; - unsigned char _pin_rx; - unsigned char _pin_tx; - using TimeSource = espurna::time::CoreClock; TimeSource::time_point _startTime; bool _warmedUp = false; diff --git a/code/espurna/sensors/PZEM004TSensor.h b/code/espurna/sensors/PZEM004TSensor.h index 9a24b44d..9c3d4c7d 100644 --- a/code/espurna/sensors/PZEM004TSensor.h +++ b/code/espurna/sensors/PZEM004TSensor.h @@ -44,17 +44,211 @@ // ---------- // UART/TTL-Serial network with single master and multiple slaves: // http://cool-emerald.blogspot.com/2009/10/multidrop-network-for-rs232.html +// +// Original code: +// -------------- +// * https://github.com/olehs/PZEM004T +// +// MIT License +// +// Copyright (c) 2018 Oleg Sokolov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: #pragma once -#include - #include "BaseSensor.h" #include "BaseEmonSensor.h" #include "../sensor.h" #include "../terminal.h" +#define PZEM_VOLTAGE (uint8_t)0xB0 +#define RESP_VOLTAGE (uint8_t)0xA0 + +#define PZEM_CURRENT (uint8_t)0xB1 +#define RESP_CURRENT (uint8_t)0xA1 + +#define PZEM_POWER (uint8_t)0xB2 +#define RESP_POWER (uint8_t)0xA2 + +#define PZEM_ENERGY (uint8_t)0xB3 +#define RESP_ENERGY (uint8_t)0xA3 + +#define PZEM_SET_ADDRESS (uint8_t)0xB4 +#define RESP_SET_ADDRESS (uint8_t)0xA4 + +#define PZEM_POWER_ALARM (uint8_t)0xB5 +#define RESP_POWER_ALARM (uint8_t)0xA5 + +#define PZEM_DEFAULT_READ_TIMEOUT 1000 +#define PZEM_ERROR_VALUE -1.0 + +#define RESPONSE_SIZE sizeof(PZEMCommand) +#define RESPONSE_DATA_SIZE RESPONSE_SIZE - 2 + +struct PZEMCommand { + uint8_t command; + uint8_t addr[4]; + uint8_t data; + uint8_t crc; +}; + +class PZEM004T { +public: + PZEM004T() = delete; + explicit PZEM004T(Stream *port) : + _serial(port) + {} + + void setReadTimeout(unsigned long msec) { + _readTimeOut = msec; + } + + unsigned long readTimeout() {return _readTimeOut;} + + float voltage(const IPAddress &addr); + float current(const IPAddress &addr); + float power(const IPAddress &addr); + float energy(const IPAddress &addr); + + bool setAddress(const IPAddress &newAddr); + bool setPowerAlarm(const IPAddress &addr, uint8_t threshold); + +private: + Stream* _serial; + unsigned long _readTimeOut = PZEM_DEFAULT_READ_TIMEOUT; + + void send(const IPAddress &addr, uint8_t cmd, uint8_t data = 0); + bool recieve(uint8_t resp, uint8_t *data = 0); + + uint8_t crc(uint8_t *data, uint8_t sz); +}; + +float PZEM004T::voltage(const IPAddress &addr) +{ + uint8_t data[RESPONSE_DATA_SIZE]; + + send(addr, PZEM_VOLTAGE); + if(!recieve(RESP_VOLTAGE, data)) + return PZEM_ERROR_VALUE; + + return (data[0] << 8) + data[1] + (data[2] / 10.0); +} + +float PZEM004T::current(const IPAddress &addr) +{ + uint8_t data[RESPONSE_DATA_SIZE]; + + send(addr, PZEM_CURRENT); + if(!recieve(RESP_CURRENT, data)) + return PZEM_ERROR_VALUE; + + return (data[0] << 8) + data[1] + (data[2] / 100.0); +} + +float PZEM004T::power(const IPAddress &addr) +{ + uint8_t data[RESPONSE_DATA_SIZE]; + + send(addr, PZEM_POWER); + if(!recieve(RESP_POWER, data)) + return PZEM_ERROR_VALUE; + + return (data[0] << 8) + data[1]; +} + +float PZEM004T::energy(const IPAddress &addr) +{ + uint8_t data[RESPONSE_DATA_SIZE]; + + send(addr, PZEM_ENERGY); + if(!recieve(RESP_ENERGY, data)) + return PZEM_ERROR_VALUE; + + return ((uint32_t)data[0] << 16) + ((uint16_t)data[1] << 8) + data[2]; +} + +bool PZEM004T::setAddress(const IPAddress &newAddr) +{ + send(newAddr, PZEM_SET_ADDRESS); + return recieve(RESP_SET_ADDRESS); +} + +bool PZEM004T::setPowerAlarm(const IPAddress &addr, uint8_t threshold) +{ + send(addr, PZEM_POWER_ALARM, threshold); + return recieve(RESP_POWER_ALARM); +} + +void PZEM004T::send(const IPAddress &addr, uint8_t cmd, uint8_t data) +{ + PZEMCommand pzem; + + pzem.command = cmd; + for(size_t i=0; iavailable()) { + _serial->read(); + } + + _serial->write(bytes, sizeof(pzem)); +} + +bool PZEM004T::recieve(uint8_t resp, uint8_t *data) +{ + uint8_t buffer[RESPONSE_SIZE]; + + unsigned long startTime = millis(); + uint8_t len = 0; + while((len < RESPONSE_SIZE) && (millis() - startTime < _readTimeOut)) + { + if (_serial->available() > 0) + { + uint8_t c = (uint8_t)_serial->read(); + if(!c && !len) + continue; // skip 0 at startup + buffer[len++] = c; + } + yield(); // do background netw tasks while blocked for IO (prevents ESP watchdog trigger) + } + + if(len != RESPONSE_SIZE) + return false; + + if(buffer[6] != crc(buffer, len - 1)) + return false; + + if(buffer[0] != resp) + return false; + + if(data) + { + for(size_t i=0; i; - virtual const char* tag() const = 0; - virtual void flush() = 0; - SerialPort() = delete; - SerialPort(PzemPtr pzem, unsigned char rx, unsigned char tx) : - _pzem(std::move(pzem)), - _rx(rx), - _tx(tx) + + explicit SerialPort(PzemPtr pzem) : + _pzem(pzem) + {} + + explicit SerialPort(Stream* stream) : + _pzem(std::make_unique(stream)) {} float read(const IPAddress& address, unsigned char magnitude) { @@ -192,79 +370,17 @@ public: bool address(const IPAddress& address) { return _pzem->setAddress(address); - } - - unsigned char rx() const { - return _rx; - } - - unsigned char tx() const { - return _tx; + send(newAddr, PZEM_SET_ADDRESS); + return recieve(RESP_SET_ADDRESS); } private: PzemPtr _pzem; bool _busy { false }; - unsigned char _rx; - unsigned char _tx; - }; - - struct SoftwareSerialPort : public SerialPort { - SoftwareSerialPort() = delete; - SoftwareSerialPort(unsigned char rx, unsigned char tx) : - SerialPort(std::make_unique(rx, tx), rx, tx) - {} - - const char* tag() const override { - return "Sw"; - } - - void flush() override { - } - }; - - struct HardwareSerialPort : public SerialPort { - HardwareSerialPort() = delete; - HardwareSerialPort(HardwareSerial* serial, unsigned char rx, unsigned char tx) : - SerialPort(std::make_unique(serial), rx, tx), - _serial(serial) - { - if ((rx == 13) && (tx == 15)) { - _serial->flush(); - _serial->swap(); - } - } - - const char* tag() const override { - return "Hw"; - } - - void flush() override { - // Clear buffer in case of late response (Timeout) - // This we cannot do it from outside the library - while (_serial->available() > 0) { - _serial->read(); - } - } - - private: - HardwareSerial* _serial; }; using PortPtr = std::shared_ptr; - static PortPtr makeHardwarePort(HardwareSerial* port, unsigned char rx, unsigned char tx) { - auto ptr = std::make_shared(port, rx, tx); - _ports.push_back(ptr); - return ptr; - } - - static PortPtr makeSoftwarePort(unsigned char rx, unsigned char tx) { - auto ptr = std::make_shared(rx, tx); - _ports.push_back(ptr); - return ptr; - } - private: PZEM004TSensor(PortPtr port, IPAddress address) : BaseEmonSensor(Magnitudes), @@ -368,11 +484,7 @@ public: // Descriptive name of the sensor String description() const override { - char buffer[32]; - snprintf_P(buffer, sizeof(buffer), - PSTR("PZEM004T @ %sSerial(%hhu,%hhu)"), - _port->tag(), _port->rx(), _port->tx()); - return String(buffer); + return F("PZEM004T"); } // Descriptive name of the slot # index @@ -514,8 +626,8 @@ void pzem_ports(::terminal::CommandContext&& ctx) { auto print = [&](const size_t index, const PortWeakPtr& ptr) { auto port = ptr.lock(); if (port) { - ctx.output.printf_P(PSTR("%u -> %sSerial (%hhu,%hhu)\n"), - index, port->tag(), port->rx(), port->tx()); + ctx.output.printf_P(PSTR("%u -> (%p)\n"), + index, port.get()); } else { ctx.output.print(F("%u -> (not configured)\n")); } diff --git a/code/espurna/sensors/PZEM004TV30Sensor.h b/code/espurna/sensors/PZEM004TV30Sensor.h index 345cfc41..f4e48722 100644 --- a/code/espurna/sensors/PZEM004TV30Sensor.h +++ b/code/espurna/sensors/PZEM004TV30Sensor.h @@ -19,9 +19,6 @@ Copyright (C) 2020 by Maxim Prokhorov #include #include -// TODO: keep this until we have external API giving us swserial stream objects -#include - #if DEBUG_SUPPORT #define PZEM_DEBUG_MSG_P(...) do { if (_debug) {\ DEBUG_MSG_P(__VA_ARGS__); }\ @@ -33,114 +30,16 @@ Copyright (C) 2020 by Maxim Prokhorov class PZEM004TV30Sensor : public BaseEmonSensor { public: using TimeSource = espurna::time::CoreClock; - - static constexpr unsigned char RxPin { PZEM004TV30_RX_PIN }; - static constexpr unsigned char TxPin { PZEM004TV30_TX_PIN }; - - static constexpr bool useSoftwareSerial() { - return 1 == PZEM004TV30_USE_SOFT; - } - - static HardwareSerial* defaultHardwarePort() { - return &PZEM004TV30_HW_PORT; - } - - static constexpr unsigned long Baudrate = 9600u; - - struct SerialPort { - virtual const char* tag() const = 0; - virtual void begin(unsigned long baudrate) = 0; - virtual Stream* operator->() = 0; - - SerialPort() = delete; - SerialPort(unsigned char rx, unsigned char tx) : - _rx(rx), - _tx(tx) - {} - - unsigned char rx() const { - return _rx; - } - - unsigned char tx() const { - return _tx; - } - - private: - unsigned char _rx; - unsigned char _tx; - }; - - struct SoftwarePort : public SerialPort { - SoftwarePort() = delete; - SoftwarePort(unsigned char rx, unsigned char tx) : - SerialPort(rx, tx), - _serial(std::make_unique(rx, tx)) - {} - - const char* tag() const override { - return "Sw"; - } - - void begin(unsigned long baudrate) override { - _serial->begin(baudrate); - } - - Stream* operator->() override { - return static_cast(_serial.get()); - } - - private: - std::unique_ptr _serial; - }; - - struct HardwarePort : public SerialPort { - HardwarePort() = delete; - HardwarePort(HardwareSerial* serial, unsigned char rx, unsigned char tx) : - SerialPort(rx, tx), - _serial(serial) - { - if ((rx == 13) && (tx == 15)) { - _serial->flush(); - _serial->swap(); - } - } - - void begin(unsigned long baudrate) override { - _serial->begin(baudrate); - } - - const char* tag() const override { - return "Hw"; - } - - Stream* operator->() override { - return static_cast(_serial); - } - - private: - HardwareSerial* _serial; - }; - - using PortPtr = std::unique_ptr; using Instance = std::unique_ptr; - static PortPtr makeHardwarePort(HardwareSerial* port, unsigned char rx, unsigned char tx) { - return std::make_unique(port, rx, tx); - } - - static PortPtr makeSoftwarePort(unsigned char rx, unsigned char tx) { - return std::make_unique(rx, tx); - } - // Note that the device (aka slave) address needs be changed first via // - some external tool. For example, using USB2TTL adapter and a PC app // - `pzem.address` with **only** one device on the line // (because we would change all 0xf8-addressed devices at the same time) - static PZEM004TV30Sensor* make(PortPtr port, uint8_t address, TimeSource::duration timeout) { + static PZEM004TV30Sensor* make(Stream* port, uint8_t address, TimeSource::duration timeout) { static_assert(std::is_same::value, ""); if (!_instance) { - _instance.reset(new PZEM004TV30Sensor(std::move(port), address, timeout)); + _instance.reset(new PZEM004TV30Sensor(port, address, timeout)); return _instance.get(); } @@ -308,7 +207,7 @@ public: return; } - (*_port)->write(builder.buffer.data(), builder.size); + _port->write(builder.buffer.data(), builder.size); size_t expect = modbusExpect(builder); if (!expect) { @@ -329,7 +228,7 @@ public: // TODO: testing is much easier, b/c we can just grab any modbus simulator and set up multiple devices const auto ts = TimeSource::now(); while ((bytes < expect) && (TimeSource::now() - ts < _read_timeout)) { - int c = (*_port)->read(); + int c = _port->read(); if (c < 0) { continue; } @@ -574,7 +473,7 @@ public: } void flush() { - while ((*_port)->read() >= 0) { + while (_port->read() >= 0) { } } @@ -616,11 +515,8 @@ public: } String description() const override { - static const String base(F("PZEM004T V3.0")); - return base + " @ " - + _port->tag() - + F("Serial, 0x") - + String(_address, 16); + static const String base(F("PZEM004TV30")); + return base + " @ 0x" + String(_address, 16); } String address(unsigned char) const override { @@ -675,16 +571,16 @@ public: private: PZEM004TV30Sensor() = delete; - PZEM004TV30Sensor(PortPtr port, uint8_t address, TimeSource::duration timeout) : + PZEM004TV30Sensor(Stream* port, uint8_t address, TimeSource::duration timeout) : BaseEmonSensor(Magnitudes), - _port(std::move(port)), + _port(port), _address(address), _read_timeout(timeout) {} static Instance _instance; - PortPtr _port; + Stream* _port { nullptr }; uint8_t _address { DefaultAddress }; TimeSource::duration _read_timeout { DefaultReadTimeout }; diff --git a/code/espurna/sensors/SDS011Sensor.h b/code/espurna/sensors/SDS011Sensor.h index a4278b0b..500d5310 100644 --- a/code/espurna/sensors/SDS011Sensor.h +++ b/code/espurna/sensors/SDS011Sensor.h @@ -2,7 +2,6 @@ // SDS011 dust sensor // Based on: https://github.com/ricki-z/SDS011 // -// Uses SoftwareSerial library // Copyright (C) 2018 by Lucas Pleß // ----------------------------------------------------------------------------- @@ -10,37 +9,15 @@ #pragma once -#include - #include "BaseSensor.h" - class SDS011Sensor : public BaseSensor { - public: - - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - unsigned char getTX() const { - return _pin_tx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -55,34 +32,19 @@ class SDS011Sensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, _pin_tx); - _serial->begin(9600); - _ready = true; _dirty = false; } // Descriptive name of the sensor String description() const override { - char buffer[32]; - snprintf_P(buffer, sizeof(buffer), - PSTR("SDS011 @ SwSerial(%hhu,%hhu)"), _pin_rx, _pin_tx); - return String(buffer); + return F("SDS011"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(SDS011_PORT, 10); } // Type for slot # index @@ -103,8 +65,6 @@ class SDS011Sensor : public BaseSensor { return 0; } - - protected: // --------------------------------------------------------------------- @@ -156,10 +116,7 @@ class SDS011Sensor : public BaseSensor { double _p2dot5 = 0; double _p10 = 0; - unsigned char _pin_rx; - unsigned char _pin_tx; - std::unique_ptr _serial; - + Stream* _serial; }; #endif // SENSOR_SUPPORT && SDS011_SUPPORT diff --git a/code/espurna/sensors/SM300D2Sensor.h b/code/espurna/sensors/SM300D2Sensor.h index 3ba0ad92..a9025655 100644 --- a/code/espurna/sensors/SM300D2Sensor.h +++ b/code/espurna/sensors/SM300D2Sensor.h @@ -1,7 +1,6 @@ // ----------------------------------------------------------------------------- // SmartMeasure SM300D2-VO2 // https://es.aliexpress.com/item/32984571140.html -// Uses SoftwareSerial library // Copyright (C) 2021 by Xose Pérez // ----------------------------------------------------------------------------- @@ -9,24 +8,17 @@ #pragma once -#include - #include "BaseSensor.h" class SM300D2Sensor : public BaseSensor { public: - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - unsigned char getRX() const { - return _pin_rx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -41,47 +33,20 @@ class SM300D2Sensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - if (_serial) { - _serial.reset(nullptr); - } - - if (3 == _pin_rx) { - Serial.begin(SM300D2_BAUDRATE); - } else if (13 == _pin_rx) { - Serial.begin(SM300D2_BAUDRATE); - Serial.flush(); - Serial.swap(); - } else { - _serial = std::make_unique(_pin_rx, -1, false); - _serial->enableIntTx(false); - _serial->begin(SM300D2_BAUDRATE); - } - _ready = true; _dirty = false; - } // Descriptive name of the sensor String description() const override { - if (_serial_is_hardware()) { - return F("SM300D2 @ HwSerial"); - } - - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("SM300D2 @ SwSerial(%hhu,NULL)"), _pin_rx); - return String(buffer); + return F("SM300D2"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char index) const override { - char buffer[4]; - snprintf_P(buffer, sizeof(buffer), PSTR("%hhu"), _pin_rx); - return String(buffer); + return String(SM300D2_PORT, 10); } // Type for slot # index @@ -119,36 +84,6 @@ class SM300D2Sensor : public BaseSensor { // Protected // --------------------------------------------------------------------- - bool _serial_is_hardware() const { - return (3 == _pin_rx) || (13 == _pin_rx); - } - - bool _serial_available() const { - if (_serial_is_hardware()) { - return Serial.available(); - } else { - return _serial->available(); - } - } - - void _serial_flush() { - if (_serial_is_hardware()) { - return Serial.flush(); - } else { - return _serial->flush(); - } - } - - uint8_t _serial_read() const { - if (_serial_is_hardware()) { - return Serial.read(); - } else { - return _serial->read(); - } - } - - // --------------------------------------------------------------------- - void _parse() { #if SENSOR_DEBUG @@ -201,9 +136,9 @@ class SM300D2Sensor : public BaseSensor { void _read() { - while(_serial_available()) { + while(_serial->available()) { - unsigned char ch = _serial_read(); + unsigned char ch = _serial->read(); if ((_position > 0) || (ch == 0x3C)) { _buffer[_position] = ch; _position++; @@ -231,8 +166,7 @@ class SM300D2Sensor : public BaseSensor { double _temperature = 0; double _humidity = 0; - unsigned char _pin_rx = SM300D2_RX_PIN; - std::unique_ptr _serial; + Stream* _serial { nullptr }; }; diff --git a/code/espurna/sensors/SenseAirSensor.h b/code/espurna/sensors/SenseAirSensor.h index d0dfc30f..833c6bf6 100644 --- a/code/espurna/sensors/SenseAirSensor.h +++ b/code/espurna/sensors/SenseAirSensor.h @@ -1,6 +1,5 @@ // ----------------------------------------------------------------------------- // SenseAir S8 CO2 Sensor -// Uses SoftwareSerial library // Contribution by Yonsm Guo // ----------------------------------------------------------------------------- @@ -8,11 +7,8 @@ #pragma once -#include - #include "BaseSensor.h" - // SenseAir sensor utils. Notice that we only read a single register. // 0xFE is the address aka "Any sensor" class SenseAir { @@ -127,28 +123,11 @@ private: class SenseAirSensor : public BaseSensor, SenseAir { public: - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - unsigned char getTX() const { - return _pin_tx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -163,19 +142,8 @@ class SenseAirSensor : public BaseSensor, SenseAir { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, _pin_tx, false); - _serial->enableIntTx(false); - _serial->begin(9600); - _serial->enableRx(true); - _serial->setTimeout(200); - _startTime = TimeSource::now(); _warmedUp = false; @@ -185,18 +153,12 @@ class SenseAirSensor : public BaseSensor, SenseAir { // Descriptive name of the sensor String description() const override { - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("SenseAir S8 @ SwSerial(%hhu,%hhu)"), _pin_rx, _pin_tx); - return String(buffer); + return F("SenseAir"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(SENSEAIR_PORT, 10); } // Type for slot # index @@ -249,16 +211,12 @@ class SenseAirSensor : public BaseSensor, SenseAir { } private: - - std::unique_ptr _serial; + Stream* _serial; using TimeSource = espurna::time::CoreClock; TimeSource::time_point _startTime; bool _warmedUp = false; - unsigned char _pin_rx; - unsigned char _pin_tx; - int16_t _co2 = 0; int16_t _lastCo2 = 0; }; diff --git a/code/espurna/sensors/T6613Sensor.h b/code/espurna/sensors/T6613Sensor.h index 08ae081a..35823b63 100644 --- a/code/espurna/sensors/T6613Sensor.h +++ b/code/espurna/sensors/T6613Sensor.h @@ -1,7 +1,6 @@ // ----------------------------------------------------------------------------- // T6613 CO2 sensor // https://www.amphenol-sensors.com/en/telaire/co2/525-co2-sensor-modules/321-t6613 -// Uses SoftwareSerial library // Copyright (C) 2017-2019 by Xose Pérez // ----------------------------------------------------------------------------- @@ -9,11 +8,8 @@ #pragma once -#include - #include "BaseSensor.h" - class T6613Sensor : public BaseSensor { public: @@ -35,28 +31,11 @@ class T6613Sensor : public BaseSensor { using TimeSource = espurna::time::CoreClock; static constexpr auto Timeout = espurna::duration::Milliseconds(1000); - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setTX(unsigned char pin_tx) { - if (_pin_tx == pin_tx) return; - _pin_tx = pin_tx; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - unsigned char getTX() const { - return _pin_tx; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -71,37 +50,19 @@ class T6613Sensor : public BaseSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, _pin_tx, false); - _serial->enableIntTx(false); - _serial->begin(19200); - _ready = true; _dirty = false; - } // Descriptive name of the sensor String description() const override { - char buffer[32]; - snprintf_P(buffer, sizeof(buffer), - PSTR("T6613 @ SwSerial(%hhu,%hhu)"), - _pin_rx, _pin_tx); - return String(buffer); + return F("T6613"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - char buffer[8]; - snprintf_P(buffer, sizeof(buffer), - PSTR("%hhu:%hhu"), _pin_rx, _pin_tx); - return String(buffer); + return String(T6613_PORT, 10); } // Type for slot # index @@ -191,9 +152,7 @@ class T6613Sensor : public BaseSensor { } double _co2 = 0; - unsigned char _pin_rx; - unsigned char _pin_tx; - std::unique_ptr _serial; + Stream* _serial { nullptr }; }; diff --git a/code/espurna/sensors/V9261FSensor.h b/code/espurna/sensors/V9261FSensor.h index 5f52198e..c9a7f4e2 100644 --- a/code/espurna/sensors/V9261FSensor.h +++ b/code/espurna/sensors/V9261FSensor.h @@ -7,8 +7,6 @@ #pragma once -#include - #include "BaseEmonSensor.h" #include "../libs/fs_math.h" @@ -34,30 +32,11 @@ class V9261FSensor : public BaseEmonSensor { BaseEmonSensor(Magnitudes) {} - // --------------------------------------------------------------------- - - void setRX(unsigned char pin_rx) { - if (_pin_rx == pin_rx) return; - _pin_rx = pin_rx; + void setPort(Stream* port) { + _serial = port; _dirty = true; } - void setInverted(bool inverted) { - if (_inverted == inverted) return; - _inverted = inverted; - _dirty = true; - } - - // --------------------------------------------------------------------- - - unsigned char getRX() const { - return _pin_rx; - } - - bool getInverted() const { - return _inverted; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- @@ -72,34 +51,20 @@ class V9261FSensor : public BaseEmonSensor { // Initialization method, must be idempotent void begin() override { - if (!_dirty) return; - - if (_serial) { - _serial.reset(nullptr); - } - - _serial = std::make_unique(_pin_rx, -1, _inverted); - _serial->enableIntTx(false); - _serial->begin(V9261F_BAUDRATE); - _reading = false; _ready = true; _dirty = false; - } // Descriptive name of the sensor String description() const override { - char buffer[28]; - snprintf_P(buffer, sizeof(buffer), - PSTR("V9261F @ SwSerial(%u,NULL)"), _pin_rx); - return String(buffer); + return F("V9261F"); } // Address of the sensor (it could be the GPIO or I2C address) String address(unsigned char) const override { - return String(_pin_rx, 10); + return String(V9261F_PORT, 10); } // Loop-like method, call it in your main loop @@ -302,9 +267,7 @@ class V9261FSensor : public BaseEmonSensor { // --------------------------------------------------------------------- - unsigned char _pin_rx { V9261F_PIN }; - bool _inverted { V9261F_PIN_INVERSE }; - std::unique_ptr _serial; + Stream* _serial { nullptr }; using TimeSource = espurna::time::CoreClock; static constexpr auto SyncInterval = TimeSource::duration { V9261F_SYNC_INTERVAL }; diff --git a/code/espurna/terminal.cpp b/code/espurna/terminal.cpp index 1766e268..a9df3864 100644 --- a/code/espurna/terminal.cpp +++ b/code/espurna/terminal.cpp @@ -48,7 +48,9 @@ constexpr size_t serialBufferSize() { return TERMINAL_SERIAL_BUFFER_SIZE; } -Stream& SerialPort = TERMINAL_SERIAL_PORT; +constexpr size_t serialPort() { + return TERMINAL_SERIAL_PORT - 1; +} } // namespace build @@ -381,11 +383,22 @@ void setup() { #if TERMINAL_SERIAL_SUPPORT namespace serial { -void loop() { +using LoopFunc = void(*)(); +void empty_loop() { +} + +namespace internal { + +Stream* stream { nullptr }; +LoopFunc loop { empty_loop }; + +} // namespace internal + +void processing_loop() { using LineBuffer = LineBuffer; static LineBuffer buffer; - static auto& port = build::SerialPort; + auto& port = *internal::stream; #if defined(ARDUINO_ESP8266_RELEASE_2_7_2) \ || defined(ARDUINO_ESP8266_RELEASE_2_7_3) \ @@ -428,6 +441,20 @@ void loop() { } } +void loop() { + internal::loop(); +} + +void setup() { + auto port = uartPort(build::serialPort()); + if (!port || (!port->rx || !port->tx)) { + return; + } + + internal::stream = port->stream; + internal::loop = processing_loop; +} + } // namespace serial #endif @@ -705,12 +732,15 @@ void setup() { void loop() { #if TERMINAL_SERIAL_SUPPORT - // TODO: check if something else is using this port? serial::loop(); #endif } void setup() { +#if TERMINAL_SERIAL_SUPPORT + serial::setup(); +#endif + #if WEB_SUPPORT // Show DEBUG panel with input web::setup(); diff --git a/code/espurna/tuya.cpp b/code/espurna/tuya.cpp index 4a0df235..68617615 100644 --- a/code/espurna/tuya.cpp +++ b/code/espurna/tuya.cpp @@ -40,8 +40,6 @@ namespace tuya { return false; } - constexpr unsigned long SerialSpeed { 9600u }; - constexpr unsigned long DiscoveryTimeout { 1500u }; constexpr unsigned long HeartbeatSlow { 9000u }; @@ -66,7 +64,7 @@ namespace tuya { String value; }; - Transport tuyaSerial(TUYA_SERIAL); + Transport* tuyaSerial { nullptr }; std::priority_queue outputFrames; template @@ -429,19 +427,18 @@ error: } void processSerial(State& state) { + while (tuyaSerial->available()) { - while (tuyaSerial.available()) { + tuyaSerial->read(); - tuyaSerial.read(); - - if (tuyaSerial.done()) { - processFrame(state, tuyaSerial); - tuyaSerial.reset(); + if (tuyaSerial->done()) { + processFrame(state, *tuyaSerial); + tuyaSerial->reset(); } - if (tuyaSerial.full()) { - tuyaSerial.rewind(); - tuyaSerial.reset(); + if (tuyaSerial->full()) { + tuyaSerial->rewind(); + tuyaSerial->reset(); } } @@ -462,7 +459,7 @@ error: // flush serial buffer before transmitting anything // send fast heartbeat until mcu responds with something case State::INIT: - tuyaSerial.rewind(); + tuyaSerial->rewind(); state = State::BOOT; case State::BOOT: sendHeartbeat(Heartbeat::Boot); @@ -509,10 +506,10 @@ error: } } - if (TUYA_SERIAL && !outputFrames.empty()) { + if (!outputFrames.empty()) { auto& frame = outputFrames.top(); dataframeDebugSend("=>", frame); - tuyaSerial.write(frame.serialize()); + tuyaSerial->write(frame.serialize()); outputFrames.pop(); } @@ -658,6 +655,15 @@ error: #endif void setup() { + const auto port = uartPort(TUYA_PORT - 1); + + // No point starting up when port is unusable + if (!port || (!port->tx || !port->rx)) { + return; + } + + tuyaSerial = new Transport(*port->stream); + #if TERMINAL_SUPPORT tuya::terminalSetup(); #endif @@ -669,8 +675,7 @@ error: filter = getSetting("tuyaFilter", 1 == TUYA_FILTER_ENABLED); // Install main loop method and WiFiStatus ping (only works with specific mode) - TUYA_SERIAL.begin(SerialSpeed); - + ::espurnaRegisterLoop(loop); ::wifiRegister([](espurna::wifi::Event event) { switch (event) { diff --git a/code/espurna/uart.cpp b/code/espurna/uart.cpp new file mode 100644 index 00000000..ee0cadc2 --- /dev/null +++ b/code/espurna/uart.cpp @@ -0,0 +1,566 @@ +/* + +UART MODULE + +Copyright (C) 2022 by Maxim Prokhorov + +*/ + +#include "espurna.h" + +#if UART_SUPPORT + +#include "uart.h" +#include "utils.h" + +#if UART_SOFTWARE_SUPPORT +#include +#endif + +#include +#include + +namespace espurna { +namespace driver { +namespace uart { +namespace { + +enum class Parity { + None, + Even, + Odd, +}; + +struct Config { + uint8_t data_bits; + Parity parity; + uint8_t stop_bits; +}; + +} // namespace +} // namespace uart +} // namespace driver + +namespace settings { +namespace internal { +namespace { + +alignas(4) static constexpr char ParityNone[] PROGMEM = "none"; +alignas(4) static constexpr char ParityEven[] PROGMEM = "even"; +alignas(4) static constexpr char ParityOdd[] PROGMEM = "odd"; + +static constexpr std::array, 3> ParityOptions PROGMEM { + {{driver::uart::Parity::None, ParityNone}, + {driver::uart::Parity::Even, ParityEven}, + {driver::uart::Parity::Odd, ParityOdd}} +}; + +} // namespace + +template <> +driver::uart::Parity convert(const String& value) { + return convert(ParityOptions, value, driver::uart::Parity::None); +} + +String serialize(driver::uart::Parity value) { + return espurna::settings::internal::serialize(ParityOptions, value); +} + +} // namespace internal +} // namespace settings + +namespace driver { +namespace uart { +namespace { + +namespace build { + +// i.e. uart0, uart1 and a single sw port +// for general use, hardware uart *should* be prefered method +constexpr size_t PortsMax { 3 }; + +// todo; technically, tx==2 is also possible +// but, we reserve that for the uart1 TX-only interface +constexpr bool uart0_normal(uint8_t tx, uint8_t rx) { + return ((tx == 1) && (rx == 3)) + || ((tx == GPIO_NONE) && (rx == 3)) + || ((tx == 1) && (rx == GPIO_NONE)); +} + +constexpr bool uart0_swapped(uint8_t tx, uint8_t rx) { + return ((tx == 15) && (rx == 13)) + || ((tx == GPIO_NONE) && (rx == 13)) + || ((tx == 15) && (rx == GPIO_NONE)); +} + +constexpr bool uart1_normal(uint8_t tx, uint8_t rx) { + return (tx == 2) && (rx == GPIO_NONE); +} + +constexpr uint8_t tx(size_t index) { + return (0 == index) ? (UART1_TX_PIN) : + (1 == index) ? (UART2_TX_PIN) : + (2 == index) ? (UART3_TX_PIN) : + GPIO_NONE; +} + +constexpr uint8_t rx(size_t index) { + return (0 == index) ? (UART1_RX_PIN) : + (1 == index) ? (UART2_RX_PIN) : + (2 == index) ? (UART3_RX_PIN) : + GPIO_NONE; +} + +constexpr uint32_t baudrate(size_t index) { + return (0 == index) ? (UART1_BAUDRATE) : + (1 == index) ? (UART2_BAUDRATE) : + (2 == index) ? (UART3_BAUDRATE) : + 0; +} + +constexpr uint8_t data_bits(size_t index) { + return (0 == index) ? (UART1_DATA_BITS) : + (1 == index) ? (UART2_DATA_BITS) : + (2 == index) ? (UART3_DATA_BITS) + : 0; +} + +constexpr Parity parity(size_t index) { + return (0 == index) ? (Parity::UART1_PARITY) : + (1 == index) ? (Parity::UART2_PARITY) : + (2 == index) ? (Parity::UART3_PARITY) + : Parity::None; +} + +constexpr uint8_t stop_bits(size_t index) { + return (0 == index) ? (UART1_STOP_BITS) : + (1 == index) ? (UART2_STOP_BITS) : + (2 == index) ? (UART3_STOP_BITS) + : 0; +} + +constexpr bool invert(size_t index) { + return (0 == index) ? (UART1_INVERT == 1) : + (1 == index) ? (UART2_INVERT == 1) : + (2 == index) ? (UART3_INVERT == 1) + : false; +} + +} // namespace build + +constexpr int data_bits_from_config(uint8_t bits) { + return (bits == 5) ? 0 : + (bits == 6) ? 0b100 : + (bits == 7) ? 0b1000 : + (bits == 8) ? 0b1100 : + data_bits_from_config(8); +} + +constexpr int parity_from_config(Parity parity) { + return (parity == Parity::None) ? 0 : + (parity == Parity::Even) ? 0b10 : + (parity == Parity::Odd) ? 0b11 : + parity_from_config(Parity::None); +} + +constexpr int stop_bits_from_config(uint8_t bits) { + return (bits == 1) ? 0b10000 : + (bits == 2) ? 0b110000 : + stop_bits_from_config(1); +} + +template +constexpr T from_config(Config); + +template <> +constexpr ::SerialConfig from_config(Config config) { + return static_cast<::SerialConfig>( + data_bits_from_config(config.data_bits) + | parity_from_config(config.parity) + | stop_bits_from_config(config.stop_bits)); +} + +namespace settings { +namespace keys { + +alignas(4) static constexpr char TxPin[] PROGMEM = "uartTx"; +alignas(4) static constexpr char RxPin[] PROGMEM = "uartRx"; + +alignas(4) static constexpr char Baudrate[] PROGMEM = "uartBaud"; + +alignas(4) static constexpr char DataBits[] PROGMEM = "uartDataBits"; +alignas(4) static constexpr char StopBits[] PROGMEM = "uartStopBits"; +alignas(4) static constexpr char Parity[] PROGMEM = "uartParity"; + +alignas(4) static constexpr char Invert[] PROGMEM = "uartInv"; + +} // namespace keys + +uint8_t tx(size_t index) { + return getSetting({keys::TxPin, index}, build::tx(index)); +} + +uint8_t rx(size_t index) { + return getSetting({keys::RxPin, index}, build::rx(index)); +} + +uint32_t baudrate(size_t index) { + return getSetting({keys::Baudrate, index}, build::baudrate(index)); +} + +uint8_t data_bits(size_t index) { + return getSetting({keys::DataBits, index}, build::data_bits(index)); +} + +uint8_t stop_bits(size_t index) { + return getSetting({keys::StopBits, index}, build::stop_bits(index)); +} + +Parity parity(size_t index) { + return getSetting({keys::Parity, index}, build::parity(index)); +} + +bool invert(size_t index) { + return getSetting({keys::Invert, index}, build::invert(index)); +} + +} // namespace settings + +using StreamPtr = std::unique_ptr; + +struct BasePort { + Type type; + bool tx; + bool rx; + StreamPtr stream; +}; + +using BasePortPtr = std::unique_ptr; + +BasePortPtr hardware_port( + uint32_t baudrate, uint8_t tx, uint8_t rx, Config config, bool invert) +{ + const int number = + build::uart0_normal(tx, rx) + ? 0 : + build::uart0_swapped(tx, rx) + ? 0 : + build::uart1_normal(tx, rx) + ? 1 + : -1; + if (number < 0) { + return nullptr; + } + + const int mode = + (tx == GPIO_NONE) + ? SERIAL_RX_ONLY : + (rx == GPIO_NONE) + ? SERIAL_TX_ONLY : + ((tx != GPIO_NONE) && (rx != GPIO_NONE)) + ? SERIAL_FULL + : -1; + if (mode < 0) { + return nullptr; + } + + auto* ptr = new HardwareSerial(number); + ptr->begin(baudrate, + from_config<::SerialConfig>(config), + static_cast(mode), + tx, invert); + if ((number == 0) && (build::uart0_swapped(tx, rx))) { + ptr->flush(); + ptr->swap(); + } + + return std::make_unique( + BasePort{ + .type = (number == 0) ? Type::Uart0 : Type::Uart1, + .tx = (tx != GPIO_NONE), + .rx = (rx != GPIO_NONE), + .stream = StreamPtr(ptr), + }); +} + +// based on the values in v6 of the lib. still, return bits instead of the octal notation used there +#if UART_SOFTWARE_SUPPORT +constexpr int software_serial_data_bits_from_config(uint8_t bits) { + return (bits == 5) ? 0 : + (bits == 6) ? 0b1 : + (bits == 7) ? 0b10 : + (bits == 8) ? 0b11 : + software_serial_data_bits_from_config(8); +} + +// btw, SoftwareSerial also has Mark and Space +// no support on the hardware peripheral though (afaik) +constexpr int software_serial_parity_from_config(Parity parity) { + return (parity == Parity::None) ? 0 : + (parity == Parity::Even) ? 0b10000 : + (parity == Parity::Odd) ? 0b11000 : + software_serial_parity_from_config(Parity::None); +} + +constexpr int software_serial_stop_bits_from_config(uint8_t bits) { + return (bits == 1) ? 0b0 : + (bits == 2) ? 0b10000000 : + software_serial_stop_bits_from_config(1); +} + +template <> +constexpr ::SoftwareSerialConfig from_config(Config config) { + return static_cast<::SoftwareSerialConfig>( + software_serial_data_bits_from_config(config.data_bits) + | software_serial_parity_from_config(config.parity) + | software_serial_stop_bits_from_config(config.stop_bits)); + +} + +BasePortPtr software_serial_port( + uint32_t baudrate, uint8_t tx, uint8_t rx, Config config, bool invert) +{ + const int8_t tx_pin = (tx == GPIO_NONE) ? -1 : tx; + const int8_t rx_pin = (rx == GPIO_NONE) ? -1 : rx; + + auto* ptr = new SoftwareSerial(tx_pin, rx_pin, invert); + ptr->begin(baudrate, from_config<::SoftwareSerialConfig>(config)); + + return std::make_unique( + BasePort{ + .type = Type::Software, + .tx = (tx_pin > 0), + .rx = (rx_pin > 0), + .stream = StreamPtr(ptr), + }); +} +#endif + +BasePortPtr make_port(size_t index) { + BasePortPtr out; + + const auto tx = settings::tx(index); + const auto rx = settings::rx(index); + if ((tx == GPIO_NONE) && (rx == GPIO_NONE)) { + return out; + } + + if ((tx != GPIO_NONE) && !gpioLock(tx)) { + return out; + } + + if ((rx != GPIO_NONE) && !gpioLock(rx)) { + gpioUnlock(tx); + return out; + } + + const auto config = Config{ + .data_bits = settings::data_bits(index), + .parity = settings::parity(index), + .stop_bits = settings::stop_bits(index), + }; + + const auto baudrate = settings::baudrate(index); + const auto invert = settings::invert(index); + + if (build::uart0_normal(tx, rx) + || build::uart0_swapped(tx, rx) + || build::uart1_normal(tx, rx)) + { + out = hardware_port(baudrate, tx, rx, config, invert); + } +#if UART_SOFTWARE_SUPPORT + else { + out = software_serial_port(baudrate, tx, rx, config, invert); + } +#endif + + return out; +} + +namespace internal { + +BasePortPtr ports[build::PortsMax]; + +} // namespace internal + +size_t ports() { + size_t out = 0; + for (const auto& port : internal::ports) { + if (!port) { + break; + } + ++out; + } + + return out; +} + +namespace settings { +namespace query { + +#define ID_VALUE(NAME)\ +String NAME (size_t id) {\ + return espurna::settings::internal::serialize(\ + espurna::driver::uart::settings::NAME(id));\ +} + +ID_VALUE(tx) +ID_VALUE(rx) +ID_VALUE(baudrate) +ID_VALUE(data_bits) +ID_VALUE(stop_bits) +ID_VALUE(parity) +ID_VALUE(invert) + +#undef ID_VALUE + +static constexpr espurna::settings::query::IndexedSetting IndexedSettings[] PROGMEM { + {keys::TxPin, query::tx}, + {keys::RxPin, query::rx}, + {keys::Baudrate, query::baudrate}, + {keys::DataBits, query::data_bits}, + {keys::StopBits, query::stop_bits}, + {keys::Parity, query::parity}, + {keys::Invert, query::invert}, +}; + +bool checkSamePrefix(StringView key) { + alignas(4) static constexpr char Prefix[] PROGMEM = "uart"; + return espurna::settings::query::samePrefix(key, Prefix); +} + +String findIndexedValueFrom(StringView key) { + return espurna::settings::query::IndexedSetting::findValueFrom( + ports(), IndexedSettings, key); + +} + +void setup() { + settingsRegisterQueryHandler({ + .check = checkSamePrefix, + .get = findIndexedValueFrom, + }); +} + +} // namespace query +} // namespace settings + +#if TERMINAL_SUPPORT +namespace terminal { +namespace commands { + +String port_type(Type type) { + const char* out = PSTR("UNKNOWN"); + + switch (type) { + case Type::Unknown: + break; + case Type::Software: + out = PSTR("SOFTWARE"); + break; + case Type::Uart0: + out = PSTR("UART0"); + break; + case Type::Uart1: + out = PSTR("UART1"); + break; + } + + return out; +} + +void uart(::terminal::CommandContext&& ctx) { + if (ctx.argv.size() == 1) { + for (size_t index = 0; index < std::size(internal::ports); ++index) { + const auto& port = internal::ports[index]; + if (!port) { + break; + } + + ctx.output.printf_P( + PSTR("%zu - %s{tx=%c rx=%c}\n"), + index, port_type(port->type).c_str(), + port->tx ? 'y' : 'n', + port->rx ? 'y' : 'n'); + } + + } else if (ctx.argv.size() == 2) { + const auto parse_id = espurna::settings::internal::convert; + const auto id = parse_id(ctx.argv[1]); + if (id >= ports()) { + terminalError(ctx, F("Invalid ID")); + return; + } + + settingsDump(ctx, settings::query::IndexedSettings, id); + } else { + terminalError(ctx, F("UART []")); + return; + } + + terminalOK(ctx); +} + +alignas(4) static constexpr char Uart[] PROGMEM = "UART"; + +static constexpr ::terminal::Command List[] PROGMEM { + {Uart, commands::uart}, +}; + +} // namespace commands + +void setup() { + espurna::terminal::add(commands::List); +} + +} // namespace terminal +#endif + +PortPtr port(size_t index) { + const auto& ptr = internal::ports[index]; + if ((index < std::size(internal::ports)) && (ptr)) { + return std::make_unique( + Port{ + .type = ptr->type, + .tx = ptr->tx, + .rx = ptr->rx, + .stream = ptr->stream.get(), + }); + } + + return nullptr; +} + +void setup() { +#if TERMINAL_SUPPORT + terminal::setup(); +#endif + + settings::query::setup(); + + for (size_t index = 0; index < build::PortsMax; ++index) { + auto& port = internal::ports[index]; + + port = make_port(index); + if (!port) { + break; + } + } +} + +} // namespace uart + +} // namespace +} // namespace driver +} // namespace espurna + +espurna::driver::uart::PortPtr uartPort(size_t index) { + return espurna::driver::uart::port(index); +} + +void uartSetup() { + espurna::driver::uart::setup(); +} + +#endif // UART_SUPPORT diff --git a/code/espurna/uart.h b/code/espurna/uart.h new file mode 100644 index 00000000..b6140af3 --- /dev/null +++ b/code/espurna/uart.h @@ -0,0 +1,40 @@ +/* + +UART MODULE + +Copyright (C) 2022 by Maxim Prokhorov + +*/ + +#pragma once + +#include + +#include + +namespace espurna { +namespace driver { +namespace uart { + +enum class Type { + Unknown, + Software, + Uart0, + Uart1, +}; + +struct Port { + Type type; + bool tx; + bool rx; + Stream* stream; +}; + +using PortPtr = std::unique_ptr; + +} // namespace uart +} // namespace driver +} // namespace espurna + +espurna::driver::uart::PortPtr uartPort(size_t index); +void uartSetup(); diff --git a/code/espurna/uartmqtt.cpp b/code/espurna/uartmqtt.cpp index 6ae50047..3eff77ce 100644 --- a/code/espurna/uartmqtt.cpp +++ b/code/espurna/uartmqtt.cpp @@ -20,10 +20,6 @@ Support queueing and handling input without termination by Maxim Prokhorov #include -#if UART_MQTT_SOFTWARE_SERIAL -#include -#endif - namespace espurna { namespace uart_mqtt { namespace { @@ -44,24 +40,6 @@ constexpr uint8_t TerminateOut { UART_MQTT_TERMINATE_OUT }; constexpr bool Encode { UART_MQTT_ENCODE }; constexpr bool Decode { UART_MQTT_DECODE }; -constexpr size_t Baudrate PROGMEM { UART_MQTT_BAUDRATE }; -constexpr auto Config PROGMEM = UART_MQTT_CONFIG; - -constexpr uint8_t RxPin { UART_MQTT_RX_PIN }; -constexpr uint8_t TxPin { UART_MQTT_TX_PIN }; - -constexpr bool uart0_normal() { - return (build::TxPin == 1) && (build::RxPin == 3); -} - -constexpr bool uart0_swapped() { - return (build::TxPin == 15) && (build::RxPin == 13); -} - -HardwareSerial& uart0() { - return Serial; -} - } // namespace build // Output is capped, prepare using a fixed-size buffer @@ -75,62 +53,13 @@ using Buffer = std::array; // Prefer smaller output instead of using `Serialized` directly using Queue = std::queue; -#if UART_MQTT_SOFTWARE_SERIAL -Stream& software_serial_port() { - static auto& port = ([]() -> Stream& { - auto* port = new SoftwareSerial(build::RxPin, build::TxPin); - port->begin(build::Baudrate, SWSERIAL_8N1); - return *port; - })(); - - return port; -} -#endif - -#if __cplusplus >= 201703L -#define CONSTEXPR constexpr -#else -#define CONSTEXPR -#endif - -Stream& hardware_port() { - // TODO: instantiate port outside of here, without Arduino config stuff - // TODO: this swap() thing is esp8266-specific - static auto& port = ([]() -> Stream& { - auto& port = build::uart0(); - - port.begin(build::Baudrate, build::Config); - if CONSTEXPR (build::uart0_swapped()) { - port.flush(); - port.swap(); - } - - return port; - })(); - - return port; -} - -Stream& port() { -#if UART_MQTT_SOFTWARE_SERIAL - if CONSTEXPR (build::uart0_normal() || build::uart0_swapped()) { - return hardware_port(); - } - - return software_serial_port(); -#else - return hardware_port(); -#endif -} - -#undef CONSTEXPR - namespace internal { Buffer buffer; auto cursor = buffer.begin(); Queue queue; +Stream* port; } // namespace internal @@ -278,7 +207,7 @@ void enqueue(String data) { internal::queue.emplace(std::move(data)); } -void write(Stream& stream, uint8_t termination, bool decode) { +void write(Print& print, uint8_t termination, bool decode) { using Clock = time::CoreClock; const auto start = Clock::now(); @@ -291,16 +220,16 @@ void write(Stream& stream, uint8_t termination, bool decode) { decoded.data(), decoded.size()); if (size) { - stream.write(decoded.data(), size); + print.write(decoded.data(), size); } if (size && termination) { - stream.write(termination); + print.write(termination); } } else { - stream.write(front.begin(), front.length()); + print.write(front.begin(), front.length()); if (termination) { - stream.write(termination); + print.write(termination); } } @@ -326,15 +255,22 @@ void mqtt_callback(unsigned int type, const char* topic, const char* payload) { } void loop() { - read(port(), + read(*internal::port, build::TerminateIn, build::Encode); - write(port(), + write(*internal::port, build::TerminateOut, build::Decode); } void setup() { + const auto port = uartPort(UART_MQTT_PORT - 1); + if (!port || (!port->rx || !port->tx)) { + return; + } + + internal::port = port->stream; + mqttRegister(mqtt_callback); espurnaRegisterLoop(loop); } diff --git a/code/espurna/web.cpp b/code/espurna/web.cpp index 7648cdd7..4c557c05 100644 --- a/code/espurna/web.cpp +++ b/code/espurna/web.cpp @@ -96,7 +96,7 @@ bool AsyncWebPrint::_addBuffer() { // - Returning 0 will immediatly close the connection from our side // - Calling _prepareRequest() **before** _buffers are filled will result in returning 0 // - Calling yield() / delay() while request AsyncWebPrint is active **may** trigger this callback out of sequence -// (e.g. Serial.print(..), DEBUG_MSG(...), or any other API trying to switch contexts) +// (e.g. Stream.write(...), Stream.read(...), DEBUG_MSG(...), or any other API trying to switch contexts) // - Receiving data (tcp ack from the previous packet) **will** trigger the callback when switching contexts. void AsyncWebPrint::_prepareRequest() { diff --git a/code/platformio.ini b/code/platformio.ini index e10beafd..5df3c503 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -152,7 +152,6 @@ shared_lib_deps = https://github.com/256dpi/arduino-mqtt#196556b6 https://github.com/mcspr/nofuss.git#0.4.0 paulstoffregen/OneWire@^2.3.5 - olehs/PZEM004T@^1.1.5 knolleary/PubSubClient@^2.8.0 https://github.com/1technophile/rc-switch#11402652 lowpowerlab/SPIFlash@^101.1.3 diff --git a/code/test/build/rfbridge.h b/code/test/build/rfbridge.h index fe79bdd5..f304cdb4 100644 --- a/code/test/build/rfbridge.h +++ b/code/test/build/rfbridge.h @@ -1,5 +1,4 @@ #define DUMMY_RELAY_COUNT 8 -#define SERIAL_BAUDRATE 19200 -#define DEBUG_SERIAL_SUPPORT 0 +#define RELAY_SUPPORT 1 #define RFB_SUPPORT 1 #define RFB_PROVIDER RFB_PROVIDER_EFM8BB1