CubeCell + capteur BH1730

Qu'est-ce que DeltaLab

DeltaLab est une association ‘loi 1901’ d’intérêt général, dont l’objectif est la création d’un espace dédié à l’innovation, à la production numérique au prototypage et à l’«expression artistique».

Le principe fondateur de l’association est d’apprendre à faire soi-même, pour passer de l’idée à l’objet.

Deltalab se spécialise en Objets Connectés, et est en train de créer un vaste «écosystème numérique» entre Drôme et Vaucluse, pour répondre à des besoins non couverts, mettre à disposition ressources et équipements pour usage professionnels et instaurer des partenariats avec les autres structures et initiatives numériques existantes.

Deltalab est aussi un FabLab (Fabrication Laboratory / Laboratoire de Fabrication ), un tiers-lieu de type makerspace où se trouve un atelier qui dispose de machines de fabrication comme des Imprimantes 3D ou des découpeuses Laser.

Deltalab se veut ouvert à tous publics : étudiants, professionnels, associations, inventeurs, designers, artistes, etc.

Contexte

Un des projets à moyen termes de DeltaLab est l’installation d’un réseau LoRaWAN permettant la collecte et le traitement d’un grand nombre de données, et ce sur une grande zone s’étendant sur l’enclave des Papes et la Drôme Provençale.

Ce document est une présentation de l’utilisation du réseau LoRaWAN dans un exemple concret : la mise en place d’un objet connecté, ici un CubeCell, équipé d’un capteur de luminosité, le BH1730.

Introduction


Ce document a pour but de montrer comment monter / programmer votre CubeCell afin qu’il puisse envoyer les données via le réseau LoRaWAN. Ici il s’agit d’une capsule équipé d’un panneau solaire, le modèle HTCC-AC02.
On verra plus tard pour l’équiper d’un capteur de température, de pression et d’humidité.

Logiciels

Matériels

Montage

Dévissez la partie transparente de la capsule.
Emboîtez le debug board de sorte que les deux points blancs soient face à face.
Branchez le câble au debug board, et......STOP!!!!!
On arrête la manipulation ici, on passe à Arduino

Arduino

Pour installer Arduino IDE, suivez le tuto du site.

Une fois installé, allez dans Fichier > Préférences et ajoutez ce lien dans URL de gestionnaire de cartes supplémentaires en cliquant sur le bouton à droite.

https://github.com/HelTecAutomation/CubeCell-Arduino/releases/download/V1.3.0/package_CubeCell_index.json

Ce fichier va vous permettre de codé pour des CubeCell.

Ensuite, allez dans Outils > type de carte > Gestionnaire de carte.
Et tapez
cube dans la barre de recherche, puis installez cette carte à la dernière version.

Toujours dans Outils, sélectionnez la carte HTCC-AC0X en allant dans Type de carte > CubeCell.

Une fois fait, vous devriez voir cela dans Outils. Veuillez donc mettre les paramètres comme indiqués sur l'image.

Avant de lancer le code, il faut brancher le CubeCell au PC, MAIS il y a une manipulation à faire avant chaque branchement du CubeCell au PC. Veuillez maintenir le bouton USER du debug board > branchez le CubeCell > relachez USER.
Une fois fait retournez dans
Outils pour sélectionner le port où est branché le CubeCell.

Puis, il faut rentrer le CubeCell en mode bootloader ce qui aura pour effet de le réinitialiser. Pour cela maintenez le bouton USER > cliquez sur RST > relâchez USER.

Affichez le Moniteur série, en cliquant sur la loupe en haut à droite : vous devriez avoir ce message sur l'image ci-dessous.

ATTENTION il faut pensez à la batterie de l'objet, donc tant que vous testez votre CubeCell il faut le réinitialiser après chaque upload pour ne pas qu'il tourne en boucle.

Branchement du capteur


Munissez-vous du capteur BH1730.
Branchez-le à l'arrière du debug board sur les ports indiquez.

Circuit

Connections

Test

Nous allons tester le capteur avec un programme.

Dans Arduino: Fichier > Exemples > Sensor - Heltec Produced > BH1750 > BH1750test.

Faites marcher le programme avec le Moniteur série en allant dans Outils pour voir le résultat.

Code Arduino


Librairies

  • BH1750

  • LoRaWan_APP

  • Arduino

  • Wire

Code

Copiez-collez le code ci-dessous dans un nouveau fichier Arduino

