// ---------------------------------------------------------------------------------- // // The White Cube version 1.0 // by Jaakko Muhonen (Robolab Fin) 4.9.2023 // Internet: www.robolab.fi // Arduino MKR1010 Wifi // 1.3" OLED I2C LCD Screen 128x6, Adafruit Si7021 I2C Temperature and Huminidy sensor, Gas Sensor MQ-2 Flying-Fish // // ---------------------------------------------------------------------------------- #include "thingProperties.h" #include #include #include #include #include "Adafruit_Si7021.h" #define SmokeAlarmVal 300 // MQ-2 sensor smoke alarm value 300ppm, same as trimmer value #define TemperatureAlarmVal 16 // Si7021 sensor temperature alarm value <16°C #define HumidityAlarmVal 30 // Si7021 sensor humidity alarm value <30% #define CaseHeat 1.8 // Adjustment of the temperature measurement accuracy due to the heat of the case °C #define MQ2Pin A0 // MQ-2 sensor analog pin #define MQ2LedPin 0 // MQ-2 sensor digital alarm led pin #define SwitchPin 1 // Switch digital pin #define LedPin 2 // Led digital pin // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // On an Arduino MKR1010 WIFI: D11(SDA), D12(SCL) #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C // Datasheet for Address: 0x3D for 128x64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Adafruit Si7021 Temperature Humidity Sensor setup. // The I2C address is 0x40 and it can not be change. SDA is digital pin 20 and SCL is digital pin 21. Adafruit_Si7021 TempHumSensor = Adafruit_Si7021(); unsigned long gShowPrevMillis=0; // Show value multitasking Previous msec unsigned long gShowCurrMillis=0; // Show value multitasking Current msec unsigned int gShowScanInterval=3000; // Show value scan interval msec 3 seconds const byte TEMPERATURE=1; // Show temperature: Lampo const byte HUMIDITY=2; // Show humidity: Kosteus const byte SMOKE=3; // Show smoke: Savu int gValueCount=TEMPERATURE; // Show value counter 1-3 byte gScreenScroll=false; // Screen scroll On/Off byte gShow=false; // Show instant screen values // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- void setup() { Serial.begin(9600); delay(2000); Serial.println(F("White Cube initialization: Start")); Serial.println(F("Connect to Arduino IoT Cloud")); // Defined in thingProperties.h initProperties(); // Connect to Arduino IoT Cloud ArduinoCloud.begin(ArduinoIoTPreferredConnection); setDebugMessageLevel(2); ArduinoCloud.printDebugInfo(); delay(3000); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); while (true); } else Serial.println(F("SSD1306 allocation Ok.")); // OLED LCD 128x64 Screen Clear display.display(); delay(2000); display.clearDisplay(); display.drawPixel(10, 10, SSD1306_WHITE); display.display(); // TPH Temperature Humidity Sensor reset if (!TempHumSensor.begin()) { Serial.println(F("TPH sensor not found")); //while (true); } else Serial.println(F("TPH sensor Ok.")); delay(1000); Serial.println(F("MQ-2 is warming up.")); pinMode(MQ2Pin, INPUT); delay(4000); // Set MQ-2 sensor led off pinMode(MQ2LedPin, OUTPUT); digitalWrite(MQ2LedPin, HIGH); // Set externsal led off pinMode(LedPin, OUTPUT); digitalWrite(LedPin, LOW); // Set MKR1010 internal led off pinMode(SwitchPin, INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); Serial.println(F("White Cube initialization: End")); } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- void loop() { if (digitalRead(SwitchPin)==LOW) { gScreenScroll=!gScreenScroll; gShowCurrMillis=gShowScanInterval; gShow=true; } if (gScreenScroll==true) ShowValuesScroll(); else ShowValuesStable(); digitalWrite(LED_BUILTIN, digitalRead(SwitchPin)); ArduinoCloud.update(); } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- // Temperature, humidity and smoke reading multitasking function. Stable text. // ---------------------------------------------------------------------------------- void ShowValuesStable(void) { float nTemperature=0, nHumidity=0, nSmoke=0; char sText[50]=""; gShowCurrMillis = millis(); // Read and show values in the screen, if the time has elapsed if (gShowCurrMillis-gShowPrevMillis>=gShowScanInterval or gShow==true) { gShowPrevMillis=gShowCurrMillis; display.clearDisplay(); display.setTextSize(2); display.setCursor(0,0); // Read and show temperature. Take into consideration the accuracy reduction due to casing. nTemperature=TempHumSensor.readTemperature()- CaseHeat; temp=nTemperature; // Read the temperature into the cloud variable if (nTemperatureSmokeAlarmVal) { display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); digitalWrite(LedPin, HIGH); smokealarm=true; // Set smokealarm On into the cloud variable } else { display.setTextColor(SSD1306_WHITE); digitalWrite(LedPin, LOW); smokealarm=false; // Set smokealarm Off into the cloud variable } ftoa(nSmoke, sText, 0); display.print(F("Kaas:")); display.println(sText); display.display(); if (gShow==true) { gShow=false; delay(2000); } } } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- // Temperature, humidity and smoke reading multitasking function. Text scrolling. // ---------------------------------------------------------------------------------- void ShowValuesScroll(void) { float nTemperature=0, nHumidity=0, nSmoke=0; char sText[50]=""; gShowCurrMillis = millis(); // Read and show values in the screen, if the time has elapsed if (gShowCurrMillis-gShowPrevMillis>=gShowScanInterval or gShow==true) { gShowPrevMillis=gShowCurrMillis; display.clearDisplay(); display.setTextSize(3); display.setCursor(0,0); switch (gValueCount) { // Read and show temperature. Take into consideration the accuracy reduction due to casing. case TEMPERATURE: nTemperature=TempHumSensor.readTemperature()- CaseHeat; temp=nTemperature; // Read the temperature into the cloud variable if (nTemperatureSmokeAlarmVal) { display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); digitalWrite(LedPin, HIGH); smokealarm=true; // Set smokealarm On into the cloud variable } else { display.setTextColor(SSD1306_WHITE); digitalWrite(LedPin, LOW); smokealarm=false; // Set smokealarm Off into the cloud variable } ftoa(nSmoke, sText, 0); display.println(F("Kaasu ")); display.print(sText); display.display(); gValueCount=1; break; } if (gShow==true) { gShow=false; delay(2000); } } } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- // Convert float to the char // ---------------------------------------------------------------------------------- void ftoa(float n, char *res, int afterpoint) { int ipart = (int)n; float fpart = n - (float)ipart; int i = intToStr(ipart, res, 0); // check for display option after point if (afterpoint != 0) { res[i] = '.'; fpart = fpart * pow(10, afterpoint); intToStr((int)fpart, res + i + 1, afterpoint); } } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- // Converts a given integer x to string str[]. d is the number // of digits required in output. If d is more than the number // of digits in x, then 0s are added at the beginning. // ---------------------------------------------------------------------------------- int intToStr(int x, char str[], int d) { int i = 0; while (x) { str[i++] = (x%10) + '0'; x = x/10; } // If number of digits required is more, then add 0s at the beginning while (i < d) str[i++] = '0'; reverse(str, i); str[i] = '\0'; return(i); } // ---------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------- // Reverses a string 'str' of length 'len' // ---------------------------------------------------------------------------------- void reverse(char *str, int len) { int i=0, j=len-1, temp; while (i