Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

IoT-druksensor:MKR GSM + Arduino Cloud + Google Spreadsheets

Componenten en benodigdheden

Arduino UNO
× 1
Arduino MKR GSM 1400
× 1
Druktransducer (0-150 psi)
× 1
Adafruit DHT22 temperatuur- en vochtigheidssensor
× 1
DS3231 RTC-module
× 1
Adafruit Logic Level Converter - BSS138 - 4-kanaals I2C-veilig Bidirectioneel
× 1
Adafruit 3.7V LiPo-batterij (2000 mAh of meer)
× 2
Voltage Step-up Converter
× 1
Basis startpakket met diverse LED's en weerstanden
× 1
Broodplank (algemeen)
× 1

Apps en online services

Google Spreadsheets
Arduino IoT Cloud
Arduino Web Editor
Arduino IDE

Over dit project

Doelstelling

Het doel van dit project was om een ​​prototype te maken voor een goedkoop apparaat om de druk op industriële apparatuur op afgelegen locaties te bewaken met behulp van mobiele data.

Projectoverzicht

Het volgende is een stapsgewijze doorloop van het project waarbij de gegevensstroom van de druktransducer naar de e-mailmelding wordt gevolgd die wordt gegenereerd door het script dat aan het Google-spreadsheet is toegevoegd.

Stap 1:Drukopnemer naar Uno

De druktransducer zet druk om in een analoog elektrisch signaal.

De Arduino Uno zet het analoge signaal van de druktransducer om in druk (psi).

Stap 2:Uno naar MKR GSM 1400 via serieel

Bij communicatie tussen twee Arduino-apparaten via serieel:

  • Verbind RX op apparaat #1 met TX op apparaat #2
  • Verbind TX op apparaat #1 met RX op apparaat #2
  • De apparaten moeten een gemeenschappelijke basis hebben

Datatransmissiefrequentie (Uno naar MKR GSM 1400)

  • NORMAAL: Elke 30 minuten (transmitFrequency) zal de Uno serieel gegevens printen naar de MKR GSM 1400 die de gegevens naar de cloud zal verzenden.
  • HOGE/LAGE TRIGGER: Als de druk boven 40 psi (highTrigger) of onder 20 psi (lowTrigger) komt en daar langer dan 2 minuten (dtLastTriggerLimit) blijft, zal de Uno de gegevens serieel afdrukken naar de MKR GSM 1400, die de gegevens naar de cloud verzendt.
  • VRAAG POLL: Als pin A1 op de Uno hoog wordt geduwd, worden de gegevens serieel afgedrukt naar de MKR GSM 1400 die de gegevens naar de cloud verzendt. Opmerking:pin A1 heet "buttonPin" in de schets voor de Uno. Er zijn 2 manieren waarop pin A1 op de Uno hoog kan worden geduwd. (1) Er zit een drukknop op het breadboard. (2) Als pin A3 op de MKR GSM 1400 hoog is, wordt pin A1 hoog gedrukt. Omdat pin A3 wordt bestuurd door een ingang in de Arduino Cloud, kan de huidige druk op elk moment op afstand worden verkregen zonder te hoeven wachten op een regelmatig geplande gegevensoverdracht.

Opmerkingen

  • De schets voor de Uno kan worden aangepast zodat meerdere ingangen zoals temperatuur, vochtigheid, batterijspanning, enz. kunnen worden bewaakt met hoge en lage instelpunten naast de druk in de huidige versie.
  • De code die wordt gebruikt om het analoge signaal van de druktransducer om te zetten in druk (psi) is gebaseerd op de instructies in de volgende YouTube-video:https://www.youtube.com/watch?v=AB7zgnfkEi4
  • Het volgende bericht op het Arduino-forum over "Serial Input Basics" was erg nuttig bij het schrijven van de code om van het ene apparaat naar het andere te communiceren met behulp van seriële gegevens:https://forum.arduino.cc/index. php?topic=288234.0

