Language: EN


How to make PID constant lighting control with Arduino

In this post, we are going to see how to make a constant lighting control by PID with a simple Led and an LDR resistance.

We have talked a lot about PID on the blog in the control theory section. So we have seen the PID controller, how to adjust a PID controller, and how to implement a PID control in Arduino

Now it’s time to move on to a practical example of PID. One of the most appropriate to start with is a lighting control, because the setup is very simple and we can easily visualize the result.

We only need to face an LED with an LDR resistance, but any other type of light emitter or sensor would do. In the setup, we face the LED with the LDR resistance as follows.


Now we want the LED to turn on and off in response to a disturbance, for example when we put our hand on the setup and cover some of the ambient light.

The first thing we have to do is to choose an appropriate setpoint, an intermediate point between fully illuminated and total (or quite dark). Otherwise, the PID will not be able to “play” the output.


For example, if you choose a setpoint lower than the one you get with the LED off, the controller will not be able to go below that, no matter how much it turns off the LED. Similarly, if the light received by the LDR is much higher than that of the LED on, it will have little effect, and the controller will be able to do little. It makes sense, right?.

So the first thing you should do is to measure the value registered by the LDR with the LED off and fully illuminated to determine a truly achievable intermediate setpoint for the controller.

Now it’s just a matter of uploading the following code,

#include <PIDController.hpp>

const long A = 1000; //Resistance in darkness in KΩ
const int B = 15; //Light resistance (10 Lux) in KΩ
const int Rc = 10; //Calibration resistance in KΩ

const int PIN_LDR = A0;
const int PIN_LED = 9;

PID::PIDParameters < double > parameters(0.4, 6.0, 0.0001);
PID::PIDController < double > pidController(parameters);

void setup()
    pinMode(PIN_LED, OUTPUT);

    pidController.Input = analogRead(PIN_LDR);
    pidController.Setpoint = 350;


float readLDR()
    float mean = 0;
    for (auto i = 0; i < 100; i++) {
        auto V = (float) analogRead(PIN_LDR);
        mean += (V * A * 10) / (B * Rc * (1024 - V));
    mean /= 100;
    return mean;

void loop() 
    auto ilum = readLDR();

    pidController.Input = ilum;

    analogWrite(PIN_LED, (int) pidController.Output);

Where we have used the PIDController library (which I have already made, so I use it). Logically you will have to adjust the values of K and the setpoint for your setup. But, as a guideline, they won’t be far from those in the example.

In the code, we are basically reading the LDR with a (simple) average of 100 measurements. We introduce this measurement as the input of the PID controller, and its output in the PWM signal to be applied to the LED.

Once we have everything ready, we turn on the setup. The result should be something like the following video, where by covering the setup it reacts by varying the intensity of the LED to maintain the designated lighting.

Also, as we can see, we can use the serial plotter of the Arduino IDE to graph the system’s response and adjust / verify its behavior.

This is a practical and real example of PID, which requires a very simple setup. This makes it very suitable for experiments with children, or in the field of teaching.

In future posts in the control theory section, we will see something a little more complex. A constant speed controller in a DC motor with encoder. Until next time!