HB-021 氧气传感器模块

STM32F103C8T6 · HAL库开发 · AO-03电化学探头 · 5V供电

工作电压
5V
通信方式
ADC模拟量
传感器探头
AO-03 电化学

1传感器原理与功能

1.1 工作原理

HB-021氧气传感器模块由精密运放电路搭配奥松(Aosong)公司的AO-03电化学氧气传感器组合而成。 AO-03采用原电池(伽伐尼)式工作原理,无需外部电源即可工作。 传感器内部包含铅阳极和氧阴极,中间填充电解液。当环境中的氧气通过透气膜扩散进入传感器内部时, 在阴极发生还原反应 O₂ + 2H₂O + 4e⁻ → 4OH⁻, 在阳极发生氧化反应 2Pb + 4OH⁻ → 2PbO + 2H₂O + 4e⁻。 整个反应产生的电流与氧气浓度成正比,AO-03在空气中输出约0.1±0.03mA的微弱电流信号。 HB-021模块内部的精密运放电路将该微弱电流转换为0.1~0.6V的模拟电压信号,由OUT引脚输出至STM32的ADC采集。

1.2 核心功能

⚡

模拟量输出

OUT引脚输出0.1~0.6V模拟电压信号,由模块内部精密运放电路将AO-03传感器的微弱电流放大后输出。

📊

浓度计算

通过标定系数53.59和偏差校准值,将采集到的电压值线性转换为氧气浓度百分比。

🖥️

OLED显示

0.96寸OLED显示屏通过软件I2C驱动,实时居中显示当前氧气浓度数值。

🔧

校准调整

程序中的偏差值为标定参数,可根据空气中20.9%的氧气浓度基准进行校准修正。

1.3 引脚定义

引脚名称功能STM32连接
VCC电源正极5V供电输入5V
GND电源地接地GND
OUT模拟输出0.1~0.6V模拟电压,与O₂浓度成正比PA0 (ADC1_IN0)

2模块外观展示

3原理图与PCB封装

原理图
PCB封装

4程序分析

4.1 系统时钟配置

配置说明:使用外部高速晶振(HSE)8MHz,通过PLL倍频9倍得到72MHz系统时钟。 APB1总线36MHz,APB2总线72MHz,ADC时钟为APB2的8分频即9MHz。模块工作电压5V,AO-03传感器无需外部供电。
stm32f1xx_it.c / system_stm32f1xx.c — SystemClock_Config()
void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; // 使用外部高速晶振 HSE 8MHz RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 8MHz × 9 = 72MHz if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler(); // 系统时钟 = PLL = 72MHz RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // HCLK = 72MHz RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1 = 36MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 = 72MHz if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) Error_Handler(); // ADC时钟 = APB2 / 8 = 9MHz PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); }

4.2 GPIO初始化

