电子发烧友App

硬声App

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示
电子发烧友网>电子资料下载>电子资料>使用Seeed Wio RP2040模块进行环境监测

使用Seeed Wio RP2040模块进行环境监测

2022-11-08 | zip | 0.08 MB | 次下载 | 免费

资料介绍

描述

环境监测应用程序对于生成有关我们周围环境质量的信息是必不可少的,包括环境是变好还是变坏,或者保持不变。环境监测应用程序生成的数据类型在决策制定中很有用,从长远来看可以作为历史数据。在这个项目中,我构建了一个环境监控系统,该系统从附加的传感器收集数据并将其发布到 MQTT 端点,该端点可以被许多最终用户订阅。

硬件设置

我们使用的是带有板载 ESP8285 WiFi 芯片的 Seeed Wio RP2040 模块。整体外形非常紧凑,适合 DIY 可穿戴/便携式项目。

Wio RP2040 模块的齿形安装孔间距与面包板不兼容,因此我们需要使用原型板焊接接头以使其与面包板兼容。

pYYBAGNo78aAbbHXAAG1T2qYRHM639.jpg
 

此外,我们需要如下图所示连接一个微型 USB 分接头,以便为模块供电和闪烁。

poYBAGNo78mAN08OAADVlTsZsJc326.jpg
 

Grove 温度/湿度/压力和气体传感器通过 I2C 连接连接到模块,如图所示。

Grove Sensor Wio RP2040模块

地线 --------- 地线

VCC。--------- 3.3V 输出

SDA --------- GPIO 6 (I2C1 SDA)

SCL。--------- GPIO 27 (I2C1 SCL)

MicroPython 固件

支持的 MicroPython 固件可以从这里下载我们可以按照以下步骤将下载的firmware-v1.15.1.uf2 USB Flashing Format文件上传到Wio RP2040 Module。

  • 将 BOOT 连接到 GND(参见上面的示意图)并将 Micro USB 分线器插入计算机的 USB 端口它将安装为称为 RPI-RP2 的大容量存储设备。
  • 断开 BOOT 和 GND
  • 将固件-v1.15.1.uf2 文件拖放到 RPI-RP2 卷上。

刷新二进制文件后,Wio RP2040 模块将重新启动,程序将开始运行。我们可以通过串行控制台(CoolTerm/screen/minicom/Putty)以 115200 的波特率连接到 MicroPython REPL。

设置 MQTT 代理

由于我们想从任何可访问的位置远程访问传感器数据,我们使用虚拟专用服务器 (VPS) 来安装 MQTT 代理。您可以使用任何本地 Linux 机器(例如,Raspberry Pi)来实现相同的目的。请按照以下步骤安装和设置代理和客户端。

1. 在 Linux (Ubuntu) 上安装 Mosquitto MQTT 代理和客户端

$ sudo apt install mosquitto mosquitto-clients

2.设置密码

$ sudo mosquitto_passwd -c /etc/mosquitto/passwd mypassword

3. 使用以下内容编辑配置文件 /etc/mosquitto/conf.d/default.conf。

allow_anonymous false
password_file /etc/mosquitto/passwd

4.重启守护进程

$ sudo systemctl restart mosquitto

或者,如果您想让它更安全,请按照此处的说明进行操作。处理 SSL 连接。

代码

请按照此处链接中的说明安装 Thonny IDE 并将以下两个文件上传到模块。此外,在 main.py 中更改 WiFi 凭据和 MQTT 代理端点/凭据。

文件:main.py

from time import sleep
import network
import mqtt
from machine import Pin, I2C, ADC, UART, SPI, PWM
from bme680 import *

i2c = I2C(1, scl=Pin(27), sda=Pin(6))
bme = BME680_I2C(i2c=i2c, address=0x76)

N1 = network.WLAN_SPI(network.STA_IF)
N1.active(True)
N1.connect("myssid", "mypsk")
sleep(1)

SERVER = 'mqtt_endpoint_url'
USER   = 'myuser'
PWD    = 'mypassword'
TOPIC  = 'sensors/data'