/*Librairies*/
#include "LoRaWan_APP.h"
#include "Arduino.h"
#include <BH1750.h>
#include <Wire.h>

/*Constantes*/
static const uint32_t DELAI_1_S = 1000;
static const uint32_t DELAI_1_M = 60 * DELAI_1_S;
static const uint32_t DELAI_1_H = 60 * DELAI_1_M;

/*Variables*/
/* OTAA para*/
/* format msb*/
uint8_t devEui[] = { /*disponible lors de la création de l'objet sur TheThingsNetwork */ };
uint8_t appEui[] = {
/*disponible lors de la création de l'objet sur TheThingsNetwork */ };
uint8_t appKey[] = {
/*disponible lors de la création de l'objet sur TheThingsNetwork */ };

/* ABP para*/
uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda, 0x85 };
uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef, 0x67 };
uint32_t devAddr = ( uint32_t )0x007e6ae1;

/*LoraWan channelsmask, default channels 0-7*/
uint16_t userChannelsMask[6] = { 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };

/*LoraWan region, select in arduino IDE tools*/
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;

/*LoraWan Class, Class A and Class C are supported*/
DeviceClass_t loraWanClass = LORAWAN_CLASS;

/*délai de transmission entre chaque paquet de données. valeur en [ms].*/
uint32_t appTxDutyCycle = 10 * DELAI_1_M;

/*OTAA or ABP*/
bool overTheAirActivation = LORAWAN_NETMODE;

/*ADR enable*/
bool loraWanAdr = LORAWAN_ADR;

/* set LORAWAN_Net_Reserve ON, the node could save the network info to flash, when node reset not need to join again */
bool keepNet = LORAWAN_NET_RESERVE;

/* Indicates if the node is sending confirmed or unconfirmed messages */
bool isTxConfirmed = LORAWAN_UPLINKMODE;

/* Application port */
uint8_t appPort = 2;

/*Nombre d’essais pour envoyer le paquet de données */
uint8_t confirmedNbTrials = 4;


/* Variable des données*/
float lux;


/* Compteur*/
int count;


/* Maximum du compteur*/
int maxtry = 50;


/* Variable du capteur*/
BH1750 lightSensor;

/*!
\brief
Prépare le contenu de la trame
*/

static void prepareTxFrame( uint8_t port )
{

pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(500);
count = 0;
lightSensor.begin();
// Activation du capteur
lux = lightSensor.readLightLevel();
// récupération de la donnée de luminosité
delay(500);

Wire.end();
digitalWrite(Vext, HIGH);
uint16_t batteryVoltage = getBatteryVoltage();
//récupère la quantité de batterie restante en mV

// Insertion des données dans le tableau de donnée qui sera envoyé
unsigned char *puc;
puc = (unsigned char *)(&lux);
appDataSize = 6;
appData[0] = puc[0];
appData[1] = puc[1];
appData[2] = puc[2];
appData[3] = puc[3];

appData[4] = (uint8_t)(batteryVoltage >> 8);
appData[5] = (uint8_t)batteryVoltage;

//Affichage des données sur le Moniteur Série
Serial.print("Lux = ");
Serial.print(lux);
Serial.print(", BatteryVoltage: ");
Serial.println(batteryVoltage);
}

void setup() {/*Initialisation du programme*/
Serial.begin(115200);
//Démarrage du moniteur série
#if(AT_SUPPORT)
enableAt();
#endif
deviceState = DEVICE_STATE_INIT;
// Statut de l'objet mis sur initialisation
LoRaWAN.ifskipjoin();
// Envoi directement les données si LORAWAN_Net_Reserve est sur ON
}

