Tuesday, October 9, 2018

Wooden Chest Air Quality Monitor

A compact air quality, temperature and humidity monitor enclosed in a small wooden chest, with a four-row LCD display.
Wooden Chest Air Quality Monitor

Hardware components

Arduino UNO & Genuino UNO
DHT11 Temperature & Humidity Sensor

PHPoC Shield for Arduino

Software apps and online services

Arduino IDE

Story



A project completed to measure the air condition in a diesel polluted building. Then the final design enclosed in a wooden box to demonstrate its function to apprentices for inspiration for their projects.
testing sensitivity to fumes using a permanent marker pen


Schematics


Capture off fritzing yxwkogotqw

Code

//***************************************************************************
//  This is a library for the CCS811 air 

//  This sketch reads the sensor

//  Designed specifically to work with the Adafruit CCS811 breakout
//  ----> http://www.adafruit.com/products/3566

 // These sensors use I2C to communicate. The device's I2C address is 0x5A 

#include <SD.h>            // sd card
#include <Wire.h>
#include "RTClib.h"      // real time clock
#include <DHT.h>                                                   // load lib dht11
#include "Adafruit_CCS811.h"
#include "Arduino.h"
#include "LiquidCrystal_PCF8574.h"

#define LCD_ADDRESS 0x27                                       // Define LCD characteristics
#define LCD_ROWS 4
#define LCD_COLUMNS 20
#define SCROLL_DELAY 150
#define BACKLIGHT 255                                         // object initialization
#define dht_apin 2
#define dht_type DHT11

int n = 1;
int val;                                                   // A simple data logger for the Arduino analog pins  

#define LOG_INTERVAL  1000 // mills between entries (reduce to take more/faster data)

                                                      // how many milliseconds before writing the logged data permanently to disk
                                                      // set it to the LOG_INTERVAL to write each time (safest)
                                                      // set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
                                                      // the last 10 reads if power is lost but it uses less power and is much faster!

#define SYNC_INTERVAL 10000 // mills between calls to flush() - to write data to the card 600000 = 10 minutes
uint32_t syncTime = 0; // time of last sync()


RTC_DS1307 RTC;                                         // define the Real Time Clock object


const int chipSelect = 10;                             // for the data logging shield, we use digital pin 10 for the SD cs line


DHT dht(dht_apin, dht_type);                          // sensor pin S to pin11

LiquidCrystal_PCF8574 lcdI2C;
Adafruit_CCS811 ccs;


File logfile;

void error(char *str)
{
  Serial.print(F("error: "));
  Serial.println(str);
}


void setup() {

 Serial.begin(9600);

  // initialize the SD card
  Serial.print(F("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(F("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(F("Logging to: "));
  Serial.println(filename);

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println(F("RTC failed"));
#endif  //ECHO_TO_SERIAL
  }
  

  logfile.println("datetime,co2  ,tvoc  ,Humidity  ,Temperature ");    
//#if ECHO_TO_SERIAL
//  Serial.println("..........,......,datetime,.....,......,......");
//#endif //ECHO_TO_SERIAL
 
  // If you want to set the aref to something other than 5v
  analogReference(EXTERNAL);
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT); 
  Serial.println(F("CCS811 test"));
  lcdI2C.print("     CCS811 test" );
  lcdI2C.setCursor (0,1); 
  lcdI2C.print("     warming up" );
  lcdI2C.setCursor (0,2);
  lcdI2C.print("data logger file No." );
  lcdI2C.setCursor (0,3);
  lcdI2C.println(filename);
  if(!ccs.begin()){
  Serial.println(F("Failed to start sensor! Please check your wiring."));
  while(1);
  }
  //calibrate temperature sensor
  while(!ccs.available());
  float temp = ccs.calculateTemperature();
  ccs.setTempOffset(temp - 25.0);

 delay(10000);                       // wait for 10 seconds
   lcdI2C.clear();                          // Clear LCD screen.
  
}

