ESP RainMaker เป็นแพลตฟอร์มที่ช่วยให้นักพัฒนาสร้างอุปกรณ์ที่เชื่อมต่อกับ ESP32-S2 SoC ของ Espressif โดยไม่ต้องวุ่นวายกับการจัดการโครงสร้างพื้นฐาน มี SDK ของอุปกรณ์ แอปโทรศัพท์ที่ปรับเปลี่ยนได้เอง มิดเดิลแวร์คลาวด์แบบโปร่งใส และยูทิลิตีโฮสต์เพื่อลดความซับซ้อนในการพัฒนาอุปกรณ์ที่เชื่อมต่อ ESP RainMaker ยังเสนอการผสานรวมกับ Amazon Alexa และ Google Voice Services โดยรองรับอุปกรณ์มาตรฐาน บางประเภท สำหรับหมวดหมู่ต่อไปนี้
- ไฟ
- สวิตช์
- เต้ารับ/เต้ารับ
- พัดลม
- เซ็นเซอร์อุณหภูมิ
ESP RainMaker เป็นโซลูชัน IoT แบบ end-to-end โดยมีระบบคลาวด์แบ็คเอนด์เป็นแกนหลัก แบ็กเอนด์สร้างขึ้นโดยใช้สถาปัตยกรรมแบบไร้เซิร์ฟเวอร์ของ AWS ซึ่งมอบความยืดหยุ่นและความสามารถในการปรับขนาดที่เหนือชั้นในแง่ของการประมวลผล การจัดเก็บข้อมูล และความสามารถในการรับส่งข้อมูล Serverless ไม่ได้หมายความว่าไม่มีเซิร์ฟเวอร์ มันซ่อนการจัดการโครงสร้างพื้นฐานของฮาร์ดแวร์และซอฟต์แวร์และให้บริการที่ใช้งานได้สำหรับแอปพลิเคชัน แอปพลิเคชันยังได้รับการออกแบบให้ไม่ทำงานบนอินสแตนซ์ของเซิร์ฟเวอร์เฉพาะ แต่ขับเคลื่อนด้วยเหตุการณ์และสามารถใช้บริการที่มีอยู่ได้ สิ่งนี้ทำให้ ESP RainMaker ง่ายต่อการบำรุงรักษาและจัดการ นอกจากนี้ยังมีเลเยอร์แอ็พพลิเคชัน API แบบเปิดซึ่งช่วยให้สามารถปรับแต่งและตอบสนองความต้องการที่หลากหลายของสภาพแวดล้อมที่แตกต่างกันได้

ESP RainMaker เป็นมากกว่าการให้บริการคลาวด์ มีเฟิร์ มแวร์ SDK แบบโอเพ่นซอร์สซึ่งสามารถเข้าถึงได้บน GitHub สามารถใช้สร้างผลิตภัณฑ์มาตรฐาน เช่น ไฟ สวิตช์ พัดลม ฯลฯ รวมถึงผลิตภัณฑ์ IoT แบบกำหนดเองโดยใช้โมเดลข้อมูล fkexible และ API โดยยังมีแอพโทรศัพท์สองประเภท: แอพ ESP RainMaker และแอพ Nova Home อีกด้วย
สอนทำโปรเจค ESP32 เปิด-ปิดไฟ 4 หลอด ด้วย ESP Rainmaker
รายการอุปกรณ์
- 4 Channel Relay Module ESP32-WROOM Development Board
- CP2102 USB 2.0 to UART TTL 5PIN Connector Module
- Adapter DC 12V 2A Power Supply
เราจะดูวิธีเริ่มต้นใช้งาน ESP Rainmaker สิ่งแรกที่เราต้องทำคือติดตั้ง Arduino IDE และเราจะกำหนดค่าให้ รองรับบอร์ด ESP32 จากนั้นเราจะกำหนดค่าให้รองรับ ESP Rainmaker แล้วอัปโหลดโค้ดแรกของเราเข้าไป
- ติดตั้ง Arduino IDE
สิ่งแรกคือการติดตั้ง Arduino IDE เพื่อให้คุณสามารถค้นหา Arduino IDE ใน Google
จากนั้นคุณมีสองทางเลือก
หนึ่งคือการติดตั้งเวอร์ชัน1 หรือเพื่อติดตั้งเวอร์ชัน 2
เราจะติดตั้งเวอร์ชัน 2 เพราะมีคุณสมบัติเพิ่มเติมบางอย่าง แต่ไม่ว่าคุณจะเลือกอะไรมันจะทำงานเช่นกัน ดังนั้นคุณสามารถเลือกอย่างใดอย่างหนึ่ง
ดาวน์โหลด Arduino IDE จากที่นี่
https://www.arduino.cc/en/software

