Episode 2: RGB LED control
-
I will be using a RGB LED to create various color combinations using three simple / basic slider widgets. The sliders will control each channel separately (red, green and blue) by setting their values between 0-255 through user input.
I will be using GUI-O IoT (MQTT) connection, but the example can be easily be ported to other connection types.
Software prerequisites:
-
Arduino IDE (https://www.arduino.cc/en/software)
-
ESP32 Arduino board support, if using ESP32 based board (see https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html)
-
Arduino Client for MQTT(https://github.com/knolleary/pubsubclient)
You can follow the setup instructions or directly download and include the PubSubClient.zip library within the Arduino IDE (Sketch -> Include Library -> Add .ZIP library) -
GUI-O design tool (https://www.gui-o.com/design-tool)
-
GUI-O application (https://play.google.com/store/apps/details?id=com.guio.guioapp)
-
For additional information about the GUI-O application, download the developer manual from https://www.gui-o.com/
Components needed:
- ESP32-WROOM-32 (or any other Arduino supported WiFi capable board; see https://github.com/knolleary/pubsubclient#compatible-hardware for compatible hardware)
- 3x 220Ω resistor
- RGB LED (common anode)
The entire tutorial is split into various steps. All necessary information is given in each step.
0. DESIGN THE GUI (optional)
The best way to create a GUI layout is to use GUI-O live designer tool.
Note that the Arduino source code already includes the necessary commands, so this step is not needed, unless you want to make some visual adjustments. If you make adjustments, please include the generated ASCII code in the Arduino source code (see section 3. MODIFY AND UPLOAD THE SOURCE CODE).
First, you need to establish a TCP/IP connection between the designer tool and GUI-O application:
- Determine the local IP address of your PC's network interface (WiFi or Ethernet)
- Under Windows, open the command prompt, enter
ipconfig
and press Enter - Under Linux, open the terminal, enter
ifconfig
and press Enter
-
Open GUI-O application and open settings menu. Select "Connections -> Ethernet" and create a new device with IP address (determined from 1.) and any port between 49152 - 65535
-
Open GUI-O designer and select "TCP/IP connection" tab. Set the IP address and port. Both values must match the device settings created within the GUI-O application. Click "Start server" button.
-
Within the GUI-O application, tap the created device and wait for successful connection.
-
In the GUI-O designer, select "File -> Load designer file" and load the RgbLedControl.gdf design file. Make the desired adjustments, if necessary. Copy / replace the GUI-O commands into the Arduino source code (see section 3. MODIFY AND UPLOAD THE SOURCE CODE).
1. CONNECT THE COMPONENTS
Connecting the components is straightforward. "D25", "D33" and "D32" are GPIO pins that are capable of producing PWM output. The values of the current limiting resistors are not optimal, but in my case, the LED is still bright enough.
2. CREATE A UNIQUE MQTT CHANNEL
Open GUI-O application and navigate to settings menu. Select "Connections -> IoT" and add a new device. After adding the device, note the In and Out token (you can share this tokens e.g., to your e-mail by pressing the "share" button).
Finally, press "Connect" menu entry to establish the connection with the MQTT server.
3. MODIFY AND UPLOAD THE SOURCE CODE
The source code has inline comments, describing the important parts of the code. You can copy the source code from the snippet below, or download it here.
The only thing that needs to be done is to set the ssid and password of your router and the unique In and Out channels that were generated by the GUI-O application (see section 2. CREATE A UNIQUE MQTT CHANNEL).
After setting these values, upload the code to your board (make sure that the correct board and upload port are selected). Reset the board after upload.
/* * GUI-O Rgb control MQTT example (using ESP32-WROOM-32) * * Copyright (C) 2022, kl3m3n * last updated on 4.11.2022 * * SPDX-License-Identifier: BSD-3-Clause */ #include <WiFi.h> #include <PubSubClient.h> static const char *ssid = "<ssid>"; // router name static const char *pass = "<pass>"; // router password static const char *mqttServer = "mqtt.gui-o.com"; // host name static const char *mqttUser = "gui-o-mqtt-generic"; // user name static const char *mqttPass = "lqXeZpv5VJyv0XBT"; // password // IMPORTANT NOTE: if optional user name was specified when adding a new IoT device, // the user name should also be included when setting the topics (e.g., "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/<user_name>") static const char *Out = "<Out>"; // GUI-O app publish topic static const char *In = "<In>"; // GUI-O app subscribe topic // mqtt client WiFiClient wiFiClient; PubSubClient mqttClient(wiFiClient); // forward declare functions for mqtt messages handling void mqttCallback(char* topic, byte* message, unsigned int length); void parseGuioMsg(const String &msg); // LED setup namespace led { static const uint8_t R_PIN = 25; static const uint8_t G_PIN = 33; static const uint8_t B_PIN = 32; // static const uint8_t R_CHANNEL = 0; static const uint8_t G_CHANNEL = 1; static const uint8_t B_CHANNEL = 2; // static const double LED_FREQ = 5000.0; static const uint8_t LED_BITS = 8; } // namespace led // LED rgb values uint8_t redValue = 0; uint8_t greenValue = 0; uint8_t blueValue = 0; void setup() { // debug output Serial.begin(115200); // setup LED ledcSetup(led::R_CHANNEL, led::LED_FREQ, led::LED_BITS); ledcSetup(led::G_CHANNEL, led::LED_FREQ, led::LED_BITS); ledcSetup(led::B_CHANNEL, led::LED_FREQ, led::LED_BITS); // attach the channels to the GPIOs ledcAttachPin(led::R_PIN, led::R_CHANNEL); ledcAttachPin(led::G_PIN, led::G_CHANNEL); ledcAttachPin(led::B_PIN, led::B_CHANNEL); // set initial values ("inverted" logic - see schematic) delay(100); ledcWrite(led::R_CHANNEL, 255 - redValue); ledcWrite(led::G_CHANNEL, 255 - greenValue); ledcWrite(led::B_CHANNEL, 255 - blueValue); // connect WiFi (keep trying...) Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while(WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println("WiFi connected!"); // setup mqtt mqttClient.setServer(mqttServer, 1883); mqttClient.setCallback(mqttCallback); } void loop() { while(!mqttClient.connected()) { Serial.println("MQTT connecting..."); // mqtt client id is the mac address (AABBCCDDEEFF) char mqttClientId[15]; uint8_t mac[6]; WiFi.macAddress(mac); snprintf(mqttClientId, sizeof(mqttClientId), "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); if(mqttClient.connect(mqttClientId, mqttUser, mqttPass)) { Serial.println("MQTT connected!"); mqttClient.subscribe(&Out[0]); } else { Serial.print("MQTT connection failed ("); Serial.print(mqttClient.state()); Serial.println(")! Retrying..."); delay(2500); } } mqttClient.loop(); } // mqtt callback function void mqttCallback(char* topic, byte* message, unsigned int length) { // build message string String msg; for(int i = 0; i < length; i++) { msg += (char) message[i]; } // parse message string parseGuioMsg(msg); } void parseGuioMsg(const String &msg) { // lambda for LED value extraction auto ledValue = [](const String &msg) -> uint8_t { uint8_t value = 0; const int idx = msg.indexOf(' '); if(idx > 0) { value = constrain(msg.substring(idx + 1).toInt(), 0, 255); value = (255 - value); // "inverted" logic - see schematic } return value; }; if(msg.startsWith("@init")) { Serial.println("GUI-O app is requesting INITIALIZATION!"); // clear screen and set background mqttClient.publish(&In[0], "@cls\r\n"); mqttClient.publish(&In[0], "@guis BGC:#FFFFFF\r\n"); delay(100); // initialize GUI mqttClient.publish(&In[0], "|LB UID:title X:50 Y:20 FSZ:4 FFA:\"font8\" TXT:\"RGB LED<br>control\"\r\n"); mqttClient.publish(&In[0], "|SL UID:red X:30 Y:50 H:1 ROT:270 FGC:#FF0000 SFGC:#FF0000 HAW:7 HAH:7 HAR:3.5 HAC:#FF0000 IP:\"\" HVAL:255 RAD:0.5\r\n"); mqttClient.publish(&In[0], "|SL UID:green X:50 Y:50 H:1 ROT:270 FGC:#00FF00 SFGC:#00FF00 HAW:7 HAH:7 HAR:3.5 HAC:#00FF00 IP:\"\" HVAL:255 RAD:0.5\r\n"); mqttClient.publish(&In[0], "|SL UID:blue X:70 Y:50 H:1 ROT:270 FGC:#0000FF SFGC:#0000FF HAW:7 HAH:7 HAR:3.5 HAC:#0000FF IP:\"\" HVAL:255 RAD:0.5\r\n"); mqttClient.publish(&In[0], "|LB UID:details X:50 Y:90 FSZ:2 TXT:\"GUI-O RGB LED control<br>demonstration by kl3m3n\"\r\n"); } else if(msg.startsWith("@red")) { redValue = ledValue(msg); ledcWrite(led::R_CHANNEL, redValue); } else if(msg.startsWith("@green")) { greenValue = ledValue(msg); ledcWrite(led::G_CHANNEL, greenValue); } else if(msg.startsWith("@blue")) { blueValue = ledValue(msg); ledcWrite(led::B_CHANNEL, blueValue); } }
4. ESTABLISH CONNECTION
Make sure that the GUI-O application is connected to the MQTT server.
Also make sure that the ESP32 board (or other Arduino supported board) is connected to the MQTT server (you can check this by observing the serial debug messages using the Arduino serial monitor).Press the Initialize button (see image below) from the GUI-O application home screen.
5. THE RESULT
Image below shows the result (screen capture) on my Android device after pressing the "Initialize" button. The sliders control each LED channel through user input.
If you have any questions or run into any problems, please let me know!
Best regards,
kl3m3n -