配置说明:使能GPIOD和GPIOA时钟。GPIOA的PA0配置为模拟模式,用于ADC1通道0采集传感器AO输出的模拟电压。
gpio.c — MX_GPIO_Init()
void MX_GPIO_Init(void) { // 使能GPIO时钟 __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); }

4.3 ADC初始化

配置说明:使用ADC1通道0(PA0),单次转换模式,软件触发。12位分辨率(0-4095), 右对齐,采样时间239.5个ADC时钟周期(约26.6μs),保证采集精度。ADC对应的GPIO在MspInit中配置为模拟模式。
adc.c — MX_ADC1_Init() & HAL_ADC_MspInit()
void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 非扫描模式 hadc1.Init.ContinuousConvMode = DISABLE; // 单次转换 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐 hadc1.Init.NbrOfConversion = 1; // 1个转换通道 HAL_ADC_Init(&hadc1); sConfig.Channel = ADC_CHANNEL_0; // 通道0 → PA0 sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // 239.5周期采样 HAL_ADC_ConfigChannel(&hadc1, &sConfig); } void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(adcHandle->Instance == ADC1) { __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // PA0 → ADC1_IN0 模拟输入 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } }

4.4 OLED显示屏初始化(软件I2C)

配置说明:OLED使用0.96寸SSD1306驱动芯片,4针I2C接口。SCL接PB15,SDA接PB14, 均配置为开漏输出模式。通过软件模拟I2C时序与OLED通信,从机地址0x78。 显示分辨率为128×64像素,支持中文和ASCII字符混合显示。
OLED.c — OLED_GPIO_Init() & OLED_Init()
// 引脚定义 #define SCL_Port GPIOB #define SCL_Pin GPIO_PIN_15 #define SDA_Port GPIOB #define SDA_Pin GPIO_PIN_14 void OLED_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); // SCL和SDA配置为开漏输出 GPIO_InitStruct.Pin = SCL_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init(SCL_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = SDA_Pin; HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct); // 释放总线 OLED_W_SCL(1); OLED_W_SDA(1); } void OLED_Init(void) { OLED_GPIO_Init(); // 引脚初始化 OLED_WriteCommand(0xAE); // 关闭显示 OLED_WriteCommand(0xD5); // 设置时钟分频 OLED_WriteCommand(0x80); // ... 其他初始化命令省略 ... OLED_WriteCommand(0xAF); // 开启显示 OLED_Clear(); OLED_Update(); }

4.5 主循环逻辑

配置说明:主循环每200ms执行一次数据采集。使用HAL_GetTick()获取系统时间戳判断间隔, 启动ADC单次转换并等待完成后读取原始值,将其转换为电压再计算氧气浓度, 最后通过OLED清屏、居中显示浓度值并更新屏幕。偏差值用于校准,保证空气中读数在20.9%左右。
main.c — while(1) 主循环
// 全局变量 uint32_t Time_Now; // 时间戳 float Voltage; // 电压值 float O2; // 氧气浓度 int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); OLED_Init(); while (1) { if(HAL_GetTick() - Time_Now >= 200) // 每200ms更新一次 { // 单通道数据获取 HAL_ADC_Start(&hadc1); if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK) Voltage = (HAL_ADC_GetValue(&hadc1) / 4095.0) * 3.3; HAL_ADC_Stop(&hadc1); // 偏差值为标定校准,空气中氧气含量约20.9%,请修改此值校准 O2 = (53.59 * Voltage + 1.2); OLED_Clear(); // 清屏 OLED_CenterPrintf(24, "氧气:%.1f", O2); // 居中显示 OLED_Update(); // 更新显示 Time_Now = HAL_GetTick(); // 更新时间戳 } } }

4.6 数据计算公式

电压转换公式

Voltage = (ADC_Value / 4095.0) × 3.3

STM32的ADC为12位分辨率,原始值范围0~4095。参考电压3.3V,将原始值线性映射到实际电压值。 HB-021模块OUT引脚输出范围为0.1~0.6V。

氧气浓度计算公式

O₂ = 53.59 × Voltage + 偏差校准值

系数53.59为HB-021模块运放电路的标定灵敏度,偏差值通过校准确定(本程序为+1.2)。 AO-03传感器在空气中输出约0.1±0.03mA电流,经模块运放电路放大后对应约0.366V电压, 此时O₂读数约为20.9%。AO-03的线性测量范围为0~30%Vol,响应时间T90<15秒,预期使用寿命约2年。

环境状态估算电压(V)ADC原始值O₂浓度(%)
低氧环境(~5%)~0.071~88~5.0
低氧环境(~10%)~0.164~204~10.0
正常空气~0.366~454~20.9
富氧环境(~25%)~0.444~551~25.0

5程序流程图

开始 HAL_Init() SystemClock_Config() MX_GPIO_Init() MX_ADC1_Init() OLED_Init() while(1) HAL_GetTick() - Time_Now ≥ 200? 否 是 HAL_ADC_Start(&hadc1) PollForConversion == HAL_OK? 否 是 Voltage = (ADC/4095.0) × 3.3 HAL_ADC_Stop(&hadc1) O₂ = 53.59 × Voltage + 偏差值 OLED_Clear / CenterPrintf / Update Time_Now = HAL_GetTick()

6交互式动画演示

氧气传感器模拟

动画说明:左侧画布模拟AO-03电化学氧气传感器工作过程。 蓝色圆点代表O₂分子,分子密度随环境浓度变化。分子通过透气膜扩散进入传感器, 在电化学反应区产生与浓度成正比的电流,经模块精密运放电路放大后转换为0.1~0.6V模拟电压由OUT引脚输出至PA0。

OLED显示与数据

氧气:--.-
0.96" OLED (128×64)
O₂浓度(%)
0.0
更新间隔
200ms
STM32处理流程:① ADC采集PA0模拟电压 → ② 12位原始值转换为电压 → ③ 线性公式计算O₂浓度 → ④ OLED清屏并居中显示 → ⑤ 循环间隔200ms