cl = mqtt.MQTTClient(USER, SERVER, mqtt_port = 1883, mqtt_user=USER, mqtt_password=PWD)

sleep(1)

if N1.isconnected():
    print("connecting...")

    print(cl.connect())
    print("connected")
    sleep(1)
    
    while True:
        try:
            temperature = str(round(bme.temperature, 2))
            humidity = str(round(bme.humidity, 2))
            pressure = str(round(bme.pressure, 2))
            gas = str(round(bme.gas/1000, 2))
            data = temperature + " " + humidity + " " + pressure + " " + gas
            cl.publish(TOPIC, data)
        except OSError as e:
            print('Failed to read sensor.')
        
        sleep(10)

文件:bme680.py(修改自 Adafruit BME680 库)

import time
import math
from micropython import const
from ubinascii import hexlify as hex

try:
  import struct
except ImportError:
  import ustruct as struct
  
_BME680_CHIPID = const(0x61)
_BME680_REG_CHIPID = const(0xD0)
_BME680_BME680_COEFF_ADDR1 = const(0x89)
_BME680_BME680_COEFF_ADDR2 = const(0xE1)
_BME680_BME680_RES_HEAT_0 = const(0x5A)
_BME680_BME680_GAS_WAIT_0 = const(0x64)
_BME680_REG_SOFTRESET = const(0xE0)
_BME680_REG_CTRL_GAS = const(0x71)
_BME680_REG_CTRL_HUM = const(0x72)
_BME280_REG_STATUS = const(0xF3)
_BME680_REG_CTRL_MEAS = const(0x74)
_BME680_REG_CONFIG = const(0x75)
_BME680_REG_PAGE_SELECT = const(0x73)
_BME680_REG_MEAS_STATUS = const(0x1D)
_BME680_REG_PDATA = const(0x1F)
_BME680_REG_TDATA = const(0x22)
_BME680_REG_HDATA = const(0x25)
_BME680_SAMPLERATES = (0, 1, 2, 4, 8, 16)
_BME680_FILTERSIZES = (0, 1, 3, 7, 15, 31, 63, 127)
_BME680_RUNGAS = const(0x10)
_LOOKUP_TABLE_1 = (2147483647.0, 2147483647.0, 2147483647.0, 2147483647.0, 2147483647.0,
  2126008810.0, 2147483647.0, 2130303777.0, 2147483647.0, 2147483647.0,
  2143188679.0, 2136746228.0, 2147483647.0, 2126008810.0, 2147483647.0,
  2147483647.0)
_LOOKUP_TABLE_2 = (4096000000.0, 2048000000.0, 1024000000.0, 512000000.0, 255744255.0, 127110228.0,
  64000000.0, 32258064.0, 16016016.0, 8000000.0, 4000000.0, 2000000.0, 1000000.0,
  500000.0, 250000.0, 125000.0)

def _read24(arr):
  ret = 0.0
  for b in arr:
    ret *= 256.0
    ret += float(b & 0xFF)
  return ret

