自制空气检测仪

题外话

受今年的疫情影响,才闲下来有点空搞点小东西玩玩,有些年头没有去接触硬件了,这次重新做点小东西,给自己回忆回忆,同时也能体现一下动手的乐趣。
在这里插入图片描述

制作前的准备

制作需要的材料

这个小的空气检测仪使用的材料分为4部分也就是主控传感器还有显示器件,以及部分元器件

  1. 主控 :Arduino nano (ATmega 328P);
  2. 元器件 150欧姆的电阻;
  3. 元器件 220uF的电容;
  4. 传感器 BME280 温湿度气压传感器;
  5. 传感器 GP2Y1014AU粉尘传感器模块(PM8);
  6. 显示器件 LCD12864 液晶屏(中文字库带背光,串/并口);

主控的选择是基于本项目所需要的性能,BME280是通过I2C协议传输数据的,GP2Y1014AU传感器是模拟量,需要使用单片机的AD(模数转换器)来采集数据。屏幕是单片机通过SPI协议进行驱动的,其实也可以使用4/8口的并口来通信,不过在I/O口不是很充足的情况下,SPI也是很好的选择。

硬件接线

屏幕

在这里插入图片描述

LCD12864 引脚
VDD VCC(5V)
VSS GND
BLK GND
BLA VCC(5V)
PSB GND
RS D8
R/W D9
E D3

如图就是SPI的接法,比较推荐,比较节约I/O资源。图中D/IRSCS1PSB
值得一提的是PSB是用来做串/并模式选择的,我们采用的SPI串行通信,所以这里PSB接低电平(GND),RS是串行片选信号。

温湿度气压传感器

在这里插入图片描述

传感器端口 引脚
VCC 3.3V / 5V(看具体的模块说明)
GND gnd
SCL A5
SDA A4

GP2Y1014AU粉尘传感器模块

在这里插入图片描述
在这里插入图片描述

https://blog.csdn.net/acktomas/article/details/88350817

这位作者的讲解比较详细,我就不作赘述。简单的说一下接线吧。

传感器端口 引脚
V-LED VCC(5V)
LED-GND GND
LED D13
S-GND GND
V0 A0
VCC VCC(5V)

在这里插入图片描述

https://blog.csdn.net/acktomas/article/details/88350817

程序驱动

LCD12864 显示驱动

使用LCD12864RSPI的库,用来驱动。

#include <LCD12864RSPI.h>

void setup() 
{
	LCDA.Initialise();         // 屏幕初始化
}

void LcdDisplay()
{
	LCDA.CLEAR();
	LCDA.DisplayString(0,0,show1,AR_SIZE(show1)); 			//0行0列开始显示
	LCDA.DisplayString(0,3,AirQulity,strlen(AirQulity));	//0行3列开始显示
}

温湿度气压 GY-BME 280

简单一些的话,可以考虑使用Adafruit_BME280的库,这个库相当好用。但是,因为和中断有冲突,所以方法不可以直接写在中断定时器里,程序会直接跑飞。

#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

void setup() 
{
	bme.begin();  
}

void get_BME_Value()
{
  int tempratureValue = (int)(bme.readTemperature()*100);
  int humidityValue = (int)(bme.readHumidity()*100);
  int pressureValue = (int)(bme.readPressure()/100.0F);
  //TODO 写对这些数据的格式化
}

GP2Y1014AU粉尘传感器模块(PM8)

这个需要使用Arduino NANO的AD(模数转换器)来采集数据,采集到数据后通过公式(公式需要进行一定的校准)。大体是基于官方的一张图。
在这里插入图片描述
V0产生有效电压的前提是,在第一个脉冲信号0.28ms后,待电平稳定后进行采集。
在这里插入图片描述

/**********************************************/
// SHARP 1014 空气传感器(0.8)
//入口函数 无
//出口函   无
/***********************************************/
void get_AirQulity()
{
  digitalWrite(ledPower, LOW);
  delayMicroseconds(delayTime);
  dustVal = analogRead(dustPin);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower, HIGH);
  delayMicroseconds(offTime);
  
  if (dustVal > 36.455)
  {
    result = (int)((float(dustVal / 1024) * 737.7) - 16.4); //个人总结
  } 

  memset(AirQulity, 0, sizeof(AirQulity));
  sprintf(AirQulity,"%d",result);
  strcat(AirQulity," ug/m3");
  strcat(AirQulity,'\0');
}

系统结构

在设计这个小系统的时候,我秉持在主循环尽可能少放方法,多使用定时器去驱动事件的运行,一方面是将方法都放在主循环中无法保证实时性,主要原因是有些方法使用**Delay()**做延时,浪费性能且阻塞进程。
Arduino Nano和Arduino UNO一致,使用MsTimer2库来开启TIME2的中端定时器。

#include <MsTimer2.h>

void setup() 
{
  MsTimer2::set(1000, LcdDisplay); 		// 1000ms 触发 LcdDisplay()
  MsTimer2::start();         			//定时2
}

void loop()
{
  get_BME_Value(); 
  delay(100);
}

总结

一个简单的小产品,希望可以带更多的人,学习嵌入式,了解软硬件间的联系。设计或许还有一些不合理的,有些做法和说明不对的地方,请留言指正。代码整理后,上传CSDN。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_27971677/article/details/106743353