element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Remote Monitoring & Control
  • Challenges & Projects
  • Project14
  • Remote Monitoring & Control
  • More
  • Cancel
Remote Monitoring & Control
Blog Plant a seed and watch it grow...  (Part 3: presenting a new unfuzzy creation, well almost)
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Remote Monitoring & Control to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: BigG
  • Date Created: 14 Aug 2019 10:30 PM Date Created
  • Views 1956 views
  • Likes 5 likes
  • Comments 1 comment
  • esp32
  • mdash
  • watering plant
  • remotemonitoringcontrolch
  • ardexpert
  • rpiexpert
Related
Recommended

Plant a seed and watch it grow...  (Part 3: presenting a new unfuzzy creation, well almost)

BigG
BigG
14 Aug 2019

Introduction

 

This blog is to close out this project for the purposes of the remote monitoring competition.

 

In blog 1, I presented an old project, which was based on fuzzy logic and used analog moisture sensors which corroded over time. The data collected was posted using an Ethernet connection to a Rasberry Pi, which acted as local server, and from the RPi data was also sent to a cloud platform for archive. The only remote control available was via the LAN where you could open up a web server on the Raspberry Pi SBC.

 

In blog 2, I wrote about the typical issues related to remote monitoring and control and presented a solution by way of mDash, a new cloud platform as a service. I provided a review of this service and walked through the available end-to-end example and then made some modifications of my own to test suitability. I alluded to the new prototype device that would monitor the plant moisture and control the watering process.

 

And finally I'm now writing up this blog (as I'm pretty much out of time), which provides an overview of the new creation.

image

 

New Remote Unit

 

image

 

The new remote unit has quite a changes.

 

For the MCU I'm using an ESP32 WiFi module. This links in with the MDash cloud platform.

 

I added in an NXP NTAG I2C Plus module, as I personally think this is the best way to provision WiFi hands down. None of this scanning for Access Points and manual SSID/Password entry required.

 

image

 

image

I swapped out the old corroded moisture sensors for capacitive based moisture sensors. The ones I'm using are from Adafruit. These are I2C based as use a microcontroller. The nice thing is that they have made provision for 4 I2C addresses, which comes in handy as I wanted one remote unit to handle two plants. If I needed to use more, I found these ones, from DFRobot, online which provide an analog output.

 

For this prototype, I am testing the use of two sensors per pot, in the following configuration as I wanted to see how much moisture levels differ between near the soil surface and at the bottom of the pot, where the roots are. My hypothesis is that you are not too concerned about horizontal moisture variances it is more about the vertical changes. Time and data will determine if this is relevant or not.

 

Then for the motor driver, I decided to use the TP6612 as can handle 12V for the motor and will happily drive two water pumps which require 200mA each. I am using a breakout board from Adafruit.

 

 

Remote Unit Firmware

 

The firmware was developed using Arduino IDE.

 

Thanks to the extensive library list, I found there were libraries available for all parts of my project.

 

<< Code to be inserted here. >>

 

 

Future expansion planned

 

There is something rather satisfying about over engineering a design, and this project is no different. I admit that "feature creep" crept in as I wanted to included some more generic environmental sensors into the project. Sadly time ran out and just left of a bunch of kit on my desk for another time.

 

{gallery} Future Plans

image

image

 

And we present...

 

image

 

Well, it's nearly there. I'm hoping to sneak in a video as well.

  • Sign in to reply

