Funpack第八期 用Arduino Nano 33 BLE Sense实现的气象站
funpack第八期 arduino 蓝牙 温度 湿度 分贝 光照强度
标签
嵌入式系统
测试
happy
更新2021-05-13
1018

内容介绍

    需求利用Arduino Nano 33 BLE Sense板子实现一个小型的环境监测,用来监测环境参数:待监测的参数包括:

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

    收到板子后,板子非常小巧,集成度非常高。开发工具直接使用了Arduino。在这次实验中,需要使用到的传感器有温度传感器(HTS221),用来测量温湿度;麦克风(MP24DT06JTR),用来收集环境声音,测量分贝值;光线传感器(APDS9960),测量当前光照强度,判断白天黑夜;气压传感器(LSP22),用来测量气压。还需要用到蓝牙模块,用来和电脑通讯。

    基本思路:开发板负责收集各个传感器的数据,做出转换和判断,然后通过蓝牙上送到上位机上做展示。
    气压、光照强度都很好搞定,直接调用例程就可以读出来了。温度这里出现了点小问题:1、测量的温度值明显与实际不符。高出实际温度挺多的。使用Arduino的例程测量,也是高出实际温度大概4~5度。和网友讨论了一下,基本的到的结论是板子的DC-DC电路导致的升温,如果想避免这个误差,按网上的资料说明,需要割断开发板背面的连接,使用外部3.3v供电。太麻烦了,只能放弃。所以这里测量出的环境温度还是偏高的。
    环境噪音:一开始的思路是用麦克风收集环境声音-->fft频谱变换-->计算分贝值。但是从查到的资料来看,思路问题不大,不同频率的声音,声音强度转换为分贝是不同的。但是每个频段计算完后,如何计算声音整体的分贝值?一直是一筹莫展。后来群里贴出了个关于声音转换分贝的帖子。Fo38wq7uSR1LoDOuU-sguilrOMjL
这里说的也是有问题的。给出的公式,与后边说明中计算使用的公式不一致。经过实际测试,使用麦克风每次采集到的声音组中最大值,求其以10为底的对数的20倍做为环境的噪音分贝值。为了应对声音的突变,做了一阶滤波处理。计算后的值和手机软件得到的环境噪音,基本匹配。

 //计算分贝值
    fenbei = 20 * log10(maxvoice); //转换分贝
    oldfenbei = 0.8 * oldfenbei + 0.2 * fenbei;

    最后就是与上位机通讯。这个开发板没有带wifi,很可惜。但是带了蓝牙。回看了funpack第四期活动中各位大佬的作品,重新学习了蓝牙的使用。可惜自己能力不够,只实现了在笔记本上用ubuntu20下的蓝牙通讯。在win10下始终搞不定。上位机端使用python。下位机需要上传的内容有:温度、湿度、气压、分贝、白天/黑夜;额外增加一个上位机控制开发板上的RGB灯的颜色。

//blue tooth
BLEService nanoService("917649A0-D98E-11E5-9EEC-0002A5D5C51B"); // Custom
BLEByteCharacteristic colorRedCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1211", BLERead | BLEWrite);   // BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic colorGreenCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1212", BLERead | BLEWrite);   // BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic colorBlueCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1213", BLERead | BLEWrite);   // BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLECharacteristic temperatureCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C50B", BLERead | BLENotify, 4);
BLECharacteristic humidityCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLENotify, 4);
BLECharacteristic pressureCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C52B", BLERead | BLENotify, 4);
BLECharacteristic fenbeiCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C53B", BLERead | BLENotify, 4);
BLECharacteristic lightCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C54B", BLERead | BLENotify, 1);

为每个需要通讯的数据建立对应的Characteristic。在loop循环函数中,一旦检测到蓝牙连接,就将计算后的数据写到对应的Characteristic里。

void loop() {
  BLEDevice central = BLE.central();
  dispColor(ledr, ledg, ledb);
  day=dayornight();
  if (samplesRead) {    //每次读取512个声音数据 16000的采样率
    uint16_t maxvoice = 0;  //最大振幅声音
    for (int i = 0; i < samplesRead; i++) {
      if (maxvoice < abs(sampleBuffer[i])) {
        maxvoice = abs(sampleBuffer[i]);
      }
    }
    //计算分贝值
    fenbei = 20 * log10(maxvoice); //转换分贝
    oldfenbei = 0.8 * oldfenbei + 0.2 * fenbei;

    temperature = HTS.readTemperature();    //温度
    humidity    = HTS.readHumidity();           //读取湿度
    pressure = BARO.readPressure();       //读取气压
    Serial.print(oldfenbei);
    Serial.print("\t");
    Serial.print(temperature);
    Serial.print("\t");
    Serial.print(humidity);
    Serial.print("\t");
    Serial.println(pressure);
    while (central.connected()) {
      if (colorRedCharacteristic.written()) {
        ledr = colorRedCharacteristic.value();
      }
      if (colorGreenCharacteristic.written()) {
        ledg = colorGreenCharacteristic.value();
      }
      if (colorBlueCharacteristic.written()) {
        ledb = colorBlueCharacteristic.value();
      }
      temperatureCharacteristic.setValue((byte*)&temperature, 4);     //温度
      humidityCharacteristic.setValue((byte*)&humidity, 4);     //湿度
      pressureCharacteristic.setValue((byte*)&pressure, 4);     //气压
      fenbeiCharacteristic.setValue((byte*)&fenbei, 4);     //分贝
      lightCharacteristic.setValue(&day,1);                //白天 or 黑夜
    }
  }
}

上位机中,建立一个线程,负责读取蓝牙数据。在主程序中使用一个定时器,每5秒让线程运行一次。线程与主程序通过信号通讯。主程序从信号中读取到环境信息,就在界面上展示出来。
     在上位机与下位机通讯中,第一次写蓝牙通讯,很多还不是很明白。线程每次工作时,都会做一次蓝牙连接,然后读取/写入数据,然后断开蓝牙连接。蓝牙连接有些消耗时间。尝试了在线程启动时,做一次蓝牙连接,然后每次线程启动时,都只做读取/写入操作,但是很不稳定,不一会就出现错误,无法正常读取数据,只能作罢。

     心得体会:这次使用Arduino来做开发,对各个硬件的例程包非常丰富,很容易就能上手获取各个传感器的信息。通过网友的指点了解了声音分贝的计算。通过往期活动的项目了解了蓝牙控制/通讯的方法。希望能够更深入地了解蓝牙通讯的方法。

附件下载

上位机.zip
下位机.zip

团队介绍

业余爱好,利用共同爱好,取悦自己。
团队成员
happy
aramy
单片机业余爱好者,瞎捣鼓小能手。

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号