Introduction
In this tutorial we will learn how to connect an Ambient Light Sensor and an ESP32, and get analog measurements using the Arduino core and the ESP32 ADC.
I’ll be using this sensor module from DFRobot.
The tests shown below were performed on a ESP32-E FireBeetle board, also from DFRobot.
The ambient light sensor
As already mentioned, we are going to use this sensor module from DFRobot. The module integrates a PT550 light sensor, which is an analog sensor with an illumination range from 1 Lux to 6000 Lux and a response time of 15us [1].
The sensor module can be supplied with a voltage range from 3.3V to 5V [1]. In our case, since we are interacting with the sensor using an ESP32, we will use a power supply of 3.3V.
In terms of connectivity, the module exposes a 3 wires terminal, which means we don’t need to solder anything. We have the following 3 wires:
- GND
- VCC
- Signal
For more details about the sensor and how to interact with it from a microcontroller, you can also consult the sensor Wiki.
Important: Please note that we are going to work directly with the output of the ESP32 ADC, meaning that we are going to be able to correlate the light intensity with the outputted value, but we are not going to perform the conversion to the Lux unit. For many projects, just having this correlation is enough, as we can use the measured values diferences as a trigger for some action.
If your use case requires the actual value in Lux, then you will need to perform the conversion of the measured voltage to that unit. Unfortunately, at the time of writing, the datasheet of the PT550 sensor is in Chinese (.pdf here) and I did not find any resource clarifying the relation between the current or voltage and the illuminance.
Furthermore, please take in consideration that the ESP32 is known to have some linearity issues in the ADC (you can read more about it here), which might make it harder to obtain precise measurements.
As such, in this tutorial we are going to keep things simple and, as mentioned, use directly the ADC values.
The electric schematic
Taking in consideration the description of the sensor module from the previous section, we are now going to analyze how to connect it to the ESP32. Like mentioned before, we only have 3 wires, which means the connection will be relatively simple.
We will power the sensor with 3.3V and connect its GND pin to a common GND with the ESP32. Additionally, we will connect the sensor signal pin to a pin of the ESP32 that has support for analog readings.
In my case I’ll use pin 36, but you can use use other analog pin. Nonetheless, make sure to read the ESP32 ADC documentation, to choose an adequate pin.
Figure 1 below illustrates the connections between the ESP32 and the sensor.
When performing the connections, make sure to double check the color of the wires as documented in the Wiki, before connecting the power source. Although the Wiki mentions that the signal wire is green, my version came with a blue wire as signal wire. Red corresponds to VCC and gray to GND.
A simple example
We will start by defining a constant that will hold the value of the ESP32 pin connected to the ambient light sensor. I’ll be using pin 36, which is accordingly to the wiring diagram shown above. If you are using a different pin, you should change this value for your configuration.
const int sensorPin = 36;
Moving on to the Arduino setup function, we will simply take care of opening a serial connection. This way, we will be able to print the sensor measurements and see them in the Arduino IDE serial monitor.
void setup()
{
Serial.begin(115200);
}
Now we are going to analyze the implementation of the Arduino main loop, where we will periodically poll the sensor for a measurement.
To get a measurement from an analog pin, we simply need to call the analogRead function, passing as input the number of the pin from where we want to obtain the measurement. Naturally, we will pass the value we have stored in our sensorPin variable.
As output, this function will return a value between 0 and 4095, since the ESP32 ADC has a resolution of 12 bits [2]. We will store this value in a variable.
int analogVal = analogRead(sensorPin);
Now that we have our measurement, we will print it to the serial port.
Serial.println(analogVal);
To finalize the Arduino loop, we will do a small delay of 200 milliseconds. If you prefer an approach based on timer interrupts rather than delays, you can check this tutorial on how to setup timer interrupts on the ESP32.
delay(200);
The complete code can be seen below.
const int sensorPin = 36;
void setup()
{
Serial.begin(115200);
}
void loop()
{
int analogVal = analogRead(sensorPin);
Serial.println(analogVal);
delay(200);
}
To test the code, simply compile it and upload it to your device, after all the wirings are done.
After that, open the Arduino IDE serial monitor. You should get an output similar to figure 2. As can be seen, we obtain the result of the ADC, which should be a value between 0 and 4095.
If you cover the sensor and no light gets to it, you should see these values lowering and getting to zero. On the other hand, if you point a light directly at it, you should see the values increasing and getting to 4095.
A more complex example
In this section we are going to cover a slightly more complex example, where we will make use of the WebSerial library and send the measurements to a web based serial monitor. For an introductory tutorial on how to get started with this library, please check here.
As usual, we will start by the library includes. Followed by that, we are going to define two variables to hold the credentials of the WiFi network to which the ESP32 will connect. The ESP32 needs to be connected to a network in order for the WebSerial interface to work.
We will also create an object of class AsyncWebServer, which is used under the hood by the WebSerial library. Although we don’t need to interact much with the AsyncWebServer object in order to use the WebSerial interface, this tutorial explains how to setup a server using it, in case you are curious.
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <WebSerial.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPass";
AsyncWebServer server(80);
Like in the previous section, we will also define a global variable to hold the number of the analog pin of the ESP32 that is connected to the sensor.
const int sensorPin = 36;
In the setup function, we will start by opening a serial connection. The reason for this is simply to print the IP address assigned to the ESP32 on the network, which will be needed for us to reach the WebSerial console.
After that we are going to connect the ESP32 to the Wifi network using the previously defined credentials, initialize the WebSerial interface and start the server.
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Could not initialize WiFi");
return;
}
Serial.println(WiFi.localIP());
WebSerial.begin(&server);
server.begin();
}
The Arduino main loop will be equal to the previous section, but this time we will print the measurement to the WebSerial interface instead.
void loop() {
int analogVal = analogRead(sensorPin);
WebSerial.println(analogVal);
delay(1000);
}
The whole code is shown below.
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <WebSerial.h>
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPass";
AsyncWebServer server(80);
const int sensorPin = 36;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Could not initialize WiFi");
return;
}
Serial.println(WiFi.localIP());
WebSerial.begin(&server);
server.begin();
}
void loop() {
int analogVal = analogRead(sensorPin);
WebSerial.println(analogVal);
delay(1000);
}
To test the code, compile it and upload it to your device, after all the electric wirings are done. Don’t forget to change the placeholders by your network credentials.
Once the procedure finishes, open the Arduino IDE serial monitor. There, you should see the IP address of the ESP32 getting printed. Copy that value.
Then, on a web browser of your choice, access the following URL, replacing #YourEspIP# by the IP address you have just copied:
http://#YourEspIP#/webserial
You should see a result similar to figure 3. As can be seen, the page shows the WebSerial console, and we can see the measurements getting printed.
Suggested ESP32 Readings
References
[1] https://dfrobot.com/product-1004.html
[2] https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html