STM32 development practice-data collection of AHT20 temperature and humidity sensor based on I2C protocol

STM32 development practice-data collection of AHT20 temperature and humidity sensor based on I2C protocol

  • Preface
  • “Software I2C” and “Hardware I2C”
    • SoftwareI2C
    • HardwareI2C
  • AHT20 temperature and humidity sensor
    • AHT20 main features
    • AHT20 parameters
    • Application areas
  • STM32 data collection of AHT20 temperature and humidity sensor based on I2C protocol
    • Ideas
    • code
    • Experimental effect
  • Summarize

Foreword

In the fields of embedded systems and the Internet of Things, STM32 microcontrollers are favored by developers because of their efficient performance and wide range of application support. In order to further expand its functionality, we can achieve more data processing and control functions by adding external sensors. The AHT20 temperature and humidity sensor is a common environmental monitoring device that can communicate with the STM32 microcontroller through the I2C protocol to collect environmental temperature and humidity data.

This experiment will introduce how to use STM32 microcontroller and AHT20 temperature and humidity sensor to collect data based on I2C protocol. Through this experiment, we will learn how to set up I2C communication on STM32, how to initialize the AHT20 sensor, and how to read and parse the temperature and humidity data sent by the AHT20. In addition, we will explore how to programmatically upload collected data to a computer or cloud platform for storage and analysis.

Through this experiment, we will have an in-depth understanding of the working principle and application method of the STM32 microcontroller and AHT20 temperature and humidity sensor. Through practical operations, we will master the data collection method based on I2C protocol and improve our embedded system and IoT application development capabilities. At the same time, this experiment will also provide some practical skills and experience to help us better solve possible problems during the development process.
ATH20

“Software I2C” and “Hardware I2C”

Software I2C and hardware I2C are two different implementations used for I2C communication in embedded systems and electronic devices.

Software I2C

Software I2C is a way of simulating I2C communication by controlling GPIO pins through software.

Hardware I2C

Hardware I2C is a way of realizing I2C communication through specialized hardware circuits.

Features Description
Implementation method Simulate I2C communication through software control of GPIO pins
Speed Relatively slow
Flexibility Relatively flexible and adaptable to special hardware environments
Reliability Limited by software implementation and may be affected by interruptions and Impact of latency
Resource occupation Requires the use of additional GPIO pins and software resources
Features Description
Implementation method Control and transmit the clock and data lines on the I2C bus through hardware circuits
Speed Fast
Stability Controlled by hardware circuits to provide stable timing and signal quality
Reliability High reliability, Reduce communication errors and interference
Resource occupation Integrated in the chip or module, no additional pins and software resources are required

The choice of using software I2C or hardware I2C depends on the specific application requirements and hardware environment. Normally, if the hardware already has an integrated hardware I2C interface, it is recommended to use hardware I2C to provide higher performance and reliability. When the hardware I2C interface cannot be used or you need to simulate I2C communication in a specific environment, you can choose to use software I2C.


It can be seen from the figure that when I2C is communicating, SDA data transmission is effective only when SCL is at a high level. The SDA signal line is used to transmit data, and the SCL signal line ensures data synchronization.
When SDA transmits data, the receiver responds to the received data. If you want to continue transmitting data, respond with a response signal (low level), otherwise respond with a non-response signal (high level).

AHT20 temperature and humidity sensor

AHT20 is a digital temperature and humidity sensor with high accuracy, fast response and low power consumption. It uses advanced CMOSens? technology to accurately measure the temperature and humidity of the environment and communicate with the main control device through the I2C interface.

Main features of AHT20

  • High-precision measurement: The AHT20 sensor has excellent temperature and humidity measurement accuracy, reaching a temperature accuracy of ±0.3°C and a humidity accuracy of ±2%.
  • Quick response: The AHT20 sensor can provide accurate temperature and humidity data with a fast response time of only 8 milliseconds.
  • Low power consumption: The AHT20 sensor adopts an ultra-low power consumption design, with an operating current of only 3μA, effectively extending battery life.
  • Wide Temperature Range: The AHT20 sensor provides stable and reliable measurements over a wide temperature range of -40°C to +85°C.
  • Digital output: The AHT20 sensor outputs digital signals through the I2C interface for communication and data interaction with the main control device.
  • Calibration and linearization: The AHT20 sensor is calibrated and linearized before leaving the factory, providing accurate measurement results.

