147
edits
| Line 62: | Line 62: | ||
| === Programming === | === Programming === | ||
| Code | Code:<syntaxhighlight lang="arduino"> | ||
| /* | |||
|   Project: The Plant Plant - The Air Between Us | |||
|   Intergration and Conversation between 2 isolated plant systems | |||
|   By using Microcontroller, sensors and IoT platform (cloud) | |||
|   -- | |||
|   Board: ESP32 Development Board | |||
|   Component: MQ-2 Gas Sensor | |||
|              DHT22 Temperature & Humidity Sensor | |||
|              Alphanumerisches LCD 16x2, blau | |||
|   -- | |||
|   Note: After the MQ-2 sensor is powered on, it needs to be preheated for  | |||
|   at least 3 minute before stable measurement readings can be obtained.  | |||
|   It is normal for the sensor to generate heat during operation due to  | |||
|   the presence of a heating wire inside. | |||
| - | */ | ||
| //add libraries | |||
| #include <Arduino.h> | |||
| #include <Adafruit_Sensor.h>     // for DHT22 | |||
| #include <DHT.h> | |||
| #include <DHT_U.h>     | |||
| #include <WiFi.h>                // for connecting Wifi    | |||
| #include "esp_wpa2.h"            //wpa2 library for connections to Enterprise networks | |||
| #include <ThingSpeak.h>          // for publishing Sensor Readings to Thingspeak | |||
| #include <Wire.h>                // for getting the LCD Address | |||
| #include <LiquidCrystal_I2C.h>   // for LCD | |||
| /* Set up: DHT22 */ | |||
| #define DHTTYPE DHT22   // sensor version, we are using DHT22 | |||
| #define DHT22_PIN1  15  // Group01 pin GPIO15  | |||
| #define DHT22_PIN2  0   // Group02 pin GPIO0  | |||
| #define DHT22_PIN3  4   // Group03 pin GPIO4 | |||
| //Create sensors called "dht..." | |||
| DHT_Unified dht01(DHT22_PIN1, DHTTYPE);  | |||
| DHT_Unified dht02(DHT22_PIN2, DHTTYPE);  | |||
| DHT_Unified dht03(DHT22_PIN3, DHTTYPE);  | |||
| int delayMS = 1500; // add delay after each reading | |||
| /* Set up: MQ2 */ | |||
| // Define the pin numbers for the Gas Sensor | |||
| #define MQ2_PIN1  34  // Group01 pin GPIO34 | |||
| #define MQ2_PIN2  35  // Group02 pin GPIO35 | |||
| #define MQ2_PIN3  32  // Group03 pin GPIO32 | |||
| /* Set up: Thingspeak */ | |||
| // due to the privacy of the account, won't show the real numbers | |||
| unsigned long ChannelNumber1 = XXXXXXX;     //Insert Thingspeak Channe's number  | |||
| unsigned long ChannelNumber2 = XXXXXXX;     //Insert 2nd Thingspeak Channe's number  | |||
| const char *WriteAPIkey1="XXXXXXXXXXXXXXXX";   // Thingspeak Official Channel API Key | |||
| const char *WriteAPIkey2="XXXXXXXXXXXXXXXX";   // 2nd Thingspeak Official Channel API Key | |||
| /* Set up: Eduroam Wifi */ | |||
| WiFiClient client; | |||
| byte mac[6]; | |||
| const char* host = "arduino.clanweb.eu";     //webserver test | |||
| String url = "/eduroam/data.php";            //URL to target PHP file test | |||
| #define EAP_ANONYMOUS_IDENTITY "meng-yun.tsai@uni-weimar.de" //anonymous@example.com, or you can use also nickname@example.com | |||
| #define EAP_IDENTITY "daro6502" //nickname@example.com,at some organizations should work nickname only without realm, but it is not recommended | |||
| #define EAP_PASSWORD "Tuniman86704_Y" //password for eduroam account | |||
| //SSID NAME | |||
| const char* ssid = "eduroam"; // eduroam SSID | |||
| /* Set up: LCD */ | |||
| // set the LCD number of columns and rows | |||
| int lcdColumns = 16; | |||
| int lcdRows = 2; | |||
| // set LCD address, number of columns and rows | |||
| // if you don't know your display address, run an I2C scanner sketch | |||
| LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);  | |||
| // set up display texts  | |||
| String messageStatic = "Our Dialogue"; | |||
| String messageScrolling; | |||
| // A string variable used to store accumulated ASCII conversations | |||
| String dialogue = "";  | |||
| // for counting letters from Ascii code  | |||
| int charCount = 0;      | |||
| /* Function: Scrolling Texts */ | |||
| // The function acepts the following arguments: | |||
| // row: row number where the text will be displayed | |||
| // message: message to scroll | |||
| // delayTime: delay between each character shifting | |||
| // lcdColumns: number of columns of your LCD | |||
| void scrollingText(int row, String message, int delayTime, int lcdColumns) { | |||
|   for (int i=0; i < lcdColumns; i++) { | |||
|     message = " " + message;   | |||
|   }  | |||
|   message = message + " ";  | |||
|   for (int pos = 0; pos < message.length(); pos++) { | |||
|     lcd.setCursor(0, row); | |||
|     lcd.print(message.substring(pos, pos + lcdColumns)); | |||
|     delay(delayTime); | |||
|   } | |||
| } | |||
| /* Functions: Group01 Flowers */ | |||
| void Group01(){ | |||
|   // Delay between measurements | |||
|   delay(delayMS);    | |||
|   //Reading DHT22 | |||
|   // Get access to sensor event through custom sensor event type | |||
|   sensors_event_t event; | |||
|   // get temperature event (by reference, not by copy) and print its value. | |||
|   // "event" is  - after this - filled with information from the sensor. | |||
|   dht01.temperature().getEvent(&event); | |||
|   if (isnan(event.temperature)) | |||
|   { | |||
|     Serial.println(F("Error reading temperature!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G1 Temperature: ")); | |||
|     Serial.print(event.temperature); | |||
|     Serial.println(F("°C")); | |||
|     ThingSpeak.setField(2, event.temperature); // write to Thingspeak Channel Field 2 | |||
|   } | |||
|   // get humidity event (by reference, not by copy) and print its value. | |||
|   // "event" is  - after this - filled with information from the sensor. | |||
|   dht01.humidity().getEvent(&event); | |||
|   if (isnan(event.relative_humidity)) | |||
|   { | |||
|     Serial.println(F("Error reading humidity!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G1 Humidity: ")); | |||
|     Serial.print(event.relative_humidity); | |||
|     Serial.println(F("%")); | |||
|     ThingSpeak.setField(3, event.relative_humidity); // write to Thingspeak Channel Field 3 | |||
|   } | |||
|   //Reading MQ2  | |||
|   int mq2g1V = analogRead(MQ2_PIN1); | |||
|   Serial.print("G1 MQ2 Analog output: "); | |||
|   Serial.println(mq2g1V); | |||
|   Serial.println(" ------------------ "); | |||
|   delay(1000); | |||
|   ThingSpeak.setField(1, mq2g1V); // write to Thingspeak Channel Field 1 | |||
| } | |||
| /* Functions: Group02 Sundew */ | |||
| void Group02(){ | |||
|   delay(delayMS);    | |||
|   //Reading DHT22 | |||
|   sensors_event_t event; | |||
|   dht02.temperature().getEvent(&event); | |||
|   if (isnan(event.temperature)) | |||
|   { | |||
|     Serial.println(F("Error reading temperature!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G2 Temperature: ")); | |||
|     Serial.print(event.temperature); | |||
|     Serial.println(F("°C")); | |||
|     ThingSpeak.setField(5, event.temperature); // write to Thingspeak Channel Field 5 | |||
|   } | |||
|   dht02.humidity().getEvent(&event); | |||
|   if (isnan(event.relative_humidity)) | |||
|   { | |||
|     Serial.println(F("Error reading humidity!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G2 Humidity: ")); | |||
|     Serial.print(event.relative_humidity); | |||
|     Serial.println(F("%")); | |||
|     ThingSpeak.setField(6, event.relative_humidity); // write to Thingspeak Channel Field 6 | |||
|   } | |||
|   //Reading MQ2  | |||
|   int mq2g2V = analogRead(MQ2_PIN2); | |||
|   Serial.print("G2 MQ2 Analog output: "); | |||
|   Serial.println(mq2g2V); | |||
|   Serial.println(" ------------------ "); | |||
|   delay(1000); | |||
|   ThingSpeak.setField(4, mq2g2V); // write to Thingspeak Channel Field 4 | |||
| } | |||
| /* Functions: Group03 Intergration */ | |||
| void Group03(){ | |||
|   delay(delayMS);    | |||
|   //Reading DHT22 | |||
|   sensors_event_t event; | |||
|   dht03.temperature().getEvent(&event); | |||
|   if (isnan(event.temperature)) | |||
|   { | |||
|     Serial.println(F("Error reading temperature!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G3 Temperature: ")); | |||
|     Serial.print(event.temperature); | |||
|     Serial.println(F("°C")); | |||
|     ThingSpeak.setField(7, event.temperature); // write to Thingspeak Channel Field 7 | |||
|   } | |||
|   dht03.humidity().getEvent(&event); | |||
|   if (isnan(event.relative_humidity)) | |||
|   { | |||
|     Serial.println(F("Error reading humidity!")); | |||
|   } | |||
|   else | |||
|   { | |||
|     Serial.print(F("G3 Humidity: ")); | |||
|     Serial.print(event.relative_humidity); | |||
|     Serial.println(F("%")); | |||
|     Serial.println(" ------------------ "); | |||
|     ThingSpeak.setField(8, event.relative_humidity); // write to Thingspeak Channel Field 8 | |||
|   } | |||
| } | |||
| void Group03_MQ2(){ | |||
|   //Reading MQ2  | |||
|   int mq2g3V = analogRead(MQ2_PIN3); | |||
|   Serial.print("G3 MQ2 Analog output: "); | |||
|   Serial.println(mq2g3V); | |||
|   delay(500); | |||
|   ThingSpeak.writeField(ChannelNumber2, 1, mq2g3V, WriteAPIkey2); | |||
|   // LCD Display   | |||
|   // convert MQ-2's value to ASCII code | |||
|   int ascii_value = map(mq2g3V, 1000, 2500, 34, 126); | |||
|   char ascii_char = (char)ascii_value; | |||
|   // a new character is added to the string (the previous one is kept) | |||
|   dialogue += ascii_char ; | |||
|   charCount++; // a ccumulated character count +1 | |||
|   // Try using spaces to create a variation in sentence length for a more natural dialogue effect. | |||
|   // when the accumulated character count exceeds 7, insert a space randomly | |||
|   if (charCount > 7) { | |||
|     // if the count exceeds 15, force to insert a space  | |||
|     if (random(0, 2) == 1 || charCount >= 15) {  | |||
|       dialogue += " "; | |||
|       charCount = 0; // after inserting a space, reset the count | |||
|     } | |||
|   } | |||
|   // if the string length exceeds the LCD display limit (32 characters) | |||
|   if (dialogue.length() > 32) {  | |||
|     dialogue = dialogue.substring(1); // remove the oldest character | |||
|   }  | |||
|   // print scrolling message | |||
|   lcd.setCursor(0, 1); | |||
|   messageScrolling = dialogue.substring(0, 16); | |||
|   scrollingText(1, messageScrolling, 350, lcdColumns); | |||
| } | |||
| void setup() | |||
| { | |||
|   // initialize serial communication | |||
|   Serial.begin(9600);  | |||
|   // connect or reconnect to wifi | |||
|   WiFi.disconnect(true); //disconnect from WiFi to set new WiFi connection | |||
|   WiFi.mode(WIFI_STA); //init wifi mode | |||
|   // start wifi connection with eduroam | |||
|   // WITHOUT CERTIFICATE - WORKING WITH EXCEPTION ON RADIUS SERVER | |||
|   WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_ANONYMOUS_IDENTITY, EAP_IDENTITY, EAP_PASSWORD);  | |||
|   // check if wifi connected | |||
|   // continue after while loop finished | |||
|   while (WiFi.status() != WL_CONNECTED) { | |||
|     delay(500); | |||
|     Serial.print(F(".")); | |||
|     } | |||
|     Serial.println(""); | |||
|     Serial.println(F("WiFi is connected!")); | |||
|     Serial.println(" "); | |||
|   // initialize DHT22 | |||
|   dht01.begin();  | |||
|   dht02.begin();  | |||
|   dht03.begin();  | |||
|   // initialize ThingSpeak | |||
|   ThingSpeak.begin(client);    | |||
|   // initialize LCD | |||
|   lcd.init(); | |||
|   // turn on LCD backlight                       | |||
|   lcd.backlight();             | |||
| } | |||
| void loop() | |||
| { | |||
|   yield(); // buffer ESP - stuff | |||
| // LCD Display | |||
|   lcd.clear(); | |||
|   // set cursor to position (column and row) | |||
|   lcd.setCursor(2, 0); | |||
|   // print static message | |||
|   lcd.print(messageStatic); | |||
| // Execute functions of 3 groups | |||
|   Group03_MQ2(); | |||
|   Group03(); | |||
|   delay(delayMS); | |||
|   Group01(); | |||
|   delay(delayMS); | |||
|   Group02(); | |||
|   delay(delayMS); | |||
|   // Write to ThingSpeak. | |||
|   int x = ThingSpeak.writeFields(ChannelNumber1, WriteAPIkey1); | |||
|   if(x == 200){ | |||
|      Serial.println("Channel update successful."); | |||
|    }else{ | |||
|      Serial.println("Problem updating channel. HTTP error code " + String(x)); | |||
|    } | |||
|    delay(15000); | |||
| } | |||
| </syntaxhighlight> | |||
| == Winterwerkschau (Exhibition) == | == Winterwerkschau (Exhibition) == | ||
edits