De code die voor de Arduino Uno in dit project wordt gebruikt, is bijgevoegd met opmerkingen waarin belangrijke informatie wordt uitgelegd.

Bestandsnaam:"InstrumentReader"

Stap 3:MKR GSM 1400 naar Arduino Cloud via mobiel

De MKR GSM 1400 verwerkt seriële gegevens van de Arduino Uno en verzendt de gegevens naar de Arduino Cloud met behulp van mobiele gegevens.

Het is vermeldenswaard dat u in de code voor de MKR GSM 1400 Serial1.read ziet in plaats van Serial.read. Het referentiemateriaal op de Arduino-website geeft een goede uitleg. De tabel in de onderstaande afbeelding laat zien dat de TX/RX-pinnen op MKR-kaarten toegankelijk zijn via Serial1.

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

Arduino Cloud

Dit project is opgezet met 2 variabelen in de Arduino Cloud. De afbeelding hieronder laat zien hoe deze variabelen worden weergegeven in het dashboard op de Arduino Cloud.

De eerste variabele met de naam "dataStringCloud" is in feite een pakket van alle gegevens van het apparaat. Deze aanpak is gekozen in plaats van één variabele voor elke waarde om de verwerking van de gegevens in Google Spreadsheets te vereenvoudigen. Met namen van afzonderlijke variabelen was het moeilijk om het verschil te zien tussen een waarde die hetzelfde bleef en een waarde die niet werd bijgewerkt. De gegevens uit dit pakket worden geparseerd in Google Spreadsheets.

De tweede variabele genaamd "pinCloud" wordt gebruikt om de MKR GSM 1400 vanuit de Arduino Cloud te besturen. Er is een schakelfunctie in de schets die de actie regelt op basis van de waarde van pinCloud. Wanneer pinCloud =1, wordt pin A1 hoog geduwd waardoor een LED op het bord gaat branden. Wanneer pinCloud =2, wordt pin A3 hoog geduwd, wat ertoe leidt dat de Arduino Uno de huidige gegevens verzendt zoals hierboven beschreven.

De code die in dit project voor de Arduino MKR GSM 1400 wordt gebruikt, is bijgevoegd met opmerkingen waarin belangrijke informatie wordt uitgelegd.

Bestandsnaam:"CommunicationsDevice"

Stap 4:Arduino Cloud naar Google Spreadsheets via Webhook

Gegevens worden via een webhook overgedragen van de Arduino Cloud naar Google Spreadsheets.

De kern van de webhook is de doPost-functie geschreven in het script van een Google Spreadsheets-bestand.

Hier is een korte samenvatting van hoe u de webhook instelt. Houd er rekening mee dat het proces begint in Google Spreadsheets. Je komt pas op het einde bij de Arduino Cloud. Begin bij B om van A naar B te komen.

  • Een nieuw Google Spreadsheets-bestand maken
  • Klik op "Extra" op de werkbalk en selecteer "Scripteditor" in de vervolgkeuzelijst
  • Schrijf code met een doPost-functie (raadpleeg GoogleSheetsScript.js dat bij dit project is gevoegd)
  • Klik op "Publiceren" op de werkbalk en selecteer "Implementeren als web-app..." in de vervolgkeuzelijst
  • Er verschijnt een dialoogvenster met 3 velden.
  • (1) Projectversie: Gebruik altijd de vervolgkeuzelijst om "Nieuw" te selecteren. Na de eerste update zal het standaard de # van de huidige versie zijn; als u de vervolgkeuzelijst niet gebruikt om "Nieuw" te selecteren, worden de wijzigingen niet van kracht.
  • (3) Wie heeft toegang tot de app: "Iedereen, zelfs anoniem"
  • Druk op implementeren na verificatie van de waarden in de 3 velden
  • Er verschijnt een tweede dialoogvenster met de "Huidige web-app-URL". Dit is de URL die u kopieert en plakt in het webhook-tabblad op de Arduino Cloud. Het is vermeldenswaard dat deze URL hetzelfde blijft, ongeacht de projectversie.
  • Klik op ok, en je bent klaar!