Top Comments

  • BigG
    BigG over 6 years ago +1
    I just had to put this one to bed... Here is my environmental sensor unit set up. It is now a standalone unit and uses the BLE Environmental Sensing Service with some added customised characteristics.…
  • BigG
    BigG over 6 years ago

    I just had to put this one to bed... Here is my environmental sensor unit set up. It is now a standalone unit and uses the BLE Environmental Sensing Service with some added customised characteristics.

     

    When I started out on the "feature creep" part, I was scratching my head as to which would be the simplest BLE module to use with my Arduino UNO, when the solution was sitting right under my nose in a box, looking all forlorn. It was the now defunct Arduino 101. And boy oh boy, it worked a treat and so much simpler than say trying to use the ESP32 BLE Arduino libraries, which don't use the correct terminology and are way too over complicated, memory/resource hungry and crash far too frequently (all classic signs, in my opinion, that the competent code writers did not fully grasp the BLE spec).

     

    You don't have permission to edit metadata of this video.
    Edit media
    x
    image
    Upload Preview
    image

     

    The fun part of the project, was including a characteristic for a small USB (5V) fan. I have options for the remote turning on and off of the fan and for auto mode, which triggers every time the sensors are sampled (the idea is to raise a bit of dust with the fan on in order to measure dust particulate concentration).

     

    The code for the project is as follows:

     

    /*
       Copyright (c) 2016 Intel Corporation.  All rights reserved.
       See the bottom of this file for the license terms.
    */
    
    
    /*
     * Sketch: _101BLE_EnvironmentalSensingService_Demo.ino
     *
     * Description:
     *     This sketch example partially implements the standard Bluetooth
     *   Low-Energy Environmental Sensing service and connection interval paramater update.
     *
     *   For more information:
     *     https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
     *
     */
    
    
     /***************************************************************************** 
     *
     * Copyright Gerrikoio, August 2019
     * 
     *  This code measures a range of environmental sensors as well as air quality (dust particulates). 
     *  
     *  The sensors include:  
     *  A BMP085 Barometric Pressure & Temp Sensor (using the Adafruit BMP085 Breakout library)  
     *  A Sensioron SVM30 sensor (library is a combo)
     *  
     *  Connect VCC of the BMP085 pressure and the Si1145 UV sensor to 3.3V (NOT 5.0V!)
     *  Pressure Sensor: EOC is not used, it signifies an end of conversion. XCLR is a reset pin, also not used here
     *  The environmental sensors use I2C to communicate
     *  Connect SCL to i2c clock (Analog pin 5 on UNO)
     *  Connect SDA to i2c data (Analog pin 4 on UNO)
     * 
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     * 
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     * 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     *  
      
      Adafruit invests time and resources providing this open source code, 
      please support Adafruit and open-source hardware by purchasing 
      products from Adafruit!
    
    
      Adafruit Library Code Written by Limor Fried/Ladyada for Adafruit Industries.  
      BSD license, all text above must be included in any redistribution
    
    
      Adafruit sensors include:
      ----> https://www.adafruit.com/products/1777
      ----> https://www.adafruit.com/products/391
    
    
    ******************************************************************************/
    
    
    
    #include <CurieBLE.h>
    
    
    #include <Wire.h>
    #include "SHTSensor.h"
    #include "Adafruit_BMP085.h"
    #include "Adafruit_SGP30.h"
    
    
    #include <SoftwareSerial.h>
    
    
    #define DT __DATE__
    #define TM __TIME__
    
    
    #define DEBUG 1
    
    
    #define GP2Y_RXD    (2u)
    #define GP2Y_TXD    (3u)
    #define RELAYPIN    (17u)
    
    
    const uint16_t DEFAULTFANONTIME =     3000;   // 3 seconds
    const uint16_t DEFAULTSAMPLETIME =    20000;  // 20 seconds
    
    
    const uint8_t CO2Descr[7] =           { 'C', 'O', '2', ' ', 'p', 'p', 'm' };
    const uint8_t TVOCDecsr[8] =          { 'T', 'V', 'O', 'C', ' ', 'p', 'p', 'b' };
    const uint8_t DustDecsr[10] =         { 'D', 'u', 's', 't', ' ', 'u', 'g', '/', 'm', '3' };
    const uint8_t ConfigDecsr[6] =        {'C', 'o', 'n', 'f', 'i', 'g'};
    
    
    const uint8_t IDVALCONFIRM = 0xBC;
    const uint8_t IDVALCHECK = 0xCB;
    
    
    const uint8_t PresentFmt1[7] = {
      0x06,       // Format = 6 = "unsigned 16-bit integer"
      0x00,       // Exponent = 0
      0x27,       // unit less (part1)
      0x00,       // unit less (part2)
      0x01,       // Namespace = 1 = "Bluetooth SIG Assigned Numbers"
      0x00,
      0x00,       // ditto (high byte)
    };
    
    
    BLEService envSensingService("181A"); // BLE Environemtal Sensing Service
                                
    // BLE Humdidity Characteristic using standard 16-bit characteristic UUID
    // Unit is in percent with a resolution of 0.01 percent (so we multiply value by 100)
    // Format is uint16
    BLEUnsignedShortCharacteristic HumidityChar("2A6F", BLERead | BLENotify );
    
    
    // BLE Pressure Characteristic using 32-bit characteristic UUID
    // Unit is in pascals with a resolution of 0.1 Pa (so we mulitply value by 10)
    // Format is uint32
    BLEUnsignedIntCharacteristic PressureChar("2A6D", BLERead | BLENotify );
    
    
    // BLE Temperature Characteristic using standard 16-bit characteristic UUID
    // Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius (so we multiply value by 100)
    // Format is sint16
    BLEShortCharacteristic TemperatureChar("2A6E", BLERead | BLENotify );
    
    
    // BLE Air Quality CO2 Characteristic using a 16-bit characteristic UUID
    // Unit is in degrees ppm with a resolution of 1 ppm (so we multiply value by 1)
    // Format is uint16
    BLEUnsignedShortCharacteristic CO2Char("AC02", BLERead | BLENotify );
    BLEDescriptor CO2Descriptor1 = BLEDescriptor("2901", CO2Descr, 7);
    BLEDescriptor CO2Descriptor2 = BLEDescriptor("2904", PresentFmt1, sizeof(PresentFmt1));
    
    
    // BLE Air Quality TVOC Characteristic using a 16-bit characteristic UUID
    // Unit is in degrees ppb with a resolution of 1 ppb (so we multiply value by 1)
    // Format is uint16
    BLEUnsignedShortCharacteristic TVOCChar("AC03", BLERead | BLENotify );
    BLEDescriptor TVOCDescriptor1 = BLEDescriptor("2901", TVOCDecsr, 8);
    BLEDescriptor TVOCDescriptor2 = BLEDescriptor("2904", PresentFmt1, sizeof(PresentFmt1));
    
    
    // BLE Dust Characteristic using a 16-bit characteristic UUID
    // unit is in ug/m3 with a resolution of 0.02 (so we multiply value by 100);
    BLEUnsignedShortCharacteristic DustChar("AC04", BLERead | BLENotify );
    BLEDescriptor DustDescriptor1 = BLEDescriptor("2901", DustDecsr, 10);
    BLEDescriptor DustDescriptor2 = BLEDescriptor("2904", PresentFmt1, sizeof(PresentFmt1));
    
    
    // BLE Config Characteristic for fan etc. using a 16-bit characteristic UUID
    BLEUnsignedShortCharacteristic ConfigChar("AC05", BLEWrite | BLERead );
    BLEDescriptor ConfigDescriptor1 = BLEDescriptor("2901", ConfigDecsr, 6);
    
    
    uint32_t 
      previousMillis = 0;  // last time the battery level was checked, in ms
    
    
    uint32_t
      oldPressureVal =          0;  // last pressure value
    
    
    uint16_t
      fanOnTime =               DEFAULTFANONTIME,
      oldHumidityVal =          0,  // last humidity value
      oldCO2val =               0,  // last CO2 value
      oldTVOCval =              0,  // last TVOC value
      oldDustVal =              0,  // last Dust value
      oldConfigVal =            0;
    
    
    int
      TempVals[3] =             {0,0,0},
      oldTempVal =              0;  // last temperature value
      
    bool
      FanAutoTriggerOn =        false;          // If true then fan will trigger upon event
    
    
    // Bosch BMP085 Digital Pressure Sensor
    Adafruit_BMP085 bmp;
    
    
    // We use the specific temp humidity sensor on the SVM30:
    SHTSensor sht(SHTSensor::SHTC1);
    
    
    // This is to measure TVOC and CO2
    Adafruit_SGP30 sgp;
    
    
    // Use software serial port for communicating with GP2Y1026.
    SoftwareSerial GP2Y(GP2Y_RXD, GP2Y_TXD);
    
    
    // -------------------------------------------------------
    // Event Handler
    // =======================================================
    
    
    void configWrittenHandler(BLEDevice central, BLECharacteristic characteristic) {
      // central wrote new value to characteristic, update LED
      uint16_t ConfigVal = ConfigChar.value();
      uint8_t ConfigArr[2] = {'\0'};
    
    
      ConfigArr[1]=(uint8_t)(ConfigVal >>8);
      ConfigArr[0]=(uint8_t)(ConfigVal);  
    
    
      Serial.print("Config Characteristic update: ");
      Serial.print(ConfigArr[0], HEX); Serial.print(":");
      Serial.println(ConfigArr[1], HEX);
    
    
      // 0x03 is for fan manual control
      if (ConfigArr[0] == 0x03) {
        if (ConfigArr[1] == 0x00) {
          Serial.println(F("FAN Default Settings"));
        }
        else if (ConfigArr[1] == 0x01) {
          Serial.println(F("FAN ON"));
          digitalWrite(RELAYPIN, HIGH);
        }
        else if (ConfigArr[1] == 0x02) {
          Serial.println(F("FAN OFF"));
          digitalWrite(RELAYPIN, LOW);
        }
        else if (ConfigArr[1] == 0x03) {
          Serial.println(F("FAN AUTO ON"));
          FanAutoTriggerOn = true;
        }
        else if (ConfigArr[1] == 0x04) {
          Serial.println(F("FAN AUTO OFF"));
          FanAutoTriggerOn = false;
        }
      }
      else if (ConfigArr[0] == 0x04) {
        Serial.print(F("Setting FAN Auto duration (sec): "));
        Serial.println(ConfigArr[1], DEC);
        // We have a design rule here that max is up to 30 seconds
        if (!ConfigArr[1]) {
          Serial.print(F("Note, FAN Auto duration can't be zero"));
        }
        else if (ConfigArr[1] > 15) {
          Serial.print(F("Note, FAN Auto duration exceedded max 15 seconds"));
        }
        else {
          fanOnTime = ConfigArr[1] * 1000;
        }
        
      }
      else if (ConfigArr[0] == 0x05) {
        if (ConfigArr[1] == IDVALCHECK) {
          Serial.println(F("Sending Config Confirmation"));
          ConfigChar.setValue(IDVALCONFIRM);
        }
      }
    
    
    }
    
    
    // -------------------------------------------------------
    // Setup
    // =======================================================
    
    
    void setup() {
      pinMode(LED_BUILTIN, OUTPUT);   // initialize the LED on pin 13 to indicate when a central is connected
      pinMode(RELAYPIN, OUTPUT);      // initialize the Relay Output pin
    
    
      #ifdef DEBUG
      while (!Serial) {;;}
      Serial.begin(115200);    // initialize serial communication
      #endif
    
    
      if (!bmp.begin()) {
      Serial.println(F("Could not find BMP085 sensor"));
      while (1) {}
      }
    
    
      // Initialise the temp & humidity sensor (SHTC1)
      if (!sht.init()) {
        Serial.println(F("SHTC1 Sensor failed to initialise"));
        digitalWrite(LED_BUILTIN, HIGH);
        while (1);
      }
      
      sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
    
    
      if (! sgp.begin()){
        Serial.println(F("SGP30 Sensor not found :("));
        while (1);
      }
    
    
      // Start the software serial port for receiving data from GP2Y1026.
      GP2Y.begin(2400);
      // Wait a second for startup.
      delay(1000);
      
      BLE.setLocalName("AmbientMonitor");
      BLE.setAdvertisedService(envSensingService);  // add the service UUID
    
    
      //Add customised attributes
      CO2Char.addDescriptor(CO2Descriptor1);
      CO2Char.addDescriptor(CO2Descriptor2);
      TVOCChar.addDescriptor(TVOCDescriptor1);
      TVOCChar.addDescriptor(TVOCDescriptor2);
      DustChar.addDescriptor(DustDescriptor1);
      DustChar.addDescriptor(DustDescriptor2);
      ConfigChar.addDescriptor(ConfigDescriptor1);
    
    
      // assign event handlers for characteristic
      ConfigChar.setEventHandler(BLEWritten, configWrittenHandler);
    
    
      
      envSensingService.addCharacteristic(HumidityChar); // add the Humdidity characteristic
      envSensingService.addCharacteristic(PressureChar); // add the Pressure characteristic
      envSensingService.addCharacteristic(TemperatureChar); // add the Temperature characteristic
      envSensingService.addCharacteristic(CO2Char); // add the CO2 characteristic
      
      envSensingService.addCharacteristic(TVOCChar); // add the TVOC characteristic
      envSensingService.addCharacteristic(DustChar); // add the Dust Particulates characteristic
      envSensingService.addCharacteristic(ConfigChar); // add the Fan characteristic
      
      BLE.addService(envSensingService);   // Add the BLE Environmental Sensing service
    
    
      // initial values for each characteristic
      HumidityChar.setValue(oldHumidityVal);
      PressureChar.setValue(oldPressureVal);
      TemperatureChar.setValue(oldTempVal);
      CO2Char.setValue(oldCO2val);
      TVOCChar.setValue(oldTVOCval);
      DustChar.setValue(oldDustVal);
      ConfigChar.setValue(oldConfigVal);
    
    
      /* Start advertising BLE.  It will start continuously transmitting BLE
         advertising packets and will be visible to remote BLE central devices
         until it receives a new connection */
    
    
      // begin initialization
      BLE.begin();
    
    
      // start advertising
      BLE.advertise();
    
    
      Serial.println(F("Bluetooth advertising and active, waiting for connection..."));
      Serial.print(DT); Serial.print(" "); Serial.println(TM);
      
    }
    
    
    
    
    // -------------------------------------------------------
    // MAIN
    // =======================================================
    
    
    void loop() {
      // listen for BLE peripherals to connect:
      BLEDevice central = BLE.central();
    
    
      // if a central is connected to peripheral:
      if (central) {
        Serial.print(F("Connected to central: "));
        // print the central's MAC address:
        Serial.println(central.address());
        // turn on the LED to indicate the connection:
        digitalWrite(LED_BUILTIN, HIGH);
    
    
        // will check update the sensor values at every default Sample Period
        // as long as the central is still connected:
        while (central.connected()) {
          long currentMillis = millis();
          if (currentMillis - previousMillis >= DEFAULTSAMPLETIME) {
            previousMillis = currentMillis;
            updateTempHumidityLevel();
            updateCO2Val();
            updatePressureVal();
            prepareDustVal();
          }
        }
        // when the central disconnects, turn off the LED:
        digitalWrite(LED_BUILTIN, LOW);
        Serial.print(F("Disconnected from central: "));
        Serial.print(F("Start Advertising again..."));
        Serial.println(central.address());
        restoreToOriginalState();
        // restart advertising
        BLE.advertise();
      }
    }
    
    
    // -------------------------------------------------------
    // Functions
    // =======================================================
    
    
    // restore variables to original state
    void restoreToOriginalState() {
      previousMillis = 0;  // last time the battery level was checked, in ms
      oldPressureVal =          0;  // last pressure value
      fanOnTime =               DEFAULTFANONTIME;
      oldHumidityVal =          0;
      oldCO2val =               0;
      oldTVOCval =              0;
      oldDustVal =              0;
      oldConfigVal =            0;
      TempVals[0] =             0;
      TempVals[1] =             0;
      TempVals[2] =             0;
      oldTempVal =              0;
      FanAutoTriggerOn =        false;          // If true then fan will trigger upon event  
    }
    
    
    /* return absolute humidity [mg/m^3] with approximation formula
    * @param temperature [°C]
    * @param humidity [%RH]
    */
    uint32_t getAbsoluteHumidity(float temperature, float humidity) {
        // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
        const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
        const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
        return absoluteHumidityScaled;
    }
    
    
    
    
    void updateTempHumidityLevel() {
    
    
      bool UpdateSGPHumidity = false;
      
      if (sht.readSample()) {
        uint16_t humidityVal = sht.getHumidity() * 100;
        TempVals[2] = sht.getTemperature() * 100;         // We grab this too
        Serial.print(F("RH %: "));  Serial.println(float(humidityVal)/100.0, 1);
      
        TempVals[1] = bmp.readTemperature() * 100;
        
        Serial.print("Temp (BMP085) = "); Serial.print(float(TempVals[1])/100.0,1); Serial.println(" *C");
        Serial.print("Temp (SHTC1) = "); Serial.print(float(TempVals[2])/100.0,1); Serial.println(" *C");
    
    
        //Calculate Average
        TempVals[0] = (TempVals[1]+TempVals[2]+0.5)/2;
        Serial.print("Average Temp = "); Serial.print(float(TempVals[0]/100.0),1); Serial.println(" *C");
        
        if (humidityVal != oldHumidityVal) {
          oldHumidityVal = humidityVal;
          HumidityChar.setValue(oldHumidityVal);
          UpdateSGPHumidity = true;
        }
        
        if (oldTempVal != TempVals[0]) {
          oldTempVal = TempVals[0];
          TemperatureChar.setValue(oldTempVal);
          UpdateSGPHumidity = true;
        }
    
    
        if (UpdateSGPHumidity) {
          sgp.setHumidity(getAbsoluteHumidity(float(TempVals[0])/100.0, float(humidityVal)/100.0));
          delay(100);
        }
      }
    }
    
    
    void updatePressureVal() {
      uint32_t PressureVal = bmp.readPressure();
      Serial.print("Pressure = "); Serial.print(bmp.readPressure()); Serial.println(" Pa");
      PressureVal *= 10L;
      if (oldPressureVal != PressureVal) {
        oldPressureVal = PressureVal;
        PressureChar.setValue(oldPressureVal);
      }
    }
    
    
    
    
    void updateCO2Val() {
      if ( sgp.IAQmeasure()) {
    
    
        uint16_t TVOCval = sgp.TVOC;
        uint16_t CO2val = sgp.eCO2;
          
        Serial.print("TVOC "); Serial.print(TVOCval); Serial.print(" ppb\t");
        Serial.print("eCO2 "); Serial.print(CO2val); Serial.println(" ppm");
    
    
        if (oldTVOCval != TVOCval) {
          oldTVOCval = TVOCval;
          TVOCChar.setValue(oldTVOCval);
        }
        if (oldCO2val != CO2val) {
          oldCO2val = CO2val;
          CO2Char.setValue(oldCO2val);
        }
      }
    }
    
    
    
    
    void prepareDustVal() {
      if (FanAutoTriggerOn) {
        digitalWrite(RELAYPIN, HIGH);
        delay(fanOnTime);
        digitalWrite(RELAYPIN, LOW);
      }
      uint16_t DustVal[3] = {'\0'};
      delay(25);
      DustVal[0] = updateDustVal();
      delay(1000);
      DustVal[1] = updateDustVal();
    
    
      DustVal[2] = (uint16_t)(float(DustVal[0]) + float(DustVal[1]) + 0.5)/2.0;
      Serial.print("Ave Dust Value for BLE is: ");
      Serial.println(DustVal[2]);
      
      if (oldDustVal != DustVal[2]) {
        oldDustVal = DustVal[2];
        DustChar.setValue(oldDustVal);
      }
      
    }
    
    
    uint16_t updateDustVal() {
      uint16_t DustVal = 0;
      static int frame[6];
      uint8_t cntr = 0;
      bool FrameEnd = false;
      bool SensorRead = false;
    
      while (!SensorRead) {
        while (!GP2Y.available()) {
          delay(5);
        }
        if (GP2Y.available()) {
          int b = GP2Y.read();
          if (b == 0xff) {
            if (FrameEnd) {
              cntr = 0;
              // Check data integrity by verifying that first value is 170
              if (frame[0] == 0xAA) {
                // Verify the checksum.
                int testSum = frame[1] + frame[2] + frame[3] + frame[4];
                if ( frame[5] != (testSum & 0xff) ) {
                  //Serial.println(F("Dust Monitor Checksum Failed"));
                }
                else {
                  // Calculate Vout = (VoutH * 256 + VoutL) / 1024.0 * 5.0;
                  float Vout = (frame[1] * 256 + frame[2]) / 1024.0 * 5.0;
                  Serial.print("Vout = ");
                  Serial.print(Vout * 1000.0);
                  Serial.print("mV, ");
                  // Determine "a" coefficient beforehand by plotting output voltage
                  // on Y axis versus dust density on X axis which you measure using
                  // a reference dust monitor. The coefficient will be different
                  // depending on the reference dust monitor used and the type of
                  // particulate matter you are testing with. By default, "a" is based
                  // on sensitivity of 0.35V per change in dust density of 100ug/m3.
                  float a = 100.0 / 0.35;
                  
                  // Calculate dust density.
                  float dustDensity = a * Vout;
                  Serial.print(F("dustDensity = "));
                  Serial.print(dustDensity);
                  Serial.print("ug/m3");
                  Serial.println("");
                  DustVal = uint16_t(100.0 * (dustDensity + 0.005));
                  SensorRead = true;
                }
              }
              //else Serial.println(F("Dust Monitor 1st Frame Error"));
            }
            else FrameEnd = true;
          }
          else {
            if (cntr < 6) {
              frame[cntr] = b;
              cntr++;
            }
            FrameEnd = false;
          }
        }
      }
      return DustVal;
    }
    
    
    
    
    /*
       Copyright (c) 2016 Intel Corporation.  All rights reserved.
    
    
       This library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
    
       This library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
    
       You should have received a copy of the GNU Lesser General Public
       License along with this library; if not, write to the Free Software
       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    */

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube