Realization of GY39 Measuring Temperature, Humidity and Light Intensity with C51 Single Chip Microcomputer

GY-39 of c51 measures temperature, humidity and light intensity

  • 1. Introduction of GY-39
    • GY39 command data frame format
    • Received data frame format
      • Calculation of light value
      • Calculation of temperature, air pressure, humidity, altitude data
  • 2. Use C51 to calculate light, temperature and humidity values
  • 3. Experimental results
  • Four, finally

1. Introduction of GY-39

GY-39 is a low-cost, air pressure, temperature and humidity, light intensity sensor module. Working voltage 3-5v, low power consumption, easy installation. Its working principle is that the MCU collects various sensor data, processes them uniformly, and directly outputs the calculated results.
GY-39 module

In this module, there are two ways to read data, serial port UART (TTL level) or IIC (2-wire). Here is to use the serial port of C51 to collect the data of GY-39.

Communication protocol
The serial port communication parameters can have the following two options:
1. Baud rate: 9600 bps Parity bit: N Data bit: 8 Stop bit: 1
2. Baud rate: 115200 bps Parity bit: N Data bit: 8 Stop bit: 1
We will use method one with a baud rate of 9600 (if it is stm32, you can use method two)

Command data frame format of GY39

The GY39 module sends data in the form of commands. To put it simply, when you send a command, GY39 will reply the corresponding data to you. For example, if you send a command to get the light intensity, Gy39 will return the light data to you.

The format of all serial port commands of the GY-39 module is:
Frame header: 0xa5 (fixed)
So command format: frame header + command + checksum (8bit)
Command part
Send command: 0xA5 + 0x81 + 0x26, which means continuous output of light intensity, save the setting after power off, and automatically and continuously output light intensity after power on again;
Send command: 0xA5 + 0x82 + 0x27, which means continuous output of temperature, air pressure, humidity, altitude, save the setting after power off, and automatically output continuously after power on again;

Received data frame format

Module output format, 8-13 bytes per frame (hexadecimal)

Either 8 bits or 13 bits

①.Byte0: 0x5A Frame header flag
②.Byte1: 0x5A frame header flag
③.Byte2: 0x15 The data type of this frame (refer to the meaning description)
④.Byte3: 0x04 data volume
⑤.Byte4: 0x00~0xFF The upper 8 bits of the data
⑤.Byte5: 0x00~0xFF, the lower 8 bits before the data
⑥.Byte6: 0x00~0xFF data high 8 bits
⑦.Byte7: 0x00~0xFF data lower 8 bits
⑧.Byte8: 0x00~0xFF checksum (accumulated sum of previous data, leaving only the lower 8 bits)

Whether it is 8-bit data or 13-bit data:

  • The first two bits are 0xA5
  • The third bit is the data type
  • The fourth bit is the length of the data bits of the data frame
  • The last digit is the checksum (you can ignore it)

The third and fourth are the most important
Third place
The third format
When the third data bit is “0X15”, it means that this data frame is a data frame with lighting data
When the third data bit is “0X45”, it means that this data frame is a data frame of temperature, air pressure, humidity, altitude data

The fourth digit
Represents the size of the data bits of the data frame
For example: 0x04 means that the next 4 bits are all data bits

Calculation of light value

Light intensity calculation method (when Byte2=0x15, data: Byte4~Byte7):
Lux=(first high 8 bits<<24) | (first low 8 bits<<16) | (last high 8 bits<<8) | last low 8 bits unit lux

Example: a frame of data
<5A-5A-15-04-00-00-FE-40-0B>
Lux=(0x00<<24)|(0x00<<16)|(0xFE<<8)|0x40
Lux=Lux/100 =650.88 (lux)

Calculation of temperature, air pressure, humidity, altitude data

Temperature, air pressure, humidity, altitude, calculation method (when Byte2=0x45):

Temperature: Byte4~Byte5
T=(high 8 bits<<8)|low 8 bits
T=T/100 unit ℃
Air pressure: Byte6~Byte9
P=(first high 8 bits<<24) | (first low 8 bits<<16) | (last high 8 bits<<8) | last low 8 bits
P=P/100 unit pa
Humidity: Byte10~Byte11
Hum=(high 8 bits<<8)|low 8 bits
Hum=Hum/100 percentile
Altitude: Byte12~Byte134
H=(high 8 bits<<8)|low 8 bits unit m