Een groot deel van de JavaScript-code die in dit project wordt gebruikt, is gemodelleerd naar de code die wordt gebruikt in een ander project met de naam "Arduino IoT Cloud Google Sheets Integration". De link naar het project staat hieronder. Ik raad je aan het eens te proberen.

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

Stap 5:Gebruik Google Spreadsheets om gegevens te ontleden

Gebruik Google Spreadsheets om de individuele waarden van dataStringCloud te ontleden en de unieke records weer te geven die zijn overgedragen vanuit de Arduino Cloud

De onderstaande link is naar het Google Spreadsheets-bestand dat is gebruikt voor een recente test van het apparaat. De cellen in dit bestand zijn gekleurd op basis van hoe ze zijn gevuld, zoals aangegeven in de legenda op elk blad.

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

Stap 6:Gebruik Google Spreadsheets om meldingen te verzenden

Het is je misschien opgevallen dat er twee functies zijn in het JavaScript-bestand voor dit project (GoogleSheetsScript.js) waarnaar hierboven wordt verwezen in stap 4.

  • doPost-functie - Verzendt gegevens van de Arduino Cloud Webhook. Het wordt uitgevoerd wanneer er nieuwe gegevens op de Arduino Cloud zijn.
  • sendEmail-functie - Verstuurt e-mails op basis van waarden die zijn geëxtraheerd uit het blad met de naam 'Gegevens' in het Google Spreadsheets-bestand voor het project. Het wordt eenmaal per minuut uitgevoerd op basis van de instellingen in de triggerconfiguratie.

Stappen om een ​​trigger in te stellen voor de sendEmail-functie

  • Google Spreadsheets-bestand openen
  • Klik op "Extra" in de werkbalk
  • Selecteer "Scripteditor" in de vervolgkeuzelijst
  • Ga vanuit het venster Scripteditor verder naar:
  • Klik op "Bewerken" in de werkbalk
  • Selecteer "Huidige projecttriggers" in de vervolgkeuzelijst
  • Ga vanuit het venster G Suite Developer Hub naar:
  • Selecteer "Trigger toevoegen" in de rechterbenedenhoek van het venster
  • Maak in het dialoogvenster dat verschijnt selecties om de functie sendEmail uit te voeren.
  • Opmerking:door de trigger op tijdgestuurde basis uit te voeren, is het mogelijk om e-mailmeldingen te genereren wanneer het apparaat stopt met updaten.

Levensduur batterij

~24 uur

Dit kan worden geoptimaliseerd door de displays uit te schakelen of te verwijderen. Een andere optie zou zijn om niet-essentiële sensoren zoals de DHT22 en de DS3231 te verwijderen.

Gegevensgebruik

~0,7 megabyte/dag

Dit kan worden geoptimaliseerd door de omvang of frequentie van datatransmissies te verminderen. Bijvoorbeeld:om de grootte te verkleinen, stuurt u alleen druk in plaats van druk, temperatuur, vochtigheid en tijd. Om de frequentie te verminderen, alleen updates per uur in plaats van elke 30 minuten.

Projectkosten

Totaal =$241

  • Arduino MKR GSM 1400 ($70)
  • Arduino Uno ($ 22)
  • 2 x 3.7V LiPo-batterijen ($30)
  • 2 x LED-schermen ($29)
  • Weerbestendige plastic doos ($ 22)
  • Druksensor ($19)
  • Temperatuur-/vochtigheidssensor - DHT22 ($10)
  • RTC-module - DS3231 ($5)
  • Voltage Step-up Converter ($5)
  • Logische niveau-omzetter ($ 4)
  • Diversen - LED's, weerstanden, bedrading, enz. ($ 25)

Hardware / Gereedschap

