diff --git a/ECU design on Fritzing/ECU-Bombyx.png b/ECU design on Fritzing/ECU-Bombyx.png index 4fbeb52..3d49be4 100644 Binary files a/ECU design on Fritzing/ECU-Bombyx.png and b/ECU design on Fritzing/ECU-Bombyx.png differ diff --git a/Libraries/DHT_sensor_library.zip b/Libraries/DHT_sensor_library.zip new file mode 100644 index 0000000..04850e6 Binary files /dev/null and b/Libraries/DHT_sensor_library.zip differ diff --git a/README.it_IT.md b/README.it_IT.md deleted file mode 100644 index 4054143..0000000 --- a/README.it_IT.md +++ /dev/null @@ -1,27 +0,0 @@ -# Documentazione ECU per Bombyx mori - -![GitHub last commit](https://img.shields.io/github/last-commit/GLWine/ECU-Bombyx?logo=github&style=social) -![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/GLWine/ECU-Bombyx?include_prereleases&style=social) -![GitHub All Releases](https://img.shields.io/github/downloads/GLWine/ECU-Bombyx/total?style=social) - -Tesi sulla progettazione e l'uso dell'unità di controllo ambientale per Bombyx mori. -Scopo: misurare gli sbalzi termici e di umidità per correlare eventuali effetti sul filato ottenuto. -Il progetto si compone di un Arduino, un sensore di umidità e temperatura, un orologio e una scheda SD. -Le letture vengono effettuate ogni 15 minuti luna dall'altra. - -[*Readme*](https://github.com/GLWine/ECU-Bombyx/blob/master/README.md) - - - - - - -
- -# Licenza [![GitHub license](https://img.shields.io/github/license/GLWine/ECU-Bombyx)](https://github.com/GLWine/ECU-Bombyx/blob/master/LICENSE.md) - -Questo programma è un software gratuito: puoi ridistribuirlo e/o modificarlo secondo i termini della GNU General Public License come pubblicato dalla Free Software Foundation, sia la versione 3 della Licenza, sia (a tua scelta) qualsiasi versione successiva. - -Questo programma è distribuito nella speranza che possa essere utile, ma SENZA ALCUNA GARANZIA; senza nemmeno la garanzia implicita di COMMERCIABILITÀ o IDONEITÀ PER UNO SCOPO PARTICOLARE. Vedi la GNU General Public License per maggiori dettagli. - -Dovresti aver ricevuto una copia della GNU General Public License insieme a questo programma. In caso contrario, consultare . diff --git a/README.md b/README.md index 6b819de..edd7751 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,11 @@ ![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/GLWine/ECU-Bombyx?include_prereleases&style=social) ![GitHub All Releases](https://img.shields.io/github/downloads/GLWine/ECU-Bombyx/total?style=social) -Thesis on the design and use of the environmental control unit for Bombyx mori. -Purpose: to measure changes in temperature and humidity to correlate any effects on the yarn obtained. -The project consists of an Arduino, a humidity and temperature sensor, a clock and an SD card. -Readings are taken every 15 minutes on the other moon. +Thesis project on the effects of climate and gases in companies that produce silk. Use of an Arduino system called ECU-Bombyx (Environmental control unit - Bombyx Mori). -[*Leggimi*](https://github.com/GLWine/ECU-Bombyx/blob/master/README.it_IT.md) +Purpose: to measure changes in temperature, humidity, eCO2 and total volatile organic compounds (TVOC) to correlate any effects on the yarn obtained. +The project consists of an Arduino, a humidity and temperature sensor, a clock module, an SD card shield and an SGP30 sensor for air quality. +Every 15 minutes The ECU-BM performs a reading that it saves in the SD. @@ -18,6 +17,55 @@ Readings are taken every 15 minutes on the other moon.
+# Installation guide + +## Phase 1: *wiring* +Before installing and starting make sure of the presence of these modules: +- DHT 22 sensor (temperature and humidity); +- Micro-SD module; +- RTC DS1302 module (clock); +- SGP30 air quality sensor; +- Arduino module one turn. 3; +Strictly carry out the wiring as indicated in the ECU-Bombyx image. + +## Phase 2: *software installation* +Step 0: install the necessary libraries. + +Step 1: install the ECU-Bombyx-Setter file from the Arduino IDE. In the "Serial monitor" view, make sure all modules respond. + +--- Skip if the previous one is successful --- + +Step 2: carefully check the wiring and that the modules are actually working. + +Step 3: install the ECU-Bombyx-Base-Line file from the Arduino IDE. This is to find the baseline for the SGP30 sensor. Based on the [manufacturer's information](https://github.com/adafruit/DHT-sensor-library/pull/138 "Baseline Set & Get"), I created the code. This passage is of fundamental importance. The procedure lasts 12, it must be done for each SGP30 you have. + +Step 4: install the ECU-Bombyx-Main file from the Arduino IDE. In the "Serial monitor" view, make sure that all modules respond and complete operations. + +Final notes: +1. will start reading every 15 minutes writing in the micro-SD. The save format is .cvs with the company name. +2. If the DHT 22 module does not mount a 4K7 Ohm resistor, it is essential to solder one between DAT and VDD. +3. (optional) Add a 100nF capacitor between VDD and GND for filtering the waves. +3. There is a voluntary error in the ECU-BOMBYX-Main code. The reason is to remind those who use the code to set the variable that gives the name the file with the readings. + +# Libraries + +I made some changes to it based on this libbrerie of DHT [Pull requests #138](https://github.com/adafruit/DHT-sensor-library/pull/138 "Fixed signed/unsigned and unused parameter warnings") + +The library to be imported with the correction is in the zip, it is sufficient to decompress it in the folder ..\Documents\Arduino\libraries\. + +## Libraries List + +Here are the lepers used for the code: + +- Adafruit SGP30 Air Quality Sensor Breakout + - Adafruit SGP30 Sensor by Adafruit V.1.2.0 +- DS1302: Trickle-Charge Timekeeping Chip + - RTC by Makuna V.2.3.4 +- DHT22 temperature-humidity sensor + extras + - DHT sensor librery by Adafruit V.1.3.9 **_modified_** + +I recommend installing all the dependencies that arduino IDE offers + # License [![GitHub license](https://img.shields.io/github/license/GLWine/ECU-Bombyx)](https://github.com/GLWine/ECU-Bombyx/blob/master/LICENSE.md) This program is free software: you can redistribute it and/or modify diff --git a/Sketch ECU/ECU-Bombyx-Base-Line/ECU-Bombyx-Base-Line.ino b/Sketch ECU/ECU-Bombyx-Base-Line/ECU-Bombyx-Base-Line.ino new file mode 100644 index 0000000..ba80df3 --- /dev/null +++ b/Sketch ECU/ECU-Bombyx-Base-Line/ECU-Bombyx-Base-Line.ino @@ -0,0 +1,235 @@ +/* The following code is used to set the starting baseline for the SGP30 module. + * The calibration process lasts 12 hours, every 30 minutes from a partial response. + * At the end he writes in the SD the two found values of the eCO2 and of the TVOC. + * + * modified 17 May 2020 by Giampiero Leserri + */ + +#include +#include +#include +#include +#include + +// set up variables using the DHT 22: +#define DHTPIN 2 //Pin select DHT +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +DHT dht(DHTPIN, DHTTYPE); // Declare the DHT data pin and model to the DHT library + +// set up variables using the SGP30: +Adafruit_SGP30 sgp; +uint16_t TVOC_base, eCO2_base; +/* return absolute humidity [mg/m^3] with approximation formula +* @param temperature [°C] +* @param humidity [%RH] +*/ +uint32_t getAbsoluteHumidity(float temperature, float humidity) +{ + // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15 + const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3] + const uint32_t absoluteHumidityScaled = static_cast(1000.0f * absoluteHumidity); // [mg/m^3] + return absoluteHumidityScaled; +} + +// set up variables using the SD utility library functions: +#define chipSelect 4 // declare the pin that is connected to the chip select +// the myFile object is created for the SD +File myFilex; +File myFiley; + +// +const unsigned long timeL = 44100000; //12 hour +static unsigned long timeS1 = 60000; // 1 minute +static unsigned long timeS2 = 1800000; //30 minute + +//const unsigned long timeL = 600000; //10 minute +//static unsigned long timeS1 = 60000; // 1 minute +//static unsigned long timeS2 = 300000; //5 minute + +void setup() +{ + Serial.begin(9600); + + Serial.print(F("Initializing SD card...")); + + if (!SD.begin(4)) + { + Serial.println(F("initialization failed!")); + while (1) + ; + } + + dht.begin(); + + Serial.println(F("initialization done.")); + + Serial.println(F("SGP30 test")); + + if (!sgp.begin()) + { + Serial.println(F("Sensor not found :(")); + while (1) + ; + } + Serial.print(F("Found SGP30 serial #")); + Serial.print(sgp.serialnumber[0], HEX); + Serial.print(sgp.serialnumber[1], HEX); + Serial.println(sgp.serialnumber[2], HEX); + Serial.println(F("Calibration start... (duration 12h)\n******************************")); + + // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate' + //sgp.setIAQBaseline(0x8E68, 0x8F41); // Will vary for each sensor! + myFilex = SD.open("Cali.csv", FILE_WRITE); + + // if the file is available, write to it: + if (myFilex) + { + myFilex.println(F("eCO2;TVOC")); + myFilex.close(); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening Cali.csv")); + } +} +// creo una varibile per far andare l'if in basso alla riga 138 +int i = 0; + +void loop() +{ + // make a string for assembling the data to log: + String dataString = ""; + + if (millis() < timeL) + { + // If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals + float temperature = dht.readTemperature(); // [°C] + float humidity = dht.readHumidity(); // [%RH] + sgp.setHumidity(getAbsoluteHumidity(temperature, humidity)); + + if (!sgp.IAQmeasure()) + { + Serial.println(F("Measurement failed")); + } + //Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t"); + //Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm"); + + if (!sgp.IAQmeasureRaw()) + { + Serial.println(F("Raw Measurement failed")); + } + //Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t"); + //Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println(""); + + delay(2000); + + if (millis() > timeS1) + { + Serial.print(F(".")); + timeS1 += 60000; + } + + if (millis() >= timeS2) + { + timeS2 += 1800000; //30 minute + //timeS2 += 300000; // 5 minute + + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) + { + Serial.println(F("Failed to get baseline readings")); + } + Serial.println(F("\n30 minutes have passed!")); + dataString = (F("0x")); + dataString += String(eCO2_base, HEX); + dataString += (F(";")); + dataString += (F("0x")); + dataString += String(TVOC_base, HEX); + + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + myFilex = SD.open("Cali.csv", FILE_WRITE); + + // if the file is available, write to it: + if (myFilex) + { + myFilex.println(dataString); + myFilex.close(); + // print to the serial port too: + Serial.println(dataString); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening BLP1")); + } + } + } + else + { + if (i < 1) + { + + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) + { + Serial.println(F("Failed to get baseline readings")); + } + Serial.println(F("\n\n\nProcess terminated!!!")); + Serial.print(F("****Baseline values: eCO2: 0x")); + Serial.print(eCO2_base, HEX); + Serial.print(F(" & TVOC: 0x")); + Serial.println(TVOC_base, HEX); + + // delete the file: + Serial.println(F("Removing old ECO2 and TVOC...")); + SD.remove("ECO2.TXT"); + SD.remove("TVOC.TXT"); + + dataString = (F("0x")); + dataString += String(eCO2_base, HEX); + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + myFilex = SD.open("ECO2.TXT", FILE_WRITE); + + // if the file is available, write to it: + if (myFilex) + { + myFilex.println(dataString); + myFilex.close(); + // print to the serial port too: + Serial.println(dataString); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening eCO2")); + } + + dataString = (F("0x")); + dataString += String(TVOC_base, HEX); + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + myFiley = SD.open("TVOC.TXT", FILE_WRITE); + + // if the file is available, write to it: + if (myFiley) + { + myFiley.println(dataString); + myFiley.close(); + // print to the serial port too: + Serial.println(dataString); + Serial.println(); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening TVOC")); + } + i = 2; + } + } +} +/* Sketch uses 20316 bytes (62%) of program storage space. Maximum is 32256 bytes. + * Global variables use 1171 bytes (57%) of dynamic memory, + * leaving 877 bytes for local variables. Maximum is 2048 bytes. + */ \ No newline at end of file diff --git a/Sketch ECU/ECU-Bombyx-Main/ECU-Bombyx-Main.ino b/Sketch ECU/ECU-Bombyx-Main/ECU-Bombyx-Main.ino index beb4ba9..0802dc7 100644 --- a/Sketch ECU/ECU-Bombyx-Main/ECU-Bombyx-Main.ino +++ b/Sketch ECU/ECU-Bombyx-Main/ECU-Bombyx-Main.ino @@ -1,158 +1,347 @@ -/* The following code is used to set the different components - * and to check that everyone answers the call, leaving the - * answer on the serial monitor. +/* The following code is used to set the various components and to verify that + * everyone answers the call. It is written on the right serial monitor. + * The data are conveyed into a single variable then written into the SD. + * + * modified 17 May 2020 by Giampiero Leserri */ // ADD the following Arduino libraries: -#include -#include -#include // RTC: RTClib by adafruit V.1.5.0 -#include /*DHT: DHT sensor librery by Adafruit V.1.3.8 - * Adafruit Unified Sensor by Adafruit V.1.1.2 - * Adafruit ADXL343 by Adafruit V.1.2.0 - */ +#include // standard Arduino library +#include // standard Arduino library +#include // standard Arduino library +#include //Adafruit SGP30 Sensor by Adafruit V1.2.0 +#include // RTC: RTC by Makuna V.2.3.4 +#include // RTC: RTC by Makuna V.2.3.4 +#include /* DHT: DHT sensor librery by Adafruit V.1.3.9 + * Adafruit Unified Sensor by Adafruit V.1.1.2 + * Adafruit ADXL343 by Adafruit V.1.2.0 + */ // set up variables using the DHT 22: -#define DHTPIN 2 //Pin select DHT -#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +#define DHTPIN 2 //Pin select DHT +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 DHT dht(DHTPIN, DHTTYPE); // Declare the DHT data pin and model to the DHT library // set up variables using the SD utility library functions: -#define chipSelect 8 // declare the pin that is connected to the chip select - -// set up variables using the DS3231 RTC: -RTC_DS3231 rtc; // declaration of the "rtc" object to the class RTC_DS3231 - -// declaration of the Global variables make a string for assembling the data to log -static String dataOnTtheRow = "000000000000000000000000000000"; -// Enter the initial company name without spaces followed -// by a progressive number for each ECU installed, -// also entering ".csv" (maximum 12 characters) -// Ex. Seta Etica ECU 1 => "SE01.csv" -static String company = ""; //fill in here +#define chipSelect 4 // declare the pin that is connected to the chip select +File myFile; // the myFile object is created for the SD + +// set up variables using the DS1302 RTC: +ThreeWire myWire(15, 16, 14); // DAT->pin A1, CLK->pin A2, RS->pin A0 +RtcDS1302 Rtc(myWire); +#define countof(a) (sizeof(a) / sizeof(a[0])) + +// set up variables using the sgp30: +Adafruit_SGP30 sgp; +uint16_t TVOC_base, eCO2_base; +float temperature = 0; // [°C] +float humidity = 0; // [%RH] +uint32_t getAbsoluteHumidity(float temperature, float humidity) +{ + // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15 + const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3] + const uint32_t absoluteHumidityScaled = static_cast(1000.0f * absoluteHumidity); // [mg/m^3] + return absoluteHumidityScaled; +} + +// declaration of the Global variables make a string +// for assembling the data to log +String dataOnTtheRow = ""; + +// Enter the initial company name without spaces followed by a progressive number +// for each ECU installed, also entering ".csv" (maximum 6.3 characters) +// Ex. Seta Etica ECU 1 => "SeEt01.csv" +const String company = "xxxxxx.csv"!; // this error allows you not to forget to set the company name + // variable to which the 15 minutes to take the readings are added -static unsigned long pouse = (15*60*1000); +uint32_t pouse = 0; +// Variable content in the if on line xxx, +// this causes every 4 readings to set the new baseline +int8_t c = 0; //********************************************************************************* -void setup() { +void setup() +{ // Open serial communications and wait for port to open: Serial.begin(9600); // 9600 bps serial port setting - delay(2000); - + delay(500); + rtcSet(); sdSet(); DHTSet(); + sgp30Set(); } -void loop() { +void loop() +{ // If 15 minutes of use have passed a reading - if(millis()>pouse){ - pouse+=(15*60*1000); // Further increase of 15 the pause value + if (millis() > pouse) + { + // Further increase of 15 the pauseMain value, causes overflow + pouse += (15UL * 60UL * 1000UL); + heatingSgp30(); + delay(2000); // Safety delay in case of DHT reset rtcMain(); DHTMain(); + sgp30Main(); sdMain(); - } + c += 1; + } } //--------------------------------------------------------------------------------- // Group of functions for setting the modules //********************************************************************************* -// The function takes care of starting and if necessary -// setting the date and time of the DS3231 -void rtcSet(){ - if (! rtc.begin()) { - Serial.println(F("Couldn't find RTC")); - while (1); +// The function takes care of starting and if necessary +// setting the date and time of the DS1302 +void rtcSet() +{ + Rtc.Begin(); + Serial.println(F("RTC initialized!")); + + if (Rtc.GetIsWriteProtected()) + { + // Serial.println(F("RTC was write protected, enabling writing now")); + Rtc.SetIsWriteProtected(false); + } + + if (!Rtc.GetIsRunning()) + { + // Serial.println(F("RTC was not actively running, starting now")); + Rtc.SetIsRunning(true); } } // The function takes care of starting the SD module and, if necessary, // creating a "CSV" file with the current date -void sdSet(){ +void sdSet() +{ Serial.print(F("Initializing SD card...")); // See if the card is present and can be initialized: - if (!SD.begin(chipSelect)) { + if (!SD.begin(chipSelect)) + { Serial.println(F("Card failed, or not present")); - // don't do anything more: - while (1); } Serial.println(F("card initialized.")); - -// Check if there is a file with the name given by the variable "company", -// otherwise it creates and initializes it - if(! SD.exists(company)){ - File dataFile = SD.open(company, FILE_WRITE); - dataFile.println(F("Data & Time;C-Temp;%-Humid")); - dataFile.close(); + + // Check if there is a file with the name given by the variable "company", + // otherwise it creates and initializes it + if (!SD.exists(company)) + { + myFile = SD.open(company, FILE_WRITE); + myFile.println(F("Data & Time;C-Temp;%-Humid;ppm-eCO2;ppb-TVOC;")); + myFile.close(); Serial.print(company); Serial.println(F(" file created")); } } // initialazied DHT22 -void DHTSet(){ -dht.begin(); -Serial.println(F("DHT22 initialized")); +void DHTSet() +{ + dht.begin(); + Serial.println(F("DHT22 initialized!")); +} + +void sgp30Set() +{ + if (!sgp.begin()) + { + Serial.println(F("Sensor not found :(")); + } + else + { + Serial.println(F("SGP30 initialized!")); + } + Serial.print(F("Found SGP30 serial #")); + Serial.print(sgp.serialnumber[0], HEX); + Serial.print(sgp.serialnumber[1], HEX); + Serial.println(sgp.serialnumber[2], HEX); + + // open the ECO2.TXT for reading: + myFile = SD.open("eCO2.txt"); + if (myFile) + { + Serial.println(F("\neCO2.txt read... ")); + + // read from the file until there's nothing else in it: + while (myFile.available()) + { + dataOnTtheRow = myFile.readStringUntil('\n'); + dataOnTtheRow.replace("\n", ""); + // goes to convert the string hexadecimal into a integer + eCO2_base = strtoul(dataOnTtheRow.c_str(), NULL, 16); + Serial.println(F("Print eCO2_base")); + Serial.println(eCO2_base, HEX); + } + // close the file: + myFile.close(); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening ECO2.TXT")); + } + + // open the TVOC.TXT for reading: + myFile = SD.open("TVOC.txt"); + if (myFile) + { + Serial.println(F("TVOC.TXT read... ")); + + // read from the file until there's nothing else in it: + while (myFile.available()) + { + dataOnTtheRow = myFile.readStringUntil('\n'); + dataOnTtheRow.replace("\n", ""); + // goes to convert the string hexadecimal into a integer + TVOC_base = strtoul(dataOnTtheRow.c_str(), NULL, 16); + Serial.println(TVOC_base, HEX); + } + + // close the file: + myFile.close(); + } + else + { + // if the file didn't open, print an error: + Serial.println(F("error opening TVOC.TXT")); + } + + // it sets the baseline calculated in 12 hours + if (!sgp.setIAQBaseline(eCO2_base, TVOC_base)) + { + Serial.println(F("the baseline was not written!")); + } } //--------------------------------------------------------------------------------- // Group of functions for utilized the modules //********************************************************************************* +// The function takes care of heating the sgp30 module +void heatingSgp30() +{ + humidity = dht.readHumidity(); + temperature = dht.readTemperature(); + sgp.setHumidity(getAbsoluteHumidity(temperature, humidity)); + for (int i = 0; i <= 30; i++) + { + sgp.IAQmeasure(); + delay(1000); + } + // Notice of end of heating + Serial.println(F("heating finished")); + + if (c == 4) + { + sgp.getIAQBaseline(&eCO2_base, &TVOC_base); + sgp.setIAQBaseline(eCO2_base, TVOC_base); + c = 0; + } +} + // The function starts writing in the string that forms the first line -void rtcMain(){ - // I create a DateTime object and call it now +void rtcMain() +{ + // I create a DateTime object and call it now // and pass it the constructor rtc.now(); - DateTime now = rtc.now(); - // I create a char variable to which I pass the scheme - // with which to create the date and time - char buf[] = "YY/MM/DD-hh:mm"; - // dnow.toString () function converts buf and - // passes the date to the variable "dataOnTtheRow" - dataOnTtheRow =(now.toString(buf)); - dataOnTtheRow +=(";"); + RtcDateTime now = Rtc.GetDateTime(); + printDateTime(now); + + if (!now.IsValid()) + { + Serial.println(); + // Common Causes: + // the battery on the device is low or even missing and + // the power line was disconnected + Serial.println(F("RTC lost confidence in the DateTime!")); + } +} + +// The function converts and writes the time to the dataOnTtheRow variable +void printDateTime(const RtcDateTime &dt) +{ + char datestring[20]; + + snprintf_P(datestring, + countof(datestring), + PSTR("%04u/%02u/%02u %02u:%02u"), + dt.Year(), + dt.Month(), + dt.Day(), + dt.Hour(), + dt.Minute()); + dataOnTtheRow = String(datestring); + dataOnTtheRow += (F(";")); } // Function for reading humidity and temperature -void DHTMain(){ +void DHTMain() +{ // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); - + // Writing of the values read in the two variables - if (isnan(h) || isnan(t)) { + if (isnan(h) || isnan(t)) + { Serial.println(F("Failed to read from DHT sensor!")); - return; } // Passing data to the variable that will write to the SD - dataOnTtheRow +=(t); - dataOnTtheRow +=(";"); - dataOnTtheRow +=(h); - dataOnTtheRow +=(";"); + dataOnTtheRow += (t); + dataOnTtheRow += (F(";")); + dataOnTtheRow += (h); + dataOnTtheRow += (F(";")); +} + +void sgp30Main() +{ + c = c + 1; + delay(2000); + // If you have a temperature / humidity sensor, you can set the absolute + // humidity to enable the humditiy compensation for the air quality signals + humidity = dht.readHumidity(); + temperature = dht.readTemperature(); + sgp.setHumidity(getAbsoluteHumidity(temperature, humidity)); + if (!sgp.IAQmeasure()) + { + dataOnTtheRow += (F("sgp not read; sgp not read;")); + } + else + { + dataOnTtheRow += (sgp.eCO2); + dataOnTtheRow += (F(";")); + dataOnTtheRow += (sgp.TVOC); + dataOnTtheRow += (F(";")); + } } // Function that writes the data collected in the SD -void sdMain(){ +void sdMain() +{ // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. - File dataFile = SD.open(company, FILE_WRITE); + myFile = SD.open(company, FILE_WRITE); // if the file is available, write to it: - if (dataFile) { - dataFile.println(dataOnTtheRow); - dataFile.close(); - } - // if the file isn't open, pop up an error: - else { - Serial.println(F("error opening datalog file")); + if (myFile) + { + myFile.println(dataOnTtheRow); + myFile.close(); + Serial.println(F("String:")); + Serial.println(dataOnTtheRow); + Serial.print(company); + Serial.println(F(" update!\n")); } - Serial.print(company); - Serial.println(F(" update")); } -//--------------------------------------------------------------------------------- \ No newline at end of file +//--------------------------------------------------------------------------------- +//Sketch uses 25922 bytes (80%) of program storage space. Maximum is 32256 bytes. +//Global variables use 1164 bytes (56%) of dynamic memory, +//leaving 884 bytes for local variables. Maximum is 2048 bytes. diff --git a/Sketch ECU/ECU-Bombyx-Setter/ECU-Bombyx-Setter.ino b/Sketch ECU/ECU-Bombyx-Setter/ECU-Bombyx-Setter.ino index 9815cb0..8d6aea2 100644 --- a/Sketch ECU/ECU-Bombyx-Setter/ECU-Bombyx-Setter.ino +++ b/Sketch ECU/ECU-Bombyx-Setter/ECU-Bombyx-Setter.ino @@ -1,54 +1,76 @@ -/* The following code is used to set the different components - * and to check that everyone answers the call, leaving the - * answer on the serial monitor. +/* The following code is used to check that all installed modules respond, + * and to set the modules (ex. RTC DS1302). + * + * modified 17 May 2020 by Giampiero Leserri */ // ADD the following Arduino libraries: -#include -#include -#include // RTC: RTClib by adafruit V.1.5.0 -#include /*DHT: DHT sensor librery by Adafruit V.1.3.8 - * Adafruit Unified Sensor by Adafruit V.1.1.2 - * Adafruit ADXL343 by Adafruit V.1.2.0 - */ - +#include // standard Arduino library +#include // standard Arduino library +#include // standard Arduino library +#include // SGP30: Adafruit SGP30 Sensor by Adafruit V1.2.0 +#include // RTC: RTC by Makuna V.2.3.4 +#include // RTC: RTC by Makuna V.2.3.4 +#include /* DHT: DHT sensor librery by Adafruit V.1.3.9 + * Adafruit Unified Sensor by Adafruit V.1.1.2 + * Adafruit ADXL343 by Adafruit V.1.2.0 + */ + // set up variables using the DHT 22: -#define DHTPIN 2 //Pin select DHT -#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 +#define DHTPIN 2 //Pin select DHT +#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 DHT dht(DHTPIN, DHTTYPE); // Declare the DHT data pin and model to the DHT library // set up variables using the SD utility library functions: -#define chipSelect 8 // declare the pin that is connected to the chip select -Sd2Card card; // standard declaration for microSD operation -SdVolume volume; // standard declaration for microSD operation -SdFile root; // standard declaration for microSD operation +#define chipSelect 4 // declare the pin that is connected to the chip select +Sd2Card card; // standard declaration for microSD operation +SdVolume volume; // standard declaration for microSD operation +SdFile root; // standard declaration for microSD operation -// set up variables using the DS3231 RTC: -RTC_DS3231 rtc; // declaration of the "rtc" object to the class RTC_DS3231 +// set up variables using the DS1302 RTC: +ThreeWire myWire(15, 16, 14); // DAT->pin A1, CLK->pin A2, RS->pin A0 +RtcDS1302 Rtc(myWire); +#define countof(a) (sizeof(a) / sizeof(a[0])) -// array declaration for the days of the week -const char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; +// set up variables using the SGP30: +Adafruit_SGP30 sgp; +uint16_t TVOC_base, eCO2_base; -void setup() { +void setup() +{ // Open serial communications and wait for port to open: Serial.begin(9600); // 9600 bps serial port setting - delay(2000); + while (!Serial) + { + ; // wait for serial port to connect. Needed for native USB port only + } + + // notice in the serial monitor that the code is about to start + Serial.println(F("Start initialization of installed components\n...............................................................\n")); + + delay(500); dhtMain(); // Start the function that contains what DHT should do - delay(2000); + delay(500); sdMain(); // Start the function that contains what the microSD must do - delay(2000); // Start the function that contains what the real-time clock should do - rtc3231(); - Serial.println(F("Setup Complete")); // warn in the serial monitor that the code has ended + delay(500); + rtc1302Set(); // Start the function that contains what the real-time clock should do + delay(500); + sgp30Set(); // Start the function that checks that the SGP30 sensor works and is well connected + + // warn in the serial monitor that the code has ended + Serial.println(F("\n\nSetup Complete!!!\n...............................................................")); } -void loop() { -// no use of the loop since they only need to be set once +void loop() +{ + // no use of the loop since they only need to be set once } // Function that realizes the presence and activity of DHT -void dhtMain(){ - Serial.println(F("DHTxx test!")); // warns that DHT will be tested - dht.begin(); // standard declaration +void dhtMain() +{ + Serial.println(F("DHT22 initializing...")); // warns that DHT will be tested + dht.begin(); // standard declaration // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) @@ -57,7 +79,8 @@ void dhtMain(){ float t = dht.readTemperature(); // Check if any reads failed and exit early (to try again). - if (isnan(h) || isnan(t)) { + if (isnan(h) || isnan(t)) + { Serial.println(F("Failed to read from DHT sensor!")); return; } @@ -67,46 +90,54 @@ void dhtMain(){ Serial.print(h); Serial.print(F("% Temperature: ")); Serial.print(t); - Serial.println(F("°C \n")); + Serial.println(F("°C")); } // Function that realizes the presence and activity of the SD -void sdMain(){ - Serial.print(F("\nInitializing SD card...")); +void sdMain() +{ + Serial.print(F("\n\nInitializing SD card...")); // we'll use the initialization code from the utility libraries // since we're just testing if the card is working! - if (!card.init(SPI_HALF_SPEED, chipSelect)) { + if (!card.init(SPI_HALF_SPEED, chipSelect)) + { Serial.println(F("initialization failed. Things to check:")); Serial.println(F("* is a card inserted?")); Serial.println(F("* is your wiring correct?")); Serial.println(F("* did you change the chipSelect pin to match your shield or module?")); - while (1); - } else { - Serial.println("Wiring is correct and a card is present."); + while (1) + ; + } + else + { + Serial.println(F("Wiring is correct and a card is present.")); } // print the type of card Serial.println(); Serial.print(F("Card type: ")); - switch (card.type()) { - case SD_CARD_TYPE_SD1: - Serial.println(F("SD1")); - break; - case SD_CARD_TYPE_SD2: - Serial.println(F("SD2")); - break; - case SD_CARD_TYPE_SDHC: - Serial.println(F("SDHC")); - break; - default: - Serial.println(F("Unknown")); + switch (card.type()) + { + case SD_CARD_TYPE_SD1: + Serial.println(F("SD1")); + break; + case SD_CARD_TYPE_SD2: + Serial.println(F("SD2")); + break; + case SD_CARD_TYPE_SDHC: + Serial.println(F("SDHC")); + break; + default: + Serial.println(F("Unknown")); } // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 - if (!volume.init(card)) { + if (!volume.init(card)) + { Serial.println(F("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card")); - while (1); + while (1) + ; } Serial.print(F("Clusters: ")); @@ -123,9 +154,9 @@ void sdMain(){ Serial.print(F("Volume type is: FAT")); Serial.println(volume.fatType(), DEC); - volumesize = volume.blocksPerCluster(); // clusters are collections of blocks - volumesize *= volume.clusterCount(); // we'll have a lot of clusters - volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB) + volumesize = volume.blocksPerCluster(); // clusters are collections of blocks + volumesize *= volume.clusterCount(); // we'll have a lot of clusters + volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB) Serial.print(F("Volume size (Kb): ")); Serial.println(volumesize); Serial.print(F("Volume size (Mb): ")); @@ -142,51 +173,131 @@ void sdMain(){ } // Function that realizes the presence and activity of the RTC -void rtc3231(){ +void rtc1302Set() +{ + Rtc.Begin(); + Serial.println(F("\n\nDS1302 initializing...")); + RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); + + if (!Rtc.IsDateTimeValid()) + { + // Common Causes: + // 1) first time you ran and the device wasn't running yet + // 2) the battery on the device is low or even missing + + Serial.println(F("RTC lost confidence in the DateTime!")); + Rtc.SetDateTime(compiled); + } + + if (Rtc.GetIsWriteProtected()) + { + Serial.println(F("RTC was write protected, enabling writing now")); + Rtc.SetIsWriteProtected(false); + } + + if (!Rtc.GetIsRunning()) + { + Serial.println(F("RTC was not actively running, starting now")); + Rtc.SetIsRunning(true); + } + + RtcDateTime now = Rtc.GetDateTime(); + if (now < compiled) + { + Serial.println(F("RTC is older than compile time! (Updating DateTime)")); + Rtc.SetDateTime(compiled); + } + else if (now > compiled) + { + Serial.println(F("RTC is newer than compile time. (this is expected)")); + } + else if (now == compiled) + { + Serial.println(F("RTC is the same as compile time! (not expected but all is fine)")); + } + + // + now = Rtc.GetDateTime(); + + printDateTime(now); Serial.println(); - if (! rtc.begin()) { - Serial.println(F("Couldn't find RTC")); - while (1); - } - - if (rtc.lostPower()) { - Serial.println(F("RTC lost power, lets set the time!")); - // If the RTC have lost power it will sets the RTC to the date & time this sketch was compiled in the following line - rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); - // This line sets the RTC with an explicit date & time, for example to set - // January 21, 2014 at 3am you would call: - // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); - Serial.println(); - } - - // show the date, the day of the week and the current time on the screen - DateTime now = rtc.now(); - - Serial.print(now.year(), DEC); - Serial.print('/'); - Serial.print(now.month(), DEC); - Serial.print('/'); - Serial.print(now.day(), DEC); - Serial.print(F(" (")); - Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); - Serial.print(F(") ")); - Serial.print(now.hour(), DEC); - Serial.print(':'); - Serial.print(now.minute(), DEC); - Serial.print(':'); - Serial.print(now.second(), DEC); - Serial.println(); - - Serial.print(F(" since midnight 1/1/1970 = ")); - Serial.print(now.unixtime()); - Serial.print(F("s = ")); - Serial.print(now.unixtime() / 86400L); - Serial.println(F("d")); - - // expresses the temperature read by the RTC - Serial.print(F("Temperature: ")); - Serial.print(rtc.getTemperature()); - Serial.println(F(" C")); - - Serial.println(); + + if (!now.IsValid()) + { + // Common Causes: + // 1) the battery on the device is low or even missing and the power line was disconnected + Serial.println(F("RTC lost confidence in the DateTime!")); + } + + delay(10000); // ten seconds +} + +void printDateTime(const RtcDateTime &dt) +{ + char datestring[20]; + + snprintf_P(datestring, + countof(datestring), + PSTR("%02u/%02u/%04u %02u:%02u:%02u"), + dt.Month(), + dt.Day(), + dt.Year(), + dt.Hour(), + dt.Minute(), + dt.Second()); + Serial.print(datestring); +} + +void sgp30Set() +{ + Serial.println(F("\n\nSGP30 initializing...")); + if (!sgp.begin()) + { + Serial.println(F("SGP30 Sensor not found :(")); + while (1) + ; + } + + Serial.print(F("Found SGP30 serial #")); + Serial.print(sgp.serialnumber[0], HEX); + Serial.print(sgp.serialnumber[1], HEX); + Serial.println(sgp.serialnumber[2], HEX); + + // + if (!sgp.IAQmeasure()) + { + Serial.println(F("Measurement failed")); + return; + } + Serial.print(F("TVOC ")); + Serial.print(sgp.TVOC); + Serial.print(F(" ppb\t")); + Serial.print(F("eCO2 ")); + Serial.print(sgp.eCO2); + Serial.println(F(" ppm")); + + if (!sgp.IAQmeasureRaw()) + { + Serial.println(F("Raw Measurement failed")); + return; + } + Serial.print(F("Raw H2 ")); + Serial.print(sgp.rawH2); + Serial.print(" \t"); + Serial.print(F("Raw Ethanol ")); + Serial.print(sgp.rawEthanol); + Serial.println(""); + + delay(1000); + + uint16_t TVOC_base, eCO2_base; + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) + { + Serial.println(F("Failed to get baseline readings")); + return; + } + Serial.print(F("****Baseline values: eCO2: 0x")); + Serial.print(eCO2_base, HEX); + Serial.print(F(" & TVOC: 0x")); + Serial.println(TVOC_base, HEX); } \ No newline at end of file