Funpack第八期- NANO微型气象站
【开源】基于Arduino nano 33 ble sense的一款微型气象采集站。
标签
嵌入式系统
显示
颜七岁
更新2021-05-14
774

内容简介:

Nano 33 BLE采用的是Nordic半导体nRF52系列的处理器, Arduino Nano 33 BLE Sense可以使用Arduino IDE进行编程。但是,也可以使用ARM Mbed OS(用于低功耗设备的实时操作系统)对Arduino Nano 33 BLE Sense中使用的nRF52840进行编程。使用Mbed OS,您可以同时运行多个线程。

nRF52采用32位的是64 MHz的32位ARM®Cortex™-M4 CPU,他可以制作出比Arduino Uno更大的程序(它具有1MB的程序存储器,大了32倍),并且具有更多的RAM空间(RAM大128倍)。主处理器还包括其他惊人的功能,例如通过NFC进行的Bluetooth®配对和超低功耗模式。

整体尺寸是非常的小 开发板宽度和我的手指的宽度差不多

外观尺寸

长度 45mm
宽度 18mm
重量 5g

------------------------------------------------点击查看相关数据手册--------------------------------------------------------

HTS221 温湿度传感器LPS22HB 压力传感器MP34DT05 数字麦克风  |  APDS-9960 环境光,接近,RGB,手势传感器

所有的传感器都采用I2C方式通信,他和nano定义一样A4 A5作为I2C的引脚使用,因此获取数据非常方便。

另外,为了让数据显示出来,我还另外添加1.3寸的OLED屏幕。

传感器布局图

开发板引脚:

 

