Funpack第八期:基于Arduino Nano 33 BLE Sense的环境监测站
使用Arduino Nano 33 BLE Sense和一块128*32 OLED屏幕,做了一个简单的环境监测站
标签
嵌入式系统
显示
Huang
更新2021-05-18
1030

一、整体功能实现

1.1环境监测站功能

利用Arduino NANO-33 BLE Sense的板载传感器, 搭建一个小型环境监测站用于监测户外环境。具体测量参数和指标如下:

  • 周边环境温度(精度:±1℃, ±0.1°F)。
  • 周边环境湿度(精度:±1%)。
  • 大气压强(精度:±1kPa, ±0.1psi)。
  • 日照强度(用于判断白天/夜晚)。
  • 周边平均噪声(精度:±1dB)。

其中,环境温度、湿度由温湿度传感器HTS221采集,大气压强由压力传感器LPS22HB采集,日照强度由环境光和手势传感器APDS9960采集,平均噪声由数字麦克风MP34DT05采集并计算实现。

此外,还需要将这些采集到的环境数据直观显示出来。本项目中使用了一块黑白两色128*32 OLED显示屏,通过四线SPI协议传输数据,并显示出来。

1.2整体代码框架

FgxpJn08apwbxfCWyC56xfD6JPeZ

 

 

 

 

 

 

 

 

 

二、各子模块实现及其对应库文件

2.1温湿度监测

调用了Arduino_HTS221库,库中调用了IIC协议读取传感器中的数据,代码如下

if (!HTS.begin()) {while (1);}
temperature 	= HTS.readTemperature();
humidity    	= HTS.readHumidity();

其中HTS.readTemperature()和HTS.readHumidity()均返回一个float类型的32bit浮点数,赋值给对应的变量。

2.2大气压强监测

调用了Arduino_LPS22HB库,LPS22HB库在头文件BARO.h中通过语句extern LPS22HBClass BARO;将别名修改为BARO,因此在代码中都是以BARO.为前缀的。具体代码如下

if (!BARO.begin()) {while (1);}
pressure    = BARO.readPressure();
BARO.readPressure()返回一个float类型的32bit浮点数,赋值给对应的变量pressure。

2.3日照强度监测

APDS9960同样是通过IIC协议进行数据传输的。在项目中调用了Arduino_APDS9960库,该库提供了颜色检测(RGB三色值)、手势检测(手势移动方向)和接近检测三个例程。在本项目中只用到了RGB三色值的读取,代码如下

if (!APDS.begin()) {while (1);}
while (! APDS.colorAvailable()) {delay(5);}
APDS.readColor(r, g, b);

APDS.readColor()函数为三个变量r,g,b各返回一个int类型的16bit整数。在OLED的显示中,使用r,g,b之和是否小于2来判断白天黑夜。如果和小于2,则判断为夜晚;如果大于等于2,则判断为白天。

  display.setCursor(0,24);
  display.setTextColor(SSD1306_WHITE);
    if(r+g+b >= 2)
      display.print(F("Day")); 
    else
      display.print(F("Night"));   

2.4环境噪声

PDM调制格式是一种单线输出的音频格式,通过单位时间内高、低电平的比例来获取传输时间段内的声音强度。该方法用数字信号表示模拟信号,高脉冲的宽度(接收端时钟采集到的高电平个数)即代表了这一时间内声波的幅值。高脉冲越宽,声波赋值越大,即声音越响。

环境噪声是相对而言较难获取的数据,在这里我借鉴了项目案例中其他成员的方案,调用内置库PDM实现功能。将采集到buffer的所有数据进行排序,选取值最大的一个作为当前的环境噪声。最后对该最大值乘5,再取以10为底的对数,最后再乘24即得到当前的环境噪声(分贝)。

PDM.onReceive(onPDMdata);
PDM.begin(1,16000);
while(!samplesRead);
convert();
void onPDMdata(){
intbytesAvailable=PDM.available();//查询可用字节数
PDM.read(sampleBuffer,bytesAvailable);//读入缓冲区
samplesRead=bytesAvailable/2;
}
void convert(){
uint32_tsample_max=0;
for(inti=0;i<samplesRead;i++){
if(sampleBuffer[i]<0)
sampleBuffer[i]=-sampleBuffer[i];
if(sampleBuffer[i]>sample_max)
sample_max=sampleBuffer[i];
}
sample=24*log10(sample_max*5);//转换分贝
samplesRead=0;
}

为了简化loop()中的代码,这里构造了两个子函数onPDMdata()和convert(),分别用于判断是否读入数据并查询可用数据byte数,以及排序得到最大值并将最大采样值转化为分贝数。

2.5 OLED显示

本项目使用的屏幕是SSD1306驱动的128*32黑白OLED。通过调用外部库Adafruit_GFX和Adafruit_SSD1306驱动,并利用了内置库SPI和Wire。

OLED的使用也是难点之一。首先需要确定所使用的显示屏驱动型号和大小,并配置好四线SPI的各引脚。这里用以下代码实现。

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_DC    D9
#define OLED_CS    D8
#define OLED_RESET D7
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_DC, OLED_RESET, OLED_CS);

这里的&SPI是指利用内置库SPI使用NANO-33 BLE的硬件SPI引脚,即P1.01-MOSI-D11和P0.13-SCK-D13,连线时注意一下即可。

随后是初始化OLED和定义工作电压

display.clearDisplay();//清屏

display.begin(SSD1306_SWITCHCAPVCC);//3.3V供电

在具体显示过程中,首先要设定字体大小和显示方式

display.setTextSize(1); // 6*8bit大小显示一个字符

display.setTextColor(SSD1306_WHITE);//黑底白字

还需要设定光标位置和显示内容

display.setCursor(0,0);

display.println("Pressure:");//显示字符串,SSD1306中有

display.setCursor(54,0);//54行,0列

display.println(pressure,1);//pressure是变量,1是指显示一位小数

对于SSD1306字库中没有的符号,比如温度单位℃,还需要用字符取模软件取模,再用绘制bitmap的方法将特殊符号画上去。

static const uint8_t PROGMEM c_6x8[] = {0x00,0x6E,0x7B,0x30,0x30,0x30,0x1E,0x00};//8*8bit大小的℃

display.drawBitmap(100,8,c_6x8,8,8,WHITE);//输入变量分别为:行,列,bitmap数组名,宽(bit),长(bit),图片颜色

 

三、收获

3.1第一次使用Arduino

这是我第一次使用Arduino完成项目,总体来说觉得真是非常非常方便,几乎所有的计算(包括科学计算)、传感器(比如初始化和读取)乃至系统搭建(比如部署TinyML)都有相应的库可以使用。我一直使用的是Arduino IDE进行编辑。尽管有一些广为人知的不便,比如不方便查看库中的源码或者是不便定位同名变量,但作为一个轻量级的IDE还是非常让我惊喜的,许多功能都可以通过一组简单的快捷键完成。通过浏览官网上BLE Sense的介绍主页(https://www.arduino.cc/en/Guide/NANO33BLESense)以及次级链接,我逐步将板载的传感器一一使用了起来,并最终完成了整个环境监测功能。在OLED的驱动上遇到了一些问题,主要是不知道有哪些库可以使用,以及库中的函数怎么调用。最后还是通过一些经验贴才找到Adafruit_SSD1306这个库(也尝试过U8G2库,但最终没玩明白)。

此外还在实践过程中学到一些小常识,比如双击复位按键会使Arduino复位进入最开始的blink程序;以及在字符串显示函数中加入F会使该字符串存入ROM中,需要时直接读取,以节省更为有限RAM(display.print里面加不加F,影响着该显示变量是存储在RAM里面动态生成还是作为常量保存在ROM里)。收获颇丰,希望以后继续和小伙伴们共同学习、共同进步。

 

最后是将代码下载到开发板里的实物演示

FnslRGTlny22onHn2LHGM_vo6fwa

附件下载
Sensor_and_OLED.ino
可烧录的代码,C,Arduino IDE编辑
团队介绍
合肥工业大学-电物学院
团队成员
黄宇康
搬砖中的大四本科生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号