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

Capteur de pression IoT :MKR GSM + Arduino Cloud + Google Sheets

Composants et fournitures

Arduino UNO
× 1
Arduino MKR GSM 1400
× 1
Capteur de pression (0-150 psi)
× 1
Capteur de température et d'humidité Adafruit DHT22
× 1
Module RTC DS3231
× 1
Adafruit Logic Level Converter - BSS138 - 4 canaux I2C-safe Bidirectionnel
× 1
Batterie LiPo Adafruit 3.7V (2000 mAh ou plus)
× 2
Convertisseur élévateur de tension
× 1
Kit de démarrage de base avec LED et résistances assorties
× 1
Planche à pain (générique)
× 1

Applications et services en ligne

Google Sheets
Arduino IoT Cloud
Éditeur Web Arduino
Arduino IDE

À propos de ce projet

Objectif

L'objectif de ce projet était de créer un prototype d'appareil à faible coût pour surveiller la pression sur les équipements industriels dans des endroits éloignés à l'aide de données cellulaires.

Procédure pas à pas du projet

Ce qui suit est une présentation étape par étape du projet suivant le flux de données du transducteur de pression à la notification par e-mail générée par le script joint à la feuille Google.

Étape 1 :transducteur de pression vers Uno

Le transducteur de pression convertit la pression en un signal électrique analogique.

L'Arduino Uno convertit le signal analogique du transducteur de pression en pression (psi).

Étape 2 :Uno vers MKR GSM 1400 via série

Lors de la communication entre deux appareils Arduino via série :

  • Connectez RX sur l'appareil n°1 à TX sur l'appareil n°2
  • Connectez TX sur l'appareil n°1 à RX sur l'appareil n°2
  • Les appareils doivent avoir un terrain d'entente

Fréquence de transmission des données (Uno vers MKR GSM 1400)

  • NORMAL : Toutes les 30 minutes (fréquence de transmission), l'Uno imprimera les données en série sur le MKR GSM 1400 qui transmettra les données au cloud.
  • DÉCLENCHEUR HAUT/BAS : Si la pression dépasse 40 psi (highTrigger) ou en dessous de 20 psi (lowTrigger) et y reste pendant plus de 2 minutes (dtLastTriggerLimit), l'Uno imprimera les données en série au MKR GSM 1400 qui les transmettra au cloud.
  • SONDAGE DE DEMANDE : Si la broche A1 de l'Uno est poussée vers le haut, elle imprimera les données en série sur le MKR GSM 1400 qui transmettra les données au cloud. Remarque :la broche A1 est nommée "buttonPin" dans le croquis de l'Uno. Il y a 2 façons pour que la broche A1 de l'Uno soit poussée vers le haut. (1) Il y a un bouton-poussoir sur la planche à pain. (2) Si la broche A3 du MKR GSM 1400 est haute, elle poussera la broche A1 haute. Étant donné que la broche A3 est contrôlée par une entrée dans le cloud Arduino, la pression actuelle peut être obtenue à distance à tout moment sans avoir à attendre une transmission de données régulièrement programmée.

Remarques

  • Le croquis de l'Uno pourrait être modifié afin que plusieurs entrées telles que la température, l'humidité, la tension de la batterie, etc. puissent être surveillées avec des points de consigne haut et bas en plus de la pression dans la version actuelle.
  • Le code utilisé pour convertir le signal analogique du transducteur de pression en pression (psi) est basé sur les instructions données dans la vidéo YouTube suivante :https://www.youtube.com/watch?v=AB7zgnfkEi4
  • Le message suivant sur le forum Arduino couvrant les « Bases de l'entrée série » a été très utile lorsqu'il s'agissait d'écrire le code pour communiquer d'un appareil à l'autre à l'aide de données série :https://forum.arduino.cc/index. php?topic=288234.0

Le code utilisé pour l'Arduino Uno dans ce projet est joint avec des commentaires expliquant les informations clés.

Nom du fichier :"InstrumentReader"

Étape 3 :MKR GSM 1400 vers Arduino Cloud via cellulaire

Le MKR GSM 1400 traite les données série de l'Arduino Uno et transmet les données à l'Arduino Cloud à l'aide de données cellulaires.

Il convient de noter que dans le code du MKR GSM 1400, vous verrez Serial1.read par opposition à Serial.read. Le matériel de référence sur le site Web Arduino donne une bonne explication. Le tableau de l'image ci-dessous montre que les broches TX/RX des cartes MKR sont accessibles via Serial1.

