Dimmer with ESP32 – ESP RainMaker Cloud platform + Mobile APP.

ESP RainMaker® is a complete system for building AIoT products with a minimal amount of code, empowering your team to develop and deploy secure, customized AIoT solutions. It covers all Espressif chips and modules, device firmware, voice-assistant integrations, phone apps and cloud backend. This helps you save a large investment in cloud, gain independence and focus on innovating your core-value offering.

In this Dimmer tutorial, we will introduce you to ESP RainMaker with ESP32 using Arduino IDE. Create Arduino code for dimming, upload to the microcontroller, and connect to the mobile APP. https://rainmaker.espressif.com/

Ready-made support for Amazon Alexa & Google Assistant integration through smart-home skills and actions. You can also create your own custom skills.

A sample sketch for a Dimmer has been included. Let’s quickly look at the code that enables this.

//This example demonstrates the ESP RainMaker with the Dimmer
#include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"

#include <RBDdimmer.h>   //Dimmer connection to microcontroller and Arduino library. https://rocketcontroller.com/dimmer-connection-to-microcontroller-and-arduino-library-examples/

#define DEFAULT_POWER_MODE true
#define DEFAULT_DIMMER_LEVEL 50
const char *service_name = "PROV_1234";
const char *pop = "abcd1234";

//GPIO for push button
#if CONFIG_IDF_TARGET_ESP32C3
static int gpio_0 = 9;
static int gpio_dimmer = 7;
static int gpio_zerocross  5 // seting of pins
#else
//GPIO for virtual device
static int gpio_0 = 0;
static int gpio_dimmer = 23;
static int gpio_zerocross  5 // seting of pins
#endif

dimmerLamp dimmer(gpio_dimmer, gpio_zerocross);

bool dimmer_state = true; 

// The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
// But, you can also define custom devices using the 'Device' base class object, as shown here
static Device my_device("Dimmer", "custom.device.dimmer", &gpio_dimmer);

void sysProvEvent(arduino_event_t *sys_event)
{
    switch (sys_event->event_id) {      
        case ARDUINO_EVENT_PROV_START:
#if CONFIG_IDF_TARGET_ESP32S2
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
        printQR(service_name, pop, "softap");
#else
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
        printQR(service_name, pop, "ble");
#endif        
        break;
        default:;
    }
}

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(param_name, "Power") == 0) {
        Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name);
        dimmer_state = val.val.b;
        (dimmer_state == false) ? dimmer.setPower(OFF) : dimmer.setPower(ON);
        param->updateAndReport(val);
    } else if (strcmp(param_name, "Level") == 0) {
        Serial.printf("\nReceived value = %d for %s - %s\n", val.val.i, device_name, param_name);
        param->updateAndReport(val);
        dimmer.setPower(val.val.i);   // DIMMING
    }
}

void setup()
{
    Serial.begin(115200);
    pinMode(gpio_0, INPUT);
    dimmer.begin(NORMAL_MODE, ON);

    Node my_node;    
    my_node = RMaker.initNode("ESP RainMaker Node");

    //Create custom dimmer device
    my_device.addNameParam();
    my_device.addPowerParam(DEFAULT_POWER_MODE);
    my_device.assignPrimaryParam(my_device.getParamByName(ESP_RMAKER_DEF_POWER_NAME));

    //Create and add a custom level parameter
    Param level_param("Level", "custom.param.level", value(DEFAULT_DIMMER_LEVEL), PROP_FLAG_READ | PROP_FLAG_WRITE);
    level_param.addBounds(value(0), value(100), value(1));
    level_param.addUIType(ESP_RMAKER_UI_SLIDER);
    my_device.addParam(level_param);

    my_device.addCb(write_callback);
    
    //Add custom dimmer device to the node   
    my_node.addDevice(my_device);

    //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();

    RMaker.start();

    WiFi.onEvent(sysProvEvent);
#if CONFIG_IDF_TARGET_ESP32S2
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
#else
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
#endif
}

void loop()
{
    if(digitalRead(gpio_0) == LOW) { //Push button pressed

        // Key debounce handling
        delay(100);
        int startTime = millis();
        while(digitalRead(gpio_0) == 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);
        } else {
          // Toggle device state
          dimmer_state = !dimmer_state;
          Serial.printf("Toggle State to %s.\n", dimmer_state ? "true" : "false");
          my_device.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, dimmer_state);
          (dimmer_state == false) ? dimmer.setPower(OFF) : dimmer.setPower(ON);
      }
    }
    delay(100);
}

The switch can be controlled with the mobile APP, as well as Alexa and Google Voice Assistant skills.

When we execute this code:

  • The device will first check if a Wi-Fi network is configured. If the network is not configured, it will launch the provisioning process. The device can then be configured using the phone apps mentioned above.
  • If a Wi-Fi configuration is found, it will connect to the configured network.
  • Once connected, it will connect to the RainMaker cloud, looking for commands to modify its parameter (switch state in this case).
  • The device will also look for commands on the local Wi-Fi network.
  • When somebody changes the switch state using phone apps or voice integrations, the write_callback() gets called.

Getting Started

Before you even get started, a few points to note

  • For using RainMaker, you first have to get started with the ESP32 support in Arduino.
  • RainMaker support is not yet part of a stable esp32-arduino release. So we will use the master branch of the ESP32 Arduino repository. We will update here and elsewhere once this support is available in a stable release.

Once your Arduino is set-up with the ESP32 support, follow these steps

  1. Open the Arduino IDE, go to Tools and set the following
  • Board: “ESP32 Dev Module”
  • Flash Size: “4MB” (according to your ESP32 controller)
  • Partition Scheme: “RainMaker”
  • Core Debug Level: “Info”
  • Port: Choose the appropriate ESP32 port as per your Host platform from the list. By connecting/disconnecting your ESP32 board, you can find out the port number.

2. Upload the Sketch onto your ESP32 board by clicking on the Upload button in the IDE, or going to Sketch -> Upload

3. Go to Tools -> Serial Monitor. Choose 115200 as Baud. If you do not see anything in the monitor window, reset your board (using the RST button).

4. Download the ESP RainMaker phone app, sign-up or sign-in and you are ready to go.

5. Follow the instructions in the Serial Monitor to add the switch from the RainMaker app. (If you do not see the instructions, double check the “Core Debug Level: Info” option under Tools)

Any control from the phone app should now reflect on the device and any change on the device (by pressing the BOOT button) should reflect in the mobile app.

You can press and hold the BOOT button for more than 3 seconds and then release for Resetting Wi-Fi, and for more than 10 seconds to Reset to Factory defaults.