diff --git a/boards.txt b/boards.txt index 1d1540dc783..f59fdad841b 100644 --- a/boards.txt +++ b/boards.txt @@ -10018,3 +10018,104 @@ franzininho_wifi_msc_esp32s2.menu.DebugLevel.verbose=Verbose franzininho_wifi_msc_esp32s2.menu.DebugLevel.verbose.build.code_debug=5 ############################################################## + +sonoff_dualr3.name=Sonoff DUALR3 + +sonoff_dualr3.upload.tool=esptool_py +sonoff_dualr3.upload.maximum_size=1310720 +sonoff_dualr3.upload.maximum_data_size=327680 +sonoff_dualr3.upload.flags= +sonoff_dualr3.upload.extra_flags= + +sonoff_dualr3.serial.disableDTR=true +sonoff_dualr3.serial.disableRTS=true + +sonoff_dualr3.build.tarch=xtensa +sonoff_dualr3.build.bootloader_addr=0x1000 +sonoff_dualr3.build.target=esp32 +sonoff_dualr3.build.mcu=esp32 +sonoff_dualr3.build.core=esp32 +sonoff_dualr3.build.variant=esp32 +sonoff_dualr3.build.board=SONOFF_DUALR3 + +sonoff_dualr3.build.f_cpu=240000000L +sonoff_dualr3.build.flash_size=4MB +sonoff_dualr3.build.flash_freq=40m +sonoff_dualr3.build.flash_mode=dio +sonoff_dualr3.build.boot=dio +sonoff_dualr3.build.partitions=rainmaker +sonoff_dualr3.build.defines= +sonoff_dualr3.build.loop_core= +sonoff_dualr3.build.event_core= + +sonoff_dualr3.menu.PartitionScheme.rainmaker=RainMaker +sonoff_dualr3.menu.PartitionScheme.rainmaker.build.partitions=rainmaker +sonoff_dualr3.menu.PartitionScheme.rainmaker.upload.maximum_size=3145728 + +sonoff_dualr3.menu.CPUFreq.240=240MHz (WiFi/BT) +sonoff_dualr3.menu.CPUFreq.240.build.f_cpu=240000000L +sonoff_dualr3.menu.CPUFreq.160=160MHz (WiFi/BT) +sonoff_dualr3.menu.CPUFreq.160.build.f_cpu=160000000L +sonoff_dualr3.menu.CPUFreq.80=80MHz (WiFi/BT) +sonoff_dualr3.menu.CPUFreq.80.build.f_cpu=80000000L +sonoff_dualr3.menu.CPUFreq.40=40MHz (40MHz XTAL) +sonoff_dualr3.menu.CPUFreq.40.build.f_cpu=40000000L +sonoff_dualr3.menu.CPUFreq.26=26MHz (26MHz XTAL) +sonoff_dualr3.menu.CPUFreq.26.build.f_cpu=26000000L +sonoff_dualr3.menu.CPUFreq.20=20MHz (40MHz XTAL) +sonoff_dualr3.menu.CPUFreq.20.build.f_cpu=20000000L +sonoff_dualr3.menu.CPUFreq.13=13MHz (26MHz XTAL) +sonoff_dualr3.menu.CPUFreq.13.build.f_cpu=13000000L +sonoff_dualr3.menu.CPUFreq.10=10MHz (40MHz XTAL) +sonoff_dualr3.menu.CPUFreq.10.build.f_cpu=10000000L + +sonoff_dualr3.menu.FlashMode.qio=QIO +sonoff_dualr3.menu.FlashMode.qio.build.flash_mode=dio +sonoff_dualr3.menu.FlashMode.qio.build.boot=qio +sonoff_dualr3.menu.FlashMode.dio=DIO +sonoff_dualr3.menu.FlashMode.dio.build.flash_mode=dio +sonoff_dualr3.menu.FlashMode.dio.build.boot=dio +sonoff_dualr3.menu.FlashMode.qout=QOUT +sonoff_dualr3.menu.FlashMode.qout.build.flash_mode=dout +sonoff_dualr3.menu.FlashMode.qout.build.boot=qout +sonoff_dualr3.menu.FlashMode.dout=DOUT +sonoff_dualr3.menu.FlashMode.dout.build.flash_mode=dout +sonoff_dualr3.menu.FlashMode.dout.build.boot=dout + +sonoff_dualr3.menu.FlashFreq.80=80MHz +sonoff_dualr3.menu.FlashFreq.80.build.flash_freq=80m +sonoff_dualr3.menu.FlashFreq.40=40MHz +sonoff_dualr3.menu.FlashFreq.40.build.flash_freq=40m + +sonoff_dualr3.menu.FlashSize.4M=4MB (32Mb) +sonoff_dualr3.menu.FlashSize.4M.build.flash_size=4MB + +sonoff_dualr3.menu.UploadSpeed.921600=921600 +sonoff_dualr3.menu.UploadSpeed.921600.upload.speed=921600 +sonoff_dualr3.menu.UploadSpeed.115200=115200 +sonoff_dualr3.menu.UploadSpeed.115200.upload.speed=115200 +sonoff_dualr3.menu.UploadSpeed.256000.windows=256000 +sonoff_dualr3.menu.UploadSpeed.256000.upload.speed=256000 +sonoff_dualr3.menu.UploadSpeed.230400.windows.upload.speed=256000 +sonoff_dualr3.menu.UploadSpeed.230400=230400 +sonoff_dualr3.menu.UploadSpeed.230400.upload.speed=230400 +sonoff_dualr3.menu.UploadSpeed.460800.linux=460800 +sonoff_dualr3.menu.UploadSpeed.460800.macosx=460800 +sonoff_dualr3.menu.UploadSpeed.460800.upload.speed=460800 +sonoff_dualr3.menu.UploadSpeed.512000.windows=512000 +sonoff_dualr3.menu.UploadSpeed.512000.upload.speed=512000 + +sonoff_dualr3.menu.DebugLevel.none=None +sonoff_dualr3.menu.DebugLevel.none.build.code_debug=0 +sonoff_dualr3.menu.DebugLevel.error=Error +sonoff_dualr3.menu.DebugLevel.error.build.code_debug=1 +sonoff_dualr3.menu.DebugLevel.warn=Warn +sonoff_dualr3.menu.DebugLevel.warn.build.code_debug=2 +sonoff_dualr3.menu.DebugLevel.info=Info +sonoff_dualr3.menu.DebugLevel.info.build.code_debug=3 +sonoff_dualr3.menu.DebugLevel.debug=Debug +sonoff_dualr3.menu.DebugLevel.debug.build.code_debug=4 +sonoff_dualr3.menu.DebugLevel.verbose=Verbose +sonoff_dualr3.menu.DebugLevel.verbose.build.code_debug=5 + +############################################################## diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/.skip.esp32c3 b/libraries/RainMaker/examples/RMakerSonoffDualR3/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/.skip.esp32s2 b/libraries/RainMaker/examples/RMakerSonoffDualR3/.skip.esp32s2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino b/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino new file mode 100644 index 00000000000..37eda40134b --- /dev/null +++ b/libraries/RainMaker/examples/RMakerSonoffDualR3/RMakerSonoffDualR3.ino @@ -0,0 +1,193 @@ +//This example demonstrates the ESP RainMaker with a standard Switch device. +#include "RMaker.h" +#include "WiFi.h" +#include "WiFiProv.h" + +#define DEFAULT_POWER_MODE false +const char *service_name = "PROV_SONOFF_DUALR3"; +const char *pop = "123456"; + +// GPIO for push button +static uint8_t gpio_reset = 0; +// GPIO for switch +static uint8_t gpio_switch1 = 32; +static uint8_t gpio_switch2 = 33; +// GPIO for virtual device +static uint8_t gpio_relay1 = 27; +static uint8_t gpio_relay2 = 14; +/* Variable for reading pin status*/ +bool switch_state_ch1 = true; +bool switch_state_ch2 = true; +// GPIO for link status LED +static uint8_t gpio_led = 13; + +struct LightSwitch { + const uint8_t pin; + bool pressed; +}; + +// Define the light switches for channel 1 and 2 +LightSwitch switch_ch1 = {gpio_switch1, false}; +LightSwitch switch_ch2 = {gpio_switch2, false}; + +//The framework provides some standard device types like switch, lightbulb, fan, temperature sensor. +static Switch my_switch1("Switch_ch1", &gpio_relay1); +static Switch my_switch2("Switch_ch2", &gpio_relay2); + +void sysProvEvent(arduino_event_t *sys_event) +{ + switch (sys_event->event_id) { + case ARDUINO_EVENT_PROV_START: +#if CONFIG_IDF_TARGET_ESP32 + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); + printQR(service_name, pop, "ble"); +#else + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); + printQR(service_name, pop, "softap"); +#endif + break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + Serial.printf("\nConnected to Wi-Fi!\n"); + digitalWrite(gpio_led, true); + break; + } +} + +void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx) +{ + const char *device_name = device->getDeviceName(); + const char *param_name = param->getParamName(); + + if(strcmp(device_name, "Switch_ch1") == 0) { + + Serial.printf("Lightbulb = %s\n", val.val.b? "true" : "false"); + + if(strcmp(param_name, "Power") == 0) { + Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); + switch_state_ch1 = val.val.b; + (switch_state_ch1 == false) ? digitalWrite(gpio_relay1, LOW) : digitalWrite(gpio_relay1, HIGH); + param->updateAndReport(val); + } + + } else if(strcmp(device_name, "Switch_ch2") == 0) { + + Serial.printf("Switch value = %s\n", val.val.b? "true" : "false"); + + if(strcmp(param_name, "Power") == 0) { + Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); + switch_state_ch2 = val.val.b; + (switch_state_ch2 == false) ? digitalWrite(gpio_relay2, LOW) : digitalWrite(gpio_relay2, HIGH); + param->updateAndReport(val); + } + + } + +} + +void ARDUINO_ISR_ATTR isr(void* arg) { + LightSwitch* s = static_cast(arg); + s->pressed = true; +} + +void setup() +{ + uint32_t chipId = 0; + + Serial.begin(115200); + + // Configure the input GPIOs + pinMode(gpio_reset, INPUT); + pinMode(switch_ch1.pin, INPUT_PULLUP); + attachInterruptArg(switch_ch1.pin, isr, &switch_ch1, CHANGE); + pinMode(switch_ch2.pin, INPUT_PULLUP); + attachInterruptArg(switch_ch2.pin, isr, &switch_ch2, CHANGE); + + // Set the Relays GPIOs as output mode + pinMode(gpio_relay1, OUTPUT); + pinMode(gpio_relay2, OUTPUT); + pinMode(gpio_led, OUTPUT); + // Write to the GPIOs the default state on booting + digitalWrite(gpio_relay1, DEFAULT_POWER_MODE); + digitalWrite(gpio_relay2, DEFAULT_POWER_MODE); + digitalWrite(gpio_led, false); + + Node my_node; + my_node = RMaker.initNode("Sonoff Dual R3"); + + //Standard switch device + my_switch1.addCb(write_callback); + my_switch2.addCb(write_callback); + + //Add switch device to the node + my_node.addDevice(my_switch1); + my_node.addDevice(my_switch2); + + //This is optional + RMaker.enableOTA(OTA_USING_PARAMS); + //If you want to enable scheduling, set time zone for your region using setTimeZone(). + //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html + // RMaker.setTimeZone("Asia/Shanghai"); + // Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone + RMaker.enableTZService(); + RMaker.enableSchedule(); + + //Service Name + for(int i=0; i<17; i=i+8) { + chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; + } + + Serial.printf("\nChip ID: %d Service Name: %s\n", chipId, service_name); + + Serial.printf("\nStarting ESP-RainMaker\n"); + RMaker.start(); + + WiFi.onEvent(sysProvEvent); +#if CONFIG_IDF_TARGET_ESP32 + WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); +#else + WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); +#endif +} + +void loop() +{ + + if (switch_ch1.pressed) { + Serial.printf("Switch 1 has been changed\n"); + switch_ch1.pressed = false; + // Toggle switch 1 device state + switch_state_ch1 = !switch_state_ch1; + Serial.printf("Toggle State to %s.\n", switch_state_ch1 ? "true" : "false"); + my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state_ch1); + (switch_state_ch1 == false) ? digitalWrite(gpio_relay1, LOW) : digitalWrite(gpio_relay1, HIGH); + } else if (switch_ch2.pressed) { + Serial.printf("Switch 2 has been changed\n"); + switch_ch2.pressed = false; + // Toggle switch 2 device state + switch_state_ch2 = !switch_state_ch2; + Serial.printf("Toggle State to %s.\n", switch_state_ch2 ? "true" : "false"); + my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state_ch2); + (switch_state_ch2 == false) ? digitalWrite(gpio_relay2, LOW) : digitalWrite(gpio_relay2, HIGH); + } + + // Read GPIO0 (external button to reset device + if(digitalRead(gpio_reset) == LOW) { //Push button pressed + Serial.printf("Reset Button Pressed!\n"); + // Key debounce handling + delay(100); + int startTime = millis(); + while(digitalRead(gpio_reset) == LOW) delay(50); + int endTime = millis(); + + if ((endTime - startTime) > 10000) { + // If key pressed for more than 10secs, reset all + Serial.printf("Reset to factory.\n"); + RMakerFactoryReset(2); + } else if ((endTime - startTime) > 3000) { + Serial.printf("Reset Wi-Fi.\n"); + // If key pressed for more than 3secs, but less than 10, reset Wi-Fi + RMakerWiFiReset(2); + } + } + delay(100); +} diff --git a/variants/sonoff_dualr3/pins_arduino.h b/variants/sonoff_dualr3/pins_arduino.h new file mode 100644 index 00000000000..eec170ae21e --- /dev/null +++ b/variants/sonoff_dualr3/pins_arduino.h @@ -0,0 +1,27 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define EXTERNAL_NUM_INTERRUPTS 16 +#define NUM_DIGITAL_PINS 40 +#define NUM_ANALOG_INPUTS 16 + +#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1) +#define digitalPinToInterrupt(p) (((p)<40)?(p):-1) +#define digitalPinHasPWM(p) (p < 34) + +static const uint8_t TX = 1; +static const uint8_t RX = 3; + +static const uint8_t BUTTON = 0; +static const uint8_t LED_LINK = 13; +static const uint8_t RELAY_2 = 14; +static const uint8_t RELAY_1 = 27; +static const uint8_t SWITCH_2 = 33; +static const uint8_t SWITCH_1 = 32; + +static const uint8_t CSE7761_TX = 25; +static const uint8_t CSE7761_RX = 26; + +#endif /* Pins_Arduino_h */