https://www.arduino.cc/reference/en/language/functions/communication/serial/

Cloud Arduino

Ce projet est configuré avec 2 variables dans le cloud Arduino. L'image ci-dessous montre comment ces variables sont affichées dans le tableau de bord sur le cloud Arduino.

La première variable nommée "dataStringCloud" est en fait un ensemble de toutes les données de l'appareil. Cette approche a été adoptée par opposition à une variable pour chaque valeur afin de simplifier le traitement des données dans Google Sheets. Avec des noms de variables individuels, il était difficile de faire la différence entre une valeur restant la même et une valeur qui n'était pas mise à jour. Les données de ce package sont analysées dans Google Sheets.

La deuxième variable nommée "pinCloud" est utilisée pour contrôler le MKR GSM 1400 depuis le Cloud Arduino. Il existe une fonction de commutation dans l'esquisse qui contrôle l'action en fonction de la valeur de pinCloud. Lorsque pinCloud =1, la broche A1 est poussée vers le haut, provoquant l'allumage d'une LED sur la carte. Lorsque pinCloud =2, la broche A3 est poussée vers le haut, ce qui amène l'Arduino Uno à envoyer les données actuelles comme décrit ci-dessus.

Le code utilisé pour l'Arduino MKR GSM 1400 dans ce projet est joint avec des commentaires expliquant les informations clés.

Nom du fichier :"CommunicationsDevice"

Étape 4 :Arduino Cloud vers Google Sheets via Webhook

Les données sont transférées du cloud Arduino vers Google Sheets à l'aide d'un webhook.

Le cœur du webhook est la fonction doPost écrite dans le script d'un fichier Google Sheets.

Voici un bref résumé de la configuration du webhook. Notez que le processus démarre dans Google Sheets. Vous n'atteignez pas le cloud Arduino avant la fin. Pour aller de A à B, commencez par B.

  • Créer un nouveau fichier Google Sheets
  • Cliquez sur "Outils" dans la barre d'outils et sélectionnez "Éditeur de script" dans la liste déroulante
  • Écrire du code avec une fonction doPost (référez-vous à GoogleSheetsScript.js joint à ce projet)
  • Cliquez sur "Publier" dans la barre d'outils et sélectionnez "Déployer en tant qu'application Web..." dans la liste déroulante
  • Une boîte de dialogue apparaîtra avec 3 champs.
  • (1) Version du projet : Utilisez toujours la liste déroulante pour sélectionner "Nouveau". Après la première mise à jour, le numéro de la version actuelle sera par défaut ; si vous n'utilisez pas la liste déroulante pour sélectionner "Nouveau", les modifications ne prendront pas effet.
  • (3) Qui a accès à l'application : "Tout le monde, même anonyme"
  • Appuyez sur déployer après avoir vérifié les valeurs dans les 3 champs
  • Une deuxième boîte de dialogue apparaîtra avec l'"URL de l'application Web actuelle". Il s'agit de l'URL que vous copierez et collerez dans l'onglet webhook sur le cloud Arduino. A noter, cette URL reste la même quelle que soit la version du projet.
  • Cliquez sur OK et vous avez terminé !

Une bonne partie du code JavaScript utilisé dans ce projet est calqué sur le code utilisé dans un autre projet nommé "Arduino IoT Cloud Google Sheets Integration". Le lien vers le projet est ci-dessous. Je vous recommande de le vérifier.

https://create.arduino.cc/projecthub/Arduino_Genuino/arduino-iot-cloud-google-sheets-integration-71b6bc?ref=part&ref_id=64347&offset=9

Étape 5 :Utilisez Google Sheets pour analyser les données

Utilisez Google Sheets pour analyser les valeurs individuelles de dataStringCloud et afficher les enregistrements uniques transférés depuis le cloud Arduino

Le lien ci-dessous renvoie au fichier Google Sheets utilisé pour un test récent de l'appareil. Les cellules de ce fichier sont colorées en fonction de la façon dont elles ont été remplies, comme indiqué dans la légende de chaque feuille.

https://docs.google.com/spreadsheets/d/1XwCir2Llw8RvGPGgZI3Yk6U5a3LeIfUACNuO1Gr_LFQ/edit?usp=sharing

Étape 6 :Utilisez Google Sheets pour envoyer des notifications

