Flutter + arduino nano 33 BLE sense = capteur BLE très simple

Dans cet article, je veux dire comment créer une station météo Bluetooth très simple (où sans elle :)) et écrire une application mobile sur Flutter pour cela.



Au début, considérez le capteur lui-même


Pour répéter, vous aurez besoin d'une carte de détection Arduino nano 33 BLE .

La carte est construite sur nrf52840. Nous l'installons via le gestionnaire de forum en arduino.



Installez immédiatement les bibliothèques nécessaires:


Ces bibliothèques sont nécessaires pour les capteurs déjà soudés sur la carte elle-même.

Un peu de théorie, puis considérons la mise en œuvre pratique


L'idée principale n'était pas de créer un plug-in, mais d'implémenter des packages de diffusion contenant toutes les informations nécessaires.

Le mode de balise Bluetooth habituel a été utilisé, mais avec la modification ManufacturerData. Ce package peut être transmis dans tous les packages publicitaires.

La taille totale d'un package publicitaire est de 31 octets. Cela comprend toutes les informations nécessaires: nom de l'appareil, données système, données utilisateur. Dans sa forme pure, l'utilisateur dans ManufacturerData fait environ 20 octets. Cela suffit pour transmettre les données des stations météorologiques.
Les avantages de cette méthode de transmission de données à moindre consommation d'énergie, pas besoin de garder une connexion constante avec l'appareil, diffusé. Un tel message peut capturer un nombre illimité de récepteurs dans le rayon de réception.
ManufacturerData est installé avant le début de la publicité.

Et maintenant la partie pratique


Dans le code Arduino, nous indiquons le type de travail de la pièce BLE et définissons les ManufacturerData de départ.Par
ailleurs, pour plus de commodité, je précise le nom de l'appareil, il est plus facile à trouver dans l'application.

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();

Les données initiales sont données sous forme d'un ensemble d'octets pour remplir le tableau.

Maintenant, dans le code principal, nous arrêtons la publicité, arrêtons la radio, mesurons les données nécessaires et remplissons ManufacturerData avec des données réelles, puis recommençons la diffusion. Cette opération est effectuée toutes les 2 secondes.

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);

Ceci termine le travail avec le capteur. Le capteur diffusera toutes les 100 ms et toutes les 2 secondes mettra à jour les données vers les données actuelles. Le résultat a été un code météo et un capteur d'implémentation très simples.

Considérons maintenant l'application mobile


Je ferai une réservation tout de suite: je ne suis pas développeur d'applications mobiles.

Pour le travail, j'ai utilisé VSCode avec le plugin Flutter. Cet environnement semble plus simple qu'Android Studio, comme je le pensais. Pour travailler avec BLE, la bibliothèque Flutter_blue a été utilisée , ce qui a grandement simplifié la connexion de l'appareil.

La logique de l'application est également assez simple. Notre capteur diffuse en mode Beacon normal, vous n'avez donc qu'à effectuer quelques actions:

  1. Scan broadcast - trouvez l'appareil avec le nom donné,
  2. Analysez-le ManufacturerData pour afficher les données à l'écran.

Voyons comment cela se fait.

Après le démarrage de l'application, une minuterie est régulièrement lancée, qui analyse les appareils Bluetooth toutes les 10 secondes pendant 2 secondes. Cela n'a aucun sens de numériser plus souvent et plus longtemps, la consommation de la batterie augmentera et le capteur diffusera généralement toutes les 100 ms.

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

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

Ensuite, nous commençons à analyser les résultats de l'analyse, vérifions s'il existe un appareil portant le nom donné dans la liste des analyses, et si oui, nous analysons son package et affichons le résultat à l'utilisateur.


  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}');
      }
    });
  }

Une petite nuance. La bibliothèque Bluetooth pour Flutter peut sembler étrange, elle reçoit les données sous la forme d'un tableau int, et en arduino nous formons un package à partir d'octets, j'ai donc formé un package dans le capteur pour simplifier son analyse. La température de 25,85 degrés est divisée en deux valeurs 25 et 85, qui sont envoyées sous forme de valeurs d'octets distinctes, et sont collectées de la même manière.

Le résultat final est une telle application.



Le code source du projet peut être téléchargé depuis Github .

All Articles