Alle hardware en tools die voor dit project zijn gebruikt, zijn gekocht bij:

  • Arduino Online-winkel (https://store.arduino.cc/)
  • Adafruit (https://www.adafruit.com/)
  • Amazon (https://www.amazon.com/)
  • Havenvracht
  • Home Depot

Tot slot...

Bedankt dat je de tijd hebt genomen om dit project te beoordelen.

Alle vragen / feedback / opmerkingen / suggesties zijn welkom / gewaardeerd.

Code

  • InstrumentReader - Schets voor Arduino Uno
  • GoogleSheetsScript.js
InstrumentReader - Schets voor Arduino UnoArduino
// Schets 1 van 2// Arduino Uno // Gegevens worden door dit apparaat verzameld en via serieel naar de MKR 1400 verzonden// De DHT22-sensor vereist 2 bibliotheken, maar er wordt er maar één in de code aangeroepen. // (1):DHT-sensorbibliotheek:https://github.com/adafruit/DHT-sensor-library // (2):Adafruit Unified Sensor Lib:https://github.com/adafruit/Adafruit_Sensor #include #include #include  // RTC-module#include  // DHT22#include "U8glib.h" // Velleman 128 x 64 OLED SPI-display // Opmerking:een andere standaard U8glib-bibliotheek werkte niet toen ik deze voor dit scherm probeerde te gebruiken. Het werkte wel toen ik de door de fabrikant aanbevolen bibliotheek gebruikte. // Bibliotheek:https://www.velleman.eu/support/downloads/?code=VMA437 // Syntaxis:https://github.com/olikraus/u8glib/wiki/userreference &https://github.com/ olikraus/u8glib/wiki/thelloworld//#include  // Optie om op SD-kaart op te slaan in Ethernet Shield voor Arduino UnoRTClib RTC;#define DHTPIN 11 // Digitale pin aangesloten op de DHT-sensor#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 variabele//const int chipSelect =10; // Optie om op SD-kaart op te slaan in Ethernet Shield voor Arduino Uno//float fileSizeSD =0.0; // Optie om op SD-kaart op te slaan in Ethernet Shield voor Arduino Unoint i =0; // Tel # metingen door de Uno (hetzelfde als # lussen in het programma) const int ledPin =9; // zendindicator (knippert wanneer een gegevensoverdracht plaatsvindt) const int ledPin2 =8; // push-zendindicator (hoog geduwd door handmatige knop op breadboard of uitvoer van MKR 1400 geactiveerd vanuit de cloud) const int buttonPin =A1;int buttonState =0;int sendFrequency =30; // Frequentie van seriële afdrukgegevensString voor het verzenden van gegevens naar het tweede apparaat (minuten)String pTransmitDateTime ="";int transmitterCounter =0;int pTransmitMinute =0;int ptriggerTransmitAlertIndicator;float cRuntimeAtTriggerStart =0.0;float dtLastTrigger =0.0;int triggerCounter =0.0;int triggerCounter;int triggerTransmitAlertCounter =0;// Invoervariabelen voor het regelen van Triggerfloat lowTrigger =20.0;float highTrigger =40.0;float dtLastTriggerLimit =2.0; // Als gedurende deze tijd aan de voorwaarde wordt voldaan, wordt een waarschuwing gegenereerdvoid setup (void) { Serial.begin(9600); Draad.begin(); dht.begin(); pinMode (ledPin, UITGANG); pinMode (ledPin2, UITGANG); pinMode (knopPin, INPUT); u8g.setRot180(); // scherm omdraaien, indien nodig (toevoegen/verwijderen van opmerkingen op deze regel om te roteren) // Optie om op SD-kaart op te slaan in Ethernet Shield voor Arduino Uno // Serial.print ("Initializing SD-kaart..."); // if (!SD.begin(chipSelect)) // kijk of de kaart aanwezig is en kan worden geïnitialiseerd // { // Serial.println ("Kaart mislukt of niet aanwezig"); // terwijl (1); // doe niets meer // } // Serial.println("kaart geïnitialiseerd.");}void loop (void) { delay (5000); DateTime nu =RTC.now(); float cRuntime =millis()/60000; float p =getPressure();// Serial.println(p); buttonState =digitalRead(buttonPin);//Serial.print("Knop:");//Serial.println(buttonState); if(buttonState ==1) {digitalWrite(ledPin2, HIGH); vertraging (30000); // vertraging zodat MKR1400 klaar is om gegevens te ontvangen als Uno:buttonPin HOOG wordt geduwd door MKR1400:pingPin } else { digitalWrite (ledPin2, LOW); } float h =dht.readHumidity(); float t =dht.readTemperature(true); // t =dht.readTemperature(true) --> temp als graden F &t =dht.readTemperature() --> temp als graden C int sendIndicator =0; if(now.minute() % sendFrequency ==0 &&now.minute() !=pTransmitMinute) {transmitIndicator =1; pTransmitMinute =nu.minute(); pTransmitDateTime =String(now.hour())+String(":")+String(now.minute())+String(":")+String(now.second()); } int triggerStatus =0; if(p <=lowTrigger || p>
=highTrigger) {// Opmerking:de variabele waarnaar wordt verwezen in de voorwaarde voor deze if-instructie wordt geëvalueerd tegen hoge en lage instelpunten // Het is snel om te veranderen welke variabele wordt geëvalueerd - dit is de alleen locatie waar de variabele is gespecificeerd 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 bestond voor min. gespecificeerde tijd voor Alert &Count =1, wat betekent dat dit de eerste lus is waar de tijd de gespecificeerde min overschreed time // OF de triggerAlert-status verandert -- dit genereert een push-waarschuwing als de TriggerStatus teruggaat naar 0, wat betekent dat niet langer aan de triggervoorwaarden wordt voldaan.) { triggerPushTransmitAlertIndicator =1; flits-LED (5.500); vertraging (5000); } ptriggerTransmitAlertIndicator =triggerTransmitAlertIndicator; // huidige indicator opgeslagen in vorige indicator. In de volgende lus wordt de hier overgedragen waarde vergeleken met de gegenereerde waarde op basis van nieuwe waarden. // Tekenreeksen maken String dataString =""; Tekenreeks cDateTime =""; Tekenreeks cHumTemp =""; Tekenreeks cP =""; dataString +="<"+String(i)+","+String(triggerTransmitAlertIndicator)+","+String(dtLastTrigger,0)+","+String(buttonState)+", "+String(now.month ())+","+String(nu.dag())+","+String(nu.jaar())+", "+String(nu.uur())+","+String(nu .minute())+","+String(nu.second())+", "+String(h)+","+String(t)+","+String(p)+">"; cDateTime +=String(nu.maand())+"/"+String(nu.dag())+"/"+String(nu.jaar())+" "+String(nu.uur())+ ":"+String(nu.minute())+":"+String(nu.seconde()); cHumTemp +="H:"+String(h)+"% T:"+String(t)+"degF"; cP +="P:"+String(p)+"psi"; if (transmitIndicator ==1 || triggerPushTransmitAlertIndicator ==1 || buttonState ==1) { char dataArray [100]; dataString.toCharArray(dataArray, 100); Serial.println(dataArray); flits-LED (10.500); verzendCounter++; } // Serial.print ("T:");// Serial.println (triggerStatus); vertraging (100); // wacht even tot het hele bericht binnen is // picture loop u8g.firstPage(); doen {draw(cDateTime,cHumTemp, cP,i,transmitCounter,now.minute(),transmitFrequency,pTransmitMinute); } while(u8g.nextPage()); vertraging (1000); //writeToSD(dataString); // Optie om op SD-kaart op te slaan in Ethernet Shield voor 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.afdruk(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("Restant:"); u8g.setPrintPos(70,48); u8g.print(DnowMinute % DtransmitFrequency);}float getPressure(){ int sensorVal=analogRead(A2);// Serial.print("Sensorwaarde:");// Serial.print(sensorVal); vlotterspanning =(sensorVal*5.0)/1023.0;// Serial.print ("Volt:"); // Serial.print (spanning); // Wanneer druk =0, analoge ingang =100 // Conversie van analoge ingang naar spanning:analoge ingang =100 -> Spanning =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); vlotterdruk_psi =((m*voltage)+ b);// Serial.print(" Druk =");// Serial.print(druk_psi);// Serial.println(" psi"); // vertraging (200); return pressure_psi;}void flashLED(int num, int t){ for (int z =1; z <=num; z++) {digitalWrite(ledPin, HIGH); vertraging (t); digitalWrite (ledPin, LAAG); vertraging (t); }}// Optie om op SD-kaart op te slaan in Ethernet Shield voor Arduino Uno //void writeToSD(String dataToWrite) //{ // // open het bestand. merk op dat er maar één bestand tegelijk geopend kan zijn, // // dus je moet dit bestand sluiten voordat je een ander opent. // Bestand dataFile =SD.open ("datalog4.txt", FILE_WRITE); // fileSizeSD =dataFile.size(); // Geeft bestandsgrootte weer in bytes // fileSizeSD =fileSizeSD / 1000000; // Converteert bytes naar MB. 1 MB =1e6 bytes // // als het bestand beschikbaar is, schrijf er dan naar:// if (dataFile) // { // dataFile.println(dataToWrite); // dataFile.close(); // // print ook naar de seriële poort:// // Serial.println(dataToWrite); // } // // als het bestand niet geopend is, verschijnt er een foutmelding:// else // { // Serial.println("error opening datalog1.txt"); // } //}
GoogleSheetsScript.jsJavaScript
// Er zijn 2 functies in deze code// doPost-functie - Verzendt gegevens van de Arduino Cloud Webhook. Het wordt uitgevoerd wanneer er nieuwe gegevens zijn op de Arduino Cloud.// sendEmail-functie - Verstuurt e-mails op basis van waarden die zijn geëxtraheerd uit het blad met de naam "Data" in het Google Spreadsheets-bestand voor het project. Het wordt eenmaal per minuut uitgevoerd op basis van de instellingen in de triggerconfiguratie. Raadpleeg voor instructies het sendEmail-functiegedeelte van de projecthub-post.// Het grootste deel van deze code (afgezien van de sendEmail-functie) is gemodelleerd naar het volgende project op de Arduino Project Hub// https://create.arduino. cc/projecthub/Arduino_Genuino/arduino-iot-cloud-google-sheets-integration-71b6bc?f=1// Dit is een link naar een GitHub-repository met het Google-script dat wordt gebruikt voor het bovengenoemde project op de Project Hub. // Deze link is gekopieerd van de beschrijving van het project op de Project Hub.// https://github.com/arduino/arduino-iot-google-sheet-script/blob/master/Code.gs// word actief spreasheetvar ss =SpreadsheetApp.getActiveSpreadsheet();// haal blad met de naam RawDatavar blad =ss.getSheetByName("RawData");var sd =ss.getSheetByName("Data");var sref =ss.getSheetByName("Referenties"); var MAX_ROWS =1440; // max aantal weer te geven gegevensrijen// 3600s / cloud_int(30s) * num_ore(12h) =(60*60*12)/30 =(3600*12)/30 =1440 metingen in 12 uur bij 30 seconden update interval// (60*24)/15 =96 metingen in een periode van 24 uur met een update-interval van 15 minuten// 15 dagen * 96 metingen/dag =1440 metingen// 90 dagen * 96 metingen/dag =8640 metingen// 365 dagen * 96 metingen/dag =35040 metingenvar HEADER_ROW =1; // rij-index van headervar TIMESTAMP_COL =1; // kolomindex van de tijdstempel-kolomfunctie doPost (e) { var cloudData =JSON.parse (e.postData.contents); // dit is een json-object dat alle informatie bevat die afkomstig is van IoT Cloud console.log (cloudData); //var webhook_id =cloudData.webhook_id; // gebruik deze drie echt niet //var device_id =cloudData.device_id; //var thing_id =cloudData.thing_id; var-waarden =cloudData.waarden; // dit is een array van json-objecten console.log(values); // Sla namen en waarden op uit de array met waarden // Elke binnenkomende eigenschap heeft een:// naam die de kolomnamen worden // waarde die in de rijen onder de kolomkop wordt geschreven var incLength =values.length; var incNamen =[]; var incValues ​​=[]; for (var i =0; i  2018) { // verwijder alle berichten die binnenkomen 'late' if (sheet.getRange(HEADER_ROW+1, 1).getValue() !='') { // HEADER_ROW + 1 =Row #2 &Column #1 --> dit is de locatie van de meest recente tijdstempel in het blad // Als de meest recente tijdstempel niet leeg is =(''), vergelijk dan de huidige tijd met de tijdstempel van de binnenkomende gegevens // Als de meest recente tijdstempel leeg is, is dit waarschijnlijk de eerste keer dat het script wordt uitgevoerd. // Sla in dit geval deze if-instructie over en ga verder met schrijven in de kolomkoppen en gegevens. // Het maakt niet uit of de gegevens te laat aankomen (huidige tijd versus tijdstempel van inkomende gegevens). var nu =nieuwe datum(); // nu var COMM_TIME =120; // Opmerking:gewijzigd in 120 om meer berichten door te laten komen, eerder ingesteld op 5 seconden en werkte goed // grove overschatting van de communicatietijd tussen cloud en app als (now.getTime() - date.getTime()> COMM_TIME * 1000) { // Als het verschil tussen de huidige tijd en de tijdstempel groter is dan 5 seconden, gooit u de gegevens weg. // Wanneer de voorwaarde in deze If-instructie waar evalueert, stopt de functie vanwege de return-instructie. opbrengst; // "De return-instructie stopt de uitvoering van een functie en retourneert een waarde van die functie." } } // Deze sectie schrijft waarden naar de koprij op basis van de namen van de binnenkomende eigenschappen // Met andere woorden, deze sectie maakt de kolomnamen // Wijs een naam toe aan de cel in de koprij &in de eerste kolom =tijdstempel blad.getRange(HEADER_ROW, 1).setValue('timestamp'); for (var i =0; i  het is 2 // kolom 1 is de tijdstempelkolom. if (lastCol ==1) { // schrijf de kolomnamen beginnend met de kolom na lastCol ==1, wat de tijdstempelkolom is // incNames is een array met de namen van alle binnenkomende eigenschappen // If lastCol ==1 , write the value from 'i'th location in the incNames array to the header row in column #2 =lastCol + 1 sheet.getRange(HEADER_ROW, lastCol + 1).setValue(incNames[i]); } else { // evaluated if the lastCol !=1 // check if the name is already in header var found =0; for (var col =2; col <=lastCol; col++) { // starting with column 2, iterate through all of the columns up to the lastCol evaluating the if statement enclosed 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; pauze; // "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

Schema's


Productieproces

  1. ADLINK werkt samen met Google Cloud om IoT-klare oplossingen te bieden
  2. Basis IoT – RaspberryPI HDC2010 hoe
  3. BMP180 I2C digitale luchtdruksensor
  4. Python/MicroPython Sensor Logger met Google Spreadsheets
  5. Windows 10 IoT Core op Raspberry Pi 2 – Adafruit-sensorgegevens
  6. Windows 10 IoT Core en SHT15
  7. UnifiedWater v1
  8. IOT - Smart Jar met ESP8266, Arduino en ultrasone sensor
  9. Arduino Cloud Sensor Tower
  10. Arduino Apple Watch
  11. Volledige controle over uw tv met Alexa en Arduino IoT Cloud