Vous avez peut-être remarqué qu'il y a deux fonctions dans le fichier JavaScript pour ce projet (GoogleSheetsScript.js) référencé ci-dessus à l'étape 4.

  • Fonction doPost - Transmet les données du Webhook Arduino Cloud. Il s'exécute lorsqu'il y a de nouvelles données sur le cloud Arduino.
  • Fonction sendEmail - Envoie des e-mails en fonction des valeurs extraites de la feuille nommée "Data" dans le fichier Google Sheets du projet. Il s'exécute une fois par minute en fonction des paramètres de la configuration du déclencheur.

Étapes pour configurer un déclencheur pour la fonction sendEmail

  • Ouvrir le fichier Google Sheets
  • Cliquez sur "Outils" dans la barre d'outils
  • Sélectionnez "Éditeur de scripts" dans la liste déroulante
  • À partir de la fenêtre de l'éditeur de script, procédez comme suit :
  • Cliquez sur "Modifier" dans la barre d'outils
  • Sélectionnez "Déclencheurs du projet en cours" dans la liste déroulante
  • À partir de la fenêtre G Suite Developer Hub, procédez comme suit :
  • Sélectionnez "Ajouter un déclencheur" dans le coin inférieur droit de la fenêtre
  • Dans la boîte de dialogue qui s'affiche, effectuez des sélections pour exécuter la fonction sendEmail.
  • Remarque :l'exécution du déclencheur en fonction du temps permet de générer des notifications par e-mail lorsque l'appareil arrête la mise à jour.

Autonomie de la batterie

~24 heures

Cela pourrait être optimisé en éteignant ou en supprimant les écrans. Une autre option serait de supprimer les capteurs non essentiels comme le DHT22 et le DS3231.

Utilisation des données

~0,7 mégaoctets/jour

Cela pourrait être optimisé en réduisant la taille ou la fréquence des transmissions de données. Par exemple :pour réduire la taille, envoyez uniquement la pression par opposition à la pression, la température, l'humidité et le temps. Pour réduire la fréquence, uniquement des mises à jour toutes les heures au lieu de toutes les 30 minutes.

Coût du projet

Total =241 $

  • Arduino MKR GSM 1400 (70 $)
  • Arduino Uno (22 $)
  • 2 piles LiPo 3,7 V (30 $)
  • 2 écrans LED (29 $)
  • Boîte en plastique résistant aux intempéries (22 $)
  • Capteur de pression (19 $)
  • Capteur de température/humidité - DHT22 (10 $)
  • Module RTC - DS3231 (5 $)
  • Convertisseur élévateur de tension (5 $)
  • Convertisseur de niveau logique (4 $)
  • Divers - LED, résistances, câblage, etc. (25 $)

Matériel / Outils

