ESP32 I2C light sensor GY-49
Introduction
In this tutorial, we will take a look at how to read information from GY-49 Light Sensor by using the I2C protocol. The goal of this lesson is to get a basic understanding of how I2C works and how to use it with ESP32
Hardware required:
- ESP32 dev board
- GY-49 sensor: For example
- Downloaded project: https://github.com/KirillYatsenko/gy-49
- esp-idf installed. Installation guide
Running the demo
Wire GY-49
First, wire up your sensor to the esp32 dev board. One of the advantages of ESP32 is that you can specify different GPIOs for the I2C bus. Since it’s working on a simple i2c protocol you will only need 2 data lines connected to it. In my project, SDA is connected to 18 GPIO and SCL to 19 GPIO like on the image below
Now you can run the app.
Navigate to the project folder, connect esp32 to the computer, and type:
idf.py flash monitor
Note: you may get lux = 0.0000… That can happen because your GY-49 has a different I2C address, please follow the tutorial to find out how to change it
How the I2C protocol works
I will try to briefly explain to you how the i2c protocol works. There is an enormous amount of information on this topic on the web
In the I2C protocol, we have only two data lines:
- SDA(serial data) line is used for sending data between master and slave
2. SCL(serial clock) line is used for synchronizing data sent over SDA line. Master configures the clock speed
When a master wants to communicate with a slave the slave’s unique 7-bit address with the read/write flag should be sent as the first byte followed by acknowledging bit and data frame byte. At the beginning of each message, the START condition should occur and the STOP condition at the end
If the master wants to read data from the specific device register it should first send a message with the write flag after the slave’s address followed by the register’s address and only then send a message with the read flag.
Let’s check the GY-49 address
Sometimes an address of the device is written in the datasheet. But I prefer to double-check it by scanning I2C devices connected to the dev board.
If you have esp-idf installed go to the
esp-idf/examples/peripherals/i2c/i2c_tools
and run the project by typing
idf.py flash monitor
First, we need to configure the i2c bus. Please type:
i2cconfig --sda=18 --scl=19
Now to get the GY-49 address type:
i2cdetect
In my case, GY-49 has a 4b address
Let’s read some specs
Cool, we have the address of our slave now we should find out the internal register address.
Open datasheet: https://datasheets.maximintegrated.com/en/ds/MAX44009.pdf
Here you can find a lot of information regarding light sensor MAX44009 installed on the GY-49 module. Go to page #9 where “Lux High-Byte Register” is described there is also some information on how to calculate lighting from this register. As you may notice the register’s address we are interested in is 0x03
Let’s try to get some values
Now we know everything we need the slave’s address is 4b and the register’s address is 0x03. Open i2c_tools and type:
I’ve got 0x4f. If you convert hex value to binary representation and calculate the lightning by the formula provided in the datasheet:
Checking out the code
The code is very simple and very short. The main point here is to understand how I2C works and then try to apply your knowledge in practice.
Inside the app_main function, the I2C bus is configured in the master mode and the RTOS task is created for reading data from the GY-49 module. By the I2C protocol, SDA/SCL lines should be at a high level so we pull up them.
In the read_lux_i2c function on line #48 I2C command is created. On line #49 start condition is defined.
Then we write the address of the MAX44009 sensor and left shift by one bit. As you may remember the first byte consists of a 7-bit address and read/write flag. So we must shift the address and the last bit would be 0 which indicates write. On line #51 register address is written to the i2c bus.
Now we can fetch the data from the sensor on line #55 and save the result to the raw variable. To stop the communication i2_master_stop is used. On line #58 program starts executing the I2C command with a timeout of 1 second.
After we’ve got the data we can calculate the illuminance by the formula provided in the sensor’s datasheet.
Summary
Follow-ups: you can add LED to the project. For example, when it’s dark in the room the dev board can turn on the diode and vice versa. Or you can go even further and use a regular lamp instead of an LED. For this, you will need something called a relay.
I hope you find something useful for yourself.
If you have any problems following this tutorial you can leave a comment below or email me: kiriyatsenko@gmail.com.