class Adafruit_BME680:
  def __init__(self, *, refresh_rate=10):
    self._write(_BME680_REG_SOFTRESET, [0xB6])
    time.sleep(0.005)
    chip_id = self._read_byte(_BME680_REG_CHIPID)
    
    if chip_id != _BME680_CHIPID:
      raise RuntimeError('Failed 0x%x' % chip_id)
    
    self._read_calibration()
    self._write(_BME680_BME680_RES_HEAT_0, [0x73])
    self._write(_BME680_BME680_GAS_WAIT_0, [0x65])
    self.sea_level_pressure = 1013.25
    self._pressure_oversample = 0b011
    self._temp_oversample = 0b100
    self._humidity_oversample = 0b010
    self._filter = 0b010
    self._adc_pres = None
    self._adc_temp = None
    self._adc_hum = None
    self._adc_gas = None
    self._gas_range = None
    self._t_fine = None
    self._last_reading = 0
    self._min_refresh_time = 1000 / refresh_rate
    
  @property
  def pressure_oversample(self):
    return _BME680_SAMPLERATES[self._pressure_oversample]

  @pressure_oversample.setter
  def pressure_oversample(self, sample_rate):
    if sample_rate in _BME680_SAMPLERATES:
      self._pressure_oversample = _BME680_SAMPLERATES.index(sample_rate)
    else:
      raise RuntimeError("Invalid")
    
  @property
  def humidity_oversample(self):
    return _BME680_SAMPLERATES[self._humidity_oversample]

  @humidity_oversample.setter
  def humidity_oversample(self, sample_rate):
    if sample_rate in _BME680_SAMPLERATES:
      self._humidity_oversample = _BME680_SAMPLERATES.index(sample_rate)
    else:
      raise RuntimeError("Invalid")
    
  @property
  def temperature_oversample(self):
      return _BME680_SAMPLERATES[self._temp_oversample]
    
  @temperature_oversample.setter
  def temperature_oversample(self, sample_rate):
    if sample_rate in _BME680_SAMPLERATES:
      self._temp_oversample = _BME680_SAMPLERATES.index(sample_rate)
    else:
      raise RuntimeError("Invalid")
    
  @property
  def filter_size(self):
    return _BME680_FILTERSIZES[self._filter]

  @filter_size.setter
  def filter_size(self, size):
    if size in _BME680_FILTERSIZES:
      self._filter = _BME680_FILTERSIZES[size]
    else:
      raise RuntimeError("Invalid")
    
  @property
  def temperature(self):
    self._perform_reading()
    calc_temp = (((self._t_fine * 5) + 128) / 256)
    return calc_temp / 100

  @property
  def pressure(self):
    self._perform_reading()
    var1 = (self._t_fine / 2) - 64000
    var2 = ((var1 / 4) * (var1 / 4)) / 2048
    var2 = (var2 * self._pressure_calibration[5]) / 4
    var2 = var2 + (var1 * self._pressure_calibration[4] * 2)
    var2 = (var2 / 4) + (self._pressure_calibration[3] * 65536)
    var1 = (((((var1 / 4) * (var1 / 4)) / 8192) *
      (self._pressure_calibration[2] * 32) / 8) +
      ((self._pressure_calibration[1] * var1) / 2))
    var1 = var1 / 262144
    var1 = ((32768 + var1) * self._pressure_calibration[0]) / 32768
    calc_pres = 1048576 - self._adc_pres
    calc_pres = (calc_pres - (var2 / 4096)) * 3125
    calc_pres = (calc_pres / var1) * 2
    var1 = (self._pressure_calibration[8] * (((calc_pres / 8) * (calc_pres / 8)) / 8192)) / 4096
    var2 = ((calc_pres / 4) * self._pressure_calibration[7]) / 8192
    var3 = (((calc_pres / 256) ** 3) * self._pressure_calibration[9]) / 131072
    calc_pres += ((var1 + var2 + var3 + (self._pressure_calibration[6] * 128)) / 16)
    return calc_pres/100

  @property
  def humidity(self):
    self._perform_reading()
    temp_scaled = ((self._t_fine * 5) + 128) / 256
    var1 = ((self._adc_hum - (self._humidity_calibration[0] * 16)) -
      ((temp_scaled * self._humidity_calibration[2]) / 200))
    var2 = (self._humidity_calibration[1] *
      (((temp_scaled * self._humidity_calibration[3]) / 100) +
       (((temp_scaled * ((temp_scaled * self._humidity_calibration[4]) / 100)) /
         64) / 100) + 16384)) / 1024
    var3 = var1 * var2
    var4 = self._humidity_calibration[5] * 128
    var4 = (var4 + ((temp_scaled * self._humidity_calibration[6]) / 100)) / 16
    var5 = ((var3 / 16384) * (var3 / 16384)) / 1024
    var6 = (var4 * var5) / 2
    calc_hum = (((var3 + var6) / 1024) * 1000) / 4096
    calc_hum /= 1000
    if calc_hum > 100:
      calc_hum = 100
    if calc_hum < 0:
      calc_hum = 0
    return calc_hum

  @property
  def altitude(self):
    pressure = self.pressure
    return 44330 * (1.0 - math.pow(pressure / self.sea_level_pressure, 0.1903))

  @property
  def gas(self):
    self._perform_reading()
    var1 = ((1340 + (5 * self._sw_err)) * (_LOOKUP_TABLE_1[self._gas_range])) / 65536
    var2 = ((self._adc_gas * 32768) - 16777216) + var1
    var3 = (_LOOKUP_TABLE_2[self._gas_range] * var1) / 512
    calc_gas_res = (var3 + (var2 / 2)) / var2
    return int(calc_gas_res)

  def _perform_reading(self):
    if (time.ticks_diff(self._last_reading, time.ticks_ms()) * time.ticks_diff(0, 1)
        < self._min_refresh_time):
      return
    self._write(_BME680_REG_CONFIG, [self._filter << 2])
    self._write(_BME680_REG_CTRL_MEAS,
      [(self._temp_oversample << 5)|(self._pressure_oversample << 2)])
    self._write(_BME680_REG_CTRL_HUM, [self._humidity_oversample])
    self._write(_BME680_REG_CTRL_GAS, [_BME680_RUNGAS])
    ctrl = self._read_byte(_BME680_REG_CTRL_MEAS)
    ctrl = (ctrl & 0xFC) | 0x01
    self._write(_BME680_REG_CTRL_MEAS, [ctrl])
    new_data = False
    while not new_data:
      data = self._read(_BME680_REG_MEAS_STATUS, 15)
      new_data = data[0] & 0x80 != 0
      time.sleep(0.005)
    self._last_reading = time.ticks_ms()
    self._adc_pres = _read24(data[2:5]) / 16
    self._adc_temp = _read24(data[5:8]) / 16
    self._adc_hum = struct.unpack('>H', bytes(data[8:10]))[0]
    self._adc_gas = int(struct.unpack('>H', bytes(data[13:15]))[0] / 64)
    self._gas_range = data[14] & 0x0F
    var1 = (self._adc_temp / 8) - (self._temp_calibration[0] * 2)
    var2 = (var1 * self._temp_calibration[1]) / 2048
    var3 = ((var1 / 2) * (var1 / 2)) / 4096
    var3 = (var3 * self._temp_calibration[2] * 16) / 16384
    self._t_fine = int(var2 + var3)
    
  def _read_calibration(self):
    coeff = self._read(_BME680_BME680_COEFF_ADDR1, 25)
    coeff += self._read(_BME680_BME680_COEFF_ADDR2, 16)
    coeff = list(struct.unpack(', bytes(coeff[1:39])))
    coeff = [float(i) for i in coeff]
    self._temp_calibration = [coeff[x] for x in [23, 0, 1]]
    self._pressure_calibration = [coeff[x] for x in [3, 4, 5, 7, 8, 10, 9, 12, 13, 14]]
    self._humidity_calibration = [coeff[x] for x in [17, 16, 18, 19, 20, 21, 22]]
    self._gas_calibration = [coeff[x] for x in [25, 24, 26]]
    self._humidity_calibration[1] *= 16
    self._humidity_calibration[1] += self._humidity_calibration[0] % 16
    self._humidity_calibration[0] /= 16
    self._heat_range = (self._read_byte(0x02) & 0x30) / 16
    self._heat_val = self._read_byte(0x00)
    self._sw_err = (self._read_byte(0x04) & 0xF0) / 16
    
  def _read_byte(self, register):
    return self._read(register, 1)[0]

  def _read(self, register, length):
    raise NotImplementedError()

  def _write(self, register, values):
    raise NotImplementedError()

class BME680_I2C(Adafruit_BME680):
  def __init__(self, i2c, address=0x77, debug=False, *, refresh_rate=10):
    self._i2c = i2c
    self._address = address
    self._debug = debug
    super().__init__(refresh_rate=refresh_rate)
    
  def _read(self, register, length):
    result = bytearray(length)
    self._i2c.readfrom_mem_into(self._address, register & 0xff, result)
    if self._debug:
      print("\t${:x} read ".format(register), " ".join(["{:02x}".format(i) for i in result]))
    return result

  def _write(self, register, values):
    if self._debug:
      print("\t${:x} write".format(register), " ".join(["{:02x}".format(i) for i in values]))
    for value in values:
      self._i2c.writeto_mem(self._address, register, bytearray([value & 0xFF]))
      register += 1

一旦上述代码上传成功并且所有凭据都OK,Wio RP2040 模块将开始以 10 秒的间隔通过 MQTT 发布传感器数据。

使用 Jupyter Notebook 订阅和可视化实时数据

我们可以在任何支持 Python3 的计算机上使用 MQTT 客户端订阅传感器数据。我们需要使用 pip 安装以下 python 模块。

$ pip3 install paho-mqtt jupyter jupyterplot 

请从 Github 存储库下载 notebooksubscriber.ipynb并运行以下命令。

$ python3 jupyter notebook

打开subscriber.ipynb 并运行它。如果所有凭据都正常,Wio RP2040 模块正在发布,并且 MQTT 代理正在运行,您将在 Jupyter Notebook 中看到实时数据,如下所示。

 

结论

Wio RP2040 模块是一款功能强大、体积小巧且价格实惠的物联网设备,可用于数据收集和远程监控。可以使用电池或移动电源轻松操作此设置。所有代码都可以在代码部分给出的 Github repo 链接中找到。感谢 Seeed Studio 为我提供 Wio RP2040 模块和 Grove 环境传感器 (BME680)。


下载该资料的人也在下载 下载该资料的人还在阅读
更多 >

评论

查看更多

下载排行

本周

  1. 1山景DSP芯片AP8248A2数据手册
  2. 1.06 MB  |  532次下载  |  免费
  3. 2RK3399完整板原理图(支持平板,盒子VR)
  4. 3.28 MB  |  339次下载  |  免费
  5. 3TC358743XBG评估板参考手册
  6. 1.36 MB  |  330次下载  |  免费
  7. 4DFM软件使用教程
  8. 0.84 MB  |  295次下载  |  免费
  9. 5元宇宙深度解析—未来的未来-风口还是泡沫
  10. 6.40 MB  |  227次下载  |  免费
  11. 6迪文DGUS开发指南
  12. 31.67 MB  |  194次下载  |  免费
  13. 7元宇宙底层硬件系列报告
  14. 13.42 MB  |  182次下载  |  免费
  15. 8FP5207XR-G1中文应用手册
  16. 1.09 MB  |  178次下载  |  免费

本月

  1. 1OrCAD10.5下载OrCAD10.5中文版软件
  2. 0.00 MB  |  234315次下载  |  免费
  3. 2555集成电路应用800例(新编版)
  4. 0.00 MB  |  33566次下载  |  免费
  5. 3接口电路图大全
  6. 未知  |  30323次下载  |  免费
  7. 4开关电源设计实例指南
  8. 未知  |  21549次下载  |  免费
  9. 5电气工程师手册免费下载(新编第二版pdf电子书)
  10. 0.00 MB  |  15349次下载  |  免费
  11. 6数字电路基础pdf(下载)
  12. 未知  |  13750次下载  |  免费
  13. 7电子制作实例集锦 下载
  14. 未知  |  8113次下载  |  免费
  15. 8《LED驱动电路设计》 温德尔著
  16. 0.00 MB  |  6656次下载  |  免费

总榜

  1. 1matlab软件下载入口
  2. 未知  |  935054次下载  |  免费
  3. 2protel99se软件下载(可英文版转中文版)
  4. 78.1 MB  |  537798次下载  |  免费
  5. 3MATLAB 7.1 下载 (含软件介绍)
  6. 未知  |  420027次下载  |  免费
  7. 4OrCAD10.5下载OrCAD10.5中文版软件
  8. 0.00 MB  |  234315次下载  |  免费
  9. 5Altium DXP2002下载入口
  10. 未知  |  233046次下载  |  免费
  11. 6电路仿真软件multisim 10.0免费下载
  12. 340992  |  191187次下载  |  免费
  13. 7十天学会AVR单片机与C语言视频教程 下载
  14. 158M  |  183279次下载  |  免费
  15. 8proe5.0野火版下载(中文版免费下载)
  16. 未知  |  138040次下载  |  免费