Methane and Carbon Dioxide sensor: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
|||
| (6 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
[https://www.dropbox.com/scl/fo/72aa1pq2uo0s4xx3f6u8o/h?rlkey=3bqskgan83l0h8tj1nflbpirp&dl=0 Dropbox Methane Folder] | [https://www.dropbox.com/scl/fo/72aa1pq2uo0s4xx3f6u8o/h?rlkey=3bqskgan83l0h8tj1nflbpirp&dl=0 Dropbox Methane Folder] | ||
= More References = | |||
* [https://bg.copernicus.org/articles/17/3659/2020/ Facilitating the use of low-cost methane (CH4) sensors in flux chambers – calibration, data processing, and an open-source make-it-yourself logger] | |||
* [https://liu.diva-portal.org/smash/record.jsf?pid=diva2%3A1380130&dswid=-4323 Facilitating the use of low-cost methane (CH4) sensors in flux chambers] | |||
* [https://bg.copernicus.org/articles/17/3659/2020/bg-17-3659-2020-supplement.pdf Technical note: Facilitating the use of low-cost methane (CH4) sensors in flux chambers – calibration, data processing, and an open-source make-it-yourself logger] | |||
= Circuit Diagram = | = Circuit Diagram = | ||
| Line 25: | Line 33: | ||
* [https://www.dropbox.com/scl/fi/pgqxv8ub9on4gdwimzpll/DHT22-temperature-humidity-sensor-datasheet.pdf?rlkey=a6vzikm99mdhee14tge8sipd6&dl=0 DHT22 datasheet] | * [https://www.dropbox.com/scl/fi/pgqxv8ub9on4gdwimzpll/DHT22-temperature-humidity-sensor-datasheet.pdf?rlkey=a6vzikm99mdhee14tge8sipd6&dl=0 DHT22 datasheet] | ||
[[File:Screenshot 2024-03-19 at 4. | [[File:Screenshot 2024-03-19 at 4.51.24 am.png | 900px]] | ||
= Arduino code = | |||
<syntaxhighlight lang="c++"> | |||
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins | |||
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden. | |||
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation. | |||
#include <SPI.h> | |||
#include <SD.h> | |||
#include <Wire.h> | |||
#include <RTClib.h> | |||
//#include "RTClib.h" //RTC library | |||
#include <cactus_io_DHT22.h> | |||
//#include "cactus_io_DHT22.h" //RH_Temp library | |||
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data) | |||
// milliseconds before writing the logged data permanently to disk | |||
// LOG_INTERVAL write each time (safest) | |||
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card | |||
uint32_t syncTime = 0; // time of last sync() | |||
#define ECHO_TO_SERIAL 1 // echo data to serial port | |||
#define WAIT_TO_START 0 // Wait for serial input in setup() | |||
#define DHT22_PIN 7 // DHT22 (RH_T) data pin | |||
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino. | |||
// The analog pins that connect to the sensors | |||
#define CH4sens A1 //CH4 sensor Vout | |||
#define CH4ref A2 //CH4 sensor Vref | |||
#define Vb A0 //Battery voltage | |||
int CH4s = 0; | |||
int CH4r = 0; | |||
int Vbat = 0; | |||
float CH4smV = 0; | |||
float CH4rmV = 0; | |||
float VbatmV = 0; | |||
float mV = 5000; | |||
float steps = 1024; | |||
//RTC_PCF8523 RTC; // define the Real Time Clock object | |||
RTC_DS1307 RTC; | |||
// for the data logging shield, we use digital pin 10 for the SD cs line | |||
const int chipSelect = 10; | |||
// the logging file | |||
File logfile; | |||
void error(char *str) //Halt if error | |||
{ | |||
Serial.print("error: "); | |||
Serial.println(str); | |||
//digitalWrite(redLEDpin, HIGH); // red LED indicates error | |||
while(1); //halt command | |||
} | |||
double RHValue = 0; | |||
double TempValue = 0; | |||
double CO2Value = 0; | |||
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip) | |||
int co2Addr = 0x7F; | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : void initPoll() | |||
// Executes : Tells sensor to take a measurement. | |||
// Notes : A fuller implementation would read the register back and | |||
// ensure the flag was set, but in our case we ensure the poll | |||
// period is >25s and life is generally good. | |||
/////////////////////////////////////////////////////////////////// | |||
void initPoll() { | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x11); | |||
Wire.write(0x00); | |||
Wire.write(0x60); | |||
Wire.write(0x35); | |||
Wire.write(0xA6); | |||
Wire.endTransmission(); | |||
delay(20); | |||
Wire.requestFrom(co2Addr, 2); | |||
byte i = 0; | |||
byte buffer[2] = {0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readRH() | |||
// Returns : The current RH Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readRH() { | |||
int RH_value = 0; // We will store the RH value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte) | |||
Wire.write(0x36); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
RH_value = 0; | |||
RH_value |= buffer[1] & 0xFF; | |||
RH_value = RH_value << 8; | |||
RH_value |= buffer[2] & 0xFF; | |||
Serial.print("RH Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)RH_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readTemp() | |||
// Returns : The current Temperature Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readTemp() { | |||
int Temp_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte) | |||
Wire.write(0x34); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
Temp_value = 0; | |||
Temp_value |= buffer[1] & 0xFF; | |||
Temp_value = Temp_value << 8; | |||
Temp_value |= buffer[2] & 0xFF; | |||
Serial.print("T Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)Temp_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readCO2() | |||
// Returns : The current CO2 Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readCO2() { | |||
int CO2_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data | |||
Wire.write(0x2A); //Checksum | |||
Wire.endTransmission(); | |||
delay(50); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
CO2_value = 0; | |||
CO2_value |= buffer[1] & 0xFF; | |||
CO2_value = CO2_value << 8; | |||
CO2_value |= buffer[2] & 0xFF; | |||
Serial.print("CO2 Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)CO2_value * (double) 1); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
void setup(void) | |||
{ | |||
Serial.begin(9600); | |||
Serial.println(); | |||
dht.begin(); //start RH_T_sensor | |||
//#if WAIT_TO_START | |||
// Serial.println("Type any character to start"); | |||
// while (!Serial.available()); | |||
//#endif //WAIT_TO_START | |||
// initialize the SD card | |||
Serial.print("Initializing SD card..."); | |||
// make sure that the default chip select pin is set to | |||
// output, even if you don't use it: | |||
pinMode(10, OUTPUT); | |||
// see if the card is present and can be initialized: | |||
if (!SD.begin(chipSelect)) { | |||
error("Card failed, or not present"); | |||
} | |||
Serial.println("card initialized."); | |||
// create a new file | |||
char filename[] = "LOGGER00.CSV"; | |||
for (uint8_t i = 0; i < 100; i++) { | |||
filename[6] = i/10 + '0'; | |||
filename[7] = i%10 + '0'; | |||
if (! SD.exists(filename)) { | |||
// only open a new file if it doesn't exist | |||
logfile = SD.open(filename, FILE_WRITE); | |||
break; // leave the loop! | |||
} | |||
} | |||
if (! logfile) { | |||
error("couldnt create file"); | |||
} | |||
Serial.print("Logging to: "); | |||
Serial.println(filename); | |||
// connect to RTC | |||
Wire.begin(); | |||
if (!RTC.begin()) { | |||
logfile.println("RTC failed"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("RTC failed"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
//if (! RTC.initialized()) { | |||
if (! RTC.isrunning()) { | |||
Serial.println("RTC is NOT running!"); | |||
// following line sets the RTC to the date & time this sketch was compiled | |||
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(2024, 5, 5, 20, 33, 0)); | |||
} | |||
logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
char time_to_read_CO2 = 1; | |||
char n_delay_wait = 0; | |||
void loop(){ | |||
DateTime now; | |||
if (time_to_read_CO2 == 1) { | |||
initPoll(); | |||
delay(50); | |||
CO2Value = readCO2(); | |||
delay(20); | |||
RHValue = readRH(); | |||
delay(20); | |||
TempValue = readTemp(); | |||
// if(RHValue >= 0) { | |||
// Serial.print("RH: "); | |||
// Serial.print(RHValue); | |||
// Serial.print("% | Temp: "); | |||
// Serial.print(TempValue); | |||
// Serial.print("C | CO2: "); | |||
// Serial.print(CO2Value, 0); | |||
// Serial.println("ppm"); | |||
// Serial.println(); | |||
// } | |||
// else { | |||
// Serial.println(" | Checksum failed / Communication failure"); | |||
// } | |||
time_to_read_CO2 = 0; | |||
} | |||
// delay for the amount of time we want between readings | |||
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); | |||
// log milliseconds since starting | |||
uint32_t m = millis(); | |||
logfile.print(m); // milliseconds since start | |||
logfile.print(", "); | |||
#if ECHO_TO_SERIAL | |||
Serial.print(m); // milliseconds since start | |||
Serial.print(", "); | |||
#endif | |||
// fetch the time | |||
now = RTC.now(); | |||
Serial.println(now.unixtime()); | |||
// log time | |||
logfile.print(now.unixtime()); // seconds since 1/1/1970 | |||
logfile.print(", "); | |||
//logfile.print('"'); | |||
logfile.print(now.year(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.month(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.day(), DEC); | |||
logfile.print(" "); | |||
logfile.print(now.hour(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.minute(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.second(), DEC); | |||
//logfile.print('"'); | |||
#if ECHO_TO_SERIAL | |||
Serial.print(now.unixtime()); // seconds since 1/1/1970 | |||
Serial.print(", "); | |||
//Serial.print('"'); | |||
Serial.print(now.year(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.month(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.day(), DEC); | |||
Serial.print(" "); | |||
Serial.print(now.hour(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.minute(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.second(), DEC); | |||
//Serial.print('"'); | |||
#endif //ECHO_TO_SERIAL | |||
// Reading temperature or humidity takes about 250 milliseconds. | |||
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor) | |||
dht.readHumidity(); | |||
dht.readTemperature(); | |||
// Check if any reads failed and exit early (to try again). | |||
if (isnan(dht.humidity) || isnan(dht.temperature_C)) { | |||
Serial.print("DHT sensor read failure!"); | |||
return; | |||
} | |||
CH4s = analogRead(CH4sens); //read CH4 Vout | |||
CH4smV = CH4s*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
CH4r = analogRead(CH4ref); //read CH4 Vref | |||
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
Vbat = analogRead(Vb); //read CH4 Vref | |||
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider. | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
logfile.print(", "); | |||
logfile.print(dht.humidity); | |||
logfile.print(", "); | |||
logfile.print(dht.temperature_C); | |||
logfile.print(", "); | |||
logfile.print(CH4smV); | |||
logfile.print(", "); | |||
logfile.print(CH4rmV); | |||
logfile.print(", "); | |||
logfile.print(VbatmV); | |||
logfile.print(", "); | |||
logfile.print(RHValue); | |||
logfile.print(", "); | |||
logfile.print(TempValue); | |||
logfile.print(", "); | |||
logfile.print(CO2Value); | |||
#if ECHO_TO_SERIAL | |||
Serial.print(", "); | |||
Serial.print(dht.humidity); | |||
Serial.print(", "); | |||
Serial.print(dht.temperature_C); | |||
Serial.print(", "); | |||
Serial.print(CH4smV); | |||
Serial.print(", "); | |||
Serial.print(CH4rmV); | |||
Serial.print(", "); | |||
Serial.print(VbatmV); | |||
Serial.print(", "); | |||
Serial.print(RHValue); | |||
Serial.print(", "); | |||
Serial.print(TempValue); | |||
Serial.print(", "); | |||
Serial.print(CO2Value); | |||
#endif //ECHO_TO_SERIAL | |||
logfile.println(); | |||
#if ECHO_TO_SERIAL | |||
Serial.println(); | |||
#endif // ECHO_TO_SERIAL | |||
if (time_to_read_CO2 == 0 ) { | |||
if (n_delay_wait < 29) | |||
n_delay_wait += 1; | |||
else { | |||
time_to_read_CO2 = 1; | |||
Serial.print("Time to read K33 sensor: "); | |||
n_delay_wait = 0; | |||
} | |||
} | |||
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card | |||
// which uses power and takes time | |||
if ((millis() - syncTime) < SYNC_INTERVAL) return; | |||
syncTime = millis(); | |||
logfile.flush(); | |||
} | |||
</syntaxhighlight> | |||
== Timestamp example for RTC - Real Time Clock == | |||
<syntaxhighlight lang="c++"> | |||
/* Timestamp functions using a DS1307 RTC connected via I2C and Wire lib | |||
** | |||
** Useful for file name | |||
** ` SD.open(time.timestamp()+".log", FILE_WRITE) ` | |||
** | |||
** | |||
** Created: 2015-06-01 by AxelTB | |||
** Last Edit: | |||
*/ | |||
#include "RTClib.h" | |||
RTC_DS1307 rtc; | |||
void setup() { | |||
Serial.begin(9600); | |||
rtc.begin(); | |||
if (! rtc.isrunning()) { | |||
Serial.println("RTC is NOT running!"); | |||
// following line sets the RTC to the date & time this sketch was compiled | |||
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)); | |||
} | |||
} | |||
void loop() { | |||
DateTime time = rtc.now(); | |||
//Full Timestamp | |||
Serial.println(String("DateTime::TIMESTAMP_FULL:\t")+time.timestamp(DateTime::TIMESTAMP_FULL)); | |||
//Date Only | |||
Serial.println(String("DateTime::TIMESTAMP_DATE:\t")+time.timestamp(DateTime::TIMESTAMP_DATE)); | |||
//Full Timestamp | |||
Serial.println(String("DateTime::TIMESTAMP_TIME:\t")+time.timestamp(DateTime::TIMESTAMP_TIME)); | |||
Serial.println("\n"); | |||
//Delay 5s | |||
delay(5000); | |||
} | |||
</syntaxhighlight> | |||
== Methane and Carbon dioxide sensor sending data to Pi == | |||
<syntaxhighlight lang="c++"> | |||
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins | |||
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden. | |||
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation. | |||
#include <SPI.h> | |||
#include <SD.h> | |||
#include <Wire.h> | |||
#include <RTClib.h> | |||
//#include "RTClib.h" //RTC library | |||
#include <cactus_io_DHT22.h> | |||
//#include "cactus_io_DHT22.h" //RH_Temp library | |||
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data) | |||
// milliseconds before writing the logged data permanently to disk | |||
// LOG_INTERVAL write each time (safest) | |||
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card | |||
uint32_t syncTime = 0; // time of last sync() | |||
#define ECHO_TO_SERIAL 1 // echo data to serial port | |||
#define WAIT_TO_START 0 // Wait for serial input in setup() | |||
#define DHT22_PIN 7 // DHT22 (RH_T) data pin | |||
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino. | |||
// The analog pins that connect to the sensors | |||
#define CH4sens A1 //CH4 sensor Vout | |||
#define CH4ref A2 //CH4 sensor Vref | |||
#define Vb A0 //Battery voltage | |||
int CH4s = 0; | |||
int CH4r = 0; | |||
int Vbat = 0; | |||
float CH4smV = 0; | |||
float CH4rmV = 0; | |||
float VbatmV = 0; | |||
float mV = 5000; | |||
float steps = 1024; | |||
//RTC_PCF8523 RTC; // define the Real Time Clock object | |||
RTC_DS1307 RTC; | |||
// for the data logging shield, we use digital pin 10 for the SD cs line | |||
const int chipSelect = 10; | |||
// the logging file | |||
File logfile; | |||
void error(char *str) //Halt if error | |||
{ | |||
Serial.print("error: "); | |||
Serial.println(str); | |||
//digitalWrite(redLEDpin, HIGH); // red LED indicates error | |||
while(1); //halt command | |||
} | |||
double RHValue = 0; | |||
double TempValue = 0; | |||
double CO2Value = 0; | |||
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip) | |||
int co2Addr = 0x7F; | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : void initPoll() | |||
// Executes : Tells sensor to take a measurement. | |||
// Notes : A fuller implementation would read the register back and | |||
// ensure the flag was set, but in our case we ensure the poll | |||
// period is >25s and life is generally good. | |||
/////////////////////////////////////////////////////////////////// | |||
void initPoll() { | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x11); | |||
Wire.write(0x00); | |||
Wire.write(0x60); | |||
Wire.write(0x35); | |||
Wire.write(0xA6); | |||
Wire.endTransmission(); | |||
delay(20); | |||
Wire.requestFrom(co2Addr, 2); | |||
byte i = 0; | |||
byte buffer[2] = {0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readRH() | |||
// Returns : The current RH Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readRH() { | |||
int RH_value = 0; // We will store the RH value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte) | |||
Wire.write(0x36); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
RH_value = 0; | |||
RH_value |= buffer[1] & 0xFF; | |||
RH_value = RH_value << 8; | |||
RH_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("RH Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)RH_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readTemp() | |||
// Returns : The current Temperature Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readTemp() { | |||
int Temp_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte) | |||
Wire.write(0x34); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
Temp_value = 0; | |||
Temp_value |= buffer[1] & 0xFF; | |||
Temp_value = Temp_value << 8; | |||
Temp_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("T Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)Temp_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readCO2() | |||
// Returns : The current CO2 Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readCO2() { | |||
int CO2_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data | |||
Wire.write(0x2A); //Checksum | |||
Wire.endTransmission(); | |||
delay(50); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
CO2_value = 0; | |||
CO2_value |= buffer[1] & 0xFF; | |||
CO2_value = CO2_value << 8; | |||
CO2_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("CO2 Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)CO2_value * (double) 1); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
void setup(void) | |||
{ | |||
Serial.begin(9600); | |||
Serial.println(); | |||
dht.begin(); //start RH_T_sensor | |||
//#if WAIT_TO_START | |||
// Serial.println("Type any character to start"); | |||
// while (!Serial.available()); | |||
//#endif //WAIT_TO_START | |||
// initialize the SD card | |||
Serial.print("Initializing SD card..."); | |||
// make sure that the default chip select pin is set to | |||
// output, even if you don't use it: | |||
pinMode(10, OUTPUT); | |||
// see if the card is present and can be initialized: | |||
if (!SD.begin(chipSelect)) { | |||
error("Card failed, or not present"); | |||
} | |||
Serial.println("card initialized."); | |||
// create a new file | |||
char filename[] = "LOGGER00.CSV"; | |||
for (uint8_t i = 0; i < 100; i++) { | |||
filename[6] = i/10 + '0'; | |||
filename[7] = i%10 + '0'; | |||
if (! SD.exists(filename)) { | |||
// only open a new file if it doesn't exist | |||
logfile = SD.open(filename, FILE_WRITE); | |||
break; // leave the loop! | |||
} | |||
} | |||
if (! logfile) { | |||
error("couldnt create file"); | |||
} | |||
Serial.print("Logging to: "); | |||
Serial.println(filename); | |||
// connect to RTC | |||
Wire.begin(); | |||
if (!RTC.begin()) { | |||
logfile.println("RTC failed"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("RTC failed"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
//if (! RTC.initialized()) { | |||
if (! RTC.isrunning()) { | |||
Serial.println("RTC is NOT running!"); | |||
// following line sets the RTC to the date & time this sketch was compiled | |||
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(2024, 5, 5, 20, 33, 0)); | |||
} | |||
//Edmond 31 May 2024 | |||
//logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
char time_to_read_CO2 = 1; | |||
char n_delay_wait = 0; | |||
void loop(){ | |||
DateTime now; | |||
if (time_to_read_CO2 == 1) { | |||
initPoll(); | |||
delay(50); | |||
CO2Value = readCO2(); | |||
delay(20); | |||
RHValue = readRH(); | |||
delay(20); | |||
TempValue = readTemp(); | |||
// if(RHValue >= 0) { | |||
// Serial.print("RH: "); | |||
// Serial.print(RHValue); | |||
// Serial.print("% | Temp: "); | |||
// Serial.print(TempValue); | |||
// Serial.print("C | CO2: "); | |||
// Serial.print(CO2Value, 0); | |||
// Serial.println("ppm"); | |||
// Serial.println(); | |||
// } | |||
// else { | |||
// Serial.println(" | Checksum failed / Communication failure"); | |||
// } | |||
time_to_read_CO2 = 0; | |||
} | |||
// delay for the amount of time we want between readings | |||
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); | |||
// log milliseconds since starting | |||
uint32_t m = millis(); | |||
logfile.print(m); // milliseconds since start | |||
logfile.print(", "); | |||
#if ECHO_TO_SERIAL | |||
//Serial.print(m); // milliseconds since start | |||
//Serial.print(", "); | |||
#endif | |||
// fetch the time | |||
now = RTC.now(); | |||
//Serial.println(now.unixtime()); | |||
// log time | |||
/* | |||
logfile.print(now.unixtime()); // seconds since 1/1/1970 | |||
logfile.print(", "); | |||
//logfile.print('"'); | |||
logfile.print(now.year(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.month(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.day(), DEC); | |||
logfile.print(" "); | |||
logfile.print(now.hour(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.minute(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.second(), DEC); | |||
//logfile.print('"'); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.print(now.unixtime()); // seconds since 1/1/1970 | |||
Serial.print(","); | |||
//Serial.print('"'); | |||
Serial.print(now.year(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.month(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.day(), DEC); | |||
Serial.print(" "); | |||
Serial.print(now.hour(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.minute(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.second(), DEC); | |||
//Serial.print('"'); | |||
#endif //ECHO_TO_SERIAL | |||
// Reading temperature or humidity takes about 250 milliseconds. | |||
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor) | |||
dht.readHumidity(); | |||
dht.readTemperature(); | |||
// Check if any reads failed and exit early (to try again). | |||
if (isnan(dht.humidity) || isnan(dht.temperature_C)) { | |||
Serial.print("DHT sensor read failure!"); | |||
return; | |||
} | |||
CH4s = analogRead(CH4sens); //read CH4 Vout | |||
CH4smV = CH4s*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
CH4r = analogRead(CH4ref); //read CH4 Vref | |||
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
Vbat = analogRead(Vb); //read CH4 Vref | |||
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider. | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
/* | |||
logfile.print(", "); | |||
logfile.print(dht.humidity); | |||
logfile.print(", "); | |||
logfile.print(dht.temperature_C); | |||
logfile.print(", "); | |||
logfile.print(CH4smV); | |||
logfile.print(", "); | |||
logfile.print(CH4rmV); | |||
logfile.print(", "); | |||
logfile.print(VbatmV); | |||
logfile.print(", "); | |||
logfile.print(RHValue); | |||
logfile.print(", "); | |||
logfile.print(TempValue); | |||
logfile.print(", "); | |||
logfile.print(CO2Value); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.print(","); | |||
Serial.print(dht.humidity); | |||
Serial.print(","); | |||
Serial.print(dht.temperature_C); | |||
Serial.print(","); | |||
Serial.print(CH4smV); | |||
Serial.print(","); | |||
Serial.print(CH4rmV); | |||
Serial.print(","); | |||
Serial.print(VbatmV); | |||
Serial.print(","); | |||
Serial.print(RHValue); | |||
Serial.print(","); | |||
Serial.print(TempValue); | |||
Serial.print(","); | |||
Serial.print(CO2Value); | |||
#endif //ECHO_TO_SERIAL | |||
/* | |||
logfile.println(); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.println(); | |||
#endif // ECHO_TO_SERIAL | |||
if (time_to_read_CO2 == 0 ) { | |||
if (n_delay_wait < 29) | |||
n_delay_wait += 1; | |||
else { | |||
time_to_read_CO2 = 1; | |||
/* | |||
Serial.print("Time to read K33 sensor: "); | |||
*/ | |||
n_delay_wait = 0; | |||
} | |||
} | |||
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card | |||
// which uses power and takes time | |||
if ((millis() - syncTime) < SYNC_INTERVAL) return; | |||
syncTime = millis(); | |||
/* | |||
logfile.flush(); | |||
*/ | |||
} | |||
</syntaxhighlight> | |||
= Methane and Carbon dioxide sensor sending data to Pi = | |||
== Python code == | |||
<syntaxhighlight lang="python"> | |||
#!/usr/bin/env python3 | |||
# dweet data | |||
import serial | |||
import datetime | |||
import time | |||
import requests | |||
import pandas as pd | |||
import plotly.express as px | |||
from water_variables import * | |||
count = 0 | |||
if __name__ == '__main__': | |||
# methane | |||
ser = serial.Serial('/dev/ttyUSB1', 9600, timeout=1) | |||
ser.reset_input_buffer() | |||
while True: | |||
count = count + 1 | |||
time.sleep(0.1) | |||
if ser.in_waiting > 0: | |||
time.sleep(0.1) | |||
try: | |||
line = ser.readline().decode('utf-8').rstrip() | |||
print(line) | |||
except: | |||
line = "0,0,0,0,0,0,0,0,0,0" | |||
#print(f"Data separated using commas {line.split(',')}") | |||
mylist = line.split(',') | |||
print(f'My list {mylist}') | |||
try: | |||
# stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2 | |||
stampunix = str(mylist[0]) | |||
date_time_not_used = str(mylist[1]) | |||
RH1 = str(mylist[2]) | |||
temp1 = str(mylist[3]) | |||
CH4smV = str(mylist[4]) | |||
CH4rmV = str(mylist[5]) | |||
VbatmV = str(mylist[6]) | |||
K33_RH = str(mylist[7]) | |||
K33_Temp = str(mylist[8]) | |||
K33_CO2 = str(mylist[9]) | |||
print("data extracted") | |||
except: | |||
stampunix = "0.0" | |||
date_time_not_used = "0.0" | |||
RH1 = "0.0" | |||
temp1 = "0.0" | |||
CH4smV = "0.0" | |||
CH4rmV = "0" | |||
VbatmV = "0.0" | |||
K33_RH = "0.0" | |||
K33_Temp = "0.0" | |||
K33_CO2 = "0.0" | |||
now = datetime.datetime.now() | |||
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S") | |||
print(f'CH4smV - {CH4smV}, K33_CO2 - {K33_CO2}, time - {date_stamp}') | |||
print(count) | |||
print() | |||
time.sleep(0.1) | |||
data = "" | |||
data = date_stamp + "," + str(RH1) + "," + str(temp1) + "," + str(CH4smV) + "," +\ | |||
str(CH4rmV) + "," + str(VbatmV) + "," + str(K33_RH) + "," + \ | |||
str(K33_Temp) + "," + str(K33_CO2) + '\n' | |||
#print(f'The data is = {data}') | |||
if count > 3000: | |||
#print(count) | |||
f = open('/home/pi/Aquarium/aquarium_methane.txt','a') | |||
f.write(data) | |||
f.close() | |||
print("Data saved") | |||
try: | |||
print("Preparing dweet") | |||
dweet_dict = {} | |||
dweet_dict.update({"RH1": str(RH1)}) | |||
dweet_dict.update({"temp1": str(temp1)}) | |||
dweet_dict.update({"CH4smV": str(CH4smV)}) | |||
dweet_dict.update({"CH4rmV": str(CH4rmV)}) | |||
dweet_dict.update({"VbatmV": str(VbatmV)}) | |||
dweet_dict.update({"K33_RH": str(K33_RH)}) | |||
dweet_dict.update({"K33_Temp": str(K33_Temp)}) | |||
dweet_dict.update({"K33_CO2": str(K33_CO2)}) | |||
dweet_dict.update({"time": str(date_stamp)}) | |||
url = "https://dweet.io/dweet/for/3083-Bundoora-aquarium_methane1?" | |||
#https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium_methane1? | |||
x = requests.post(url, json=dweet_dict) | |||
print(x.text) | |||
except: | |||
print("Dweet failed") | |||
count = 0 | |||
# check dweet with - https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium1 | |||
# Step 2: Read the data from the text file into a Pandas DataFrame | |||
#data = pd.read_csv('/home/pi/Aquarium/aquarium_methane.txt') | |||
# Step 3: Create a Plotly figure with two scatter plots | |||
#fig = px.scatter(data, x='datetime', y=['temperature','dissolvedOxygen'], | |||
#labels={'datetime': 'Date and Time', 'value': 'Temperature (°C)'}, | |||
#title='Aquarium temperature and DO') | |||
# Step 4: Customize the plot layout | |||
#fig.update_layout(xaxis_title='Date and Time', yaxis_title='Temperature (°C)') | |||
# Step 5: Save the plot as an HTML file | |||
#fig.write_html('/home/pi/Aquarium/temperature_plot_DO_EC_chem_aquarium.html') | |||
#print("Aquarium plot saved as temperature_plot.html") | |||
</syntaxhighlight> | |||
== Working Arduino Code 6 June 2024 == | |||
<syntaxhighlight lang="c++"> | |||
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins | |||
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden. | |||
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation. | |||
#include <SPI.h> | |||
#include <SD.h> | |||
#include <Wire.h> | |||
#include <RTClib.h> | |||
//#include "RTClib.h" //RTC library | |||
#include <cactus_io_DHT22.h> | |||
//#include "cactus_io_DHT22.h" //RH_Temp library | |||
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data) | |||
// milliseconds before writing the logged data permanently to disk | |||
// LOG_INTERVAL write each time (safest) | |||
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card | |||
uint32_t syncTime = 0; // time of last sync() | |||
#define ECHO_TO_SERIAL 1 // echo data to serial port | |||
#define WAIT_TO_START 0 // Wait for serial input in setup() | |||
#define DHT22_PIN 7 // DHT22 (RH_T) data pin | |||
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino. | |||
// The analog pins that connect to the sensors | |||
#define CH4sens A1 //CH4 sensor Vout | |||
#define CH4ref A2 //CH4 sensor Vref | |||
#define Vb A0 //Battery voltage | |||
int CH4s = 0; | |||
int CH4r = 0; | |||
int Vbat = 0; | |||
float CH4smV = 0; | |||
float CH4rmV = 0; | |||
float VbatmV = 0; | |||
float mV = 5000; | |||
float steps = 1024; | |||
//RTC_PCF8523 RTC; // define the Real Time Clock object | |||
RTC_DS1307 RTC; | |||
// for the data logging shield, we use digital pin 10 for the SD cs line | |||
const int chipSelect = 10; | |||
// the logging file | |||
File logfile; | |||
void error(char *str) //Halt if error | |||
{ | |||
Serial.print("error: "); | |||
Serial.println(str); | |||
//digitalWrite(redLEDpin, HIGH); // red LED indicates error | |||
while(1); //halt command | |||
} | |||
double RHValue = 0; | |||
double TempValue = 0; | |||
double CO2Value = 0; | |||
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip) | |||
int co2Addr = 0x7F; | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : void initPoll() | |||
// Executes : Tells sensor to take a measurement. | |||
// Notes : A fuller implementation would read the register back and | |||
// ensure the flag was set, but in our case we ensure the poll | |||
// period is >25s and life is generally good. | |||
/////////////////////////////////////////////////////////////////// | |||
void initPoll() { | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x11); | |||
Wire.write(0x00); | |||
Wire.write(0x60); | |||
Wire.write(0x35); | |||
Wire.write(0xA6); | |||
Wire.endTransmission(); | |||
delay(20); | |||
Wire.requestFrom(co2Addr, 2); | |||
byte i = 0; | |||
byte buffer[2] = {0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readRH() | |||
// Returns : The current RH Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readRH() { | |||
int RH_value = 0; // We will store the RH value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte) | |||
Wire.write(0x36); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
RH_value = 0; | |||
RH_value |= buffer[1] & 0xFF; | |||
RH_value = RH_value << 8; | |||
RH_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("RH Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)RH_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readTemp() | |||
// Returns : The current Temperature Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readTemp() { | |||
int Temp_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte) | |||
Wire.write(0x34); //Checksum | |||
Wire.endTransmission(); | |||
delay(20); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
Temp_value = 0; | |||
Temp_value |= buffer[1] & 0xFF; | |||
Temp_value = Temp_value << 8; | |||
Temp_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("T Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)Temp_value / (double) 100); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
/////////////////////////////////////////////////////////////////// | |||
// Function : double readCO2() | |||
// Returns : The current CO2 Value, ?1 if error has occured | |||
/////////////////////////////////////////////////////////////////// | |||
double readCO2() { | |||
int CO2_value = 0; // We will store the temperature value inside this variable. | |||
digitalWrite(13, HIGH); | |||
////////////////////////// | |||
/* Begin Write Sequence */ | |||
////////////////////////// | |||
Wire.beginTransmission(co2Addr); //int K33 == 0x68 | |||
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes) | |||
Wire.write(0x00); //Sensor address in ?? EEPROM ?? | |||
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data | |||
Wire.write(0x2A); //Checksum | |||
Wire.endTransmission(); | |||
delay(50); | |||
///////////////////////// | |||
/* Begin Read Sequence */ | |||
///////////////////////// | |||
Wire.requestFrom(co2Addr, 4); | |||
byte i = 0; | |||
byte buffer[4] = {0, 0, 0, 0}; | |||
while(Wire.available()) { | |||
buffer[i] = Wire.read(); | |||
i++; | |||
} | |||
CO2_value = 0; | |||
CO2_value |= buffer[1] & 0xFF; | |||
CO2_value = CO2_value << 8; | |||
CO2_value |= buffer[2] & 0xFF; | |||
/* | |||
Serial.print("CO2 Data "); | |||
Serial.print(buffer[0], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[1], HEX); | |||
Serial.print("|"); | |||
Serial.print(buffer[2], HEX); | |||
Serial.print("|"); | |||
Serial.println(buffer[3], HEX); | |||
*/ | |||
byte sum = 0; //Checksum Byte | |||
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow | |||
if(sum == buffer[3]) { | |||
// Success! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double)CO2_value * (double) 1); | |||
} | |||
else { | |||
// Failure! | |||
digitalWrite(13, LOW); | |||
delay(10); | |||
return ((double) -1); | |||
} | |||
} | |||
void setup(void) | |||
{ | |||
Serial.begin(9600); | |||
Serial.println(); | |||
dht.begin(); //start RH_T_sensor | |||
//#if WAIT_TO_START | |||
// Serial.println("Type any character to start"); | |||
// while (!Serial.available()); | |||
//#endif //WAIT_TO_START | |||
// initialize the SD card | |||
Serial.print("Initializing SD card..."); | |||
// make sure that the default chip select pin is set to | |||
// output, even if you don't use it: | |||
pinMode(10, OUTPUT); | |||
// see if the card is present and can be initialized: | |||
if (!SD.begin(chipSelect)) { | |||
error("Card failed, or not present"); | |||
} | |||
Serial.println("card initialized."); | |||
// create a new file | |||
char filename[] = "LOGGER00.CSV"; | |||
for (uint8_t i = 0; i < 100; i++) { | |||
filename[6] = i/10 + '0'; | |||
filename[7] = i%10 + '0'; | |||
if (! SD.exists(filename)) { | |||
// only open a new file if it doesn't exist | |||
logfile = SD.open(filename, FILE_WRITE); | |||
break; // leave the loop! | |||
} | |||
} | |||
if (! logfile) { | |||
error("couldnt create file"); | |||
} | |||
Serial.print("Logging to: "); | |||
Serial.println(filename); | |||
// connect to RTC | |||
Wire.begin(); | |||
if (!RTC.begin()) { | |||
logfile.println("RTC failed"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("RTC failed"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
//if (! RTC.initialized()) { | |||
if (! RTC.isrunning()) { | |||
Serial.println("RTC is NOT running!"); | |||
// following line sets the RTC to the date & time this sketch was compiled | |||
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(2024, 5, 5, 20, 33, 0)); | |||
} | |||
//Edmond 31 May 2024 | |||
//logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#if ECHO_TO_SERIAL | |||
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2"); | |||
#endif //ECHO_TO_SERIAL | |||
} | |||
char time_to_read_CO2 = 1; | |||
char n_delay_wait = 0; | |||
void loop(){ | |||
DateTime now; | |||
if (time_to_read_CO2 == 1) { | |||
initPoll(); | |||
delay(50); | |||
CO2Value = readCO2(); | |||
delay(20); | |||
RHValue = readRH(); | |||
delay(20); | |||
TempValue = readTemp(); | |||
// if(RHValue >= 0) { | |||
// Serial.print("RH: "); | |||
// Serial.print(RHValue); | |||
// Serial.print("% | Temp: "); | |||
// Serial.print(TempValue); | |||
// Serial.print("C | CO2: "); | |||
// Serial.print(CO2Value, 0); | |||
// Serial.println("ppm"); | |||
// Serial.println(); | |||
// } | |||
// else { | |||
// Serial.println(" | Checksum failed / Communication failure"); | |||
// } | |||
time_to_read_CO2 = 0; | |||
} | |||
// delay for the amount of time we want between readings | |||
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); | |||
// log milliseconds since starting | |||
uint32_t m = millis(); | |||
logfile.print(m); // milliseconds since start | |||
logfile.print(", "); | |||
#if ECHO_TO_SERIAL | |||
//Serial.print(m); // milliseconds since start | |||
//Serial.print(", "); | |||
#endif | |||
// fetch the time | |||
now = RTC.now(); | |||
//Serial.println(now.unixtime()); | |||
// log time | |||
/* | |||
logfile.print(now.unixtime()); // seconds since 1/1/1970 | |||
logfile.print(", "); | |||
//logfile.print('"'); | |||
logfile.print(now.year(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.month(), DEC); | |||
logfile.print("/"); | |||
logfile.print(now.day(), DEC); | |||
logfile.print(" "); | |||
logfile.print(now.hour(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.minute(), DEC); | |||
logfile.print(":"); | |||
logfile.print(now.second(), DEC); | |||
//logfile.print('"'); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.print(now.unixtime()); // seconds since 1/1/1970 | |||
Serial.print(","); | |||
//Serial.print('"'); | |||
Serial.print(now.year(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.month(), DEC); | |||
Serial.print("/"); | |||
Serial.print(now.day(), DEC); | |||
Serial.print(" "); | |||
Serial.print(now.hour(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.minute(), DEC); | |||
Serial.print(":"); | |||
Serial.print(now.second(), DEC); | |||
//Serial.print('"'); | |||
#endif //ECHO_TO_SERIAL | |||
// Reading temperature or humidity takes about 250 milliseconds. | |||
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor) | |||
dht.readHumidity(); | |||
dht.readTemperature(); | |||
// Check if any reads failed and exit early (to try again). | |||
if (isnan(dht.humidity) || isnan(dht.temperature_C)) { | |||
Serial.print("DHT sensor read failure!"); | |||
return; | |||
} | |||
CH4s = analogRead(CH4sens); //read CH4 Vout | |||
CH4smV = CH4s*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
CH4r = analogRead(CH4ref); //read CH4 Vref | |||
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
Vbat = analogRead(Vb); //read CH4 Vref | |||
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider. | |||
delay(10); //delay between reading of different analogue pins adviced. | |||
/* | |||
logfile.print(", "); | |||
logfile.print(dht.humidity); | |||
logfile.print(", "); | |||
logfile.print(dht.temperature_C); | |||
logfile.print(", "); | |||
logfile.print(CH4smV); | |||
logfile.print(", "); | |||
logfile.print(CH4rmV); | |||
logfile.print(", "); | |||
logfile.print(VbatmV); | |||
logfile.print(", "); | |||
logfile.print(RHValue); | |||
logfile.print(", "); | |||
logfile.print(TempValue); | |||
logfile.print(", "); | |||
logfile.print(CO2Value); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.print(","); | |||
Serial.print(dht.humidity); | |||
Serial.print(","); | |||
Serial.print(dht.temperature_C); | |||
Serial.print(","); | |||
Serial.print(CH4smV); | |||
Serial.print(","); | |||
Serial.print(CH4rmV); | |||
Serial.print(","); | |||
Serial.print(VbatmV); | |||
Serial.print(","); | |||
Serial.print(RHValue); | |||
Serial.print(","); | |||
Serial.print(TempValue); | |||
Serial.print(","); | |||
Serial.print(CO2Value); | |||
#endif //ECHO_TO_SERIAL | |||
/* | |||
logfile.println(); | |||
*/ | |||
#if ECHO_TO_SERIAL | |||
Serial.println(); | |||
#endif // ECHO_TO_SERIAL | |||
if (time_to_read_CO2 == 0 ) { | |||
if (n_delay_wait < 29) | |||
n_delay_wait += 1; | |||
else { | |||
time_to_read_CO2 = 1; | |||
/* | |||
Serial.print("Time to read K33 sensor: "); | |||
*/ | |||
n_delay_wait = 0; | |||
} | |||
} | |||
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card | |||
// which uses power and takes time | |||
if ((millis() - syncTime) < SYNC_INTERVAL) return; | |||
syncTime = millis(); | |||
/* | |||
logfile.flush(); | |||
*/ | |||
} | |||
</syntaxhighlight> | |||
== Working Python Code 6 June 2024 == | |||
<syntaxhighlight lang="python"> | |||
#!/usr/bin/env python3 | |||
# dweet data | |||
import serial | |||
import datetime | |||
import time | |||
import requests | |||
import pandas as pd | |||
import plotly.express as px | |||
from water_variables import * | |||
count = 0 | |||
if __name__ == '__main__': | |||
# methane | |||
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1) | |||
ser.reset_input_buffer() | |||
while True: | |||
count = count + 1 | |||
time.sleep(0.1) | |||
if ser.in_waiting > 0: | |||
time.sleep(0.1) | |||
try: | |||
line = ser.readline().decode('utf-8').rstrip() | |||
print(line) | |||
except: | |||
line = "0,0,0,0,0,0,0,0,0,0" | |||
#print(f"Data separated using commas {line.split(',')}") | |||
mylist = line.split(',') | |||
print(f'My list {mylist}') | |||
try: | |||
# stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2 | |||
stampunix = str(mylist[0]) | |||
date_time_not_used = str(mylist[1]) | |||
RH1 = str(mylist[2]) | |||
temp1 = str(mylist[3]) | |||
CH4smV = str(mylist[4]) | |||
CH4rmV = str(mylist[5]) | |||
VbatmV = str(mylist[6]) | |||
K33_RH = str(mylist[7]) | |||
K33_Temp = str(mylist[8]) | |||
K33_CO2 = str(mylist[9]) | |||
print("data extracted") | |||
except: | |||
stampunix = "0.0" | |||
date_time_not_used = "0.0" | |||
RH1 = "0.0" | |||
temp1 = "0.0" | |||
CH4smV = "0.0" | |||
CH4rmV = "0" | |||
VbatmV = "0.0" | |||
K33_RH = "0.0" | |||
K33_Temp = "0.0" | |||
K33_CO2 = "0.0" | |||
now = datetime.datetime.now() | |||
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S") | |||
print(f'CH4smV - {CH4smV}, K33_CO2 - {K33_CO2}, time - {date_stamp}') | |||
print(count) | |||
print() | |||
time.sleep(0.1) | |||
data = "" | |||
data = date_stamp + "," + str(RH1) + "," + str(temp1) + "," + str(CH4smV) + "," +\ | |||
str(CH4rmV) + "," + str(VbatmV) + "," + str(K33_RH) + "," + \ | |||
str(K33_Temp) + "," + str(K33_CO2) + '\n' | |||
#print(f'The data is = {data}') | |||
if count > 3000 and K33_CO2 != "0.00": | |||
#print(count) | |||
f = open('/home/pi/Aquarium/aquarium_methane.txt','a') | |||
f.write(data) | |||
f.close() | |||
print("Data saved") | |||
try: | |||
print("Preparing dweet") | |||
dweet_dict = {} | |||
dweet_dict.update({"RH1": str(RH1)}) | |||
dweet_dict.update({"temp1": str(temp1)}) | |||
dweet_dict.update({"CH4smV": str(CH4smV)}) | |||
dweet_dict.update({"CH4rmV": str(CH4rmV)}) | |||
dweet_dict.update({"VbatmV": str(VbatmV)}) | |||
dweet_dict.update({"K33_RH": str(K33_RH)}) | |||
dweet_dict.update({"K33_Temp": str(K33_Temp)}) | |||
dweet_dict.update({"K33_CO2": str(K33_CO2)}) | |||
dweet_dict.update({"time": str(date_stamp)}) | |||
url = "https://dweet.io/dweet/for/3083-Bundoora-aquarium_methane1?" | |||
#https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium_methane1? | |||
x = requests.post(url, json=dweet_dict) | |||
print(x.text) | |||
except: | |||
print("Dweet failed") | |||
count = 0 | |||
# check dweet with - https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium1 | |||
# Step 2: Read the data from the text file into a Pandas DataFrame | |||
data = pd.read_csv('/home/pi/Aquarium/aquarium_methane.txt') | |||
# Step 3: Create a Plotly figure with two scatter plots | |||
fig = px.scatter(data, x='date_stamp', y=['CH4rmV','K33_CO2'], | |||
labels={'date_stamp': 'Date and Time', 'value': 'Gas quantity'}, | |||
title='Aquarium methane and CO2') | |||
# Step 4: Customize the plot layout | |||
fig.update_layout(xaxis_title='Date and Time', yaxis_title='Gas quantity') | |||
# Step 5: Save the plot as an HTML file | |||
fig.write_html('/home/pi/Aquarium/methane_aquarium.html') | |||
print("Aquarium plot saved as methane_aquarium.html") | |||
</syntaxhighlight> | |||
Latest revision as of 05:09, 11 June 2024
References
More References
Circuit Diagram
Pinout for Methane Sensor
- NGM2611-E13 - pre-calibrated module for Methane (Figaro)
- Methane Sensor Specifications RS Electrical
- Methane sensor RS
Pinout for CO2 Sensor
- SenseAir K33 LP T/RH CO2 Sensor
- SenseAir K33 LP T/RH CO2 Sensor Specification document
Pinout DHT22 Temperature and Humidity sensor
- DHT22 temperature and humidity sensor
- DHT22 datasheet
Arduino code
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden.
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation.
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
//#include "RTClib.h" //RTC library
#include <cactus_io_DHT22.h>
//#include "cactus_io_DHT22.h" //RH_Temp library
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data)
// milliseconds before writing the logged data permanently to disk
// LOG_INTERVAL write each time (safest)
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
#define ECHO_TO_SERIAL 1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
#define DHT22_PIN 7 // DHT22 (RH_T) data pin
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino.
// The analog pins that connect to the sensors
#define CH4sens A1 //CH4 sensor Vout
#define CH4ref A2 //CH4 sensor Vref
#define Vb A0 //Battery voltage
int CH4s = 0;
int CH4r = 0;
int Vbat = 0;
float CH4smV = 0;
float CH4rmV = 0;
float VbatmV = 0;
float mV = 5000;
float steps = 1024;
//RTC_PCF8523 RTC; // define the Real Time Clock object
RTC_DS1307 RTC;
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
// the logging file
File logfile;
void error(char *str) //Halt if error
{
Serial.print("error: ");
Serial.println(str);
//digitalWrite(redLEDpin, HIGH); // red LED indicates error
while(1); //halt command
}
double RHValue = 0;
double TempValue = 0;
double CO2Value = 0;
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip)
int co2Addr = 0x7F;
///////////////////////////////////////////////////////////////////
// Function : void initPoll()
// Executes : Tells sensor to take a measurement.
// Notes : A fuller implementation would read the register back and
// ensure the flag was set, but in our case we ensure the poll
// period is >25s and life is generally good.
///////////////////////////////////////////////////////////////////
void initPoll() {
Wire.beginTransmission(co2Addr);
Wire.write(0x11);
Wire.write(0x00);
Wire.write(0x60);
Wire.write(0x35);
Wire.write(0xA6);
Wire.endTransmission();
delay(20);
Wire.requestFrom(co2Addr, 2);
byte i = 0;
byte buffer[2] = {0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
}
///////////////////////////////////////////////////////////////////
// Function : double readRH()
// Returns : The current RH Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readRH() {
int RH_value = 0; // We will store the RH value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr);
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte)
Wire.write(0x36); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
RH_value = 0;
RH_value |= buffer[1] & 0xFF;
RH_value = RH_value << 8;
RH_value |= buffer[2] & 0xFF;
Serial.print("RH Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)RH_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readTemp()
// Returns : The current Temperature Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readTemp() {
int Temp_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte)
Wire.write(0x34); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
Temp_value = 0;
Temp_value |= buffer[1] & 0xFF;
Temp_value = Temp_value << 8;
Temp_value |= buffer[2] & 0xFF;
Serial.print("T Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)Temp_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readCO2()
// Returns : The current CO2 Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readCO2() {
int CO2_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data
Wire.write(0x2A); //Checksum
Wire.endTransmission();
delay(50);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
CO2_value = 0;
CO2_value |= buffer[1] & 0xFF;
CO2_value = CO2_value << 8;
CO2_value |= buffer[2] & 0xFF;
Serial.print("CO2 Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)CO2_value * (double) 1);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
void setup(void)
{
Serial.begin(9600);
Serial.println();
dht.begin(); //start RH_T_sensor
//#if WAIT_TO_START
// Serial.println("Type any character to start");
// while (!Serial.available());
//#endif //WAIT_TO_START
// initialize the SD card
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
Serial.println("card initialized.");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
error("couldnt create file");
}
Serial.print("Logging to: ");
Serial.println(filename);
// connect to RTC
Wire.begin();
if (!RTC.begin()) {
logfile.println("RTC failed");
#if ECHO_TO_SERIAL
Serial.println("RTC failed");
#endif //ECHO_TO_SERIAL
}
//if (! RTC.initialized()) {
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
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(2024, 5, 5, 20, 33, 0));
}
logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#if ECHO_TO_SERIAL
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#endif //ECHO_TO_SERIAL
}
char time_to_read_CO2 = 1;
char n_delay_wait = 0;
void loop(){
DateTime now;
if (time_to_read_CO2 == 1) {
initPoll();
delay(50);
CO2Value = readCO2();
delay(20);
RHValue = readRH();
delay(20);
TempValue = readTemp();
// if(RHValue >= 0) {
// Serial.print("RH: ");
// Serial.print(RHValue);
// Serial.print("% | Temp: ");
// Serial.print(TempValue);
// Serial.print("C | CO2: ");
// Serial.print(CO2Value, 0);
// Serial.println("ppm");
// Serial.println();
// }
// else {
// Serial.println(" | Checksum failed / Communication failure");
// }
time_to_read_CO2 = 0;
}
// delay for the amount of time we want between readings
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
// log milliseconds since starting
uint32_t m = millis();
logfile.print(m); // milliseconds since start
logfile.print(", ");
#if ECHO_TO_SERIAL
Serial.print(m); // milliseconds since start
Serial.print(", ");
#endif
// fetch the time
now = RTC.now();
Serial.println(now.unixtime());
// log time
logfile.print(now.unixtime()); // seconds since 1/1/1970
logfile.print(", ");
//logfile.print('"');
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
//logfile.print('"');
#if ECHO_TO_SERIAL
Serial.print(now.unixtime()); // seconds since 1/1/1970
Serial.print(", ");
//Serial.print('"');
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.print(now.second(), DEC);
//Serial.print('"');
#endif //ECHO_TO_SERIAL
// Reading temperature or humidity takes about 250 milliseconds.
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor)
dht.readHumidity();
dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(dht.humidity) || isnan(dht.temperature_C)) {
Serial.print("DHT sensor read failure!");
return;
}
CH4s = analogRead(CH4sens); //read CH4 Vout
CH4smV = CH4s*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
CH4r = analogRead(CH4ref); //read CH4 Vref
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
Vbat = analogRead(Vb); //read CH4 Vref
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider.
delay(10); //delay between reading of different analogue pins adviced.
logfile.print(", ");
logfile.print(dht.humidity);
logfile.print(", ");
logfile.print(dht.temperature_C);
logfile.print(", ");
logfile.print(CH4smV);
logfile.print(", ");
logfile.print(CH4rmV);
logfile.print(", ");
logfile.print(VbatmV);
logfile.print(", ");
logfile.print(RHValue);
logfile.print(", ");
logfile.print(TempValue);
logfile.print(", ");
logfile.print(CO2Value);
#if ECHO_TO_SERIAL
Serial.print(", ");
Serial.print(dht.humidity);
Serial.print(", ");
Serial.print(dht.temperature_C);
Serial.print(", ");
Serial.print(CH4smV);
Serial.print(", ");
Serial.print(CH4rmV);
Serial.print(", ");
Serial.print(VbatmV);
Serial.print(", ");
Serial.print(RHValue);
Serial.print(", ");
Serial.print(TempValue);
Serial.print(", ");
Serial.print(CO2Value);
#endif //ECHO_TO_SERIAL
logfile.println();
#if ECHO_TO_SERIAL
Serial.println();
#endif // ECHO_TO_SERIAL
if (time_to_read_CO2 == 0 ) {
if (n_delay_wait < 29)
n_delay_wait += 1;
else {
time_to_read_CO2 = 1;
Serial.print("Time to read K33 sensor: ");
n_delay_wait = 0;
}
}
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
// which uses power and takes time
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();
logfile.flush();
}
Timestamp example for RTC - Real Time Clock
/* Timestamp functions using a DS1307 RTC connected via I2C and Wire lib
**
** Useful for file name
** ` SD.open(time.timestamp()+".log", FILE_WRITE) `
**
**
** Created: 2015-06-01 by AxelTB
** Last Edit:
*/
#include "RTClib.h"
RTC_DS1307 rtc;
void setup() {
Serial.begin(9600);
rtc.begin();
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
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));
}
}
void loop() {
DateTime time = rtc.now();
//Full Timestamp
Serial.println(String("DateTime::TIMESTAMP_FULL:\t")+time.timestamp(DateTime::TIMESTAMP_FULL));
//Date Only
Serial.println(String("DateTime::TIMESTAMP_DATE:\t")+time.timestamp(DateTime::TIMESTAMP_DATE));
//Full Timestamp
Serial.println(String("DateTime::TIMESTAMP_TIME:\t")+time.timestamp(DateTime::TIMESTAMP_TIME));
Serial.println("\n");
//Delay 5s
delay(5000);
}
Methane and Carbon dioxide sensor sending data to Pi
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden.
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation.
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
//#include "RTClib.h" //RTC library
#include <cactus_io_DHT22.h>
//#include "cactus_io_DHT22.h" //RH_Temp library
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data)
// milliseconds before writing the logged data permanently to disk
// LOG_INTERVAL write each time (safest)
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
#define ECHO_TO_SERIAL 1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
#define DHT22_PIN 7 // DHT22 (RH_T) data pin
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino.
// The analog pins that connect to the sensors
#define CH4sens A1 //CH4 sensor Vout
#define CH4ref A2 //CH4 sensor Vref
#define Vb A0 //Battery voltage
int CH4s = 0;
int CH4r = 0;
int Vbat = 0;
float CH4smV = 0;
float CH4rmV = 0;
float VbatmV = 0;
float mV = 5000;
float steps = 1024;
//RTC_PCF8523 RTC; // define the Real Time Clock object
RTC_DS1307 RTC;
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
// the logging file
File logfile;
void error(char *str) //Halt if error
{
Serial.print("error: ");
Serial.println(str);
//digitalWrite(redLEDpin, HIGH); // red LED indicates error
while(1); //halt command
}
double RHValue = 0;
double TempValue = 0;
double CO2Value = 0;
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip)
int co2Addr = 0x7F;
///////////////////////////////////////////////////////////////////
// Function : void initPoll()
// Executes : Tells sensor to take a measurement.
// Notes : A fuller implementation would read the register back and
// ensure the flag was set, but in our case we ensure the poll
// period is >25s and life is generally good.
///////////////////////////////////////////////////////////////////
void initPoll() {
Wire.beginTransmission(co2Addr);
Wire.write(0x11);
Wire.write(0x00);
Wire.write(0x60);
Wire.write(0x35);
Wire.write(0xA6);
Wire.endTransmission();
delay(20);
Wire.requestFrom(co2Addr, 2);
byte i = 0;
byte buffer[2] = {0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
}
///////////////////////////////////////////////////////////////////
// Function : double readRH()
// Returns : The current RH Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readRH() {
int RH_value = 0; // We will store the RH value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr);
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte)
Wire.write(0x36); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
RH_value = 0;
RH_value |= buffer[1] & 0xFF;
RH_value = RH_value << 8;
RH_value |= buffer[2] & 0xFF;
/*
Serial.print("RH Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)RH_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readTemp()
// Returns : The current Temperature Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readTemp() {
int Temp_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte)
Wire.write(0x34); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
Temp_value = 0;
Temp_value |= buffer[1] & 0xFF;
Temp_value = Temp_value << 8;
Temp_value |= buffer[2] & 0xFF;
/*
Serial.print("T Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)Temp_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readCO2()
// Returns : The current CO2 Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readCO2() {
int CO2_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data
Wire.write(0x2A); //Checksum
Wire.endTransmission();
delay(50);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
CO2_value = 0;
CO2_value |= buffer[1] & 0xFF;
CO2_value = CO2_value << 8;
CO2_value |= buffer[2] & 0xFF;
/*
Serial.print("CO2 Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)CO2_value * (double) 1);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
void setup(void)
{
Serial.begin(9600);
Serial.println();
dht.begin(); //start RH_T_sensor
//#if WAIT_TO_START
// Serial.println("Type any character to start");
// while (!Serial.available());
//#endif //WAIT_TO_START
// initialize the SD card
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
Serial.println("card initialized.");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
error("couldnt create file");
}
Serial.print("Logging to: ");
Serial.println(filename);
// connect to RTC
Wire.begin();
if (!RTC.begin()) {
logfile.println("RTC failed");
#if ECHO_TO_SERIAL
Serial.println("RTC failed");
#endif //ECHO_TO_SERIAL
}
//if (! RTC.initialized()) {
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
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(2024, 5, 5, 20, 33, 0));
}
//Edmond 31 May 2024
//logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#if ECHO_TO_SERIAL
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#endif //ECHO_TO_SERIAL
}
char time_to_read_CO2 = 1;
char n_delay_wait = 0;
void loop(){
DateTime now;
if (time_to_read_CO2 == 1) {
initPoll();
delay(50);
CO2Value = readCO2();
delay(20);
RHValue = readRH();
delay(20);
TempValue = readTemp();
// if(RHValue >= 0) {
// Serial.print("RH: ");
// Serial.print(RHValue);
// Serial.print("% | Temp: ");
// Serial.print(TempValue);
// Serial.print("C | CO2: ");
// Serial.print(CO2Value, 0);
// Serial.println("ppm");
// Serial.println();
// }
// else {
// Serial.println(" | Checksum failed / Communication failure");
// }
time_to_read_CO2 = 0;
}
// delay for the amount of time we want between readings
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
// log milliseconds since starting
uint32_t m = millis();
logfile.print(m); // milliseconds since start
logfile.print(", ");
#if ECHO_TO_SERIAL
//Serial.print(m); // milliseconds since start
//Serial.print(", ");
#endif
// fetch the time
now = RTC.now();
//Serial.println(now.unixtime());
// log time
/*
logfile.print(now.unixtime()); // seconds since 1/1/1970
logfile.print(", ");
//logfile.print('"');
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
//logfile.print('"');
*/
#if ECHO_TO_SERIAL
Serial.print(now.unixtime()); // seconds since 1/1/1970
Serial.print(",");
//Serial.print('"');
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.print(now.second(), DEC);
//Serial.print('"');
#endif //ECHO_TO_SERIAL
// Reading temperature or humidity takes about 250 milliseconds.
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor)
dht.readHumidity();
dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(dht.humidity) || isnan(dht.temperature_C)) {
Serial.print("DHT sensor read failure!");
return;
}
CH4s = analogRead(CH4sens); //read CH4 Vout
CH4smV = CH4s*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
CH4r = analogRead(CH4ref); //read CH4 Vref
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
Vbat = analogRead(Vb); //read CH4 Vref
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider.
delay(10); //delay between reading of different analogue pins adviced.
/*
logfile.print(", ");
logfile.print(dht.humidity);
logfile.print(", ");
logfile.print(dht.temperature_C);
logfile.print(", ");
logfile.print(CH4smV);
logfile.print(", ");
logfile.print(CH4rmV);
logfile.print(", ");
logfile.print(VbatmV);
logfile.print(", ");
logfile.print(RHValue);
logfile.print(", ");
logfile.print(TempValue);
logfile.print(", ");
logfile.print(CO2Value);
*/
#if ECHO_TO_SERIAL
Serial.print(",");
Serial.print(dht.humidity);
Serial.print(",");
Serial.print(dht.temperature_C);
Serial.print(",");
Serial.print(CH4smV);
Serial.print(",");
Serial.print(CH4rmV);
Serial.print(",");
Serial.print(VbatmV);
Serial.print(",");
Serial.print(RHValue);
Serial.print(",");
Serial.print(TempValue);
Serial.print(",");
Serial.print(CO2Value);
#endif //ECHO_TO_SERIAL
/*
logfile.println();
*/
#if ECHO_TO_SERIAL
Serial.println();
#endif // ECHO_TO_SERIAL
if (time_to_read_CO2 == 0 ) {
if (n_delay_wait < 29)
n_delay_wait += 1;
else {
time_to_read_CO2 = 1;
/*
Serial.print("Time to read K33 sensor: ");
*/
n_delay_wait = 0;
}
}
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
// which uses power and takes time
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();
/*
logfile.flush();
*/
}
Methane and Carbon dioxide sensor sending data to Pi
Python code
#!/usr/bin/env python3
# dweet data
import serial
import datetime
import time
import requests
import pandas as pd
import plotly.express as px
from water_variables import *
count = 0
if __name__ == '__main__':
# methane
ser = serial.Serial('/dev/ttyUSB1', 9600, timeout=1)
ser.reset_input_buffer()
while True:
count = count + 1
time.sleep(0.1)
if ser.in_waiting > 0:
time.sleep(0.1)
try:
line = ser.readline().decode('utf-8').rstrip()
print(line)
except:
line = "0,0,0,0,0,0,0,0,0,0"
#print(f"Data separated using commas {line.split(',')}")
mylist = line.split(',')
print(f'My list {mylist}')
try:
# stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2
stampunix = str(mylist[0])
date_time_not_used = str(mylist[1])
RH1 = str(mylist[2])
temp1 = str(mylist[3])
CH4smV = str(mylist[4])
CH4rmV = str(mylist[5])
VbatmV = str(mylist[6])
K33_RH = str(mylist[7])
K33_Temp = str(mylist[8])
K33_CO2 = str(mylist[9])
print("data extracted")
except:
stampunix = "0.0"
date_time_not_used = "0.0"
RH1 = "0.0"
temp1 = "0.0"
CH4smV = "0.0"
CH4rmV = "0"
VbatmV = "0.0"
K33_RH = "0.0"
K33_Temp = "0.0"
K33_CO2 = "0.0"
now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")
print(f'CH4smV - {CH4smV}, K33_CO2 - {K33_CO2}, time - {date_stamp}')
print(count)
print()
time.sleep(0.1)
data = ""
data = date_stamp + "," + str(RH1) + "," + str(temp1) + "," + str(CH4smV) + "," +\
str(CH4rmV) + "," + str(VbatmV) + "," + str(K33_RH) + "," + \
str(K33_Temp) + "," + str(K33_CO2) + '\n'
#print(f'The data is = {data}')
if count > 3000:
#print(count)
f = open('/home/pi/Aquarium/aquarium_methane.txt','a')
f.write(data)
f.close()
print("Data saved")
try:
print("Preparing dweet")
dweet_dict = {}
dweet_dict.update({"RH1": str(RH1)})
dweet_dict.update({"temp1": str(temp1)})
dweet_dict.update({"CH4smV": str(CH4smV)})
dweet_dict.update({"CH4rmV": str(CH4rmV)})
dweet_dict.update({"VbatmV": str(VbatmV)})
dweet_dict.update({"K33_RH": str(K33_RH)})
dweet_dict.update({"K33_Temp": str(K33_Temp)})
dweet_dict.update({"K33_CO2": str(K33_CO2)})
dweet_dict.update({"time": str(date_stamp)})
url = "https://dweet.io/dweet/for/3083-Bundoora-aquarium_methane1?"
#https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium_methane1?
x = requests.post(url, json=dweet_dict)
print(x.text)
except:
print("Dweet failed")
count = 0
# check dweet with - https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium1
# Step 2: Read the data from the text file into a Pandas DataFrame
#data = pd.read_csv('/home/pi/Aquarium/aquarium_methane.txt')
# Step 3: Create a Plotly figure with two scatter plots
#fig = px.scatter(data, x='datetime', y=['temperature','dissolvedOxygen'],
#labels={'datetime': 'Date and Time', 'value': 'Temperature (°C)'},
#title='Aquarium temperature and DO')
# Step 4: Customize the plot layout
#fig.update_layout(xaxis_title='Date and Time', yaxis_title='Temperature (°C)')
# Step 5: Save the plot as an HTML file
#fig.write_html('/home/pi/Aquarium/temperature_plot_DO_EC_chem_aquarium.html')
#print("Aquarium plot saved as temperature_plot.html")
Working Arduino Code 6 June 2024
// A simple CH4, CO2, RH, T data logger for the Arduino analog pins
// By David Bastviken and Nguyen Thanh Duc, Linkoping University, Sweden.
//Thanks to cactus.io and Adafruit for code components. For setup of RTC, see separate logger shield documentation.
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
//#include "RTClib.h" //RTC library
#include <cactus_io_DHT22.h>
//#include "cactus_io_DHT22.h" //RH_Temp library
#define LOG_INTERVAL 2000 // mills between logging entries (reduce to take more/faster data)
// milliseconds before writing the logged data permanently to disk
// LOG_INTERVAL write each time (safest)
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
#define ECHO_TO_SERIAL 1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
#define DHT22_PIN 7 // DHT22 (RH_T) data pin
DHT22 dht(DHT22_PIN); // Initialize DHT sensor for normal 16mhz Arduino.
// The analog pins that connect to the sensors
#define CH4sens A1 //CH4 sensor Vout
#define CH4ref A2 //CH4 sensor Vref
#define Vb A0 //Battery voltage
int CH4s = 0;
int CH4r = 0;
int Vbat = 0;
float CH4smV = 0;
float CH4rmV = 0;
float VbatmV = 0;
float mV = 5000;
float steps = 1024;
//RTC_PCF8523 RTC; // define the Real Time Clock object
RTC_DS1307 RTC;
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
// the logging file
File logfile;
void error(char *str) //Halt if error
{
Serial.print("error: ");
Serial.println(str);
//digitalWrite(redLEDpin, HIGH); // red LED indicates error
while(1); //halt command
}
double RHValue = 0;
double TempValue = 0;
double CO2Value = 0;
// This is the modified address of the CO2 sensor, 7bits shifted left (defaul 0x68, but collide with RTC chip)
int co2Addr = 0x7F;
///////////////////////////////////////////////////////////////////
// Function : void initPoll()
// Executes : Tells sensor to take a measurement.
// Notes : A fuller implementation would read the register back and
// ensure the flag was set, but in our case we ensure the poll
// period is >25s and life is generally good.
///////////////////////////////////////////////////////////////////
void initPoll() {
Wire.beginTransmission(co2Addr);
Wire.write(0x11);
Wire.write(0x00);
Wire.write(0x60);
Wire.write(0x35);
Wire.write(0xA6);
Wire.endTransmission();
delay(20);
Wire.requestFrom(co2Addr, 2);
byte i = 0;
byte buffer[2] = {0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
}
///////////////////////////////////////////////////////////////////
// Function : double readRH()
// Returns : The current RH Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readRH() {
int RH_value = 0; // We will store the RH value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr);
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x14); //Two bytes starting from 0x14 (high byte) and 0x15 (low byte)
Wire.write(0x36); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
RH_value = 0;
RH_value |= buffer[1] & 0xFF;
RH_value = RH_value << 8;
RH_value |= buffer[2] & 0xFF;
/*
Serial.print("RH Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)RH_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readTemp()
// Returns : The current Temperature Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readTemp() {
int Temp_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x12); //Two bytes starting from 0x12 (high byte) and 0x13 (low byte)
Wire.write(0x34); //Checksum
Wire.endTransmission();
delay(20);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
Temp_value = 0;
Temp_value |= buffer[1] & 0xFF;
Temp_value = Temp_value << 8;
Temp_value |= buffer[2] & 0xFF;
/*
Serial.print("T Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)Temp_value / (double) 100);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
///////////////////////////////////////////////////////////////////
// Function : double readCO2()
// Returns : The current CO2 Value, ?1 if error has occured
///////////////////////////////////////////////////////////////////
double readCO2() {
int CO2_value = 0; // We will store the temperature value inside this variable.
digitalWrite(13, HIGH);
//////////////////////////
/* Begin Write Sequence */
//////////////////////////
Wire.beginTransmission(co2Addr); //int K33 == 0x68
Wire.write(0x22); //Command number 2 (Read Ram, 2 bytes)
Wire.write(0x00); //Sensor address in ?? EEPROM ??
Wire.write(0x08); //Two bytes starting from 0x08 (high byte) and 0x09 (low byte). They contain the CO2 data
Wire.write(0x2A); //Checksum
Wire.endTransmission();
delay(50);
/////////////////////////
/* Begin Read Sequence */
/////////////////////////
Wire.requestFrom(co2Addr, 4);
byte i = 0;
byte buffer[4] = {0, 0, 0, 0};
while(Wire.available()) {
buffer[i] = Wire.read();
i++;
}
CO2_value = 0;
CO2_value |= buffer[1] & 0xFF;
CO2_value = CO2_value << 8;
CO2_value |= buffer[2] & 0xFF;
/*
Serial.print("CO2 Data ");
Serial.print(buffer[0], HEX);
Serial.print("|");
Serial.print(buffer[1], HEX);
Serial.print("|");
Serial.print(buffer[2], HEX);
Serial.print("|");
Serial.println(buffer[3], HEX);
*/
byte sum = 0; //Checksum Byte
sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
if(sum == buffer[3]) {
// Success!
digitalWrite(13, LOW);
delay(10);
return ((double)CO2_value * (double) 1);
}
else {
// Failure!
digitalWrite(13, LOW);
delay(10);
return ((double) -1);
}
}
void setup(void)
{
Serial.begin(9600);
Serial.println();
dht.begin(); //start RH_T_sensor
//#if WAIT_TO_START
// Serial.println("Type any character to start");
// while (!Serial.available());
//#endif //WAIT_TO_START
// initialize the SD card
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
Serial.println("card initialized.");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
error("couldnt create file");
}
Serial.print("Logging to: ");
Serial.println(filename);
// connect to RTC
Wire.begin();
if (!RTC.begin()) {
logfile.println("RTC failed");
#if ECHO_TO_SERIAL
Serial.println("RTC failed");
#endif //ECHO_TO_SERIAL
}
//if (! RTC.initialized()) {
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
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(2024, 5, 5, 20, 33, 0));
}
//Edmond 31 May 2024
//logfile.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#if ECHO_TO_SERIAL
Serial.println("millis,stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2");
#endif //ECHO_TO_SERIAL
}
char time_to_read_CO2 = 1;
char n_delay_wait = 0;
void loop(){
DateTime now;
if (time_to_read_CO2 == 1) {
initPoll();
delay(50);
CO2Value = readCO2();
delay(20);
RHValue = readRH();
delay(20);
TempValue = readTemp();
// if(RHValue >= 0) {
// Serial.print("RH: ");
// Serial.print(RHValue);
// Serial.print("% | Temp: ");
// Serial.print(TempValue);
// Serial.print("C | CO2: ");
// Serial.print(CO2Value, 0);
// Serial.println("ppm");
// Serial.println();
// }
// else {
// Serial.println(" | Checksum failed / Communication failure");
// }
time_to_read_CO2 = 0;
}
// delay for the amount of time we want between readings
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
// log milliseconds since starting
uint32_t m = millis();
logfile.print(m); // milliseconds since start
logfile.print(", ");
#if ECHO_TO_SERIAL
//Serial.print(m); // milliseconds since start
//Serial.print(", ");
#endif
// fetch the time
now = RTC.now();
//Serial.println(now.unixtime());
// log time
/*
logfile.print(now.unixtime()); // seconds since 1/1/1970
logfile.print(", ");
//logfile.print('"');
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
//logfile.print('"');
*/
#if ECHO_TO_SERIAL
Serial.print(now.unixtime()); // seconds since 1/1/1970
Serial.print(",");
//Serial.print('"');
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.print(now.second(), DEC);
//Serial.print('"');
#endif //ECHO_TO_SERIAL
// Reading temperature or humidity takes about 250 milliseconds.
// Sensor readings may also be up to 2 seconds 'old' (its a slow sensor)
dht.readHumidity();
dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(dht.humidity) || isnan(dht.temperature_C)) {
Serial.print("DHT sensor read failure!");
return;
}
CH4s = analogRead(CH4sens); //read CH4 Vout
CH4smV = CH4s*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
CH4r = analogRead(CH4ref); //read CH4 Vref
CH4rmV = CH4r*(mV/steps); //convert pin reading to mV
delay(10); //delay between reading of different analogue pins adviced.
Vbat = analogRead(Vb); //read CH4 Vref
VbatmV = Vbat *(mV/steps); //convert pin reading to mV, NOT YET correcting for the voltage divider.
delay(10); //delay between reading of different analogue pins adviced.
/*
logfile.print(", ");
logfile.print(dht.humidity);
logfile.print(", ");
logfile.print(dht.temperature_C);
logfile.print(", ");
logfile.print(CH4smV);
logfile.print(", ");
logfile.print(CH4rmV);
logfile.print(", ");
logfile.print(VbatmV);
logfile.print(", ");
logfile.print(RHValue);
logfile.print(", ");
logfile.print(TempValue);
logfile.print(", ");
logfile.print(CO2Value);
*/
#if ECHO_TO_SERIAL
Serial.print(",");
Serial.print(dht.humidity);
Serial.print(",");
Serial.print(dht.temperature_C);
Serial.print(",");
Serial.print(CH4smV);
Serial.print(",");
Serial.print(CH4rmV);
Serial.print(",");
Serial.print(VbatmV);
Serial.print(",");
Serial.print(RHValue);
Serial.print(",");
Serial.print(TempValue);
Serial.print(",");
Serial.print(CO2Value);
#endif //ECHO_TO_SERIAL
/*
logfile.println();
*/
#if ECHO_TO_SERIAL
Serial.println();
#endif // ECHO_TO_SERIAL
if (time_to_read_CO2 == 0 ) {
if (n_delay_wait < 29)
n_delay_wait += 1;
else {
time_to_read_CO2 = 1;
/*
Serial.print("Time to read K33 sensor: ");
*/
n_delay_wait = 0;
}
}
// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
// which uses power and takes time
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();
/*
logfile.flush();
*/
}
Working Python Code 6 June 2024
#!/usr/bin/env python3
# dweet data
import serial
import datetime
import time
import requests
import pandas as pd
import plotly.express as px
from water_variables import *
count = 0
if __name__ == '__main__':
# methane
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
ser.reset_input_buffer()
while True:
count = count + 1
time.sleep(0.1)
if ser.in_waiting > 0:
time.sleep(0.1)
try:
line = ser.readline().decode('utf-8').rstrip()
print(line)
except:
line = "0,0,0,0,0,0,0,0,0,0"
#print(f"Data separated using commas {line.split(',')}")
mylist = line.split(',')
print(f'My list {mylist}')
try:
# stampunix,datetime,RH%,tempC,CH4smV, CH4rmV, VbatmV, K33_RH, K33_Temp, K33_CO2
stampunix = str(mylist[0])
date_time_not_used = str(mylist[1])
RH1 = str(mylist[2])
temp1 = str(mylist[3])
CH4smV = str(mylist[4])
CH4rmV = str(mylist[5])
VbatmV = str(mylist[6])
K33_RH = str(mylist[7])
K33_Temp = str(mylist[8])
K33_CO2 = str(mylist[9])
print("data extracted")
except:
stampunix = "0.0"
date_time_not_used = "0.0"
RH1 = "0.0"
temp1 = "0.0"
CH4smV = "0.0"
CH4rmV = "0"
VbatmV = "0.0"
K33_RH = "0.0"
K33_Temp = "0.0"
K33_CO2 = "0.0"
now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")
print(f'CH4smV - {CH4smV}, K33_CO2 - {K33_CO2}, time - {date_stamp}')
print(count)
print()
time.sleep(0.1)
data = ""
data = date_stamp + "," + str(RH1) + "," + str(temp1) + "," + str(CH4smV) + "," +\
str(CH4rmV) + "," + str(VbatmV) + "," + str(K33_RH) + "," + \
str(K33_Temp) + "," + str(K33_CO2) + '\n'
#print(f'The data is = {data}')
if count > 3000 and K33_CO2 != "0.00":
#print(count)
f = open('/home/pi/Aquarium/aquarium_methane.txt','a')
f.write(data)
f.close()
print("Data saved")
try:
print("Preparing dweet")
dweet_dict = {}
dweet_dict.update({"RH1": str(RH1)})
dweet_dict.update({"temp1": str(temp1)})
dweet_dict.update({"CH4smV": str(CH4smV)})
dweet_dict.update({"CH4rmV": str(CH4rmV)})
dweet_dict.update({"VbatmV": str(VbatmV)})
dweet_dict.update({"K33_RH": str(K33_RH)})
dweet_dict.update({"K33_Temp": str(K33_Temp)})
dweet_dict.update({"K33_CO2": str(K33_CO2)})
dweet_dict.update({"time": str(date_stamp)})
url = "https://dweet.io/dweet/for/3083-Bundoora-aquarium_methane1?"
#https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium_methane1?
x = requests.post(url, json=dweet_dict)
print(x.text)
except:
print("Dweet failed")
count = 0
# check dweet with - https://dweet.io/get/latest/dweet/for/3083-Bundoora-aquarium1
# Step 2: Read the data from the text file into a Pandas DataFrame
data = pd.read_csv('/home/pi/Aquarium/aquarium_methane.txt')
# Step 3: Create a Plotly figure with two scatter plots
fig = px.scatter(data, x='date_stamp', y=['CH4rmV','K33_CO2'],
labels={'date_stamp': 'Date and Time', 'value': 'Gas quantity'},
title='Aquarium methane and CO2')
# Step 4: Customize the plot layout
fig.update_layout(xaxis_title='Date and Time', yaxis_title='Gas quantity')
# Step 5: Save the plot as an HTML file
fig.write_html('/home/pi/Aquarium/methane_aquarium.html')
print("Aquarium plot saved as methane_aquarium.html")