任务要求:(任务二

        检测参数:

  • 周边环境温度(精度:±0.1°C, ±0.1°F)

  • 周边环境湿度(精度:±1%)

  • 大气压强(精度:±0.1kPa, ±0.1psi)

  • 日照强度(用于判断白天/夜晚)

  • 周边平均噪声(精度:±1dB)

代码分享:

此次使用到如下库:

ArduinoHTS221库 //温湿度库

#include <Arduino_HTS221.h> //温湿度库
float Temperature, Humidity;

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

void loop() {
  Temperature = HTS.readTemperature();   // 温度
  Humidity = HTS.readHumidity();  // 湿度
}

ArduinoLPS22HB库 //气压库

#include <Arduino_LPS22HB.h> //大气压库
float Pressure;

void setup() {

    BARO.begin();
}

void loop() {

  Pressure = BARO.readPressure();  //气压
}

PDM库//麦克风库

#include <PDM.h>
short sampleBuffer[256];//缓冲区以读取样本,每个样本为16位
volatile int samplesRead;//读取的样本数

void setup() {

    PDM.onReceive(onPDMdata);
    PDM.begin(1, 16000);  //初始化PDM与:一个通道(单声道模式)  16 kHz的采样率
}

void loop() {
//音量处理,转换为DB
    while (!samplesRead);
    uint32_t sample_max = 0;
    for (int i = 0; i < samplesRead; i++) {
    if(sampleBuffer[i] < 0)
    sampleBuffer[i] = -sampleBuffer[i];
    if(sampleBuffer[i] > sample_max) 
    sample_max= sampleBuffer[i];}
    uint32_t sample = 24*log10(sample_max*5); 
    samplesRead = 0;//清除

    Serial.println(sample);//串口显示当前噪音
}

ArduinoAPDS9960库 //环境光库

#include <Arduino_APDS9960.h>
int r, g, b,a;
void setup() {
    APDS.begin();
}

void loop() {
  // 检查颜色读数是否可用
  while (! APDS.colorAvailable()) {
    delay(5);
  }
  APDS.readColor(r, g, b, a);
  // 显示光照强度值
  Serial.print("lx = ");
  Serial.println(a);
//光照判断
    if(a>10)
    {
    Serial.print("Day");
    }else{
    Serial.print("Night");
    }
}

 

本工程采用1.3寸OLED屏幕。采用arduino自带的milils函数实现定时器功能,每三秒切换一个界面:

开机画面 3s
温湿度 3s
气压 3s
噪声 3s
光照+黑白天判断 3s

Fkj4ThLX5uA7m8FcdU9yaqskRb0aFmTFRIlzYiWhd8P8fXJt7_F_Otw4Fqvff7vHEM9do1CUzg_J8uXqfXVnFrt0PaeYUt7z-pM8woQMuqC7WnD7

工程源码

#include <Arduino_HTS221.h> //温湿度库
#include <Arduino_LPS22HB.h> //大气压库
#include <PDM.h>//麦克风
#include <Arduino_APDS9960.h>//日照强度
#include <Arduino.h>
#include <U8g2lib.h>//oled
#include <Wire.h>

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

#define INTERVAL_MESSAGE1 3000

unsigned long time_1 = 0;//定时
int count=0;

//所有传感器全局变量
float Pressure;
float Temperature, Humidity;
int r, g, b,a;

short sampleBuffer[256];//缓冲区以读取样本,每个样本为16位
volatile int samplesRead;//读取的样本数

void setup() {
  Serial.begin(9600);
//----------OLED初始化  
  u8g2.setI2CAddress(0x3c*2);
  u8g2.begin();
//----------传感器初始化
    PDM.onReceive(onPDMdata);//初始化麦克风
    BARO.begin();//初始化气压
    HTS.begin();//初始化温湿度
    APDS.begin();//初始化光照颜色
    PDM.begin(1, 16000);  //初始化PDM与:一个通道(单声道模式)  16 kHz的采样率

//--------------开机画面显示-----------
//--------------Weather Station-----------
//--------------Funpack 8-----------
//--------------Welcome!-----------
    u8g2.setFont(u8g2_font_t0_11b_tr);
    u8g2.clearBuffer();
    u8g2.setCursor(20, 10);
    u8g2.print("Weather Station");
    u8g2.drawLine(0,13,128,13);     //画一条水平面直线  16表示高度
    u8g2.setFont(u8g2_font_ncenB12_tr);
    u8g2.setCursor(22, 38);//长&&宽
    u8g2.print("Funpack 8");
    u8g2.setCursor(22, 60);//长&&宽
    u8g2.print("Welcome!");
    u8g2.sendBuffer();
}

void loop() {
   
  Pressure = BARO.readPressure();  //气压
  Temperature = HTS.readTemperature();   // 温度
  Humidity = HTS.readHumidity();  // 湿度

  while (! APDS.colorAvailable()) {
    delay(5);
  }
    if(millis() >= time_1 + INTERVAL_MESSAGE1){
        time_1 +=INTERVAL_MESSAGE1;
            count++;
    }
   
     if (count==5)
    {
         count=1;//标志位清零
    }   
//3秒一个显示动画       
        switch (count)
    {
        case 1:
              Tem_Hum_UI();                 
              break;
        case 2:
              Pressure_UI();
              break;
        case 3:
              PDM_UI();
              break;
        case 4:
              lx_sensor();
              break;     
        default:
     break;
    }
}

//上栏界面
void Setpu_UI(){
    u8g2.setFont(u8g2_font_t0_11b_tr);
    u8g2.clearBuffer();
    u8g2.setCursor(20, 10);
    u8g2.print("Weather Station");
    u8g2.drawLine(0,13,128,13);     //画一条水平面直线  13表示高度
    //u8g2.sendBuffer();
}
//气压界面
void Pressure_UI() {
    Serial.print("Pressure = ");Serial.println(Pressure);
    Setpu_UI();
    u8g2.setFont(u8g2_font_logisoso24_tn);     
    u8g2.setCursor(5, 50);
    u8g2.print(Pressure);
    u8g2.setFont(u8g2_font_ncenB12_tr);  
    u8g2.setCursor(90, 60);
    u8g2.print("kPa");
    u8g2.sendBuffer();
}

//温湿度界面
void Tem_Hum_UI(){
    Setpu_UI();  
    u8g2.setFont(u8g2_font_ncenB12_tr); 
    //温度
    u8g2.setCursor(5, 40);//长&&宽
    u8g2.print("Tem:");
    u8g2.setCursor(55, 40);
    u8g2.print(Temperature-5);
    u8g2.setCursor(100, 40);
    u8g2.print("*C");
    Serial.print("Temperature = ");Serial.println(Temperature-5);
    //湿度
    u8g2.setCursor(5, 60);
    u8g2.print("Hum:");
    u8g2.setCursor(55, 60);
    u8g2.print(Humidity);
    u8g2.setCursor(100, 60);
    u8g2.print("%");
    Serial.print("Humidity = ");Serial.println(Humidity);
    u8g2.sendBuffer();
}

//噪音设置
void onPDMdata() {
//查询可用字节数
  int bytesAvailable = PDM.available();
//读入样本缓冲区
  PDM.read(sampleBuffer, bytesAvailable);
// 16位,每个样本2个字节
  samplesRead = bytesAvailable / 2;
}
//噪音界面
void PDM_UI(){
//音量处理
    while (!samplesRead);
    uint32_t sample_max = 0;
    for (int i = 0; i < samplesRead; i++) {
    if(sampleBuffer[i] < 0)
    sampleBuffer[i] = -sampleBuffer[i];
    if(sampleBuffer[i] > sample_max) 
    sample_max= sampleBuffer[i];}
    uint32_t sample = 24*log10(sample_max*5); 
    samplesRead = 0;//清除      
    Setpu_UI(); 
    u8g2.setFont(u8g2_font_fub30_t_symbol); //大字体
    u8g2.setCursor(5, 48);
    u8g2.print("-");    
    u8g2.setCursor(20, 55);
    u8g2.print(sample);//显示噪声
    
    u8g2.setFont(u8g2_font_lubB14_tf);  
    u8g2.setCursor(88, 55);
    u8g2.print("dB");

    u8g2.sendBuffer();
    Serial.println(sample);
}

//光照检测
void lx_sensor(){   
  while (! APDS.colorAvailable()) {
    delay(5);
  }
    APDS.readColor(r, g, b, a);
    Setpu_UI();
    Serial.print("lx = ");
    Serial.println(a);
    u8g2.setFont(u8g2_font_ncenB12_tr);       
    u8g2.setCursor(20, 40);
    u8g2.print(a);   
    u8g2.setCursor(65, 40);
    u8g2.print(" Lx");

//光照判断
    if(a>10)
    {
    u8g2.setFont(u8g2_font_ncenB12_tr);
    u8g2.setCursor(50, 60);
    u8g2.print("Day");
    }else{
    u8g2.setFont(u8g2_font_ncenB12_tr); 
    u8g2.setCursor(50, 60);
    u8g2.print("Night");
    }
    u8g2.sendBuffer();
}

 

 

槽点1:arduino nano 33 ble sener 虽然内置很多传感器,比如手势和(光照或颜色)似乎是不能同时工作的。只能另选其一,原本想法通过手势来切换页面,但实际测试过程中,光照部分没有输出值,很纳闷。

槽点2:温度传感器在PCB布局上没有靠边,时间长温度显示要比实际搞出4-5度。目前解决方案通过代码进行的纠错(非常不负责任)。

 

活动心得:

第一次使用这么小的nano,而且在很小的PCB布局上面还内置了,温湿度,颜色,手势,气压,麦克风,加速度等等传感器,到手拆开后就被经验到了。使用Arduino开发比较容易上手,基本上玩单片机都会知道这个平台,官方也提供了很多资料,还是非常容易上手。如果想学习蓝牙或者低功耗的朋友,千万不要错过这款开发板。此次非常感谢硬核学堂和得捷电子提供本次活动,拓展了知识,还有众多爱好者一起讨论与学习。

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