Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Surveillance environnementale temps réel avec Arduino MKR1000 et capteurs Environment Click

Composants et fournitures

Composant Quantité
Arduino MKR1000 1
MikroE Environment Click (capteur BME680) 1

Outils et machines nécessaires

Applications et services en ligne

À propos du projet

Introduction

Nous avions des capteurs Environment Click sous la main, alors nous les avons connectés à l'Arduino MKR1000 pour les visualiser sur la plateforme IoT WolkAbout. L'idée : une mesure par minute, publication des résultats toutes les 15 minutes. Si la publication échoue (réseau occupé ou autre), les résultats sont conservés dans la mémoire Flash de l'appareil. Avec un maximum de 96 écritures par jour, on minimise le risque d'endommager la Flash (Arduino garantit 10 000 cycles d'écriture).

Configuration matérielle

Le capteur Environment Click se connecte aux broches de communication I2C (broches 11 et 12 sur le MKR1000), Vcc et masse.

Configuration logicielle

Bibliothèques requises (installables via le gestionnaire de bibliothèques de l'IDE Arduino ou via GitHub) :

Une fois installées, copiez le contenu du sketch Environment monitoring depuis les pièces jointes dans l'IDE Arduino.

Le sketch implémente une structure de tampon circulaire pour stocker les résultats de mesure, et comment stocker cette structure en Flash avec la bibliothèque FlashStorage. La lecture et la publication temporisées sont gérées par la bibliothèque RTCZero. Au début, après connexion WiFi, on envoie un ping à WolkAbout IoT Platform pour obtenir l'époque actuelle qui sera fournie à la bibliothèque RTC pour horodater correctement les lectures.

Une interruption d'alarme change des drapeaux pour les tâches à faire (lire et publier) et le reste est géré dans la fonction loop(). Pour une consommation minimale, le WiFi est mis en mode basse consommation ainsi que le MKR1000. Le capteur sur l'Environment Click passe automatiquement en basse consommation jusqu'à ce qu'une lecture soit demandée.

Modifications à faire dans le sketch :

Pour obtenir ces identifiants, créez d'abord un device en utilisant un device type. Le device type pour ce projet, Environment click-deviceType.json, est dans les pièces jointes. Créez-en une copie. Connectez-vous ou créez un compte sur WolkAbout IoT Platform et ouvrez l'application Device Management.

  1. Onglet Device Type Management → bouton + → Upload → sélectionnez votre copie du device type.
  2. Créez un device à partir de ce type : Create device.
  3. Donnez un nom, Connectivity Type = MQTT, cochez Create Default Semantic (nécessaire pour créer des widgets sur le tableau de bord).
  4. Save → le formulaire avec les identifiants du device s'affiche. Sauvegardez ces infos et entrez-les dans le sketch.

Vérifiez et téléversez le sketch sur votre carte. Il reste à créer l'affichage des données reçues.

Sur WolkAbout IoT Platform, section Visualisation and Monitoring → + Add dashboard → nommez-le, scope = nom du device. Ajoutez des widgets : Add widget.

Le tableau de bord est prêt à recevoir les données. Déployez le device dans l'environnement choisi et surveillez les conditions à distance.

Conclusion

En connectant l'Arduino MKR1000 et l'Environment Click à la plateforme WolkAbout IoT, vous avez créé un moyen économe en énergie de signaler les conditions environnementales d'un lieu à distance. Cette solution peut être étendue grâce au moteur de règles de WolkAbout, qui permet de recevoir différents types de notifications si une valeur dépasse un seuil défini.

Pour plus d'infos sur le moteur de règles et autres fonctionnalités, consultez la page User Guides de WolkAbout.

Code

Sketch Environment monitoring (Arduino)

Importez ce sketch dans l'IDE Arduino et modifiez les identifiants WiFi et device.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "WolkConn.h"
#include "MQTTClient.h"

/* Nombre de outbound_message_t à stocker */
#define STORAGE_SIZE 32
#define SEALEVELPRESSURE_HPA (1013.25)

/* Tampon circulaire pour stocker les messages sortants à persister */
typedef struct {
    boolean valid;
    outbound_message_t outbound_messages[STORAGE_SIZE];
    uint32_t head;
    uint32_t tail;
    boolean empty;
    boolean full;
} Messages;

static Messages data;

/* Détails de connexion */
const char* ssid = "ssid";
const char* wifi_pass = "wifi_pass";
const char *device_key = "device_key";
const char *device_password = "device_password";
const char* hostname = "api-demo.wolkabout.com";
int portno = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

/* Contexte WolkConnect-Arduino */
static wolk_ctx_t wolk;

/* Initialisation stockage Flash */
FlashStorage(flash_store, Messages);

/* Init communication I2C capteur */
Adafruit_BME680 bme;
RTCZero rtc;

bool read;
const byte readEvery = 1;   // Lecture capteur chaque minute (doit être < 60)
bool publish;
const byte publishEvery = 10; // Publication toutes les 10 minutes (doit être < 60)
byte publishMin;

/* Stockage Flash et implémentation persistance personnalisée */
void _flash_store() {
    data.valid = true;
    flash_store.write(data);
}

void increase_pointer(uint32_t* pointer) {
    if ((*pointer) == (STORAGE_SIZE - 1)) (*pointer) = 0;
    else (*pointer)++;
}

void _init() {
    data = flash_store.read();
    if (data.valid == false) {
        data.head = 0;
        data.tail = 0;
        data.empty = true;
        data.full = false;
    }
}

bool _push(outbound_message_t* outbound_message) {
    if (data.full) increase_pointer(&data.head);
    memcpy(&data.outbound_messages[data.tail], outbound_message, sizeof(outbound_message_t));
    increase_pointer(&data.tail);
    data.empty = false;
    data.full = (data.tail == data.head);
    return true;
}

bool _peek(outbound_message_t* outbound_message) {
    memcpy(outbound_message, &data.outbound_messages[data.head], sizeof(outbound_message_t));
    return true;
}

bool _pop(outbound_message_t* outbound_message) {
    memcpy(outbound_message, &data.outbound_messages[data.head], sizeof(outbound_message_t));
    increase_pointer(&data.head);
    data.full = false;
    data.empty = (data.tail == data.head);
    return true;
}

bool _is_empty() {
    return data.empty;
}

void init_wifi() {
    if (WiFi.status() != WL_CONNECTED) {
        while (WiFi.begin(ssid, wifi_pass) != WL_CONNECTED) {
            delay(1000);
        }
    }
}

void setup_wifi() {
    delay(10);
    if (WiFi.status() != WL_CONNECTED) {
        int numAttempts = 0;
        while (WiFi.begin(ssid, wifi_pass) != WL_CONNECTED) {
            numAttempts++;
            if (numAttempts == 10) {
                Serial.println("Couldn't reach WiFi!");
                break;
            }
            delay(1000);
        }
    }
}

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
    
    _init();
    init_wifi();
    
    wolk_init(&wolk, NULL, NULL, NULL, NULL, device_key, device_password, &client, hostname, portno, PROTOCOL_JSON_SINGLE, NULL, NULL);
    wolk_init_custom_persistence(&wolk, _push, _peek, _pop, _is_empty);
    
    if (!bme.begin()) {
        digitalWrite(LED_BUILTIN, HIGH); // LED allumée si erreur capteur
    }
    
    /* Initialisation capteur */
    bme.setTemperatureOversampling(BME680_OS_8X);
    bme.setHumidityOversampling(BME680_OS_2X);
    bme.setPressureOversampling(BME680_OS_4X);
    bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
    bme.setGasHeater(320, 150); // 320°C pendant 150 ms
    delay(200);
    
    read = true;
    publish = true;
    
    /* Récupération époque actuelle depuis le serveur */
    wolk_connect(&wolk);
    delay(100);
    wolk_update_epoch(&wolk);
    while (!(wolk.pong_received)) {
        wolk_process(&wolk);
        digitalWrite(LED_BUILTIN, HIGH);
        delay(1000);
    }
    digitalWrite(LED_BUILTIN, LOW);
    wolk_disconnect(&wolk);
    
    rtc.begin();
    rtc.setEpoch(wolk.epoch_time);
    rtc.setAlarmTime(rtc.getHours(), (rtc.getMinutes() + readEvery) % 60, rtc.getSeconds());
    rtc.enableAlarm(rtc.MATCH_MMSS);
    rtc.attachInterrupt(alarmMatch);
    publishMin = (rtc.getMinutes() + publishEvery) % 60;
    
    WiFi.lowPowerMode();
}

void loop() {
    /* L'interruption ne fait que mettre les drapeaux, le travail se fait ici */
    if (read) {
        read = false;
        if (!bme.performReading()) {
            digitalWrite(LED_BUILTIN, HIGH);
        }
        wolk_add_numeric_sensor_reading(&wolk, "T", bme.temperature, rtc.getEpoch());
        wolk_add_numeric_sensor_reading(&wolk, "H", bme.humidity, rtc.getEpoch());
        wolk_add_numeric_sensor_reading(&wolk, "P", bme.pressure / 100.0, rtc.getEpoch());
        wolk_add_numeric_sensor_reading(&wolk, "GR", bme.gas_resistance, rtc.getEpoch());
        wolk_add_numeric_sensor_reading(&wolk, "A", bme.readAltitude(SEALEVELPRESSURE_HPA), rtc.getEpoch());
        
        /* Nouvelle alarme pour prochaine lecture */
        int alarmMin = (rtc.getMinutes() + readEvery) % 60;
        rtc.setAlarmMinutes(alarmMin);
        delay(100);
    }
    
    if (publish) {
        publish = false;
        setup_wifi();
        wolk_connect(&wolk);
        if (!wolk.is_connected) {
            _flash_store();
        }
        delay(100);
        if (wolk_publish(&wolk) == W_TRUE) {
            _flash_store();
        }
        /* Nouveau temps de publication */
        publishMin = (rtc.getMinutes() + publishEvery) % 60;
        delay(100);
        wolk_disconnect(&wolk);
        delay(100);
    }
    delay(100);
}

/* Routine d'interruption temporisée */
void alarmMatch() {
    read = true;
    if (publishMin == rtc.getMinutes()) {
        publish = true;
    }
}

Environment click-deviceType.json (JSON)

Type de device pour créer un device sur WolkAbout IoT Platform.

[
  {
    "name": "Environment click",
    "description": "Device type for the BME680 sensor on MikroElektronika's board Environment Click",
    "guid": "def68ff6-63c5-4f9c-a066-bcc944b7bd2d",
    "deviceType": "STANDARD",
    "protocol": "JSON",
    "connectivityType": null,
    "firmwareUpdateType": null,
    "feeds": [
      { "name": "Temperature", "reference": "T", "unit": { "name": "CELSIUS", "guid": "7c805d10-a879-11e9-83cd-0a0027000005" } },
      { "name": "Humidity", "reference": "H", "unit": { "name": "HUMIDITY_PERCENT", "guid": "7c8080a3-a879-11e9-83cd-0a0027000005" } },
      { "name": "Pressure", "reference": "P", "unit": { "name": "MILLIBAR", "guid": "7c807980-a879-11e9-83cd-0a0027000005" } },
      { "name": "Gas Resistance", "reference": "GR", "unit": { "name": "OHM", "guid": "7c805890-a879-11e9-83cd-0a0027000005" } },
      { "name": "Altitude", "reference": "A", "unit": { "name": "METRE", "guid": "7c805a59-a879-11e9-83cd-0a0027000005" } }
    ],
    "actuators": [],
    "alarms": [],
    "configs": [],
    "attributes": [
      { "name": "CONNECTIVITY_TYPE", "dataType": "ENUM", "validationRegex": "^(MQTT|HTTP)$", "options": ["MQTT", "HTTP"], "defaultValue": "MQTT", "required": true, "readOnly": true },
      { "name": "FIRMWARE_UPDATE_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "defaultValue": null, "required": false, "readOnly": true },
      { "name": "FIRMWARE_VERSION", "dataType": "STRING", "defaultValue": null, "required": false, "readOnly": true },
      { "name": "FILE_DIRECT_DOWNLOAD_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "defaultValue": null, "required": false, "readOnly": true },
      { "name": "FILE_URL_DOWNLOAD_ENABLED", "dataType": "BOOLEAN", "validationRegex": "^(true|false)$", "defaultValue": null, "required": false, "readOnly": true }
    ]
  }
]

Ressources utiles

Schéma de câblage

Disponible dans la section « Schémas ».

Processus de fabrication

  1. Construire un Spybot Arduino piloté par Bluetooth
  2. Capteur CO2 K30 : Surveillance en temps réel de la qualité de l'air intérieur
  3. FlickMote : Télécommande IR à gestes pour maison connectée
  4. TV-B-Gone DIY Arduino : Télécommande universelle pour toutes les TV
  5. Construire une horloge maître LED personnalisée avec alarme – Visible à 12 mètres
  6. Find Me : Localisateur d'objets intelligent avec Arduino et Bluetooth
  7. Solutions d'alimentation optimisées pour projets Arduino
  8. Morpion sur matrice LED MAX7219 avec boîtier en carton
  9. Construire un robot quadrupède Arduino intelligent : guide étape par étape