Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

IoT-Drucksensor:MKR GSM + Arduino Cloud + Google Sheets

Komponenten und Verbrauchsmaterialien

Arduino UNO
× 1
Arduino MKR GSM 1400
× 1
Druckaufnehmer (0-150 psi)
× 1
Adafruit DHT22 Temperatur- und Feuchtigkeitssensor
× 1
DS3231 RTC-Modul
× 1
Adafruit Logic Level Converter - BSS138 - 4-Kanal I2C-sicher Bidirektional
× 1
Adafruit 3,7 V LiPo-Akku (2000 mAh oder höher)
× 2
Spannungserhöhungswandler
× 1
Einfaches Starter-Kit mit verschiedenen LEDs und Widerständen
× 1
Breadboard (generisch)
× 1

Apps und Onlinedienste

Google Tabellen
Arduino IoT Cloud
Arduino Web Editor
Arduino-IDE

Über dieses Projekt

Ziel

Ziel dieses Projekts war die Entwicklung eines Prototyps für ein kostengünstiges Gerät zur Überwachung des Drucks auf Industrieanlagen an abgelegenen Standorten mithilfe von Mobilfunkdaten.

Exemplarische Vorgehensweise für das Projekt

Im Folgenden finden Sie eine Schritt-für-Schritt-Anleitung des Projekts, die den Datenfluss vom Druckaufnehmer bis zur E-Mail-Benachrichtigung verfolgt, die durch das an das Google Sheet angehängte Skript generiert wird.

Schritt 1:Druckwandler zu Uno

Der Druckmessumformer wandelt den Druck in ein analoges elektrisches Signal um.

Der Arduino Uno wandelt das analoge Signal vom Druckaufnehmer in Druck (psi) um.

Schritt 2:Uno zu MKR GSM 1400 über Seriell

Bei der Kommunikation zwischen zwei Arduino-Geräten über Seriell:

  • Verbinde RX auf Gerät #1 mit TX auf Gerät #2
  • Verbinde TX auf Gerät #1 mit RX auf Gerät #2
  • Die Geräte müssen eine gemeinsame Masse haben

Datenübertragungsfrequenz (Uno zu MKR GSM 1400)

  • NORMAL: Alle 30 Minuten (Sendefrequenz) druckt der Uno Daten seriell an das MKR GSM 1400, das die Daten an die Cloud überträgt.
  • HIGH/LOW TRIGGER: Wenn der Druck über 40 psi (highTrigger) oder unter 20 psi (lowTrigger) steigt und dort länger als 2 Minuten bleibt (dtLastTriggerLimit), druckt der Uno Daten seriell an den MKR GSM 1400, der die Daten an die Cloud überträgt.
  • ABFRAGE-UMFRAGE: Wenn Pin A1 am Uno hoch gedrückt wird, werden Daten seriell an den MKR GSM 1400 gedruckt, der die Daten an die Cloud überträgt. Hinweis:Pin A1 heißt in der Skizze für das Uno "buttonPin". Es gibt 2 Möglichkeiten, wie Pin A1 am Uno hochgedrückt werden kann. (1) Auf dem Steckbrett befindet sich ein Druckknopf. (2) Wenn Pin A3 am MKR GSM 1400 hoch ist, wird Pin A1 hoch gedrückt. Da Pin A3 über einen Eingang in der Arduino Cloud gesteuert wird, kann der aktuelle Druck jederzeit aus der Ferne abgerufen werden, ohne auf eine regelmäßig geplante Datenübertragung warten zu müssen.

Hinweise

  • Die Skizze für den Uno könnte modifiziert werden, sodass in der aktuellen Version neben dem Druck auch mehrere Eingänge wie Temperatur, Feuchtigkeit, Batteriespannung usw. mit hohen und niedrigen Sollwerten überwacht werden können.
  • Der Code zum Umwandeln des analogen Signals vom Druckaufnehmer in Druck (psi) basiert auf den Anweisungen im folgenden YouTube-Video:https://www.youtube.com/watch?v=AB7zgnfkEi4
  • Der folgende Beitrag im Arduino-Forum zu "Grundlagen der seriellen Eingabe" war sehr hilfreich, wenn es darum ging, den Code zu schreiben, um mit seriellen Daten von einem Gerät zum anderen zu kommunizieren:https://forum.arduino.cc/index. php?topic=288234.0