2. กำหนดค่าให้ รองรับบอร์ด ESP32
ไปที่ File > Preferences

คัดลอกและวางบรรทัดต่อไปนี้ลงในฟิลด์ Boards Manager URLs
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

คลิกไอคอนตัวจัดการบอร์ดที่มุมด้านซ้าย ค้นหา ESP32 และกดปุ่มติดตั้งสำหรับ esp32 โดย Espressif Systems

เลือกบอร์ด ESP32 ตามรุ่นที่ใช้ เป็น ESP32 Dev Module

3. กำหนดค่าให้รองรับ ESP Rainmaker
กำหนดค่าให้รองรับ ESP Rainmaker

เลือก Enabled

esptool --chip ESP32 --port COM5 erase_flash
4. อัปโหลดโค้ด
เชื่อมต่อ CP2102 USB กับ 4 Channel Relay Module

เชื่อมต่อ Adapter กับ 4 Channel Relay Module

เมื่อต้องการอัพโหลดโปรแกรมลงบอร์ด ให้ใส่จัมเปอร์ที่ขา IO0 และ GND

#include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"
#include <EEPROM.h>
//---------------------------------------------------
const char *service_name = "LED-4CH";
const char *pop = "led4321";
//---------------------------------------------------
#define EEPROM_SIZE 4
//---------------------------------------------------
// define the Device Names
char device1[] = "Switch1";
char device2[] = "Switch2";
char device3[] = "Switch3";
char device4[] = "Switch4";
//---------------------------------------------------
// define the GPIO connected with Relays and switches
static uint8_t RELAY_1 = 26; //D26
static uint8_t RELAY_2 = 25; //D23
static uint8_t RELAY_3 = 32; //D32
static uint8_t RELAY_4 = 33; //D33
//---------------------------------------------------
static uint8_t WIFI_LED = 2; //D2
static uint8_t gpio_reset = 0;
//---------------------------------------------------
/* Variable for reading pin status*/
// Relay State
bool STATE_RELAY_1 = LOW; //Define integer to remember the toggle state for relay 1
bool STATE_RELAY_2 = LOW; //Define integer to remember the toggle state for relay 2
bool STATE_RELAY_3 = LOW; //Define integer to remember the toggle state for relay 3
bool STATE_RELAY_4 = LOW; //Define integer to remember the toggle state for relay 4
//---------------------------------------------------
// Switch State
//bool SwitchState_1 = LOW;
//bool SwitchState_2 = LOW;
//bool SwitchState_3 = LOW;
//bool SwitchState_4 = LOW;
//---------------------------------------------------
//The framework provides some standard device types
//like switch, lightbulb, fan, temperature sensor.
static Switch my_switch1(device1, &RELAY_1);
static Switch my_switch2(device2, &RELAY_2);
static Switch my_switch3(device3, &RELAY_3);
static Switch my_switch4(device4, &RELAY_4);
//---------------------------------------------------
/****************************************************************************************************
* sysProvEvent Function
*****************************************************************************************************/
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(WIFI_LED, HIGH);
break;
}
}
/****************************************************************************************************
* write_callback Function
*****************************************************************************************************/
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, device1) == 0) {
Serial.printf("Lightbulb1 = %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);
STATE_RELAY_1 = val.val.b;
STATE_RELAY_1 = !STATE_RELAY_1;
control_relay(1, RELAY_1, STATE_RELAY_1);
//(STATE_RELAY_1 == false) ? digitalWrite(RELAY_1, HIGH) : digitalWrite(RELAY_1, LOW);
//param->updateAndReport(val);
}
}
//----------------------------------------------------------------------------------
else if (strcmp(device_name, device2) == 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);
STATE_RELAY_2 = val.val.b;
STATE_RELAY_2 = !STATE_RELAY_2;
control_relay(2, RELAY_2, STATE_RELAY_2);
//(STATE_RELAY_2 == false) ? digitalWrite(RELAY_2, HIGH) : digitalWrite(RELAY_2, LOW);
//param->updateAndReport(val);
}
}
//----------------------------------------------------------------------------------
else if (strcmp(device_name, device3) == 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);
STATE_RELAY_3 = val.val.b;
STATE_RELAY_3 = !STATE_RELAY_3;
control_relay(3, RELAY_3, STATE_RELAY_3);
//(STATE_RELAY_3 == false) ? digitalWrite(RELAY_3, HIGH) : digitalWrite(RELAY_3, LOW);
//param->updateAndReport(val);
}
}
//----------------------------------------------------------------------------------
else if (strcmp(device_name, device4) == 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);
STATE_RELAY_4 = val.val.b;
STATE_RELAY_4 = !STATE_RELAY_4;
control_relay(4, RELAY_4, STATE_RELAY_4);
//(STATE_RELAY_4 == false) ? digitalWrite(RELAY_4, HIGH) : digitalWrite(RELAY_4, LOW);
//param->updateAndReport(val);
}
}
//----------------------------------------------------------------------------------
}
/****************************************************************************************************
* setup Function
*****************************************************************************************************/
void setup() {
//------------------------------------------------------------------------------
uint32_t chipId = 0;
Serial.begin(115200);
//------------------------------------------------------------------------------
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
//------------------------------------------------------------------------------
//IrReceiver.begin(IR_RECEIVE_PIN); // Start the IR receiver
//------------------------------------------------------------------------------
// Set the Relays GPIOs as output mode
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(RELAY_3, OUTPUT);
pinMode(RELAY_4, OUTPUT);
//------------------------------------------------------------------------------
pinMode(gpio_reset, INPUT);
pinMode(WIFI_LED, OUTPUT);
digitalWrite(WIFI_LED, LOW);
//------------------------------------------------------------------------------
// Write to the GPIOs the default state on booting
digitalWrite(RELAY_1, !STATE_RELAY_1);
digitalWrite(RELAY_2, !STATE_RELAY_2);
digitalWrite(RELAY_3, !STATE_RELAY_3);
digitalWrite(RELAY_4, !STATE_RELAY_4);
//------------------------------------------------------------------------------
Node my_node;
my_node = RMaker.initNode("Tech Trends Shameer");
//------------------------------------------------------------------------------
//Standard switch device
my_switch1.addCb(write_callback);
my_switch2.addCb(write_callback);
my_switch3.addCb(write_callback);
my_switch4.addCb(write_callback);
//------------------------------------------------------------------------------
//Add switch device to the node
my_node.addDevice(my_switch1);
my_node.addDevice(my_switch2);
my_node.addDevice(my_switch3);
my_node.addDevice(my_switch4);
//------------------------------------------------------------------------------
//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
//------------------------------------------------------------------------------
STATE_RELAY_1 = EEPROM.read(0);
STATE_RELAY_2 = EEPROM.read(1);
STATE_RELAY_3 = EEPROM.read(2);
STATE_RELAY_4 = EEPROM.read(3);
digitalWrite(RELAY_1, STATE_RELAY_1);
digitalWrite(RELAY_2, STATE_RELAY_2);
digitalWrite(RELAY_3, STATE_RELAY_3);
digitalWrite(RELAY_4, STATE_RELAY_4);
my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, STATE_RELAY_1);
my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, STATE_RELAY_2);
my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, STATE_RELAY_3);
my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, STATE_RELAY_4);
Serial.printf("Relay1 is %s \n", STATE_RELAY_1 ? "ON" : "OFF");
Serial.printf("Relay2 is %s \n", STATE_RELAY_2 ? "ON" : "OFF");
Serial.printf("Relay3 is %s \n", STATE_RELAY_3 ? "ON" : "OFF");
Serial.printf("Relay4 is %s \n", STATE_RELAY_4 ? "ON" : "OFF");
//------------------------------------------------------------------------------
}
/****************************************************************************************************
* loop Function
*****************************************************************************************************/
void loop() {
//------------------------------------------------------------------------------
// 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);
if (WiFi.status() != WL_CONNECTED) {
//Serial.println("WiFi Not Connected");
digitalWrite(WIFI_LED, LOW);
} else {
//Serial.println("WiFi Connected");
digitalWrite(WIFI_LED, HIGH);
}
//------------------------------------------------------------------------------
}
/****************************************************************************************************
* control_relay Function
*****************************************************************************************************/
void control_relay(int relay_no, int relay_pin, boolean &status) {
status = !status;
digitalWrite(relay_pin, status);
EEPROM.write(relay_no - 1, status);
EEPROM.commit();
String text = (status) ? "ON" : "OFF";
Serial.println("Relay" + String(relay_no) + " is " + text);
}
https://lungmaker.com/code/led_4ch.ino
แสดงการอัพโหลดสำเร็จ

