AGS10有害气体传感器
AGS10是一款采用数字信号输出的MEMS TVOC传感器。配置了专用的数字模块采集技术和气体感应传感技术,确保了产品具有极高的可靠性与卓越的长期稳定性,同时具有低功耗、高灵敏度、快速响应、成本低、驱动电路简单等特点。
模块来源
规格参数
工作电压 : 3.0-6.0 V
典型功率 : 75mW
采样周期 : ≥2s
接口速率 :I2C从机模式(≤15kHz)
预热时间 : ≥120s
工作温度 : 0~50℃
工作湿度 : 0~95%RH
寿命 : >5年(25℃,清洁空气中)
输出单位 : ppb
测量范围 : 0~99999 ppb
典型精度( 25℃/50%RH): 25% 读数
标准测试气体 : 乙醇
模块尺寸:15*10.6mm
工作原理
通信步骤
AGS10传感器采用标准I2C通信协议,适应多种设备。IIC的物理接口包含串行数据信号(SDA)与串行时钟信号(SCL)两个接口。两个接口需通过1kΩ~10kΩ电阻上拉至VDD。SDA用于读、写传感器数据。SCL上电必须保持高电平直到进行IIC通信开始,否则会引起I 2C通讯不良。当I 2C通信时SCL用于主机与传感器之间的通讯同步。多个I2C设备可以共享总线,但是只能允许一个主机设备出现在总线上。既然采用的是IIC,那么我们需要知道它的IIC通信地址。
读取TVOC数据的步骤:
具体实现读取数据代码如下:
uint8_t ags10_read(void)
{
uint8_t timeout = 0;
uint8_t data[] = {0};
//发送起始信号S
AGS10_IIC_Start();
//发送器件地址+写
AGS10_IIC_Send_Byte(0X34);
//等待应答ACK,如不应答则结束该函数
if( AGS10_I2C_WaitAck() == 1 ) return 1;
//发送寄存器地址
AGS10_IIC_Send_Byte(0X00);
//等待应答ACK,如不应答则结束该函数
if( AGS10_I2C_WaitAck() == 1 ) return 2;
//发送停止信号P
AGS10_IIC_Stop();
do{
delay_1ms(1);
timeout++;
//重新发送起始信号
AGS10_IIC_Start();
//发送器件地址+读
AGS10_IIC_Send_Byte(0X35);
}while( (AGS10_I2C_WaitAck() == 1) && (timeout >= 50) );
//如果超时
if( timeout >= 50 ) return 3;
//读取5个数据
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Nack();
AGS10_IIC_Stop();
//CRC校验
if( Calc_CRC8(data,4) != data[] )
{
// printf("Check failed\r\n");
return 4;
}
//数据整合
TVOC_data = (data[]<<16) | (data[]<<8) | data[] ;
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
移植工程
AGS10通讯方式为I2C通讯,我们只需要用天空星实现I2C通讯,并按照数据手册对AGS10进行控制,就可以获取实时的有害气体浓度数据。这里我给出的代码是基于软件I2C,便于理解I2C通讯协议。
引脚选择
移植步骤
移植步骤中的导入.c和.h文件与【2.1 DHT11温湿度传感器】相同,只是将.c和.h文件更改为bsp_ags10.c与bsp_ags10.h。见2.1.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
bsp_ags10.c
#include "bsp_ags10.h"
#include "board.h"
#include "stdio.h"
/******************************************************************
* 函 数 名 称:ags10_gpio_init
* 函 数 说 明:对AGS10的IIC引脚初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:
******************************************************************/
void ags10_gpio_init(void)
{
//打开SDA与SCL的引脚时钟
rcu_periph_clock_enable(RCU_AGS10_SCL);
rcu_periph_clock_enable(RCU_AGS10_SDA);
//设置SCL引脚模式为上拉输出
gpio_mode_set(PORT_AGS10_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_AGS10_SCL);
//设置引脚为开漏模式,翻转速度2MHz
gpio_output_options_set(PORT_AGS10_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_AGS10_SCL);
//设置引脚输出高电平SCL等待信号
gpio_bit_write(PORT_AGS10_SCL, GPIO_AGS10_SCL, SET);
//设置SDA引脚
gpio_mode_set(PORT_AGS10_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_AGS10_SDA);
gpio_output_options_set(PORT_AGS10_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_AGS10_SDA);
gpio_bit_write(PORT_AGS10_SDA, GPIO_AGS10_SDA, SET);
}
//起始信号
void AGS10_IIC_Start(void)
{
AGS10_SDA_OUT();
AGS10_SDA(1);
AGS10_SCL(1);
delay_us(5);
AGS10_SDA(0);
delay_us(5);
AGS10_SCL(0);
delay_us(5);
}
//停止信号
void AGS10_IIC_Stop(void)
{
AGS10_SDA_OUT();
AGS10_SCL(0);
AGS10_SDA(0);
AGS10_SCL(1);
delay_us(5);
AGS10_SDA(1);
delay_us(5);
}
//发送非应答
void AGS10_IIC_Send_Nack(void)
{
AGS10_SDA_OUT();
AGS10_SCL(0);
AGS10_SDA(0);
AGS10_SDA(1);
AGS10_SCL(1);
delay_us(5);
AGS10_SCL(0);
AGS10_SDA(0);
}
//发送应答
void AGS10_IIC_Send_Ack(void)
{
AGS10_SDA_OUT();
AGS10_SCL(0);
AGS10_SDA(1);
AGS10_SDA(0);
AGS10_SCL(1);
delay_us(5);
AGS10_SCL(0);
AGS10_SDA(1);
}
/**********************************************************
* 函 数 名 称:I2C_WaitAck
* 函 数 功 能:等待从机应答
* 传 入 参 数:无
* 函 数 返 回:1=非应答 0=应答
* 作 者:LC
* 备 注:无
**********************************************************/
unsigned char AGS10_I2C_WaitAck(void)
{
char ack = 0;
unsigned char ack_flag = 10;
AGS10_SCL(0);
AGS10_SDA(1);
AGS10_SDA_IN();
delay_us(5);
AGS10_SCL(1);
delay_us(5);
while( (AGS10_GETSDA()==1) && ( ack_flag ) )
{
ack_flag--;
delay_us(5);
}
//非应答
if( ack_flag <= 0 )
{
AGS10_IIC_Stop();
return 1;
}
else//应答
{
AGS10_SCL(0);
AGS10_SDA_OUT();
}
return ack;
}
//发送一个字节
void AGS10_IIC_Send_Byte(uint8_t dat)
{
int i = 0;
AGS10_SDA_OUT();
AGS10_SCL(0);
for( i = 0; i < 8; i++ )
{
AGS10_SDA( (dat & 0x80) >> 7 );
delay_us(1);
AGS10_SCL(1);
delay_us(5);
AGS10_SCL(0);
delay_us(5);
dat<<=1;
}
}
//接收一个字节
unsigned char AGS10_IIC_Read_Byte(void)
{
unsigned char i,receive=0;
AGS10_SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
AGS10_SCL(0);
delay_us(5);
AGS10_SCL(1);
delay_us(5);
receive<<=1;
if( AGS10_GETSDA() )
{
receive |= 1;
}
}
AGS10_SCL(0);
return receive;
}
//********************************************************************
//函数名称:Calc_CRC8
//功能 :CRC8 计算,初值:0xFF,多项式:0x31(x8 + x5 + x4 +1)
//参数 :u8* dat:需要校验数据的首地址;u8 Num:CRC 校验数据长度
//返回 :crc:计算出的校验值
//********************************************************************
uint8_t Calc_CRC8(uint8_t *dat, uint8_t Num)
{
uint8_t i, byte, crc=0xFF;
for(byte=0; byte<Num; byte++)
{
crc ^= (dat[]);
for( i = 0; i < 8; i++ )
{
if(crc & 0x80) crc = ( crc << 1 ) ^ 0x31;
else crc = ( crc << 1 );
}
}
return crc;
}
/**********************************************************
* 函 数 名 称:ags10_read
* 函 数 功 能:读取AGS10的TVOC浓度数据
* 传 入 参 数:无
* 函 数 返 回:1: 通信失败
* 2:发送失败
* 3:等待超时
* 4: 校验失败
* 作 者:LCKFB
* 备 注:
**********************************************************/
uint32_t ags10_read(void)
{
uint8_t timeout = 0;
uint8_t data[] = {0};
uint32_t TVOC_data = 0;
AGS10_IIC_Start();
AGS10_IIC_Send_Byte(0X34);
if( AGS10_I2C_WaitAck() == 1 ) return 1;
AGS10_IIC_Send_Byte(0X00);
if( AGS10_I2C_WaitAck() == 1 ) return 2;
AGS10_IIC_Stop();
do{
delay_ms(1);
timeout++;
AGS10_IIC_Start();
AGS10_IIC_Send_Byte(0X35);
}while( (AGS10_I2C_WaitAck() == 1) && (timeout >= 50) );
//如果超时
if( timeout >= 50 ) return 3;
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Ack();
data[] = AGS10_IIC_Read_Byte();
AGS10_IIC_Send_Nack();
AGS10_IIC_Stop();
if( Calc_CRC8(data,4) != data[] )
{
// printf("Check failed\r\n");
return 4;
}
TVOC_data = (data[]<<16) | (data[]<<8) | data[] ;
return TVOC_data;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
bsp_ags10.h
#ifndef _BSP_AGS10_H_
#define _BSP_AGS10_H_
#include "gd32f4xx.h"
#define RCU_AGS10_SCL RCU_GPIOA
#define PORT_AGS10_SCL GPIOA
#define GPIO_AGS10_SCL GPIO_PIN_2
#define RCU_AGS10_SDA RCU_GPIOA
#define PORT_AGS10_SDA GPIOA
#define GPIO_AGS10_SDA GPIO_PIN_0
#define AGS10_SDA_IN() {gpio_mode_set(PORT_AGS10_SDA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_AGS10_SDA);} //SDA输入模式
#define AGS10_SDA_OUT() {gpio_mode_set(PORT_AGS10_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_AGS10_SDA);} //SDA输出模式
#define AGS10_SCL(BIT) gpio_bit_write( PORT_AGS10_SCL, GPIO_AGS10_SCL, BIT?SET:RESET)
#define AGS10_SDA(BIT) gpio_bit_write( PORT_AGS10_SDA, GPIO_AGS10_SDA, BIT?SET:RESET)
#define AGS10_GETSDA() gpio_input_bit_get( PORT_AGS10_SDA, GPIO_AGS10_SDA)
void ags10_gpio_init(void);
uint32_t ags10_read(void);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
移植验证
在main.c中编写以下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2023-11-02 LCKFB-yzh first version
*/
#include "board.h"
#include "bsp_ags10.h"
int main(void)
{
board_init();
bsp_uart_init();
//AGS10有害气体传感器初始化
ags10_gpio_init();
printf("start\r\n");
while(1)
{
//显示TVOC浓度
printf("TVOC = %d ppb\r\n",ags10_read() );
delay_ms(1000);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
代码下载
链接在开发板介绍
章节的资料下载!!