Der für das Arduino Uno in diesem Projekt verwendete Code ist mit Kommentaren versehen, die wichtige Informationen erläutern.

Dateiname:"InstrumentReader"

Schritt 3:MKR GSM 1400 zu Arduino Cloud über Mobilfunk

Der MKR GSM 1400 verarbeitet serielle Daten vom Arduino Uno und überträgt die Daten per Mobilfunk an die Arduino Cloud.

Es ist erwähnenswert, dass im Code für das MKR GSM 1400 Serial1.read im Gegensatz zu Serial.read angezeigt wird. Das Referenzmaterial auf der Arduino-Website gibt eine gute Erklärung. Die Tabelle im Bild unten zeigt, dass auf die TX/RX-Pins auf MKR-Boards über Serial1 zugegriffen wird.

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

Arduino-Cloud

Dieses Projekt wird mit 2 Variablen in der Arduino Cloud eingerichtet. Das Bild unten zeigt, wie diese Variablen im Dashboard der Arduino Cloud angezeigt werden.

Die erste Variable namens "dataStringCloud" ist praktisch ein Paket aller Daten vom Gerät. Dieser Ansatz wurde im Gegensatz zu einer Variablen für jeden Wert gewählt, um die Verarbeitung der Daten in Google Tabellen zu vereinfachen. Bei einzelnen Variablennamen war es schwierig, den Unterschied zwischen einem gleich bleibenden und einem nicht aktualisierten Wert zu erkennen. Die Daten aus diesem Paket werden in Google Sheets geparst.

Die zweite Variable namens "pinCloud" wird verwendet, um das MKR GSM 1400 aus der Arduino Cloud zu steuern. In der Skizze gibt es eine Umschaltfunktion, die die Aktion basierend auf dem Wert von pinCloud steuert. Wenn pinCloud =1 ist, wird Pin A1 hoch gedrückt, wodurch eine LED auf der Platine aufleuchtet. Wenn pinCloud =2, wird Pin A3 hoch geschoben, was dazu führt, dass das Arduino Uno die aktuellen Daten wie oben beschrieben sendet.

Der in diesem Projekt für den Arduino MKR GSM 1400 verwendete Code ist mit Kommentaren versehen, die wichtige Informationen erläutern.

Dateiname:"CommunicationsDevice"

Schritt 4:Arduino Cloud zu Google Sheets über Webhook

Die Daten werden mithilfe eines Webhooks von der Arduino Cloud an Google Sheets übertragen.

Der Kern des Webhooks ist die doPost-Funktion, die in das Skript einer Google Sheets-Datei geschrieben wurde.

Hier ist eine kurze Zusammenfassung, wie Sie den Webhook einrichten. Beachten Sie, dass der Vorgang in Google Tabellen beginnt. Erst zum Schluss kommt man in die Arduino Cloud. Um von A nach B zu gelangen, beginne bei B.

  • Neue Google Tabellen-Datei erstellen
  • Klicke in der Symbolleiste auf "Extras" und wähle im Dropdown-Menü "Skript-Editor" aus
  • Code mit einer doPost-Funktion schreiben (siehe GoogleSheetsScript.js im Anhang zu diesem Projekt)
  • Klicke in der Symbolleiste auf "Veröffentlichen" und wähle im Dropdown-Menü "Als Web-App bereitstellen..." aus
  • Ein Dialogfeld mit 3 Feldern wird angezeigt.
  • (1) Projektversion: Verwenden Sie immer das Dropdown-Menü, um "Neu" auszuwählen. Nach dem ersten Update wird standardmäßig die # der aktuellen Version verwendet; Wenn Sie nicht das Dropdown-Menü verwenden, um "Neu" auszuwählen, werden die Änderungen nicht wirksam.
  • (3) Wer hat Zugriff auf die App: "Jeder, auch anonym"
  • Drücken Sie auf Bereitstellen, nachdem Sie die Werte in den 3 Feldern überprüft haben
  • Ein zweites Dialogfeld mit der "Aktuellen Web-App-URL" wird angezeigt. Dies ist die URL, die Sie kopieren und in die Registerkarte Webhook in der Arduino Cloud einfügen. Bemerkenswert ist, dass diese URL unabhängig von der Projektversion gleich bleibt.
  • Klicken Sie auf OK, und Sie sind fertig!