void loop() {
    float h = dht.readHumidity();
    float f = dht.readTemperature();
    if(ccs.available()){
    float temp = ccs.calculateTemperature();
    if(!ccs.readData()){
     
DateTime now;
 
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));   // delay for the amount of time we want between readings
   
  now = RTC.now();  // fetch the time

 int H = now.hour(); // Get the hours right now and store them in an integer called h
 int M = now.minute(); // Get the minutes right now and store them in an integer called m
 int S = now.second(); // Get the seconds right now and store them in an integer called s
  
  logfile.print(now.year(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.day(), DEC);
  logfile.print(" ");
  if (H<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  if (M<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  if (S<10){   // Add a zero, if necessary, as above
  logfile.print(0);
 }
  logfile.print(now.second(), DEC);
  logfile.print('"');
  Serial.print('"');
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  if (H<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  if (M<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.minute(), DEC);
  Serial.print(F(":"));
  if (S<10){   // Add a zero, if necessary, as above
  Serial.print(0);
 }
  Serial.print(now.second(), DEC);
  Serial.print(F("    "));
  Serial.print(F("CO2: "));
  Serial.print(ccs.geteCO2());
  Serial.print(F("ppm, TVOC: "));
  Serial.print(ccs.getTVOC());
  Serial.print(F("ppb   Temp:"));
  Serial.println(f);                          // temp from dht11
    
    
    lcdI2C.setCursor (0,0);  
    lcdI2C.print ("CO2  ");  
    lcdI2C.setCursor (5,0);  
    lcdI2C.print ("       ");
    lcdI2C.setCursor (5,0); 
    lcdI2C.print(ccs.geteCO2());              // Print print String to LCD on first line
    lcdI2C.setCursor (0,1);                    // Set cursor at the begining of line 2
    lcdI2C.print ("tVOC ");
    lcdI2C.print(ccs.getTVOC());          // Print print String to LCD on second line
    lcdI2C.print ("     ");
    lcdI2C.setCursor (12,1); 
    if (H<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
    }
    lcdI2C.print(now.hour(), DEC);
    lcdI2C.print (":");
    if (M<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
 }
    lcdI2C.print(now.minute(), DEC);
    lcdI2C.print (":");
    if (S<10){   // Add a zero, if necessary, as above
    lcdI2C.print(0);
 }
   lcdI2C.print(now.second(), DEC); 
   lcdI2C.setCursor (0,2);  
   lcdI2C.print ("Humidity    ="); // print on the lcd Humidity = 
   lcdI2C.print(h); // to print the humidity
   lcdI2C.print("% "); //print "percentage" symbol
   lcdI2C.setCursor (0,3); 
   lcdI2C.print("Temperature ="); // print on the lcd temp = 
   lcdI2C.print (f); // print on the lcd temperture
   lcdI2C.print((char)223); // print "degrees" symbol 
   lcdI2C.print("C"); // print "C" with spaces after to fill 20 character line

  
  logfile.print(", ");    
  logfile.print(ccs.geteCO2());
  logfile.print(",");    
  logfile.print(ccs.getTVOC());
  logfile.print(",");
  logfile.print(h);
  logfile.print(",");
  logfile.print(f);
  logfile.println();


  
  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  
  // blink LED to show we are syncing data to the card & updating FAT!
 
  logfile.flush();


    
    }
    else{
      Serial.println(F("ERROR!"));
      while(1);
    }
  }
 
}


Drinking Cola equals to Drinking Toilet Cleaner? A DIY Electronic PH Test Paper Will Tell You the Truth

I have heard of various adverse cola using methods long since. One of these methods is using as the toilet cleaner. Seriously? In the holiday, our member Mr. Mi with his son Little Mi made an electronic PH test paper with micro:bit. The test paper will tell you the truth!


The introduction indicates the highlight of the DF scientific kit is to upload data to IoT platform. The sample plate test figure above shows that the scientific kit shall include a PH sensor. The experimental design in the figure is to map the PH value into the steering engine and show the test result with pointer. 

Required components of the project include:

  • Micro:bit×1
  • RGB lamp ring expansion board ×1
  • PH sensor ×1



  • RGB lamp ring expansion board was made two weeks ago.

    From the front of expansion board, you can see the onboard 24 RGB LEDs and microphone.



    From the back, you can see a buzzer, two P1, P0 IO expansion ports and corresponding reuse selection switch. 
    The kit supports PH2.0 and USB external power supply.
    DF always has neat tricks for connection of expansion board and micro:bit. 



    Micro:mate adopts flexible PogoPin.

    For RGB lamp ring expansion board, the nuts are directly embedded into PCB.


    Under microspur, you can see nuts are not simply welded on PCB surface but embedded in PCB. The threads run through the board. This process is unclear, not common and simple.

    Insulation paper is pasted on the front.


    When screwed in, screws will contact the golden finger to achieve circuit connection with expansion board accordingly.



    The installation is finished hereto.


    Another main component PH sensor is introduced as follows:


    Contents: including sensor, connection board and connection line. In this project, the connection line in the figure above needs to be replaced with double-end PH2.0-3pin connection line matched with ring RGB expansion board.

    Electrode feature, immersed in protective liquid.


    The switchover board was made early, so its version is V1.1 Arduino design. Its operating voltage is 5V. Now, there is new version V2, and its operating voltage is 3.3-5V, so it is more suitable to micro:bit.


    The sensor is connected to the switchover board through BNC port.




    Connect Sensor to Pi Port


    P1 port is also used for onboard microphone, so the microphone needs to be forbidden.

    Our program design is to provide prompt sound during operation, so the buzzer switch needs to be turned on (P2 port is forbidden at this moment).


    RGB lamp ring is current consuming, so external power supply needs to be connected through PH2.0 or USB port.
    Makeshift Program
    We took some time in commissioning and improvement. Particularly, the max. input value of mapping module perplexed us, because PH sensor at hand was Arduino design. Its operating voltage is 5V, and we also lacked the technical data on PH sensor applying to micro:bit, so the value 700 is just a relative ideal value after we tested.

    Mapping module phMap is used to switch on corresponding number of lamps according to the analog quantity read by P1.

    Mapping module rgbMap is used to show corresponding “PH color card” simulated by RGB lamp rings according to the analog quantity read by P1.




    Firstly, we selected following common liquid in daily life as the test objects:

    Tap water, Coca Cola, rose red vinegar, milk, liquid detergent and toilet cleaner.




    At first, test tap water for reference. 
    The reading is 436. End-point color of RGB lamp ring – light blue.


    Then, test Coca Cola. 
    Only a LED of lamp ring is on (red) and the reading is 32!


    For the rose red vinegar, the sensor reading is 71. 
    Two LEDs of RGB lamp ring are on. The end-point color is orange.


    For devondale milk, the sensor reading is 359. 
    The end-point color of RGB lamp ring is green. Milk belongs to acid food.



    For White Cat liquid detergent, 
    the sensor reading is 364 and 
    the end-point color of RGB lamp ring is green.



    For the toilet cleaner, the reading is 26. 
    No lamps of RGB lamp ring are on. 
    It means it has strong acidity.




    For baking soda, the reading is 464, 
    and the end-point lamp of RGB lamp ring is green.


    The last test object is soap for cleaning clothes.
    The reading is 573. The end-point color of RGB lamp ring is indigo blue! 
    It will become purple if the concentration is higher. 
    It conforms to our knowledge on “alkali soap”.

    Conclusion: drinking cola = drinking toilet cleaner 
    This is tenable simply from the perspective of pH value.
    I drank up the remaining cola to stay calm.
    In device design, the sensor is sensitive to pH value.
    Although no true PH value can be converted through a formula, 
    the analog quantity reading can be quantified 
    and the color card can be simulated through RGB lamp ring for visual display.