Example: a frame of data
< 5A -5A -45 -0A -0B -2D -00 -97 -C4 -3F -12- 77 -00- 9C-FA >
T=(0x0B<<8)|0x2D=2861
Temperature T=2861/100=28.61 (℃ )
P=(0x00<<24)|(0x97<<16)|(C4<<8)|3F=9946175
Air pressure P=9946175/100=99461.75 (pa)
Hum=(0x12<<8)| 77=4727
Humidity Hum=4727/100=47.27 (%)
Altitude H=(0x00<<8)|0x9c=156 (m)

2. Use C51 to calculate light, temperature and humidity values

wiring:
TXD -> DR
RXD -> CT
As shown in the picture:
wiring diagram

Because GY-39 requires the MCU to send commands continuously, it will read the data and send it to our 51 MCU, so we use the polling method to continuously send our command data frames to the MCU, so that we can always get data.

our main function

while(1)
{<!-- -->
//======================== Processing light intensity ========================
        send_buff(buff1,2);
delay_ms(10);
if(Receive_ok==2)
        {<!-- -->

            Lux = (raw_data[4]<<24)|(raw_data[5]<<16)|(raw_data[6]<<8)|raw_data[7];
            LCD_ShowString(2,1,"Lux:");
            LCD_ShowNum(2,5,Lux/100,3);
            LCD_ShowString(2,8,".");
            LCD_ShowNum(2,9,Lux 0,2);
            Receive_ok = 0;
        }
delay_ms(500);
//================== Processing temperature, humidity ===========================
        send_buff(buff1,3);
delay_ms(10);
        if(Receive_ok==1)
        {<!-- -->
HUM = (raw_data[10]<<8)|raw_data[11];
LCD_ShowString(1,1,"HU:");
LCD_ShowNum(1,4,HUM/100,2);
LCD_ShowString(1,6,".");
LCD_ShowNum(1,7,HUM 0,2);
TE =(raw_data[4]<<8)|raw_data[5];
LCD_ShowString(1,9,"TE:");
LCD_ShowNum(1,12,TE/100,2);
LCD_ShowString(1,14,".");
LCD_ShowNum(1,15,TE 0,2);
            Receive_ok = 0;
        }
        delay_ms(500); // give a delay
}

C51 sends command data to GY-39

void send_buff(u8 *tem_buff,u8 buff_size)
{<!-- -->
    u8 i;
    for(i=0;i<buff_size;i + + )
    {<!-- -->
        SBUF = tem_buff[i];
        while(TI==0){<!-- -->};
TI = 0;
    }
}

Serial port interrupt function

void USART_IRQHandler(void)interrupt 4
{<!-- -->
static uint8_t i=0, rebuf[15]={<!-- -->0};
uint8_t sum=0;
if(RI)//receive completion flag
{<!-- -->
rebuf[i++]=SBUF;
        RI=0;//clear interrupt receiving flag
if (rebuf[0]!=0x5a)//The frame header is wrong
i=0;
if ((i==2) & amp; & amp;(rebuf[1]!=0x5a))//The frame header is wrong
i=0;
if(i>3)//i is equal to 4, the data volume byte rebuf[3] has been received
{<!-- -->

if(i!=(rebuf[3] + 5))//judging whether a frame of data is received
return;
switch(rebuf[2])//Process after receiving
{<!-- -->
case 0x45:
if(!Receive_ok)//Receive new data only after data processing is completed
{<!-- -->
memcpy(raw_data,rebuf,15);//Copy the received data
Receive_ok=1;//Receive completion flag
}
break;
case 0x15:
            if(!Receive_ok)//Receive new data only after data processing is completed
{<!-- -->
memcpy(raw_data,rebuf,9);//Copy the received data
Receive_ok=2;//Receive completion flag
}
            break;//Original data reception, can imitate the way of 0x45
case 0x35:break;
}
i=0;//Cache clear 0
}
}
}

3. Experimental results

Experimental results

4. Finally

Code click here to download the link