Ein Großteil des in diesem Projekt verwendeten JavaScript-Codes ist dem Code nachempfunden, der in einem anderen Projekt namens "Arduino IoT Cloud Google Sheets Integration" verwendet wird. Der Link zum Projekt ist unten. Ich würde empfehlen, es sich anzusehen.

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

Schritt 5:Verwenden von Google Tabellen zum Analysieren von Daten

Verwenden Sie Google Sheets, um die einzelnen Werte von dataStringCloud zu analysieren und die eindeutigen Datensätze anzuzeigen, die von der Arduino Cloud übertragen wurden

Der folgende Link führt zu der Google Sheets-Datei, die für einen kürzlich durchgeführten Test des Geräts verwendet wurde. Die Zellen in dieser Datei sind entsprechend ihrer Befüllung eingefärbt, wie in der Legende auf jedem Blatt angegeben.

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

Schritt 6:Verwenden von Google Tabellen zum Senden von Benachrichtigungen

Sie haben vielleicht bemerkt, dass die JavaScript-Datei für dieses Projekt (GoogleSheetsScript.js) zwei Funktionen enthält, auf die oben in Schritt 4 verwiesen wurde.

  • doPost-Funktion - Überträgt Daten vom Arduino Cloud Webhook. Es wird ausgeführt, wenn neue Daten in der Arduino Cloud vorhanden sind.
  • sendEmail-Funktion - Sendet E-Mails basierend auf Werten, die aus dem Blatt namens "Data" in der Google Sheets-Datei für das Projekt extrahiert wurden. Es wird einmal pro Minute basierend auf den Einstellungen im Trigger-Setup ausgeführt.

Schritte zum Einrichten eines Triggers für die Funktion sendEmail

  • Google Tabellen-Datei öffnen
  • Klicke in der Symbolleiste auf "Extras"
  • Wählen Sie im Dropdown-Menü "Skript-Editor" aus
  • Fahren Sie im Skripteditorfenster fort zu:
  • Klicke in der Symbolleiste auf "Bearbeiten"
  • Wählen Sie im Dropdown-Menü "Trigger des aktuellen Projekts" aus
  • Fahren Sie im G Suite Developer Hub-Fenster fort zu:
  • Wähle "Trigger hinzufügen" in der unteren rechten Ecke des Fensters
  • Machen Sie im angezeigten Dialogfeld eine Auswahl, um die Funktion sendEmail auszuführen.
  • Hinweis:Durch die zeitgesteuerte Ausführung des Triggers können E-Mail-Benachrichtigungen generiert werden, wenn das Gerät nicht mehr aktualisiert.

Akkulaufzeit

~24 Stunden

Dies könnte durch Ausschalten oder Entfernen der Displays optimiert werden. Eine andere Möglichkeit wäre, nicht unbedingt benötigte Sensoren wie den DHT22 und den DS3231 zu entfernen.

Datennutzung

~0,7 Megabyte/Tag

Dies könnte durch Reduzierung der Größe oder Häufigkeit der Datenübertragungen optimiert werden. Beispiel:Um die Größe zu reduzieren, senden Sie nur Druck anstelle von Druck, Temperatur, Feuchtigkeit und Zeit. Um die Häufigkeit zu reduzieren, nur stündliche Updates statt alle 30 Minuten.

Projektkosten

Gesamt =$241

  • Arduino MKR GSM 1400 ($70)
  • Arduino Uno ($22)
  • 2 x 3,7-V-LiPo-Batterien ($30)
  • 2 x LED-Anzeigen ($29)
  • Wetterbeständige Plastikbox ($22)
  • Drucksensor ($19)
  • Temperatur- / Feuchtigkeitssensor - DHT22 ($10)
  • RTC-Modul - DS3231 ($5)
  • Spannungs-Aufwärtswandler ($5)
  • Logikpegel-Umrechner ($4)
  • Verschiedenes - LEDs, Widerstände, Verkabelung usw. ($25)

Hardware / Werkzeuge

