Flutter + Arduino Nano 33 BLE感应=非常简单的BLE传感器

在本文中,我想告诉您如何制作一个非常简单的蓝牙气象站(没有它的地方:)),并在Flutter上编写一个移动应用程序。



首先,请考虑传感器本身


要重复,您将需要一个Arduino nano 33 BLE感应

该评估板基于nrf52840构建。我们通过arduino中的董事会经理安装它。



立即安装必要的库:


这些库对于已经焊接在电路板上的传感器来说是必需的。

有点理论,然后考虑实际实现


主要思想不是制造插件设备,而是实现广播消息,其中包含所有必需的信息。

使用了常规的蓝牙标签模式,但对ManufacturerData进行了修改。该包可以在每个广告包中传输。

广告包的总大小为31个字节。其中包括所有必要的信息:设备名称,系统数据,用户数据。以纯格式,ManufacturerData中的用户约为20个字节。这足以传输气象站数据。
这种数据传输方法的优点是功耗较低,无需与广播设备保持恒定连接。这样的消息可以在接收半径内捕获无限数量的接收者。
在开始投放广告之前已安装了ManufacturerData。

现在是实际部分


在arduino代码中,我们指示BLE部件的工作类型并设置开始的ManufacturerData,
此外,为了方便起见,我指定了设备的名称,因此在应用程序中更容易找到。

BLE.setLocalName("nrf52840.ru");
BLE.setConnectable(false);
byte data[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
BLE.setManufacturerData(data, 8);
// start advertising
BLE.advertise();

初始数据以一组字节填充数组的形式给出。

现在,在主要代码中,我们停止广播,停止广播,测量必要的数据,并用实际数据填充ManufacturerData,然后开始广播。该操作每2秒执行一次。

BLE.stopAdvertise();
// read all the sensor values
---------------------
       
---------------------
byte data[8] = { 0x00, 0x01, t1, t2, h1, h2, p1, p2}; // t -  (2 ), h -  (2 ), p -  (2 )
BLE.setManufacturerData(data, 8);
BLE.advertise();
// wait 2 second to print again
delay(2000);

这样就完成了传感器的工作。传感器每100毫秒广播一次,每2秒钟将数据更新到当前一次。结果是一个非常简单的天气代码和实施传感器。

现在考虑移动应用


我将立即预订:我不是移动应用程序开发人员。

为了工作,我将VSCode与Flutter插件一起使用。我认为,这种环境似乎比Android Studio简单。为了使用BLE,使用Flutter_blue库,该库大大简化了设备的连接。

应用程序的逻辑也很简单。我们的传感器以常规信标模式广播,因此您只需要执行以下几项操作:

  1. 扫描广播-查找具有给定名称的设备,
  2. 解析ManufacturerData以在屏幕上显示数据。

让我们看看这是如何完成的。

启动应用程序后,将定期启动计时器,该计时器每10秒钟扫描一次蓝牙设备,持续2秒钟。扫描得更多,更长的时间是没有意义的,电池消耗会增加,并且传感器通常每100ms广播一次。

DeviceScanner() {
   _subscribeToScanEvents();
   _timer = new Timer.periodic(const Duration(seconds: 10), startScan);
 }

void startScan(Timer timer) {
   FlutterBlue.instance.startScan(timeout: Duration(seconds: 2));
}

接下来,我们开始分析扫描结果,检查扫描列表中是否存在具有给定名称的设备,如果是,我们将分析其程序包并将结果显示给用户。


  void _subscribeToScanEvents() {
    FlutterBlue.instance.scanResults.listen((scanResults) {
      for (ScanResult scanResult in scanResults) {
        if (scanResult.device.name.toString() == "nrf52840.ru") {
          final int rssi = scanResult.rssi;
          final String name = scanResult.device.name;
          final String mac = scanResult.device.id.toString();
          final double temp = scanResult.advertisementData.manufacturerData[256]
                  [0] +
              scanResult.advertisementData.manufacturerData[256][1] * 0.01;
          final double humm = scanResult.advertisementData.manufacturerData[256]
                  [2] +
              scanResult.advertisementData.manufacturerData[256][3] * 0.01;
          final double press =
              scanResult.advertisementData.manufacturerData[256][4] +
                  scanResult.advertisementData.manufacturerData[256][5] * 0.01;
          final SensorData sensorData = new SensorData(
              name: name,
              rssi: rssi,
              mac: mac,
              temperature: temp,
              humidity: humm,
              pressure: press);
          _streamController.add(sensorData);
          print(
              'Manufacturer data ${scanResult.advertisementData.manufacturerData}');
          FlutterBlue.instance.stopScan();
        }

        print(
            '${scanResult.device.name} found! mac: ${scanResult.device.id} rssi: ${scanResult.rssi}');
      }
    });
  }

有点细微差别。Flutter的蓝牙库可能看起来很奇怪,它以int数组的形式接收数据,在arduino中,我们从字节组成一个包,因此我在传感器中形成了一个包以简化其分析。25.85度的温度分为两个值25和85,它们作为单独的字节值发送,并以相同的方式收集。

最终的结果就是这样一个应用程序。



可以从Github下载项目源代码

All Articles