Helpful? spread the word!

Let’s see how we can remotely control an RGB LED connected to our ESP8266 NodeMCU board. In this tutorial, we will set up an asynchronous web server and an API REST to control an RGB LED. For easily controlling it, we will develop a multi-platform app using Felgo. This app, same source code, can be compiled for Desktop (Linux, Windows and macOS) and mobile devices (iOS and Android). Have a look at the video below to see the app in action.

Background

We already covered some of the basics in previous tutorials. Check the following links to learn more about these topics.

Hardware

We need an ESP8266 NodeMCU board, a breadboard, an RGB LED and some wires. If you have doubts about the different kinds of boards, have a look at An Introductory Guide to ESP8266, ESP-XX modules and NodeMCU. You can buy the parts separately or as a set (excluding the NodeMCU board). There are plenty of options. Hardware used in the particular example can be bought in the following links. The kit below is quite complete, it includes many sensors and even a development board compatible with Arduino UNO R3. I recommend that you buy it if you plan to work on additional projects, otherwise buying the parts separately is more cost effective.

These are affiliate links. This means if you click on the link and purchase the promoted item, we will receive a small affiliate commission at no extra cost to you, the price of the product is the same. We would really appreciate your support to our work and website if this is fine for you.

Outline

  • Circuit diagram
  • ESP8266 NodeMCU sketch
  • Custom app for Desktop, iOS and Android

Circuit diagram

An RGB LED has indeed three LEDs, one per color, and four pins. The largest one is the common cathode (-) or anode (+) lead, depending on the RGB LED. If we have a common cathode (-) RGB, we have to connect this lead to the ground (GND pin). On the other hand, if our RGB has a common anode (+) lead, we have to connect it to the power (PWD pin).

The lead that is alone in one of the sides of the common lead corresponds to the red LED. The other two leads at the other side correspond to the green and blue LEDs, being the green lead the closer to the common LED lead.

In my particular case, I have a common cathode (-) RGB LED, therefore the common lead must be connected to the ground pin. The red, green and blue leads are connected, through three 220-Ω resistances, to the 12 (D6), 13 (D7) and 15 (D8) pins, respectively. The diagram is shown below. If you want to know more details about LEDs and the NodeMCU pin map, read Basic ESP8266 NodeMCU tutorial: Breadboard, Pinout and Dimmable LED with Pulse-Width Modulation (PWM).

RGB LED sketch
RGB LED sketch

ESP8266 NodeMCU sketch

Our sketch is shown below. We need to install the ArduinoJSON, ESPAsyncTCP and ESPAsyncWebServer libraries on Arduino IDE. Check, Getting started with ESP8266 NodeMCU remote control from custom apps on Desktop, iOS and Android for further details about how to install libraries and the asynchronous web server.

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

const char ssid[]          = "WiFi_ID";
const char pass[]          = "WiFi_Password";
const int  port            = 2390;
const String REQUEST_LED_R = "/led_r";
const String REQUEST_LED_G = "/led_g";
const String REQUEST_LED_B = "/led_b";
const char PARAM_VALUE[]   = "value";
const char STATE[]         = "state";
const int  R_PIN           = 12;
const int  G_PIN           = 13;
const int  B_PIN           = 15;

const int MIN_ANALOG = 1023;
const int MAX_ANALOG = 0;
const int MIN_COLOR  = 0;
const int MAX_COLOR  = 255;

AsyncWebServer server(port);

void setup() {

  Serial.begin(115200);

  pinMode(R_PIN, OUTPUT);
  pinMode(G_PIN, OUTPUT);
  pinMode(B_PIN, OUTPUT);

  analogWrite(R_PIN,MIN_ANALOG);
  analogWrite(G_PIN,MIN_ANALOG);
  analogWrite(B_PIN,MIN_ANALOG);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  Serial.print("Connecting ");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }

  Serial.println("");
  Serial.print("WiFi connected to: ");
  Serial.println(WiFi.SSID());
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Red LED
  server.on(REQUEST_LED_R.c_str(), HTTP_GET, [] (AsyncWebServerRequest *request) {

    // Set LED value
    setLEDvalue(request,R_PIN);
    
    // Send Json response to client
    sendJsonResponse(request);
    
  });

  // Green LED
  server.on(REQUEST_LED_G.c_str(), HTTP_GET, [] (AsyncWebServerRequest *request) {

    // Set LED value
    setLEDvalue(request,G_PIN);
    
    // Send Json response to client
    sendJsonResponse(request);
    
  });

  // Blue LED
  server.on(REQUEST_LED_B.c_str(), HTTP_GET, [] (AsyncWebServerRequest *request) {

    // Set LED value
    setLEDvalue(request,B_PIN);
    
    // Send Json response to client
    sendJsonResponse(request);
    
  });      

  server.onNotFound(notFound);
  server.begin();
}

