Introduction
This post is for Project14 September 2020 theme Control Systems. My project is a simple on/off control system. It is a supplemental home air quality controller to my ecobee thermostat system. The ecobee thermostat has control to my air conditioner, furnace and ventilation fans. It does a good to control my home temperature. However, home air quality is also very important to our health. Especially in this COVID-19 era, we work and live at home all the time. Adding air quality monitoring and control to my ecobee system becomes important.
To define the air quality, we use the following classification table. When the AQI value is greater than 100, we will turn on the fan to bring fresh air to the house. To save energy, when the AQI value is lower than 50, we will turn off the fan.
Image resource: https://www.airnow.gov/sites/default/files/2018-04/aqi_brochure_02_14_0.pdf
The system consists of the following components: Raspberry Pi 3, ecobee thermostat, network equipment (such as wireless router) and furnace. The following diagram illustrates the interactions among all components.
System Diagram
BOM
1. Raspberry Pi 3 Model B and T5454DV Power Supply
2. Raspberry Pi 7" Touchscreen Display (optional)
5. Keyboard & Mouse
6. 8GB micro SD card
The wires in the above assembly photo are power supply to the LCD touch screen.
How It Works
As depicted in the above system diagram, an environment click board (i.e., Bosch BME680 sensor on board) is plugged into the Raspberry Pi 3 through a Pi 3 click shield board. The sensor is sampling VOC (Volatile Organic compounds gases) raw values which is processed by Bosch Sensortec Environmental Cluster (BSEC) software module and eventually transformed into air quality index numbers. When the index number is greater or lower than high/low thresholds, the Pi3 will communicate to the ecobee system (https://api.ecobee.com) using ecobee API through the my home network system. If the indoor air quality is deteriorated, the RPi3 can command ecobee to turn on the ventilation system so fresh air can be brought into house to improve air quality.
To summarize, the system involves the following activities:
1. Sensor acquires raw data (temperature, pressure, humidity and gas VOC);
2. BSEC software (in C) processes data and outputs AQI number;
3. Application software (in Python) communicates with ecobee through APIs;
4. ecobee turns on/off fan as needed.
Acquire & Process Sensor Data
As mentioned before, we use BSEC software to process sensor data. It contains the processing algorithm as well as the sensor driver code. We can download Bosch's BSEC software from here - https://www.bosch-sensortec.com/software-tools/software/bsec/.
BSEC software is written in C. There is some customization required for Raspberry Pi platform. For example, we need to provide functions to read and write sensor chip and time functions.
int8_t bus_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len) { // ... // Please insert system specific function to write to the bus where BME680 is connected // ... i2c_smbus_write_i2c_block_data(g_i2cFileDescriptor, reg_addr, data_len, reg_data_ptr); return 0; } int8_t bus_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len) { // ... // Please insert system specific function to read from bus where BME680 is connected // ... i2c_smbus_read_i2c_block_data(g_i2cFileDescriptor, reg_addr, data_len, reg_data_ptr); return 0; } void sleep(uint32_t t_ms) { // ... // Please insert system specific function sleep or delay for t_ms milliseconds // ... usleep(t_ms*1000); } int64_t get_timestamp_us() { int64_t system_current_time = 0; // ... // Please insert system specific function to retrieve a timestamp (in microseconds) // ... struct timeval currentTime; gettimeofday(¤tTime, NULL); system_current_time = (int64_t)currentTime.tv_sec * 1000000 + currentTime.tv_usec; return system_current_time; }
My application software is written in Python so I have to wrap BSEC into a Python module. I used SWIG to wrap BSEC software. There's only one C function needs to expose in Python.
int run(PyObject *bsec_output_func) { ... }
On the other hand, there's also one Python function needs to expose in C. This is an output callback function used by BSEC to pass the AQI numbers.
def ecobeeControl(iaq: float, iaq_accuracy: int): ... return
For the complete source code, please check out the reference #3.
Communicate with ecobee
My furnace is controlled by ecobee so my application needs to talk to ecobee through its APIs. In order to use ecobee APIs, you need to go through a few steps:
1. Register ecobee Device and Create an Account
2. Sign Up ecobee Developer Account
3. Create ecobee Application
4. Obtain Authorization Codes
5. Add ecobee Application to My Apps List
6. Obtain Access Token and Refresh Token
All ecobee APIs are HTTPS requests. Every time we use an API, we need to provide a valid access token which is expired in an hour after we obtain it. To get a new access token, we need a refresh token which is expired in a year. Every time we request a new access code, we also get a new refresh token.
Once we successfully set up our access to ecobee APIs, we can write Python code to control the fan
def ecobeeControl(iaq: float, iaq_accuracy: int): while (updateAccessToken(myTokens) == False): time.sleep(1) if not ecobeeControl.systemReady : if iaq_accuracy > 0 : ecobeeControl.systemReady = True print("System is ready to use") else: if iaq > 100.0 and iaq_accuracy > 0 and not ecobeeControl.fanIsOn : while (controlThermostat(myTokens, "setHoldFanOn.json") == False): time.sleep(1) ecobeeControl.fanIsOn = True print(f'IAQ {iaq:.0f}, IAQ Accuracy {iaq_accuracy:d}, fan is turned on') return if iaq < 50.0 and iaq_accuracy > 0 and ecobeeControl.fanIsOn : while (controlThermostat(myTokens, "resumeProgram.json") == False): time.sleep(1) ecobeeControl.fanIsOn = False print(f'IAQ {iaq:.0f}, IAQ Accuracy {iaq_accuracy:d}, fan is turned off') return ecobeeControl.systemReady = False ecobeeControl.fanIsOn = False AirQualityReader.run(ecobeeControl)
For the complete source code, please check out the reference #3.
Test
Last but not least, we ran the Python application software and the following video shows how the system behaves. The sensor took a few minutes to do a quick calibration. Once the system is ready to use, I put a marker pen close to the Bosch sensor BME680. It mimics the polluted air quality. After the sensor measured the raw data and BSEC software processd the data, the Python application detected the AQI which is greater than the high threshold value (i.e., 100). It made HTTPS request to turn on the fan. We can hear the fan noise around 1:05 in the video. After I moved the pen away from the sensor, the AOI numbers were going down. Once it became lower than the low threshold (i.e., 50), the application made another HTTPS request to turn off the fan (around 2:25 in the video).
Reference
1. Raspberry Pi Click Board Sensor Kit - Review
2. RoadTest Review a Raspberry Pi 3 Model B ! - Review
3. Source code: https://github.com/cmgit1/ecobeeAirQualityControl
4. https://www.airnow.gov/sites/default/files/2018-04/aqi_brochure_02_14_0.pdf
5. ecobee API document https://www.ecobee.com/home/developer/api/