FastBond2阶段1-基于ESP32C3的空气质量检测节点设计(及传感器测试)
一、前言
在上回Fastbond2阶段1的文档中,展示了使用Scheme-it绘制的系统款图,并展示了项目中使用到的活动规定厂家芯片:ESP32S3
本项目在实际实践中,考虑到检测节点普遍有低功耗需求,且节点传感器多为iic通信,对通信io需求没有那么大,所以选择使用ESP32C3替代原本节点的s3设计。另外由于原计划作为无线上位机的esp32s2芯片没有蓝牙功能,所以将上位机替换为板载ESP32S3芯片的Adafruit ESP32-S3 Reverse TFT Feather开发板,此开发板板载tft屏幕,非常适合进行数据的显示。
另外在实际购买传感器的过程中我还发现了来自Sensirion SCD40二氧化碳传感器,这该传感器基于光声传感原理以及Sensirion的PASens®和CMOSens® 专利技术,体积小巧,性能卓越。集成性价比极佳的湿度和温度传感器,实现片上信号补偿,并具备额外湿度和温度输出。 SCD40通过监测CO2分子吸收的能量测量CO2浓度。当发射红外脉冲时,CO2分子周期性的吸收红外线,这会引起额外的分子振动,从而会在腔内产生压力波。CO2浓度越高,吸收的光就越多,因此声波的振幅越大,通过内部麦克风测量、计算得出CO2浓度。相比于ENS160,它的二氧化碳数据准确度理论上来说会更加准确。所以本次也将其纳入了测试。
本文后续将展示使用kicad绘制的原理图及pcb,以及成品的功能测试和说明。
二、原理图及pcb介绍
首先是原理图部分,原理图采用kicad绘制,这是一款免费且完全开源的pcb绘制工具,同时配套的还有freecad,这也是一款非常实用的3d建模软件,可用于为电路板设计外壳等。
本次测试实际使用四颗传感器,SCD40,SGP40,ENS160,BME680,四颗传感器都需要3.3V电源,其中ENS160还需要1.8V供电,所以板载了两颗AP2112K LDO,分别负责了3.3V和1.8V的降压工作。
实际PCB layout时考虑到都是传感器芯片,工作时也会自发热,所以实际pcb尺寸为5*10cm,且将每个传感器单独放置在一片较空旷的区域,尽量减小传感器聚集后自发热造成的误差。
三、实际功能实现与测试
从这块板上的四颗传感器可以读取到非常丰富的空气质量数据,接下来会进行数据准确度的判断以及无线传输的实现,其中数据准确度参考标准为我桌上的青萍空气质量传感器。
鉴于多数传感器Datasheet中都有提到传感器需要充分预热后数据才能更加准确,所以将开发板上电静置30分钟后再通过串口进行初步的数据读取与分析。
实际读取数据后发现BME680的温度数据较高,同时湿度也较低,试着在电路板边加电风扇增加空气流动,但bme680温度高湿度低的问题依旧。通过热成像检测后发现位于传感器板右上角的BME680传感器的确是四个传感器里最“热”的,具体原因查询了挺久也没有找到合理的解释,所以后续只采用了BME680的气压数据。
接下来就是ESP32C3端的蓝牙数据传输和ESP32S3端的蓝牙数据接收机在TFT屏幕上显示了,这部分相对简单,我对传感器读取和显示代码都进行了函数封装,直接阅读调用代码即可。
封装后的ESP32C3传感器数据读取及蓝牙发送(具体封装函数可以查看工程)
ScdRead(SCD41_co2, SCD41_temperature, SCD41_humidity);
delay(1);
Serial.print("SCD41_Co2:"); Serial.print(SCD41_co2); Serial.print("\t");
Serial.print("SCD41_Temperature:"); Serial.print(SCD41_temperature); Serial.print("\t\t");
Serial.print("SCD41_Humidity:"); Serial.println(SCD41_humidity);
SgpRead(sraw, SGP40_voc_index, SCD41_temperature, SCD41_humidity);
delay(1);
Serial.print("Raw measurement:"); Serial.print(sraw); Serial.print("\t");
Serial.print("Voc Index:"); Serial.println(SGP40_voc_index);
BmeRead(BME680_temperature, BME680_pressure, BME680_humidity, BME680_gas);
delay(1);
Serial.print("Temperature = "); Serial.print(BME680_temperature); Serial.print(" *C\t");
Serial.print("Pressure = "); Serial.print(BME680_pressure); Serial.print(" hPa\t");
Serial.print("Humidity = "); Serial.print(BME680_humidity); Serial.print(" %\t");
Serial.print("Gas = "); Serial.print(BME680_gas); Serial.println(" KOhms");
EnsRead(ENS160_aqi, ENS160_tvOC, ENS160_eco2);
delay(1);
Serial.print("ENS160_AQI: "); Serial.print(ENS160_aqi); Serial.print("\t");
Serial.print("TVOC: "); Serial.print(ENS160_tvOC); Serial.print("ppb\t");
Serial.print("eCO2: "); Serial.print(ENS160_eco2); Serial.println("ppm\t");
tempX=SCD41_temperature;
pCharacteristicAccX->setValue(tempX);//setValue takes uint8_t, uint16_t, uint32_t, int, float, double and string
tempY=SCD41_humidity;
pCharacteristicAccY->setValue(tempY);
tempZ=float(SCD41_co2);
pCharacteristicAccZ->setValue(tempZ);
tempI=float(SGP40_voc_index);
pCharacteristicAccI->setValue(tempI);
tempJ=float(ENS160_eco2);
pCharacteristicAccJ->setValue(tempJ);
tempK=float(BME680_pressure);
pCharacteristicAccK->setValue(tempK);
封装后的ESP32S3端的数据接收与显示(具体封装函数可以查看工程)
float XValue = pRemoteCharacteristicACCx->readFloat();
float YValue = pRemoteCharacteristicACCy->readFloat();
float ZValue = pRemoteCharacteristicACCz->readFloat();
float IValue = pRemoteCharacteristicACCI->readFloat();
float JValue = pRemoteCharacteristicACCJ->readFloat();
float KValue = pRemoteCharacteristicACCK->readFloat();
SCD41_temperature = XValue;
SCD41_humidity = YValue;
SCD41_co2 = uint16_t(ZValue);
SGP40_voc_index = int32_t(IValue);
ENS160_eco2 = uint16_t(JValue);
BME680_pressure = uint32_t(KValue);
Serial.print("SCD41_Temperature:"); Serial.print(SCD41_temperature); Serial.print("\t\t");
Serial.print("SCD41_Humidity:"); Serial.print(SCD41_humidity); Serial.print("\t");
Serial.print("SCD41_Co2:"); Serial.println(SCD41_co2);
Serial.print("SGP40 Voc Index:"); Serial.println(SGP40_voc_index);
Serial.print("ENS160 eCO2: "); Serial.print(ENS160_eco2); Serial.println("ppm\t");
Serial.print("Pressure = "); Serial.print(BME680_pressure); Serial.println(" hPa\t");
TftRefresh();
ESP32C3发送端实际电路连接
ESP32S3接收端
于是就得到了这样的显示,其中我将ENS160获取的ECo2数据和SCD40传感器的Co2数据放在了同一行,其他温湿度、气压以及voc数据各自一行,不同类型数据采用不同颜色显示,阅读起来非常方便。
我将最为关心的二氧化碳数据和青萍空气质量传感器的二氧化碳数据进行对比后,实际发现大体上变化趋势是类似的,但是ENS160的数据在环境有变化(如对着传感器呼一口气)的情况下变化速度更快,波动也更大。个人判断这是因为SCD40传感器对外有一层透气膜,而ENS160只是在屏蔽罩上开孔。
四、总结
很感谢硬禾学堂举办的FastBond2活动,让我有机会对常见的空气质量检测传感器做了一个简单的测试,并基于他们制作了一个控制质量检测节点系统的demo。根据这次实验的结果,对于我个人相对看重的二氧化碳数据测量,在只是日常环境二氧化碳趋势测量的前提下,ens160和scd40的数据都较为可信,可以根据实际使用大小的需求和成本的需求进行选择。SCD40更适合产品对体积要求不高,且对数据准确度要求高的项目,而ens160可以用于对体积有较高要求以及成本较低的传感器中。而这次发现BME680温度高的问题,我也会继续搜索相关论坛讨论,试着找出原因。