void setLEDvalue(AsyncWebServerRequest *request, const int pin)
{
  if (request->hasParam(PARAM_VALUE)) 
  {
    int value = request->getParam(PARAM_VALUE)->value().toInt();
    int analogValue = 
           map(value,MIN_COLOR,MAX_COLOR,MIN_ANALOG,MAX_ANALOG);
    analogWrite(pin,analogValue);  
  }
}

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void sendJsonResponse(AsyncWebServerRequest *request) {
  // Create and fill json object for client response
  DynamicJsonBuffer jsonBuffer;
  JsonObject &json = jsonBuffer.createObject();
 
  json[STATE] = "Done!";
  
  AsyncResponseStream *response = 
     request->beginResponseStream("application/json");
  json.printTo(*response);
  request->send(response);          
}

void loop(){}

The different part of the code with respect to the previous example (Getting started with ESP8266 NodeMCU remote control from custom apps on Desktop, iOS and Android ) is that we have declared three server.on statements for each one of the colors: red (REQUEST_LED_R), green (REQUEST_LED_G) and blue (REQUEST_LED_B). On each of them, we do the same: set the LED value accordingly to the value requested (setLEDvalue function) and send a response to the client (sendJsonResponse function).

Assuming that the ESP8266 NodeMCU IP address is 192.168.1.43, we are expecting requests of the following types. Once our sketch is loaded and our NodeMCU is powered up, we can check them in our browser.

http://192.168.1.43:2390/led_r?value=255
http://192.168.1.43:2390/led_g?value=0
http://192.168.1.43:2390/led_b?value=72

The setLEDvalue function checks that the request has the PARAM_VALUE (“value”) parameter, reads the value as a string and converts it to an integer value. We expect in the request values in [0,255] = [MIN_COLOR, MAX_COLOR].

Since we are applying Pulse-Width Modulation (PWM) to set the brightness of each LED, we have to set the range in [0,1023] = [MIN_ANALOG, MAX_ANALOG]. Have a look at Basic ESP8266 NodeMCU tutorial: Breadboard, Pinout and Dimmable LED with Pulse-Width Modulation (PWM) for more information about PWM.

We use the map function to map a value from the [0, 255] range to the [0, 1023] range. After that, we set the converted value (analogValue) to the appropriate pin.

void setLEDvalue(AsyncWebServerRequest *request, const int pin)
{
  // If state is a parameter then read it and call setLEDvalue
  if (request->hasParam(PARAM_VALUE)) 
  {
    int value = request->getParam(PARAM_VALUE)->value().toInt();
    int analogValue = 
           map(value,MIN_COLOR,MAX_COLOR,MIN_ANALOG,MAX_ANALOG);
    analogWrite(pin,analogValue);  
  }
}

The sendJsonResponse function sends a simple JSON object for acknowledgment purposes. We can inspect this response in our browser after sending a request.

{"state" = "Done!"}

Custom app for Desktop, iOS and Android

This app is open source and it’s available in our GitHub account. It is similar to one previously develop in Getting started with ESP8266 NodeMCU remote control from custom apps on Desktop, iOS and Android.

QML main screen
Felgo custom app

In this case, the body of our app has three sliders (red, green and blue colors). The QML code for the red slider is shown below, the same applies for the others. In this component code, we set some visual configuration together with the interval [from, to] = [0, 255] and the step size (1). We also call the processValueChanged JavaScript function when the slider value changes.

AppSlider{
   id: sRed
   anchors.horizontalCenter: parent.horizontalCenter
   width: parent.width - 2*dp(50)
   tintedTrackColor: "red"
   from: 0
   to: 255
   stepSize: 1
   onValueChanged: processValueChanged(confDialog.ip, 
                                       key_r_led, value)
}

The processValueChanged function receives as parameters: the IP address, a LED identifier (key_r_led, key_g_led or key_b_led) and the LED value. This function checks if the IP address is valid an uses a generic function to send a HTTP request to the asynchronous web server in our ESP8266 NodeMCU. This process and the code are explained in Getting started with ESP8266 NodeMCU remote control from custom apps on Desktop, iOS and Android.

This is the end of this tutorial! I hope you liked the content. Remember to stay tuned to Mechatronics Blog for cool and fun tutorials.

Leave a Reply

avatar
2000
  Subscribe  
Notify of
shares