Tout le matériel et les outils utilisés pour ce projet ont été achetés auprès des sociétés suivantes :

  • Boutique en ligne Arduino (https://store.arduino.cc/)
  • Adafruit (https://www.adafruit.com/)
  • Amazon (https://www.amazon.com/)
  • Fret portuaire
  • Home Depot

En conclusion...

Merci d'avoir pris le temps d'examiner ce projet.

Toutes les questions/rétroactions/commentaires/suggestions sont les bienvenues/appréciées.

Code

  • InstrumentReader - Esquisse pour Arduino Uno
  • GoogleSheetsScript.js
InstrumentReader - Sketch pour Arduino UnoArduino
// Sketch 1 of 2// Arduino Uno // Les données sont collectées par cet appareil et transmises au MKR 1400 via série// Le capteur DHT22 nécessite 2 bibliothèques, mais une seule est appelée dans le code. // (1) :Bibliothèque de capteurs DHT :https://github.com/adafruit/DHT-sensor-library // (2) :Adafruit Unified Sensor Lib :https://github.com/adafruit/Adafruit_Sensor #include #include #include  // Module RTC#include  // DHT22#include "U8glib.h" // Écran Velleman 128 x 64 OLED SPI // Remarque :une autre bibliothèque U8glib standard n'a pas fonctionné lorsque j'ai essayé de l'utiliser pour cet affichage. Cela a fonctionné lorsque j'ai utilisé la bibliothèque recommandée par le fabricant. // Bibliothèque :https://www.velleman.eu/support/downloads/?code=VMA437 // Syntaxe :https://github.com/olikraus/u8glib/wiki/userreference &https://github.com/ olikraus/u8glib/wiki/thelloworld//#include  // Option d'enregistrement sur carte SD dans Ethernet Shield pour Arduino UnoRTClib RTC;#define DHTPIN 11 // Broche numérique connectée au capteur DHT#define DHTTYPE DHT22 / / DHT 22 (AM2302), AM2321DHT dht (DHTPIN, DHTTYPE); U8GLIB_SH1106_128X64 u8g (3, 4, 6, 7); // (CLK/SCK :3, MOSI :4, CS :6, DC(A0) :7) // u8g(sck, mosi, cs, a0 [, reset]) int y_pos =0 ; // variable globale//const int chipSelect =10; // Option pour enregistrer sur une carte SD dans Ethernet Shield pour Arduino Uno // float fileSizeSD =0.0; // Option pour enregistrer sur une carte SD dans Ethernet Shield pour Arduino Unoint i =0; // Nombre de lectures effectuées par l'Uno (identique au nombre de boucles du programme) const int ledPin =9; // indicateur de transmission (clignote lorsqu'une transmission de données se produit) const int ledPin2 =8; // indicateur de transmission push (poussé haut par le bouton manuel sur la maquette ou sortie de MKR 1400 activé depuis le cloud)const int buttonPin =A1;int buttonState =0;int transmitFrequency =30; // Fréquence d'impression série dataString pour l'envoi de données au deuxième périphérique (minutes)String pTransmitDateTime ="";int transmitCounter =0;int pTransmitMinute =0;int ptriggerTransmitAlertIndicator;float cRuntimeAtTriggerStart =0.0;float dtLastTrigger =0.0;int triggerCounter =0.0;int triggerTransmitAlertCounter =0;// Variables d'entrée pour contrôler Triggerfloat lowTrigger =20.0;float highTrigger =40.0;float dtLastTriggerLimit =2.0; // Si la condition est remplie pendant cette durée, une alerte sera généréevoid setup (void) { Serial.begin(9600); Fil.begin(); dht.begin(); pinMode(ledPin, SORTIE); pinMode(ledPin2, SORTIE); pinMode(boutonPin, INPUT); u8g.setRot180(); // retournez l'écran, si nécessaire (ajoutez/supprimez des commentaires sur cette ligne à faire pivoter) // Option pour enregistrer sur la carte SD dans Ethernet Shield pour Arduino Uno // Serial.print ("Initialisation de la carte SD..."); // if (!SD.begin(chipSelect)) // voir si la carte est présente et peut être initialisée // { // Serial.println("Card failed, or not present"); // tandis que (1); // ne rien faire de plus // } // Serial.println("carte initialisée.");}void loop (void) { delay(5000); DateHeure maintenant =RTC.now(); float cRuntime =millis()/60000 ; float p =getPressure();// Serial.println(p); buttonState =digitalRead(buttonPin);// Serial.print("Button:");// Serial.println(buttonState); if(buttonState ==1) { digitalWrite(ledPin2, HIGH); retard (30000); // retard pour permettre à MKR1400 de se préparer à recevoir des données si Uno:buttonPin est poussé HAUT par MKR1400:pingPin } else { digitalWrite(ledPin2, BAS); } float h =dht.readHumidity(); float t =dht.readTemperature(true); // t =dht.readTemperature(true) --> temp si degrés F &t =dht.readTemperature() --> temp si degrés C int transmitIndicator =0; if(now.minute() % transmitFrequency ==0 &&now.minute() !=pTransmitMinute) { transmitIndicator =1; pTransmitMinute =now.minute(); pTransmitDateTime =String(now.hour())+String(":")+String(now.minute())+String(":")+String(now.second()); } int triggerStatus =0; if(p <=lowTrigger || p>
=highTrigger) { // Remarque :la variable référencée dans la condition pour cette instruction if est évaluée par rapport aux points de consigne haut et bas // Il est rapide de changer la variable évaluée - c'est le seul emplacement où la variable est spécifiée triggerStatus =1 ; triggerCounter++ ; } else { triggerCounter =0; } if(triggerStatus ==1 &&triggerCounter ==1) { cRuntimeAtTriggerStart =cRuntime; } dtLastTrigger =cRuntime - cRuntimeAtTriggerStart ; int triggerTransmitAlertIndicator =0; if((dtLastTrigger> dtLastTriggerLimit) &&triggerStatus ==1) { triggerTransmitAlertIndicator =1; triggerTransmitAlertCounter++ ; } else { triggerTransmitAlertCounter =0; } if(triggerTransmitAlertCounter> 0 &&triggerTransmitAlertCounter % 10 ==0) { flashLED (2 500); } int triggerPushTransmitAlertIndicator =0; if((triggerTransmitAlertIndicator ==1 &&triggerTransmitAlertCounter ==1) || ptriggerTransmitAlertIndicator !=triggerTransmitAlertIndicator) // if(TriggerStatus a existé pendant le temps spécifié pour Alert &Count =1 ce qui signifie qu'il s'agit de la première boucle où le temps a dépassé le minimum spécifié heure // OU le statut triggerAlert change -- cela générera une alerte push si le TriggerStatus revient à 0, ce qui signifie que les conditions de déclenchement ne sont plus remplies.) { triggerPushTransmitAlertIndicator =1; flashLED (5 500); retard (5000); } ptriggerTransmitAlertIndicator =triggerTransmitAlertIndicator; // indicateur actuel stocké dans l'indicateur précédent. Lors de la boucle suivante, la valeur transférée ici sera comparée à la valeur générée sur la base de nouvelles valeurs. // Créer des chaînes String dataString =""; Chaîne cDateTime ="" ; Chaîne cHumTemp ="" ; Chaîne cP ="" ; dataString +="<"+String(i)+","+String(triggerTransmitAlertIndicator)+","+String(dtLastTrigger,0)+","+String(buttonState)+", "+String(now.month ())+","+String(now.day())+","+String(now.year())+", "+String(now.hour())+","+String(now .minute())+","+String(now.second())+", "+String(h)+","+String(t)+","+String(p)+">" ; cDateTime +=Chaîne(maintenant.mois())+"/"+Chaîne(maintenant.jour())+"/"+Chaîne(maintenant.année())+" "+Chaîne(maintenant.heure())+ ":"+String(now.minute())+":"+String(now.second()); cHumTemp +="H:"+String(h)+"% T:"+String(t)+"degF" ; cP +="P:"+Chaîne(p)+"psi" ; if(transmitIndicator ==1 || triggerPushTransmitAlertIndicator ==1 || buttonState ==1) { char dataArray[100]; dataString.toCharArray(dataArray, 100); Serial.println(dataArray); flashLED (10 500); TransmitCounter++ ; } // Serial.print("T:");// Serial.println(triggerStatus); retard (100); // attendez un peu que le message entier arrive // ​​boucle d'image u8g.firstPage(); do { draw(cDateTime,cHumTemp, cP,i,transmitCounter,now.minute(),transmitFrequency,pTransmitMinute); } while(u8g.page suivante()); retard(1000); // writeToSD(dataString); // Option pour enregistrer sur une carte SD dans Ethernet Shield pour Arduino Uno i++;}void draw(String DcDateTime,String DcHumTemp, String DcP, int Di, int DtransmitCounter,int DnowMinute,int DtransmitFrequency, int DpTransmitMinute) { u8g.begin(); u8g.setFont(u8g_font_5x7) ; //u8g_font_micro //u8g_font_5x7 //u8g_font_5x8 //u8g_font_6x10 u8g.setFontPosTop(); u8g.setPrintPos(0,0); u8g.print(DcDateTime); u8g.setPrintPos(0,8) ; u8g.print(2); u8g.setPrintPos(10,8) ; u8g.print(DcHumTemp); u8g.setPrintPos(0,16); u8g.print("3 #:"); u8g.setPrintPos(30,16); u8g.print(Di); u8g.setPrintPos (50,16); u8g.print(DcP); u8g.setPrintPos(0,24); u8g.print("4 #t:"); u8g.setPrintPos(30,24); u8g.print(DtransmitCounter); u8g.setPrintPos(50,24); u8g.print("tFreq:"); u8g.setPrintPos(83,24); u8g.print(DtransmitFrequency); u8g.setPrintPos(0,32); u8g.print(5) ; u8g.setPrintPos(10,32); u8g.print("nowMinute:"); u8g.setPrintPos(70,32); u8g.print(DnowMinute); u8g.setPrintPos(0,40); u8g.print(6) ; u8g.setPrintPos(10,40); u8g.print("pTransmitMinute:"); u8g.setPrintPos(95,40); u8g.print(DpTransmitMinute); u8g.setPrintPos(0,48); u8g.print(7) ; u8g.setPrintPos(10,48); u8g.print("Reste :"); u8g.setPrintPos(70,48); u8g.print(DnowMinute % DtransmitFrequency);}float getPressure(){ int sensorVal=analogRead(A2);// Serial.print("Sensor Value:"); // Serial.print(sensorVal); float voltage =(sensorVal*5.0)/1023.0;// Serial.print(" Volts:"); // Serial.print(tension); // Lorsque Pression =0, Entrée Analogique =100 // Conversion de l'Entrée Analogique en Tension :Entrée Analogique =100 -> Tension =100*(5/1023) =0.4889 float m =((150-0)/(4.5- 0,4889)); float b =150 - (m*4.5);// Serial.print(" m ="); // Serial.print(m); // Serial.print(" b ="); // Serial.print( b); float pressure_psi =((m*voltage)+ b);// Serial.print(" Pressure =");// Serial.print(pressure_psi);// Serial.println(" psi"); // retard (200); return pressure_psi;}void flashLED(int num, int t){ for (int z =1; z <=num; z++) { digitalWrite(ledPin, HIGH); retard(t); digitalWrite(ledPin, LOW); retard(t); }}// Option pour enregistrer sur la carte SD dans Ethernet Shield pour Arduino Uno //void writeToSD (String dataToWrite) //{ // // ouvrir le fichier. notez qu'un seul fichier peut être ouvert à la fois, // // vous devez donc fermer celui-ci avant d'en ouvrir un autre. // Fichier dataFile =SD.open("datalog4.txt", FILE_WRITE); // fileSizeSD =dataFile.size(); // Renvoie la taille du fichier en octets // fileSizeSD =fileSizeSD / 1000000; // Convertit les octets en Mo. 1 Mo =1e6 octets // // si le fichier est disponible, écrivez-y :// if (dataFile) // { // dataFile.println(dataToWrite); // dataFile.close(); // // imprimer également sur le port série :// // Serial.println(dataToWrite); // } // // si le fichier n'est pas ouvert, affiche une erreur :// else // { // Serial.println("error opening datalog1.txt"); // } //}
GoogleSheetsScript.jsJavaScript
// Il y a 2 fonctions dans ce code// fonction doPost - Transmet les données du Webhook Arduino Cloud. Il s'exécute lorsqu'il y a de nouvelles données sur le cloud Arduino.// fonction sendEmail - Envoie des e-mails en fonction des valeurs extraites de la feuille nommée "Data" dans le fichier Google Sheets pour le projet. Il s'exécute une fois par minute en fonction des paramètres de la configuration du déclencheur. Pour obtenir des instructions, reportez-vous à la partie fonction sendEmail de la publication du hub de projet.// La majorité de ce code (hormis la fonction sendEmail) est calquée sur le projet suivant sur le hub de projet Arduino // https://create.arduino. cc/projecthub/Arduino_Genuino/arduino-iot-cloud-google-sheets-integration-71b6bc?f=1// Il s'agit d'un lien vers un référentiel GitHub avec le script Google utilisé pour le projet mentionné ci-dessus sur Project Hub. // Ce lien a été copié à partir de la description du projet sur le Project Hub.// https://github.com/arduino/arduino-iot-google-sheet-script/blob/master/Code.gs// devenir actif spreasheetvar ss =SpreadsheetApp.getActiveSpreadsheet();// obtenir une feuille nommée RawDatavar sheet =ss.getSheetByName("RawData");var sd =ss.getSheetByName("Data");var sref =ss.getSheetByName("References"); var MAX_ROWS =1440 ; // nombre max de lignes de données à afficher // 3600s / cloud_int(30s) * num_ore(12h) =(60*60*12)/30 =(3600*12)/30 =1440 lectures en 12 heures à 30 secondes de mise à jour intervalle// (60*24)/15 =96 lectures sur une période de 24 heures à un intervalle de mise à jour de 15 minutes// 15 jours * 96 lectures/jour =1440 lectures// 90 jours * 96 lectures/jour =8640 lectures// 365 jours * 96 lectures/jour =35040 lecturesvar HEADER_ROW =1 ; // index de ligne de headervar TIMESTAMP_COL =1; // index de colonne de l'horodatage columnfunction doPost(e) { var cloudData =JSON.parse(e.postData.contents); // il s'agit d'un objet json contenant toutes les informations provenant d'IoT Cloud console.log(cloudData); //var webhook_id =cloudData.webhook_id; // vraiment pas en utilisant ces trois //var device_id =cloudData.device_id; //var thing_id =cloudData.thing_id; valeurs var =cloudData.values ; // il s'agit d'un tableau d'objets json console.log(values); // Stocke les noms et les valeurs du tableau des valeurs // Chaque propriété entrante a un :// nom qui deviendra le nom des colonnes // valeur qui sera écrite dans les lignes sous l'en-tête de colonne var incLength =values.length; var incNames =[]; var IncValues ​​=[]; for (var i =0; i  2018) { // rejeter tous les messages qui arrivent 'tard' if (sheet.getRange(HEADER_ROW+1, 1).getValue() !='') { // HEADER_ROW + 1 =Row #2 &Column #1 --> c'est l'emplacement de l'horodatage le plus récent dans la feuille // Si l'horodatage le plus récent n'est pas vide =(''), comparez l'heure actuelle à l'horodatage des données entrantes // Si l'horodatage le plus récent est vide, c'est probablement la première fois que le script est exécuté. // Dans ce cas, ignorez cette instruction if et continuez à écrire dans les en-têtes de colonne et les données. // Peu importe si les données arrivent en retard (heure actuelle vs horodatage des données entrantes). var maintenant =nouvelle date(); // maintenant var COMM_TIME =120; // Remarque :modifié à 120 pour permettre à plus de messages de passer, précédemment défini à 5 secondes et a fonctionné ok // surestimation approximative du temps de communication entre le cloud et l'application si (now.getTime() - date.getTime()> COMM_TIME * 1000) { // Si la différence entre l'heure actuelle et l'horodatage est supérieure à 5 secondes, supprimez les données. // Lorsque la condition de cette instruction If est vraie, la fonction s'arrêtera en raison de l'instruction return. retourner; // "L'instruction return arrête l'exécution d'une fonction et renvoie une valeur de cette fonction." } } // Cette section écrit des valeurs dans la ligne d'en-tête en fonction des noms des propriétés entrantes // En d'autres termes, cette section crée les noms de colonne // Attribue un nom à la cellule qui se trouve dans la ligne d'en-tête et dans la première colonne =feuille d'horodatage.getRange(HEADER_ROW, 1).setValue('timestamp'); for (var i =0; i  c'est 2 // la colonne 1 est la colonne d'horodatage. if (lastCol ==1) { // écrivez les noms de colonnes en commençant par la colonne après lastCol ==1 qui est la colonne d'horodatage // incNames est un tableau contenant les noms de toutes les propriétés entrantes // If lastCol ==1 , écrivez la valeur du 'i' emplacement du tableau incNames dans la ligne d'en-tête de la colonne #2 =lastCol + 1 sheet.getRange(HEADER_ROW, lastCol + 1).setValue(incNames[i]); } else { // évalué si le lastCol !=1 // vérifie si le nom est déjà dans l'en-tête var found =0; for (var col =2; col <=lastCol; col++) { // en commençant par la colonne 2, parcourt toutes les colonnes jusqu'à lastCol en évaluant l'instruction if incluse if (sheet.getRange(HEADER_ROW, col).getValue( ) ==incNames[i]) { // la condition de cette instruction If compare la valeur de la ligne d'en-tête et de la colonne # =col à la 'i'ème valeur dans le tableau des noms de propriété entrants // Cette instruction if est évaluée for each iteration of the for loop that it is enclosed in. // The condition is evaluated for all of the columns from column #2 to the last column. // It is checking to see if the 'i'th value in the incNames array exists in any of the columns in the header row. // If the 'i'th value in the incNames array finds a match to any of the values in the header row, set found =1 &exit the for loop with the break statment. found =1; Pause; // "The break statement breaks the loop and continues executing the code after the loop" } // close if statement evaluated for each iteration of the for loop that it is enclosed in. } // close for loop to check the 'i'th value in the incNames array to the values in the header row. if (found ==0) { // This If statemnt will be evaluated after the preceeding for loop has completed. // If found ==0 it means that the 'i'th value in the incNames array did not match any of the existing values in the header row. // If found ==0, write the 'i'th value in the incNames array to the column after the last column. // If new properties are added to the incoming data over time, the existing columns will not be impacted. The new property will be added to the column after the last column. sheet.getRange(HEADER_ROW, lastCol+1).setValue(incNames[i]); } // close if statement } // close else, since this is the end of the code block inside the main for loop, the next i will be evaluated up to i =incLength // The block of code inside this for loop is evaluated for each value at location i in the incNames array. // The values of i range from 0 to incLength (the number of values in the names array) // In JavaScript the index in arrays starts at 0. In other words, the 1st value in the array is at location =0. } // close main for loop used to write column names (assigning values from names array to header row) // redefine last coloumn and last row since new names could have been added var lastCol =sheet.getLastColumn(); var lastRow =sheet.getLastRow(); // delete last row to maintain constant the total number of rows if (lastRow> MAX_ROWS + HEADER_ROW - 1) { sheet.deleteRow(lastRow); } // insert new row after deleting the last one sheet.insertRowAfter(HEADER_ROW); // reset style of the new row, otherwise it will inherit the style of the header row var range =sheet.getRange('A2:Z2'); //range.setBackground('#ffffff'); range.setFontColor('#000000'); range.setFontSize(10); range.setFontWeight('normal'); // write the timestamp sheet.getRange(HEADER_ROW+1, TIMESTAMP_COL).setValue(date).setNumberFormat("yyyy-MM-dd HH:mm:ss"); // write values in the respective columns for (var col =1+TIMESTAMP_COL; col <=lastCol; col++) { // for loop to assign the value from incValues to the approrpriate column // This block of code was replaced by an if statement checking for blank values after the incoming data is populated. // Copy previous values // This is to avoid empty cells if not all properties are updated at the same time // sheet.getRange(HEADER_ROW+1, col).setValue(sheet.getRange(HEADER_ROW+2, col).getValue()); for (var i =0; i  2018), used to eliminate dupicate messages from the Arduino Cloud} // close doPost functionfunction sendEmail (){ var emailAddress =sd.getRange("V3").getValue(); var lastPressure =sd.getRange("K3").getValue(); // pressure at last update var lastUpdate =sd.getRange("A3").getValue(); // datetime of last update var ssLink ="https://docs.google.com/spreadsheets/d/1XwCir2Llw8RvGPGgZI3Yk6U5a3LeIfUACNuO1Gr_LFQ/edit#gid=1123486497"; var triggerAlertCount =sd.getRange("L6").getValue(); var triggerMonitor =sd.getRange("M3").getValue(); var dtLastStatusChange =sd.getRange("P3").getValue(); var dtLastDeviceUpdate1 =sd.getRange("S3").getValue(); var dtLastDeviceUpdate2 =sd.getRange("S4").getValue(); var emailSentNoUpdate =sd.getRange("T3").getValue(); var emailSentStartedReading =sd.getRange("U3").getValue(); var message ="Last Device Update:" + "\n" + lastUpdate + "\n\n" + " Last Pressure:" + "\n\t" + lastPressure.toFixed(2) + " psi" + "\n\n" + " Link to Spreadsheet:" + "\n\t" + ssLink; if(triggerMonitor ==0){ sd.getRange("L5").setValue(0); sd.getRange("L6").setValue(0); } if(triggerMonitor ==-1 &&triggerAlertCount <=4){ sd.getRange("L3").setValue(lastUpdate); // emailSent sd.getRange("L5").setValue(-1); sd.getRange("L6").setValue(triggerAlertCount + 1); var subject ="Status Change Alert - Outside Setpoints"; MailApp.sendEmail(emailAddress, subject, message); } if(triggerMonitor ==1 &&triggerAlertCount <=4){ sd.getRange("L3").setValue(lastUpdate); // emailSent sd.getRange("L5").setValue(1); sd.getRange("L6").setValue(triggerAlertCount + 1); var subject ="Status Change Alert - Normal"; MailApp.sendEmail(emailAddress, subject, message); } if(emailSentNoUpdate ==0 &&dtLastDeviceUpdate1> 60 &&dtLastDeviceUpdate2> 60){ sd.getRange("T3").setValue(1); // emailSentNoUpdate sd.getRange("U3").setValue(0); // emailSentStartedReading sd.getRange("T4").setValue(now.getTime()); // emailSentNoUpdate var subject ="Alert - Over 60 minutes Since Last Device Update"; MailApp.sendEmail(emailAddress, subject, message); } if(emailSentNoUpdate ==1 &&dtLastDeviceUpdate1 <60){ // removed the following from the condition:&&dtLastDeviceUpdate2> 60 sd.getRange("T3").setValue(0); // emailSentNoUpdate sd.getRange("U3").setValue(1); // emailSentStartedReading sd.getRange("U4").setValue(now.getTime()); // emailSentStartedReading var subject ="Alert - Device Started Updating"; MailApp.sendEmail(emailAddress, subject, message); }} 
CommunicationsDevice - Sketch for MKR 1400

Schémas


Processus de fabrication

  1. ADLINK s'associe à Google Cloud pour proposer des solutions prêtes pour l'IoT
  2. IdO de base – RaspberryPI HDC2010 comment
  3. Capteur de pression barométrique numérique BMP180 I2C
  4. Enregistreur de capteur Python/MicroPython avec Google Sheets
  5. Windows 10 IoT Core sur Raspberry Pi 2 – Données du capteur Adafruit
  6. Windows 10 IoT Core et SHT15
  7. UnifiedWater v1
  8. IOT - Smart Jar utilisant ESP8266, Arduino et capteur à ultrasons
  9. Tour de capteur cloud Arduino