diff --git a/cvd_safety/README.md b/cvd_safety/README.md new file mode 100644 index 0000000..36cf8ba --- /dev/null +++ b/cvd_safety/README.md @@ -0,0 +1,31 @@ +## Alert System for use with CVD Systems + +The code in this module implements a QDA (Quazar Data Acquisition System) based approach to detect malfunction in the CVD (Chemical Vapour Deposition) setup. + +The following parameters are monitored : + 1. Smoke Concentration + 2. LPG Concentration + 3. Methane Concentration + 4. Hydrogen Concentration + 5. Temperature outside the CVD furnace + +## Hardware Setup + +- QDAL414B (Qty : 1) +- MQ-2 Gas Sensors (Qty : 2) +- PT100 Temperature Sensors (Qty : 2) + +The MQ-2 are interfaced to Channel-1 and Channel-2 of QDAL414B. The PT100 Temperature Sensors are interfaced to Channel-3 and Channel-4. + +The QDAL414B is connected to a computer using a USB interface. + +## Prerequisites + +- Configure ssmtp to send mail from the terminal using your gmail account. +- Install QDAL41xB driver + +## Usage + +- Compile using `make`. Make sure the QDAL41xB driver is installed before this step. +- Make sure the QDAL414B is connected and powered on. +- Use `./test` to execute the program diff --git a/cvd_safety/alarm.wav b/cvd_safety/alarm.wav new file mode 100644 index 0000000..77c02a3 Binary files /dev/null and b/cvd_safety/alarm.wav differ diff --git a/cvd_safety/lab_safety_iQ.cxx b/cvd_safety/lab_safety_iQ.cxx new file mode 100644 index 0000000..676c7ba --- /dev/null +++ b/cvd_safety/lab_safety_iQ.cxx @@ -0,0 +1,268 @@ +// g++ -pthread -Wall -O3 -std=c++14 test.cxx -o test -lL412B -lftdi + +// QDAL41xB specific driver libraries +#include + +// LiveData datastructure defined here +#include + +// Standard libraries +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Constant definitions +#define SMOKE_SENS_THRESHOLD 1.15 +#define TEMP_SENS_THRESHOLD 115.0 + +#define PRINT_PRECISION 8 + +void send_alert (int channel); +void add_status_to_email (std::string status); +void open_gas_valves (std::unique_ptr &driver); +void close_gas_valves (std::unique_ptr &driver); + +int main (void) +{ + + /*************************************************** + * Looks for L41x type of devices. + ***************************************************/ + auto device_list = L412B::Driver::scan(); + + /*************************************************** + * If no device is detected, gracefully return + * with -1 exit status. + ***************************************************/ + if (device_list.empty()) + { + std::cout << "No QDA device found." << std::endl; + return (-1); + } + + /*************************************************** + * Get the Serial number of the first QDAL41xB device + * found. All subsequent instructions for data + * acquisition will refer to this QDAL41xB device + ***************************************************/ + auto serialNo = device_list[0].serialNo(); + std::cout << "Serial No:" << serialNo <(); + std::cout << "driver type is " << typeid(driver).name() << std::endl; + + /*************************************************** + * Connect to QDAL41xB device + ***************************************************/ + driver->connect (serialNo); + + std::cout << "Press Enter to open gas valves and start monitoring" << std::endl; + std::cin.ignore(); + open_gas_valves(driver); + + /*************************************************** + * Start acquiring data from the QDAL41xB + ***************************************************/ + driver->start_acquisition (); + + + while(1) + { + /*************************************************** + * Stream collected data from the QDAL41xB device + ***************************************************/ + auto live_data = driver->live_data(); + + /*************************************************** + * live_data is a std::vector + * LiveData is defined in driver/include/Data.h + * LiveData.time() : Returns the time axis value (double) of the data + * LiveData.chn() : QDAL41xB channel (int) where the data originated + * LiveData.data() : Returns the data value (float) + * LiveData.logical_chn() : float /Use : TODO/ + ***************************************************/ + + /*************************************************** + * Keep polling until data is available + ***************************************************/ + if (live_data.empty()) continue; + + + /*************************************************** + * If data is available, check for threshold violations + ***************************************************/ + for (unsigned int i = 0; i < live_data.size(); i++) + { + // Checking data points spaced 1 second apart + double intpart = 0.0; + + // Compare fractional part of time to zero + if (std::modf (live_data[i].time() * 1.0, &intpart) == 0.00) + { + // Data for Channel-1 (Smoke Sensor) + if (live_data[i].chn() == 0) + { + // Display data on terminal + std::cout << std::setprecision(PRINT_PRECISION) << "Time : \a" << live_data[i].time() << "\t Chn 1: " << live_data[i].data() << "\t"; + + // Alert if signal is above threshold + if (live_data[i].data() > SMOKE_SENS_THRESHOLD) + { + close_gas_valves (driver); + send_alert (live_data[i].chn()); + break; + } + + } + + // Data for Channel-2 (Smoke Sensor) + if (live_data[i].chn() == 1) + { + std::cout << std::setprecision(PRINT_PRECISION) << "Time : \a" << live_data[i].time() << "\t Chn 2: " << live_data[i].data() << std::endl; + + // Alert if signal is above threshold + if (live_data[i].data() > SMOKE_SENS_THRESHOLD) + { + close_gas_valves (driver); + send_alert (live_data[i].chn()); + break; + } + + } + + // Data for Channel-3 (Temperature Sensor) + if (live_data[i].chn() == 2) + { + std::cout << std::setprecision(PRINT_PRECISION) << "Time : \a" << live_data[i].time() << "\t Chn 3: " << live_data[i].data() << "\t"; + + // Alert if signal is above threshold + if (live_data[i].data() > TEMP_SENS_THRESHOLD) + { + close_gas_valves (driver); + send_alert (live_data[i].chn()); + break; + } + + } + + // Data for Channel-4 (Temperature Sensor) + if (live_data[i].chn() == 3) + { + std::cout << std::setprecision(PRINT_PRECISION) << "Time : \a" << live_data[i].time() << "\t Chn 4: " << live_data[i].data() << "\n" << std::endl; + + // Alert if signal is above threshold + if (live_data[i].data() > TEMP_SENS_THRESHOLD) + { + close_gas_valves (driver); + send_alert (live_data[i].chn()); + break; + } + } + + } + + } + + } // while (1) + + /*************************************************** + * Stop acquisition + ***************************************************/ + driver->stop_acquisition (); + + /*************************************************** + * Disconnect QDAL41xB device + ***************************************************/ + driver->disconnect(); + + return 0; + +} // end main + +void add_status_to_email (std::string status) +{ + // Open mail.txt to append data to end of file + ofstream mail_file; + mail_file.open ("mail.txt", ios::out | ios::app); + + if (mail_file.is_open()) + { + mail_file << status; + mail_file.close(); + } + + else + { + std::cout << "Unable to add alert status to mail." << std::endl; + } + + +} + +void open_gas_valves (std::unique_ptr &driver) +{ + std::cout << "Switching on all gas supplies!" << std::endl; + uint8_t data = 0b00000001; + driver->clr_gpo (data); +} + +void close_gas_valves (std::unique_ptr &driver) +{ + std::cout << "Switching off all gas supplies!" << std::endl; + uint8_t data = 0b00000001; + driver->set_gpo (data); +} + +void send_alert (int channel) +{ + std::string status; + + switch (channel) + { + case 0 : status = "Smoke Sensor 1 : HIGH"; + break; + case 1 : status = "Smoke Sensor 2 : HIGH"; + break; + case 2 : status = "Temperature Sensor 1 : HIGH"; + break; + case 3 : status = "Temperature Sensor 2 : HIGH"; + break; + default : status = "Alert! Cause : Unknown"; + break; + } + + // Display Alert status on terminal + std::cout << "\n\n\t\t ****** DANGER ******" << std::endl; + std::cout << "\nAlert Status" << std::endl; + std::cout << "*********************" << std::endl; + std::cout << status << "\n" << std::endl; + + // Update alert email with alert status + add_status_to_email ("\n\nAlert Status\n"); + add_status_to_email ("*******************\n"); + add_status_to_email (status); + + std::cout << "Sending alert mails..." << std::endl; + // Send email to gitansh@quazartech.com + system("ssmtp gitansh@quazartech.com < mail.txt"); + + // Send email to mani@quazartech.com + system("ssmtp mani@quazartech.com < mail.txt"); + +// // Send email to kc@quazartech.com +// system("ssmtp kc@quazartech.com < mail.txt"); + + // Send email to nishant@quazartech.com + system("ssmtp nishant@quazartech.com < mail.txt"); + + std::cout << "\t \t Alert mails sent." << std::endl; + system("aplay alarm.wav"); +} \ No newline at end of file diff --git a/cvd_safety/mail.txt b/cvd_safety/mail.txt new file mode 100644 index 0000000..f3d38c4 --- /dev/null +++ b/cvd_safety/mail.txt @@ -0,0 +1,55 @@ +From: gitansh95@gmail.com +Subject: Testing : CVD UNUSUAL ACTIVITY ALERT! + +IMMEDIATE ATTENTION REQUIRED! +The gas leakage and temperature monitoring systems have detected unusual levels. Possible risk of FIRE! +Location : Quazar Tech. Workshop, 103b, Begumpur Village, New Delhi + +PEASE SEE LAST LINE OF THIS EMAIL FOR THE CAUSE OF ALERT. + + + *^^^*///// + *.* + *****(/(***** (TEMP SENSOR-1) (TEMP SENSOR-2) + ( ) .-------------------------------------------------. + ,,,,,,,,( ),,,,,,,. | | + Pressure ,,. ( ) ,,. | Tubular Furnace | + Regulator ,,. (***********) ,,. | QBAKE1200 | + ,,. On/Off Valve ,,. | | + (***/********, ,,. ,,. | | + *#/(/ ,,. ,,. | | + ___ .. ,,. |-----------| ,,. | | + / \ * / ,,. | | ,,. (********************************************************) + < * > ./ /,,,,,,,,,,,,,| |,,,,,,,,,,,,,,,,,(********************************************************),,,. + \ / . / | | (********************************************************) ,,. + / \ |___________| |.................................................| ,,. + .///(((///( Restrictor ,,. + |,,,,,,,,,,| (SMOKE SENSOR-1) (SMOKE SENSOR-2) ,,. + |,,,,,,,,,,| ,,. + |,,,,,,,,,,| ,,. + |,,,,,,,,,,| ,,. + |,,,,,,,,,,| ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| / \ ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| | | ,,. + |,,,,,,,,,,| .* *. ,,. + |,,,,,,,,,,| \ / ,,. + |,,,,,,,,,,| . .,,,,,,,,,,,,,,,,,,,,,. + |,,,,,,,,,,| . ,,,,,,,,,,,,,,,,,,,,,,. + |,,,,,,,,,,| / \ + |,,,,,,,,,,| * * + |,,,,,,,,,,| \ / + |,,,,,,,,,,| ^^^ + |,,,,,,,,,,| Soap Bubble Meter + |,,,,,,,,,,| + |,,,,,,,,,,| Oxygen Cylinder + |,,,,,,,,,,| (Grade-1) + |,,,,,,,,,,| + \,,,,,,,,/ diff --git a/cvd_safety/makefile b/cvd_safety/makefile new file mode 100644 index 0000000..80c5679 --- /dev/null +++ b/cvd_safety/makefile @@ -0,0 +1,15 @@ +objects = lab_safety_iQ.o + +CC = "/usr/bin/g++" + +test : $(objects) + @ echo Building $@ + $(CC) -o test lab_safety_iQ.o -pthread -Wall -O3 -std=c++14 -lL412B -lftdi + +lab_safety_iQ.o : lab_safety_iQ.cxx + $(CC) -c lab_safety_iQ.cxx -pthread -Wall -O3 -std=c++14 -lL412B -lftdi + +.PHONY : clean +clean : + @ echo Cleaning... + rm -f test $(objects) \ No newline at end of file