AHT20 parameters

The following are the main parameters of the AHT20 temperature and humidity sensor:

Parameter Description
Operating voltage 1.8V to 3.6V
Temperature measurement range -40°C to +85°C
Temperature accuracy ±0.3°C
Humidity measurement range 0%RH to 100%RH
Humidity accuracy ±2%RH
I2C address 0x38
Response time 8 milliseconds
Operating current 3μA
Encapsulation TO-39

Application fields

AHT20 temperature and humidity sensor is widely used in various fields, such as:

  • Indoor environment monitoring
  • Smart home system
  • Agriculture and Greenhouse Monitoring
  • Instrumentation and Industrial Automation
  • Weather stations and meteorological observations

The high accuracy, fast response and low power consumption of the AHT20 sensor make it an ideal choice for temperature and humidity measurements.

Data collection of STM32 AHT20 temperature and humidity sensor based on I2C protocol

Ideas

  1. Hardware connection:
    • Connect STM32 and AHT20 temperature and humidity sensor through I2C bus.
    • Make sure the I2C pins of the STM32 (such as SDA and SCL) are connected to the corresponding pins of the AHT20 sensor.
  2. Initialize I2C:
    • In the code of STM32, initialize the I2C bus and configure the I2C pins and parameters of STM32.
    • Set the I2C clock frequency and other related parameters.
  3. Configure the AHT20 sensor:
    • Sends the I2C start signal and sends the I2C address of the AHT20 sensor.
    • Send configuration commands to the AHT20 sensor, such as setting measurement mode and frequency, etc.
  4. Read temperature and humidity data:
    • Send a command to read data to the AHT20 sensor.
    • Receiving temperature and humidity data from the AHT20 sensor can be completed through the I2C read operation.
    • Parse the received data and obtain the temperature and humidity values.
  5. Data processing:
    • Convert the received raw data into actual temperature and humidity values.
    • Conversions can be made using the formulas and calculation methods provided by the AHT20 sensor.
  6. Output Data:
    • Output the obtained temperature and humidity values through the serial port, LCD display or other peripherals.
    • Data can be sent to the computer through the serial port for real-time monitoring and recording.
  7. Loop collection:
    • Set up loops in your code to repeatedly perform data collection and processing operations at regular intervals.
    • You can use a delay function or timer to control the acquisition frequency.

The above is a basic experimental idea, which can be configured and coded according to the specific STM32 development board and programming environment. In the actual experiment, you also need to pay attention to the correctness of the power supply and signal line connection, as well as the correct configuration and reading of the sensor data according to the data sheet of the AHT20 sensor.

Code

bsp_i2c.c

#include "bsp_i2c.h"
#include "delay.h"

uint8_t ack_status=0;
uint8_t readByte[6];
uint8_t AHT20_status=0;

uint32_t H1=0; //Humility
uint32_t T1=0; //Temperature

