ESP32 – Simple Luminance Controller

In this tutorial, the aim is to control the light brightness of a room. For this, an ESP32, a led (to simulate the actuator), and an LDR resistor are used. The luminosity value is set via the serial port.
In order to deepen your knowledge about LDR resistance, I advise you to visit this tutorial. For the next steps, you can use the Arduino IDE or PlatformIO together with the VS Code. If you have any questions about installing the libraries in Arduino IDE, you can view the following link. If you need more information about how to configure PlatformIO and VS Code, check this.

Parts Required

  • Arduino.h (just when use PlatformIO);
  • analogWrite.h (for PlatformIO and Arduino IDE);
  • ESP32;
  • Micro-USB to USB-A cable
  • LDR resistor;
  • LED;
  • 10kΩ resistor;
  • 330Ω resistor;
  • Jumper wires;
  • 1 Breadboard.

Circuit

The board used for this assembly is represented in Figure 1.

In order to control the LED intensity, it must be connected to a pin that supports PWM (Pulse Width Modulation, if you need more information you can read this tutorial). For this reason, the LED is connected to pin D4 (see Figure 1). As it is necessary to use another ADC to be able to convert the voltage value obtained in the voltage divider of the LDR, this was connected to pin D15 of the development board used. These connections can be seen in Figure 2.

Figure 1 (Source [1])
Figure 2 (Adapted from [2])

Libraries

In order to be able to correctly use the analog inputs (according to the code presented), it is necessary to install libraries that allow these operations to be carried out. In case these libraries are not installed, it is not possible to use the functions related to analog pins. Because it is through them that some configurations are made.

In PlatformIO, the following library presented in Figure 3 was used. You can search for “AnalogWrite.h” library and click on the Install button.

Figure 3

For the Arduino IDE, the library shown in Figure 4 was used. To show this window you can press ” Cntrl + Shift + i ” or click Sketch -> Include Library -> Manage Libraries…

Figure 4

Code

In order to carry out the necessary operations, we used only the “analogWrite.h” library in addition to the “Arduino.h” (which is usual, since the project created is based on the Arduino framework).


The developed process goes through the following steps:

  1. Illumination reading (obtained by LDR);
  2. Setting the desired luminance (serial port reading);
  3. Verification of the desired luminance;
  4. LED brightness adjustment.

In order to obtain the luminance value, is used the “conversion” function used in this tutorial.

#include <Arduino.h>
#include <analogWrite.h>

#define LEDPIN 4
#define LDRPIN 15

#define VIN 3.3    // V power voltage, 3.3v in case of NodeMCU
#define R 10000    // Voltage devider resistor value
#define MAXLUM 500 // Maximum luminance value [lux]

int read_value = 0;
int luminance_read_lux;

int wait_time = 500;            // Time delay [ms]
int counter = 6;                // Defines interval for set the desired lumination value
                                // Refreshing time = counter * wait_time
float input_value = 0;          // Variable to store the value obtained when read serial port
int luminance_input = 0;        // Variable to store the value of luminance desired
int led_output = 0;             // Variable that defines the duty cycle of PWM
int output_value_remap = 0;     // Variable to store the rescale value of luminance
int adjust_increment_value = 1; // Step of adjust the PWM duty cycle

// This function convert the value read with ADC into luminance value
int conversion(int raw_val)
{
  // Conversion rule
  float Vout = float(raw_val) * (VIN / float(4096)); // Conversion analog to voltage
  float RLDR = (R * (VIN - Vout)) / Vout;            // Conversion voltage to resistance
  int lux = 500 / (RLDR / 1000);                     // Conversion resitance to lumen
  return lux;
}

// This function is used to read and return the serial port
float readSerialInput()
{
  Serial.println("Introduce the luminance desired: ");
  while (Serial.available() == 0)
  {
    // Wait 2000ms, if no input the program continue
    delay(2000);
    break;
  }

  float numeric_input = Serial.parseFloat();

  // Print on serial port what you received
  Serial.print("I received: ");
  Serial.println(numeric_input);
  return numeric_input;
}

void setup()
{
  // Start serial port
  Serial.begin(9600);

  // Read the voltage in D15 and convert to luminance
  read_value = analogRead(LDRPIN);
  luminance_read_lux = conversion(read_value);
}

void loop()
{

  if (counter == 6)
  {

    Serial.println("\n***************************************************************");

    // Read serial port
    input_value = readSerialInput();
    if (input_value != 0)
    {
      // If reading is not 0, the value will be resccaled for PWM duty cycle output
      luminance_input = input_value;
      output_value_remap = map(luminance_input, 0, MAXLUM, 0, 4096);
      led_output = output_value_remap;

      // Set the PWM duty cycle
      analogWrite(LEDPIN, led_output, 4095);
    }
    // Print the luminance input value
    Serial.print("Luminance desired: ");
    Serial.println(luminance_input);
    counter = 0;
  }
  else
  {
    Serial.println("\n----------------------------------------------------------------");
    Serial.print("\t Luminance desired: ");
    Serial.println(luminance_input);

    counter++;

    // Read the voltage in D15 and convert to luminance
    read_value = analogRead(LDRPIN);
    luminance_read_lux = conversion(read_value);

    if (luminance_read_lux < luminance_input)
    {
      // Increase PWM duty cycle, if obtained is lower than desired
      led_output = led_output + adjust_increment_value;
    }
    if (luminance_read_lux > luminance_input)
    {
      // Decrease PWM duty cycle, if desired is lower than obtained
      led_output = led_output - adjust_increment_value;
    }

    // Makes sure that the value that defines the duty cycle belongs to [0, 4095]
    if (led_output < 0)
    {
      led_output = 0;
    }
    if (led_output > 4095)
    {
      led_output = 4095;
    }

    // Set the PWM duty cycle
    analogWrite(LEDPIN, (uint32_t)led_output, 4095);

    // Print the luminance read value
    Serial.print("\t Luminance read: ");
    Serial.println(luminance_read_lux);

    // Print the PWM duty cycle [0, 4095]
    Serial.print("\t PWM output: ");
    Serial.println(led_output);

    delay(wait_time);
  }
}

Results

In Figure 5 and Figure 6 is represented the output result on the serial port. In Figure 7 you can see my hardware implementation.

Figure 5
Figure 6
Figure 7

References

[1] https://circuits4you.com

[2] https://www.programmersought.com/article/46417861001/

Leave a Reply

Your email address will not be published. Required fields are marked *