void loop() {/*Tourne en boucle le programme*/
switch ( deviceState )
{
case DEVICE_STATE_INIT:
{
#if(LORAWAN_DEVEUI_AUTO)
// Génère le DevEUI si cette option est mise sur Generate by ChipID dans // les Outils
LoRaWAN.generateDeveuiByChipID();
#endif
#if(AT_SUPPORT)
getDevParam();
//Récupère les EUIs de l'objet
#endif
printDevParam();
//Affiche les EUIs de l'objet
LoRaWAN.init(loraWanClass, loraWanRegion);
// Initialise la connection avec TheThingsNetwork
deviceState = DEVICE_STATE_JOIN;
// passe l'état de l'objet à joindre pour dire qu'il est prêt à
// rentrer en communication avec TTN
break;
}
case DEVICE_STATE_JOIN:
{
LoRaWAN.join();
// l'objet établie la connection avec TTN
break;
}
case DEVICE_STATE_SEND:
{
prepareTxFrame( appPort );
// Prépare le message de données à envoyer
LoRaWAN.send();
// Envoi du message
deviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_CYCLE:
{
//Prépare le temps de cycle de sommeil
txDutyCycleTime = appTxDutyCycle + randr( 0, APP_TX_DUTYCYCLE_RND );
LoRaWAN.cycle(txDutyCycleTime);
deviceState = DEVICE_STATE_SLEEP;
// passe l'état de l'objet en sommeil
break;
}
case DEVICE_STATE_SLEEP:
{
LoRaWAN.sleep();
// Cycle de sommeil de l'objet
break;
}
default:
{
deviceState = DEVICE_STATE_INIT;
// Par défaut, l'objet est en état d'initialisation
break;
}
}
}

The Things Network


Avant de lancer le programme, il faut créer la réception des données sinon le code tournera en boucle sans rien faire.

Sur The Things Network, il est possible d'enregistrer son objet pour voir le flux de données.

Avant cela, si vous n'avez pas d'antenne LoRaWAN pour recevoir les données allez ici.

Ajout du device

  • Sur TTN (www.thethingsnetwork.org/), connectez-vous (ou créez un compte), allez dans la console en cliquant sur votre profil, allez dans Applications et Ajoutez une nouvelle appli. Renseignez un ID, un nom et une description (facultatif).

  • Dans cette application, ajoutez un nouveau End Device. Renseignez les informations de votre objet connecté.

    • Brand: HelTec AutoMation

    • Model: HTCC-AC02 (Class A OTAA)

    • Profile (Region): EU_863_870

  • Sélectionnez la fréquence dans Frequency plan dont l'endroit correspond à la région où sera placé votre objet. En Europe, on prendra la fréquence Europe 863-870 MHz(SF9 for RX2-recommended).

  • L’AppEUI devrait être renseigné par le fabricant ou remplissez avec des zéros.

  • Le DevEUI est soit renseigné par le fabricant ou imprimé sur le paquet soit générer par le bouton juste à droite.

  • L’Appkey est soit renseigné par le fabricant soit générer par le bouton juste à droite.

ET MAINTENANT

Dans l'overview de votre End Device , vous avez accès aux EUIs et à l’AppKey nécessaires dans le programme. Pour les EUIs, cliquez sur les chevrons à droite de chacun d'eux, ils seront au format msb.
Et ça tombe bien, sur Arduino les EUIs sont au format msb. Vous pouvez les copiez et les collez dans le code.

ATTENTION: Pour l' AppKey, il faudra la rendre visible en cliquant sur l'œil et dans le code remplacez seulement les chiffres après les 0x.

Décodage du payload

On utilise un décodeur sur TTN car les données qui sont créées par les objets sont au format binaire donc illisible pour l’homme.

On utilisera le langage Javascript pour créer notre propre décodeur.

Dans Application > End devices > votre device > Payload Formatters et dans Uplink sélectionnez Javascript dans le menu déroulant. Copiez-collez le code ci-dessous dans la zone 'Formatter parameter'. Et cliquez sur Save changes pour sauvegarder. Et vérifiez l'indentation sinon cela ne fonctionnera pas.


function B2F32(bytes) { // Convertit les données binaires en nombres à virgules

var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand === 0) return sign * 0.0;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
}

function Decoder(bytes, port) { // Envoi du message de donnée au serveur MQTT
var lux = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
var batterie = bytes[5] << 8 | bytes[4];
return{
lux: B2F32(lux), batterie
}; }

Maintenant vous pouvez upload votre programme, si vous voulez suivre ce que le programme fait allez dans Outils et cliquez sur Moniteur série.

Serveur MQTT

Pour que l’on puisse récupérer les données avec Node-RED, nous allons créer un serveur MQTT.

Toujours dans TheThingsNetwork dans votre Application, allez dans Integrations > MQTT. Cliquez sur Generate new API key et copiez-la car elle ne sera plus visible si vous quittez la page. L' API key servira de mot de passe.

Ça y est, on peut maintenant traiter les données avec Node-RED.

Node-RED

Flow

Explications

    • Le capteur envoie ses données et TTN les récupère. Node-RED les lit ensuite grâce à la node mqtt-in.

    • Les données sont récupérées par les nodes de dashboard qui permettent de les afficher : une jauge de niveau pour la lumière, ainsi qu'un graphe pour l'évolution de cette dernière.

    • Chaque fois que vous finissez de configurer un node, cliquez sur Done.

    • ATTENTION : pour enregistrer vos modifications, cliquez sur Deploy.

