ESP32 I2C light sensor GY-49

Kirill Yatsenko
5 min readOct 26, 2020
Photo by Kristine Weilert on Unsplash

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:

  1. ESP32 dev board
  2. GY-49 sensor: For example
  3. Downloaded project: https://github.com/KirillYatsenko/gy-49
  4. 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

GY-49 wiring

Now you can run the app.

Navigate to the project folder, connect esp32 to the computer, and type:

idf.py flash monitor
DEMO

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:

  1. 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

general i2c message

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.

i2c request for reading from the specific register

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
i2c tools

First, we need to configure the i2c bus. Please type:

i2cconfig --sda=18 --scl=19

Now to get the GY-49 address type:

i2cdetect
i2cdetect command

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

MAX44009 Datasheet

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:

i2cget

I’ve got 0x4f. If you convert hex value to binary representation and calculate the lightning by the formula provided in the datasheet:

lux calculation

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.

app_main function

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.

read_lux_task and read_lux_i2c functions

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.

--

--