เลือก Serial Monitor

เปลี่ยนเป็น 115200 baud

เลือกเป็น Both NL & CR

ถอด จัมเปอร์ที่ขา IO0 และ GND ออก

รีสตาร์ท ESP32 โดยกดปุ่ม EN


ก๊อบปี้ URL ด้านล่าง ไปใช้งานที่เว็บเบราว์เซอร์
https://rainmaker.espressif.com/qrcode.html?data={"ver":"v1","name":"LED-4CH","pop":"led4321","transport":"ble"}

5. ติดตั้งแอพ ESP Rainmaker
แอพ ESP RainMaker เป็นแอพเนทีฟแบบโอเพ่นซอร์สที่สร้างขึ้นสำหรับ Android และ iOS แอปเหล่านี้มี UI ที่ปรับเปลี่ยนได้เอง ซึ่งหมายความว่าฟังก์ชันใดๆ ที่เพิ่มเข้ามาในเฟิร์มแวร์ RainMaker สามารถใช้งานได้ผ่านแอปเหล่านี้โดยไม่มีการเปลี่ยนแปลงใดๆ ทำให้การพัฒนาผลิตภัณฑ์ง่ายและรวดเร็วขึ้นมาก เนื่องจากสิ่งเหล่านี้เป็นโอเพ่นซอร์สจึงสามารถกำหนดค่าและปรับแต่งตามความต้องการของคุณ
ใช้สมาร์ทโฟนดาวน์โหลดและติดตั้งแอพ ESP Rainmaker

เปิดแอพ ESP Rainmaker -> Add Devices

สแกนบาร์โค้ด จาก เว็บเบราว์เซอร์

เลือก Join Other Network

ลงชื่อเข้าใช้เครือข่าย WiFI และ รหัสผ่าน -> PROVISION

รอการติดตั้ง

แสดงการติดตั้งสำเร็จ

6. ทดสอบการใช้งานเบื้องต้น
ทดสอบ ปิดสวิตช์ทั้งหมด

ผลลัพธ์ : ไม่มีไฟ relay indicator ติด

เปิดสวิตช์ ตัวที่ 1

ผลลัพธ์ : ไฟ relay indicator ดวงที่ 1 ติด

เปิดสวิตช์ ตัวที่ 2 เพิ่ม

ผลลัพธ์ : ไฟ relay indicator ดวงที่ 2 ติด