Alle für dieses Projekt verwendeten Hardware und Tools wurden von folgenden Anbietern erworben:

  • Arduino Online-Shop (https://store.arduino.cc/)
  • Adafruit (https://www.adafruit.com/)
  • Amazon (https://www.amazon.com/)
  • Hafenfracht
  • Heimdepot

Fazit...

Vielen Dank, dass Sie sich die Zeit genommen haben, dieses Projekt zu überprüfen.

Alle Fragen / Feedback / Kommentare / Vorschläge sind willkommen / geschätzt.

Code

  • InstrumentReader - Sketch für Arduino Uno
  • GoogleSheetsScript.js
InstrumentReader - Sketch für Arduino UnoArduino
// Sketch 1 of 2// Arduino Uno // Daten werden von diesem Gerät gesammelt und seriell an den MKR 1400 übertragen // Der DHT22 Sensor benötigt 2 Bibliotheken, aber nur eine wird im Code aufgerufen. // (1):DHT-Sensorbibliothek:https://github.com/adafruit/DHT-sensor-library // (2):Adafruit Unified Sensor Lib:https://github.com/adafruit/Adafruit_Sensor #include #include #include  // RTC-Modul#include  // DHT22#include "U8glib.h" // Velleman 128 x 64 OLED SPI Display // Hinweis:Eine andere Standard-U8glib-Bibliothek funktionierte nicht, als ich versuchte, sie für diese Anzeige zu verwenden. Es hat funktioniert, als ich die vom Hersteller empfohlene Bibliothek verwendet habe. // Bibliothek:https://www.velleman.eu/support/downloads/?code=VMA437 // Syntax:https://github.com/olikraus/u8glib/wiki/userreference &https://github.com/ olikraus/u8glib/wiki/thelloworld//#include  // Option zum Speichern auf SD-Karte in Ethernet Shield für Arduino UnoRTClib RTC;#define DHTPIN 11 // Digitaler Pin mit dem DHT-Sensor verbunden#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; // globale Variable // const int chipSelect =10; // Option zum Speichern auf SD-Karte in Ethernet Shield für Arduino Uno // float fileSizeSD =0.0; // Option zum Speichern auf SD-Karte in Ethernet Shield für Arduino Unoint i =0; // Anzahl der vom Uno durchgeführten Messwerte (wie # Schleifen im Programm) const int ledPin =9; // Sendeanzeige (blinkt bei einer Datenübertragung)const int ledPin2 =8; // Sendeanzeige drücken (hoch gedrückt durch manuelle Taste auf dem Steckbrett oder Ausgabe von MKR 1400 aus der Cloud aktiviert) const int buttonPin =A1;int buttonState =0;int transmitFrequency =30; // Häufigkeit des seriellen Druckens dataString zum Senden von Daten an das zweite Gerät (Minuten)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;// Eingabevariablen zur Steuerung von Triggerfloat lowTrigger =20.0;float highTrigger =40.0;float dtLastTriggerLimit =2.0; // Wenn die Bedingung für diese Zeit erfüllt ist, wird eine Warnung generiertvoid setup (void) { Serial.begin (9600); Wire.begin(); dht.begin(); pinMode (ledPin, AUSGANG); pinMode (ledPin2, AUSGANG); pinMode (buttonPin, INPUT); u8g.setRot180(); // Bildschirm umdrehen, falls erforderlich (Kommentare in dieser Zeile zum Drehen hinzufügen/entfernen) // Option zum Speichern auf SD-Karte im Ethernet Shield für Arduino Uno // Serial.print ("SD-Karte initialisieren..."); // if (! SD.begin (chipSelect)) // sehen, ob die Karte vorhanden ist und initialisiert werden kann // { // Serial.println ( "Karte fehlgeschlagen oder nicht vorhanden"); // während (1); // mach nichts mehr //} // Serial.println("Karte initialisiert.");}void loop (void) { delay(5000); DateTime now =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); Verzögerung (30000); // Verzögerung, damit MKR1400 bereit ist, Daten zu empfangen, wenn Uno:buttonPin von MKR1400:pingPin auf HIGH gedrückt wird. Else { DigitalWrite (ledPin2, LOW); } float h =dht.readHumidity(); float t =dht.readTemperature(true); // t =dht.readTemperature(true) --> Temp wenn Grad F &t =dht.readTemperature() --> Temp wenn Grad C int transmitIndicator =0; if(now.minute() % sendFrequency ==0 &&now.minute() !=pTransmitMinute) { sendIndicator =1; pTransmitMinute =now.minute(); pTransmitDateTime =String(now.hour())+String(":")+String(now.minute())+String(":")+String(now.second()); } int triggerStatus =0; if(p <=lowTrigger || p>
=highTrigger) { // Hinweis:Die Variable, auf die in der Bedingung für diese if-Anweisung verwiesen wird, wird gegen hohe und niedrige Sollwerte ausgewertet // Es ist schnell zu ändern, welche Variable ausgewertet wird - dies ist die einzige Stelle, an der die Variable angegeben ist triggerStatus =1; triggerCounter++; aufrechtzuerhalten. Sonst { TriggerCounter =0; } if(triggerStatus ==1 &&triggerCounter ==1) { cRuntimeAtTriggerStart =cRuntime; } dtLastTrigger =cRuntime - cRuntimeAtTriggerStart; int triggerTransmitAlertIndicator =0; if((dtLastTrigger> dtLastTriggerLimit) &&triggerStatus ==1) { triggerTransmitAlertIndicator =1; triggerTransmitAlertCounter++; aufrechtzuerhalten. Sonst { triggerTransmitAlertCounter =0; } if(triggerTransmitAlertCounter> 0 &&triggerTransmitAlertCounter % 10 ==0) { flashLED (2.500); } int triggerPushTransmitAlertIndicator =0; if((triggerTransmitAlertIndicator ==1 &&triggerTransmitAlertCounter ==1) || ptriggerTransmitAlertIndicator !=triggerTransmitAlertIndicator) // if(TriggerStatus existierte für die angegebene Mindestzeit für Alert &Count =1, was bedeutet, dass dies die erste Schleife ist, in der die angegebene Mindestzeit überschritten wurde time // ODER der triggerAlert-Status ändert sich -- dies erzeugt einen Push-Alarm, wenn der TriggerStatus auf 0 zurückgeht, was bedeutet, dass die Triggerbedingungen nicht mehr erfüllt sind.) { triggerPushTransmitAlertIndicator =1; Blitz-LED (5.500); Verzögerung (5000); } ptriggerTransmitAlertIndicator =triggerTransmitAlertIndicator; // aktueller Indikator im vorherigen Indikator gespeichert. In der nächsten Schleife wird der hier übertragene Wert mit dem auf Basis neuer Werte generierten Wert verglichen. // Strings erstellen String dataString =""; String cDateTime =""; String cHumTemp =""; Zeichenfolge 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 +=String(now.month())+"/"+String(now.day())+"/"+String(now.year())+" "+String(now.hour())+ ":"+String(now.minute())+":"+String(now.second()); cHumTemp +="H:"+String(h)+"% T:"+String(t)+"GradF"; cP +="P:"+String(p)+"psi"; if(transmitIndicator ==1 || triggerPushTransmitAlertIndicator ==1 || buttonState ==1) { char dataArray[100]; dataString.toCharArray(dataArray, 100); Serial.println (dataArray); flashLED (10.500); sendCounter++; } // Serial.print ("T:"); // Serial.println (triggerStatus); Verzögerung (100); // Warten Sie ein bisschen, bis die gesamte Nachricht ankommt // Bildschleife u8g.firstPage(); do { draw(cDateTime,cHumTemp, cP,i,transmitCounter,now.minute(),transmitFrequency,pTransmitMinute); } while(u8g.nextPage()); Verzögerung (1000); // writeToSD (dataString); // Option zum Speichern auf SD-Karte in Ethernet Shield für 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("jetztMinute:"); 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("Rest:"); u8g.setPrintPos(70,48); u8g.print (DnowMinute % DtransmitFrequency);} float getPressure () {int sensorVal =analogRead (A2); // Serial.print ( "Sensorwert:"); // Serial.print (sensorVal); Schwimmerspannung =(sensorVal * 5,0) / 1023.0; // Serial.print ("Volt:"); // Serial.print (Spannung); // Wenn Druck =0, Analogeingang =100 // Umwandlung von Analogeingang in Spannung:Analogeingang =100 -> Spannung =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); Schwimmerdruck_psi =((m * Spannung) + b); // Serial.print ("Druck ="); // Serial.print (Druck_psi); // Serial.println ("psi"); // Verzögerung (200); Rücklaufdruck_psi;}void flashLED (int num, int t) { for (int z =1; z <=num; z++) { digitalWrite (ledPin, HIGH); Verzögerung(t); digitalWrite (ledPin, LOW); Verzögerung(t); }} // Option zum Speichern auf SD-Karte in Ethernet Shield für Arduino Uno //void writeToSD (String dataToWrite) //{ // // Datei öffnen. Beachten Sie, dass immer nur eine Datei geöffnet sein kann, // // Sie müssen diese also schließen, bevor Sie eine andere öffnen. // Datei dataFile =SD.open("datalog4.txt", FILE_WRITE); // fileSizeSD =dataFile.size(); // Gibt die Dateigröße in Bytes zurück // fileSizeSD =fileSizeSD / 1000000; // Konvertiert Bytes in MB. 1 MB =1e6 Byte // // wenn die Datei verfügbar ist, schreibe darauf:// if (dataFile) // { // dataFile.println(dataToWrite); // dataFile.close(); // // auch auf den seriellen Port drucken:// // Serial.println (dataToWrite); // } // // Wenn die Datei nicht geöffnet ist, wird ein Fehler angezeigt:// else // { // Serial.println ( "Fehler beim Öffnen von datalog1.txt"); // } //}
GoogleSheetsScript.jsJavaScript
// Dieser Code enthält 2 Funktionen // doPost-Funktion - Überträgt Daten vom Arduino Cloud Webhook. Es wird ausgeführt, wenn neue Daten in der Arduino Cloud vorhanden sind. // sendEmail-Funktion - Sendet E-Mails basierend auf Werten, die aus dem Blatt mit dem Namen "Data" in der Google Sheets-Datei für das Projekt extrahiert wurden. Es wird einmal pro Minute basierend auf den Einstellungen im Trigger-Setup ausgeführt. Anweisungen finden Sie im Abschnitt zur sendEmail-Funktion des Projekt-Hub-Posts.// Der Großteil dieses Codes (abgesehen von der sendEmail-Funktion) ist dem folgenden Projekt auf dem Arduino Project Hub// https://create.arduino nachempfunden. cc/projecthub/Arduino_Genuino/arduino-iot-cloud-google-sheets-integration-71b6bc?f=1// Dies ist ein Link zu einem GitHub-Repository mit dem Google-Skript, das für das oben genannte Projekt im Project Hub verwendet wird. // Dieser Link wurde aus der Projektbeschreibung im Project Hub kopiert.// https://github.com/arduino/arduino-iot-google-sheet-script/blob/master/Code.gs// aktiv werden spreasheetvar ss =SpreadsheetApp.getActiveSpreadsheet();// Blatt mit dem Namen RawData abrufenvar sheet =ss.getSheetByName("RawData");var sd =ss.getSheetByName("Data");var sref =ss.getSheetByName("References"); var MAX_ROWS =1440; // maximale Anzahl der anzuzeigenden Datenzeilen // 3600s / cloud_int(30s) * num_ore(12h) =(60*60*12)/30 =(3600*12)/30 =1440 Messwerte in 12 Stunden bei 30 Sekunden Aktualisierung Intervall// (60*24)/15 =96 Messwerte in 24 Stunden bei 15 Minuten Aktualisierungsintervall // 15 Tage * 96 Messwerte/Tag =1440 Messwerte// 90 Tage * 96 Messwerte/Tag =8640 Messwerte// 365 Tage * 96 Messwerte/Tag =35040 Messwertevar HEADER_ROW =1; // Zeilenindex der Headervar TIMESTAMP_COL =1; // Spaltenindex der Zeitstempelspaltenfunktion doPost(e) { var cloudData =JSON.parse(e.postData.contents); // Dies ist ein Json-Objekt, das alle Informationen enthält, die von IoT Cloud stammen console.log(cloudData); //var webhook_id =cloudData.webhook_id; // diese drei wirklich nicht verwenden //var device_id =cloudData.device_id; //var thing_id =cloudData.thing_id; var-Werte =cloudData.values; // Dies ist ein Array von Json-Objekten console.log(values); // Namen und Werte aus dem Werte-Array speichern // Jede eingehende Eigenschaft hat einen:// Namen, der zu den Spaltennamen wird // Wert, der in die Zeilen unterhalb der Spaltenüberschrift geschrieben wird var incLength =values.length; var IncNames =[]; var IncValues ​​=[]; for (var i =0; i  2018) { // alle eingehenden Nachrichten verwerfen 'late' if (sheet.getRange(HEADER_ROW+1, 1).getValue() !='') { // HEADER_ROW + 1 =Zeile #2 &Spalte #1 --> Dies ist die Position des neuesten Zeitstempels im Blatt // Wenn der neueste Zeitstempel nicht leer ist =(''), dann vergleiche die aktuelle Zeit mit dem Zeitstempel der eingehenden Daten // Wenn der neueste Zeitstempel leer ist, ist es höchstwahrscheinlich das erste Mal das Skript es läuft. // In diesem Fall überspringen Sie diese if-Anweisung und schreiben Sie in die Spaltenüberschriften und Daten. // Es spielt keine Rolle, ob die Daten zu spät ankommen (aktuelle Zeit vs. Zeitstempel der eingehenden Daten). var now =neues Datum(); // jetzt var COMM_TIME =120; // Hinweis:auf 120 geändert, um mehr Nachrichten durchzulassen, zuvor auf 5 Sekunden eingestellt &ok // grobe Überschätzung der Kommunikationszeit zwischen Cloud und App if (now.getTime() - date.getTime()> COMM_TIME * 1000) { // Wenn die Differenz zwischen der aktuellen Zeit und dem Zeitstempel größer als 5 Sekunden ist, verwerfen Sie die Daten. // Wenn die Bedingung in dieser If-Anweisung wahr ist, wird die Funktion aufgrund der return-Anweisung beendet. Rückkehr; // "Die return-Anweisung stoppt die Ausführung einer Funktion und gibt einen Wert dieser Funktion zurück." } } // Dieser Abschnitt schreibt Werte in die Kopfzeile basierend auf den Namen der eingehenden Eigenschaften // Mit anderen Worten, dieser Abschnitt erstellt die Spaltennamen // Weisen Sie der Zelle in der Kopfzeile &in der ersten einen Namen zu Spalte =Zeitstempelblatt.getRange(HEADER_ROW, 1).setValue('timestamp'); for (var i =0; i  es ist 2 // Spalte 1 ist die Zeitstempelspalte. if (lastCol ==1) { // Schreibe die Spaltennamen beginnend mit der Spalte nach lastCol ==1, was die Zeitstempelspalte ist // incNames ist ein Array mit den Namen aller eingehenden Eigenschaften // If lastCol ==1 , schreibe den Wert von der 'i'ten Stelle im incNames-Array in die Kopfzeile in Spalte #2 =lastCol + 1 sheet.getRange(HEADER_ROW, lastCol + 1).setValue(incNames[i]); } else { // ausgewertet, wenn lastCol !=1 // Überprüfen Sie, ob der Name bereits im Header vorhanden ist var found =0; for (var col =2; col <=lastCol; col++) { // Beginne mit Spalte 2, iteriere durch alle Spalten bis zu lastCol und bewerte die eingeschlossene if-Anweisung if (sheet.getRange(HEADER_ROW, col).getValue( ) ==incNames[i]) { // the condition of this If statement compares the value in the header row &column # =col to the 'i'th value in the array of incoming property names // This if statement is evaulated 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; brechen; // "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

Schaltpläne


Herstellungsprozess

  1. ADLINK arbeitet mit Google Cloud zusammen, um IoT-fähige Lösungen anzubieten
  2. Einfaches IoT – RaspberryPI HDC2010 wie es geht
  3. BMP180 I2C Digitaler barometrischer Drucksensor
  4. Python/MicroPython Sensor Logger mit Google Tabellen
  5. Windows 10 IoT Core auf Raspberry Pi 2 – Adafruit-Sensordaten
  6. Windows 10 IoT Core und SHT15
  7. UnifiedWater v1
  8. IOT - Smart Jar mit ESP8266, Arduino und Ultraschallsensor
  9. Arduino Cloud Sensor Tower
  10. Arduino Apple Watch