Pour le refaire

Mqtt-in

Pour commencer, on va vouloir récupérer les données reçu par l’antenne LoRaWAN via TTN. Prenez ce node, double-cliquez dessus.

Dans le menu de sélection Server, prenez Add new mqtt-broker et cliquez sur le bouton à côté.

Dans la partie Security, entrez les identifiants en accord avec ceux lors de la création du serveur MQTT.

Dans la partie Connection, précisez l’adresse du serveur MQTT de la Console The Things Stack. Et dans Protocol, sélectionnez MQTT V3.1.1.

Revenez dans les propriétés. Le topic sert à préciser de quel objet on veut traiter les données. Voici le format du topic : v3/username/devices/device_id/up. Faites attention à ce qu’il n’y est pas d’espace surtout au début et à la fin.

Sélectionnez le QoS que vous voulez (privilégiez le 2).

Et dans Output, prenez a parsed JSON object.

Pour finir, branchez une node de debug pour voir si les données de l’objet choisi arrive bien.

Debug

N'hésitez pas à connectez des nodes de debug, cela permet de savoir si vos données arrive bien et au bon format.
Pour voir les données là où vous avez connecté des debug, cliquez sur le petit insecte en haut à droite de l'écran, puis all nodes puis current flow pour voir le flux du flow sur lequel vous travaillez.

Change

Pour la température, cliquez sur add en bas à gauche de Rules.
Mettez la première règle sur
Set. Entrez topic, puis lux ou Lumière en-dessous.
Ajoutez une deuxième règle et mettez-la sur
Move, entrez payload.uplink_message.decoded_payload.lux dans le premier champ et payload dans le deuxième.
Faites la même chose pour
la batterie, changez juste les valeurs de lumière( remplacez lux par batterie et Lumière par Batterie).
Et n’oubliez pas de faire attention à ne pas laisser d’espace.

Function

Copiez-collez ceci dans la section Function

  • Pour la lumière:

var lux = Math.round(msg.payload);
var newMsg = { payload: lux , topic:"Lumiere"};
return newMsg;


  • Pour la batterie:

var value = msg.payload;
if (value < 3000){
msg = "Batterie faible!!!";
}
else msg = "Batterie en bon état";
return {
payload:{ msg:msg }
}

Level

  • Group : add new ui_group

    • ui_tab : créez une nouvelle

    • width(largeur) : à votre guise

    • name : celui que vous voulez

  • Input : payload

  • Layout : Single Vertical

  • Label : Niveau de luminosité

  • High : mettez la couleur orange

  • Warn : mettez la couleur jaune

  • Normal : mettez la couleur blanche

  • Off : mettez la couleur noire

  • Show : Interpolated colors

  • Range : min : 0 ; max : 65000

  • Sectors : 20000 puis 40000

  • Format : Unit : lx ; decimals : 2

  • Stripe shape : Superfine

  • Tick values : Segments

Chart

  • Group: le même que celui du level

  • Type: line chart

  • axe Y: min = -15 , max = 45 (ou 0 / 40 - pour la beauté de la grille )

  • Cochez la case enlarge points

  • Réglez le nombre de points max ou la durée représentée comme vous le souhaitez

Text

  • Group: le même que celui des gauges

  • Label: Etat de la Batterie

  • Value format: {{msg.payload.msg}}

  • Layout: prenez celui avec label au-dessus de value

  • Name(optionnel): donnez un nom

Interface utilisateur

L'intérêt de tout ceci est pour la visualisation des données. Node-RED permet ceci avec une interface utilisateur.
Pour y accéder, avec le moteur de recherche que vous voulez, tapez l'ip du serveur Node-RED, puis deux points, puis le numéro port puis /ui (XXX.XXX.XXX.XXX:YYYY/ui).

Mise en forme

Pour mettre en forme l'interface utilisateur, retournez dans Node-RED
Cliquez sur les trois barres en haut à droite, allez dans
View puis cliquez sur Dashboard.
En mettant le curseur sur le
nom du groupe des jauges et du graphe, cliquez sur layout.
Sur la droite réglez la largeur de l'interface sur
Width. Ensuite cliquez sur Done, puis sur Deploy et revenez dans le layout pour faire la mise en forme. Essayez d'obtenir le résultat ci-dessous.