uint8_t AHT20_OutData[4];
uint8_t AHT20sendOutData[10] = {<!-- -->0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

void IIC_Init(void)
{<!-- -->
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
\t   
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //¨a?¨a¨?¨o?3?
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
 
IIC_SCL=1;
IIC_SDA=1;
 
}
//2¨2¨|¨2IIC?e¨o?D?o?
void IIC_Start(void)
{<!-- -->
SDA_OUT(); //sda¨o?3?
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
 IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//¥?á?I2C?á¨1?êáà¤?é?¨a?¨°?¨?¨o?¨oy?Y
}
//2¨2¨|¨2IIC¨a?ê?1D?o?
void IIC_Stop(void)
{<!-- -->
SDA_OUT();//sda¨o?3?
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//?¤?é?¨aI2C?á¨1?¨¢¨o?D?o?
delay_us(4);
}
//|쨨y¨?|eD?o?|ì?¨¤
//?¤|ì?|ì?êo1?ê¨?¨o?¨?|e¨o?ì¨1
// 0?ê¨?¨o?¨?|e3¨|1|
u8 IIC_Wait_Ack(void)
{<!-- -->
u8 ucErrTime=0;
SDA_IN(); //SDA¨|¨¨?a¨o?¨¨?
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{<!-- -->
ucErrTime + + ;
if(ucErrTime>250)
{<!-- -->
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//¨o?à?¨?¨o?3?0
return 0;
}
//2¨2¨|¨2ACK¨?|e
void IIC_Ack(void)
{<!-- -->
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//2?2¨2¨|¨2ACK¨?|e
void IIC_NAck(void)
{<!-- -->
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC?¤?é?¨a¨°á¨2
//?¤|쨨2¨?D?T¨?|e
//1?ê?¨?D¨?|e
//0?êT¨?|e
void IIC_Send_Byte(u8 txd)
{<!-- -->
    u8t;
SDA_OUT();
    IIC_SCL=0;//¨¤-|ì¨a¨o?à?¨a¨o?¨oy?Y?¨o?
    for(t=0;t<8;t + + )
    {<!-- -->
        IIC_SDA=(txd & amp;0x80)>>7;
        txd<<=1;
delay_us(2); //TEA5767?a¨¨y?¨?¨o?à¨oà?D?|ì?
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
    }
}
//?¨¢1?á¨2?ê?ack=1¨o?à?ê¤?é?¨aACK?ê?ack=0?ê¤?é?¨anACK
u8 IIC_Read_Byte(unsigned char ack)
{<!-- -->
unsigned char i,receive=0;
SDA_IN();//SDA¨|¨¨?a¨o?¨¨?
  for(i=0;i<8;i + + )
{<!-- -->
    IIC_SCL=0;
    delay_us(2);
IIC_SCL=1;
    receive<<=1;
    if(READ_SDA)receive + + ;
delay_us(1);
  }
if (!ack)
IIC_NAck();//?¤?é?¨anACK
else
IIC_Ack(); //?¤?é?¨aACK
return receive;
}
 
void IIC_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)
{<!-- -->
IIC_Start();
\t
if(device_addr==0xA0) //eeprom|ì?¤¨?¨?¨21?á¨2
IIC_Send_Byte(0xA0 + ((addr/256)<<1));//?¤?é?¨a|ì?¤
else
IIC_Send_Byte(device_addr); //?¤?ét|ì?¤
IIC_Wait_Ack();
IIC_Send_Byte(addr & amp;0xFF); //?¤?é?¨a|ì¨a|ì?¤
IIC_Wait_Ack();
IIC_Send_Byte(data); //?¤?é?¨a?á¨2
IIC_Wait_Ack();
  IIC_Stop();//2¨2¨|¨2¨°?¨a?ê?1¨?t
if(device_addr==0xA0) //
delay_ms(10);
else
delay_us(2);
}
 
uint16_t IIC_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead) //?¨¢?¨°?¨¢¨oy?Y
{<!-- -->
uint16_t data;
IIC_Start();
if(device_addr==0xA0)
IIC_Send_Byte(0xA0 + ((addr/256)<<1));
else
IIC_Send_Byte(device_addr);
IIC_Wait_Ack();
IIC_Send_Byte(addr & amp;0xFF); //?¤?é?¨a|ì¨a|ì?¤
IIC_Wait_Ack();
 
IIC_Start();
IIC_Send_Byte(device_addr + 1); //?¤?ét|ì?¤
IIC_Wait_Ack();
if(ByteNumToRead == 1)//LM75?¨¨¨oy?Y?a11bit
{<!-- -->
data=IIC_Read_Byte(0);
}
else
{<!-- -->
data=IIC_Read_Byte(1);
data=(data<<8) + IIC_Read_Byte(0);
}
IIC_Stop();//2¨2¨|¨2¨°?¨a?ê?1¨?t
return data;
}


/**********
*¨|?2¤aIO?¨2ê?¨|I2C
*
*¨a¨°a¨oaAHT20|ìI2C
*o?¥¨oy¨?DIICo¨aI2C|ìàe?êá?騰a?êêêêê?
*
*2020/2/23?á?o¨?DT¨¨¨2
*
*************/
void read_AHT20_once(void)
{<!-- -->
delay_ms(10);

reset_AHT20();
delay_ms(10);

init_AHT20();
delay_ms(10);

startMeasure_AHT20();
delay_ms(80);

read_AHT20();
delay_ms(5);
}


void reset_AHT20(void)
{<!-- -->

I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("1");
else printf("1-n-");
I2C_WriteByte(0xBA);
ack_status = Receive_ACK();
if(ack_status) printf("2");
else printf("2-n-");
I2C_Stop();

/*
AHT20_OutData[0] = 0;
AHT20_OutData[1] = 0;
AHT20_OutData[2] = 0;
AHT20_OutData[3] = 0;
*/
}



void init_AHT20(void)
{<!-- -->
I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("3");
else printf("3-n-");
I2C_WriteByte(0xE1);
ack_status = Receive_ACK();
if(ack_status) printf("4");
else printf("4-n-");
I2C_WriteByte(0x08);
ack_status = Receive_ACK();
if(ack_status) printf("5");
else printf("5-n-");
I2C_WriteByte(0x00);
ack_status = Receive_ACK();
if(ack_status) printf("6");
else printf("6-n-");
I2C_Stop();
}



void startMeasure_AHT20(void)
{<!-- -->
//----------------
I2C_Start();

I2C_WriteByte(0x70);
ack_status = Receive_ACK();
if(ack_status) printf("7");
else printf("7-n-");
I2C_WriteByte(0xAC);
ack_status = Receive_ACK();
if(ack_status) printf("8");
else printf("8-n-");
I2C_WriteByte(0x33);
ack_status = Receive_ACK();
if(ack_status) printf("9");
else printf("9-n-");
I2C_WriteByte(0x00);
ack_status = Receive_ACK();
if(ack_status) printf("10");
else printf("10-n-");
I2C_Stop();
}



void read_AHT20(void)
{<!-- -->
uint8_t i;

for(i=0; i<6; i + + )
{<!-- -->
readByte[i]=0;
}

//-------------
I2C_Start();

I2C_WriteByte(0x71);
ack_status = Receive_ACK();
readByte[0]= I2C_ReadByte();
Send_ACK();

readByte[1]= I2C_ReadByte();
Send_ACK();

readByte[2]= I2C_ReadByte();
Send_ACK();

readByte[3]= I2C_ReadByte();
Send_ACK();

readByte[4]= I2C_ReadByte();
Send_ACK();

readByte[5]= I2C_ReadByte();
SendNot_Ack();
//Send_ACK();

I2C_Stop();

//-------------
if( (readByte[0] & amp; 0x68) == 0x08 )
{<!-- -->
H1 = readByte[1];
H1 = (H1<<8) | readByte[2];
H1 = (H1<<8) | readByte[3];
H1 = H1>>4;

H1 = (H1*1000)/1024/1024;

T1 = readByte[3];
T1 = T1 & 0x0000000F;
T1 = (T1<<8) | readByte[4];
T1 = (T1<<8) | readByte[5];

T1 = (T1*2000)/1024/1024 - 500;

AHT20_OutData[0] = (H1>>8) & amp; 0x000000FF;
AHT20_OutData[1] = H1 & 0x000000FF;

AHT20_OutData[2] = (T1>>8) & amp; 0x000000FF;
AHT20_OutData[3] = T1 & 0x000000FF;
}
else
{<!-- -->
AHT20_OutData[0] = 0xFF;
AHT20_OutData[1] = 0xFF;

AHT20_OutData[2] = 0xFF;
AHT20_OutData[3] = 0xFF;
printf("lyy");

}
printf("\r\\
");
printf("?è:%d%d.%d",T1/100,(T1/10) ,T1 );
printf("êa?è:%d%d.%d",H1/100,(H1/10) ,H1 );
printf("\r\\
");
}




uint8_tReceive_ACK(void)
{<!-- -->
uint8_t result=0;
uint8_t cnt=0;

IIC_SCL = 0;
SDA_IN();
delay_us(4);

IIC_SCL = 1;
delay_us(4);

while(READ_SDA & amp; & amp; (cnt<100))
{<!-- -->
cnt + + ;
}

IIC_SCL = 0;
delay_us(4);

if(cnt<100)
{<!-- -->
result=1;
}
return result;
}



void Send_ACK(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 0;
delay_us(4);

IIC_SDA = 0;
delay_us(4);

IIC_SCL = 1;
delay_us(4);
IIC_SCL = 0;
delay_us(4);

SDA_IN();
}



void SendNot_Ack(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 0;
delay_us(4);

IIC_SDA = 1;
delay_us(4);

IIC_SCL = 1;
delay_us(4);

IIC_SCL = 0;
delay_us(4);

IIC_SDA = 0;
delay_us(4);
}


void I2C_WriteByte(uint8_t input)
{<!-- -->
uint8_t i;
SDA_OUT();
for(i=0; i<8; i + + )
{<!-- -->
IIC_SCL = 0;
delay_ms(5);

if(input & 0x80)
{<!-- -->
IIC_SDA = 1;
//delaymm(10);
}
else
{<!-- -->
IIC_SDA = 0;
//delaymm(10);
}

IIC_SCL = 1;
delay_ms(5);

input = (input<<1);
}

IIC_SCL = 0;
delay_us(4);

SDA_IN();
delay_us(4);
}


uint8_t I2C_ReadByte(void)
{<!-- -->
uint8_t resultByte=0;
uint8_t i=0, a=0;

IIC_SCL = 0;
SDA_IN();
delay_ms(4);

for(i=0; i<8; i + + )
{<!-- -->
IIC_SCL = 1;
delay_ms(3);

a=0;
if(READ_SDA)
{<!-- -->
a=1;
}
else
{<!-- -->
a=0;
}

//resultByte = resultByte | a;
resultByte = (resultByte << 1) | a;

IIC_SCL = 0;
delay_ms(3);
}

SDA_IN();
delay_ms(10);

return resultByte;
}


void set_AHT20sendOutData(void)
{<!-- -->
/*--------------------------
* 0xFA 0x06 0x0A temperature(2 Bytes) humility(2Bytes) short Address(2 Bytes)
* And Check (1 byte)
*-------------------------*/
AHT20sendOutData[3] = AHT20_OutData[0];
AHT20sendOutData[4] = AHT20_OutData[1];
AHT20sendOutData[5] = AHT20_OutData[2];
AHT20sendOutData[6] = AHT20_OutData[3];

// AHT20sendOutData[7] = (drf1609.shortAddress >> 8) & amp; 0x00FF;
// AHT20sendOutData[8] = drf1609.shortAddress & amp; 0x00FF;

// AHT20sendOutData[9] = getXY(AHT20sendOutData,10);
}


void I2C_Start(void)
{<!-- -->
SDA_OUT();
IIC_SCL = 1;
delay_ms(4);

IIC_SDA = 1;
delay_ms(4);
IIC_SDA = 0;
delay_ms(4);

IIC_SCL = 0;
delay_ms(4);
}



void I2C_Stop(void)
{<!-- -->
SDA_OUT();
IIC_SDA = 0;
delay_ms(4);

IIC_SCL = 1;
delay_ms(4);

IIC_SDA = 1;
delay_ms(4);
}

main.c

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "stm32f10x.h" // Device header


int main(void)
{<!-- -->
delay_init(); //?¨?¨o?ào?¥¨oy3?¨o?¥
uart_init(115200); //¨23?¨o?¥?a115200
IIC_Init();
while(1)
{<!-- -->
printf("Temperature and humidity display:");
read_AHT20_once();
delay_ms(1500);
  }
}

Experimental results

For better output effect, the data is output to the OLED display. For the usage of the OLED display, see the next article (not released yet, so stay tuned)

Summary

In this experiment, we learned how to use the STM32 development board to collect data from the AHT20 temperature and humidity sensor through the I2C protocol.
First, we understand the basic principles and communication process of the I2C protocol. I2C is a serial communication protocol that uses two lines (SDA and SCL) for data transmission. Among them, the SDA line is used for data transmission, and the SCL line is used for clock synchronization.
Next, we connected the AHT20 sensor to the I2C bus on the STM32 development board and initialized the I2C controller in the code. Then, we implemented communication with the AHT20 sensor by sending the I2C Start signal, sending the device address, sending the register address, sending data and other steps.
In terms of data collection, we obtained real-time temperature and humidity data by reading the temperature and humidity registers of the AHT20 sensor. Then, we processed and converted the original data to obtain more readable temperature and humidity values.
Finally, we output the collected temperature and humidity data through the serial port for further data analysis and processing.
Through this experiment, we mastered the data collection method of the AHT20 temperature and humidity sensor based on the I2C protocol. This is of great significance to our application of temperature and humidity sensors and environmental monitoring in actual projects.
We can further expand this experiment, such as storing the collected data on an SD card or cloud platform to achieve functions such as remote monitoring and data analysis.
In general, this experiment helped us deeply understand the application of the I2C protocol and the working principle of the AHT20 temperature and humidity sensor, which provided a good foundation for our subsequent development of the Internet of Things and embedded systems.