В данной статье мы изучим взаимодействие интегрированного датчика окружающей среды BME680 с платой Arduino. BME680 — это датчик, который измеряет относительную влажность, барометрическое давление, температуру окружающей среды, летучие органические вещества (VOC) и IAQ (Indoor air quality - качество воздуха внутри зданий и сооружений).
Поскольку давление меняется с высотой, BME680 можно использовать для измерения приблизительной высоты . Используя некоторые математические уравнения, относящиеся к температуре и влажности, мы также можем вывести точку росы. Все параметры можно получить из библиотеки и кода Arduino Adafruit BME680.
BME680 — это сильно модернизированная версия датчиков BMP180 и BME280 с дополнительными функциями. Ранее на нашем сайте мы рассматривали проекты метеостанций на базе аналогичных датчиков:
- простая метеостанция на датчике BME280 и Arduino;
- метеостанция на ESP32 и датчике BME280;
- метеостанция IoT Live на NodeMCU ESP8266 и датчике BMP180;
- метеостанция на Raspberry Pi и датчике BMP180.
Здесь же мы реализуем такую же самую метеостанцию с датчиком BME680 и платой Arduino. Помимо метеостанции, мы также будем измерять индекс качества воздуха (IAQ) и летучие органические вещества (VOC). Если вас интересует именно измерение летучих органических соединений (VOC), то для этого существует специальный датчик CCS811.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- Датчик BME680 (купить на AliExpress).
- Макетная плата
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Интегрированный датчик окружающей среды BME680
BME680 — это цифровой датчик 4-в-1 с измерением газа, влажности, давления и температуры на основе проверенных принципов измерения. Датчик газа на BME680 может обнаруживать широкий спектр летучих органических соединений для мониторинга качества воздуха в помещении. Датчик имеет высокую линейность и высокую точность.
BME680 специально разработан для мобильных приложений и носимых устройств, где размер и низкое энергопотребление являются критическими требованиями. BME680 имеет такие функции, как специальный режим работы, оптимизированное энергопотребление, долговременная стабильность и высокая устойчивость к воздействию помех. Для измерения качества воздуха газовый датчик в BME680 может обнаруживать широкий спектр газов, таких как летучие органические соединения (VOC). Чтобы узнать больше о датчике BME680, вы можете проверить техническое описание BME680.
Технические характеристики и особенности BME680
1. Рабочее напряжение: от 1,7 В до 3,6 В.
2. Диапазон рабочих температур: от -40 до +85 ℃.
3. Диапазон рабочей влажности: от 0 до 100% относительной влажности.
4. Диапазон рабочего давления: от 300 до 1100 гПа.
5. Диапазон IAQ: от 0 до 500 PPM.
6. Тип интерфейса: I2C (до 3,4 МГц)/ SPI (3 и 4 провода, до 10 МГц).
7. Адрес I2C: 0x76 (по умолчанию)/ 0x77 (опционально).
8. Ток в режиме ожидания: от 0,29 до 0,8 мкА.
9. Ток в режиме сна: от 0,15 до 1 мкА.
10. Обнаружение и измерение летучих органических соединений (этан, изопрен, этанол, ацетон, оксид углерода)
Распиновка BME680
Большинство плат с чипом BME680 имеют 6 контактов, некоторые из плат, такие как Grove BME680 Board, BlueDot BME680 Board или Pimoroni BME680 имеют больше или меньше контактов. Но общая функциональность контактов остается прежней.
1. VCC: контакт питания, для работы которого требуется напряжение от 1,7 В до 3,6 В.
2. GND: контакт земли (общего провода).
3. SCL: контакт последовательной синхронизации для интерфейса I2C/контакт SCK для связи по SPI.
4. SDA: контакт последовательных данных для интерфейса I2C/контакт MOSI для связи по SPI.
5. SDO: контакт MISO для связи по SPI.
6. CS: контакт выбора чипа для интерфейса SPI.
Типичные приложения и BME680
- Качество воздуха в помещении.
- Домашняя автоматизация и управление.
- Интернет вещей.
- Прогноз погоды.
- Используется в портативных устройствах, таких как мобильные телефоны, планшетные ПК, GPS-устройства, носимые устройства, часы.
- Улучшение GPS (например, улучшение времени до первого определения местоположения, точный расчет траектории, обнаружение уклона).
- Внутренняя навигация (обнаружение смены этажа, обнаружение лифта).
- Навигация на открытом воздухе, приложения для отдыха и спорта.
- Индикация вертикальной скорости (скорость подъема/опускания).
Изменение адреса по умолчанию I2C BME680
Плата BME680 имеет адрес I2C по умолчанию 0x76. Но вы можете изменить адрес I2C, чтобы использовать до двух подобных плат с одной платой Raspberry Pi или Arduino. Чтобы изменить адрес I2C на 0x77, просто подключите SDO к GND .
BME680 как датчик IAQ (качества воздуха в помещении)
BME680 — это датчик на основе оксида металла , который обнаруживает VOC путем адсорбции на своем чувствительном слое. BME680 реагирует на большинство летучих соединений, загрязняющих воздух в помещении (за исключением CO2). BME680 способен измерять сумму загрязняющих VOC в окружающем воздухе, таких как выделение газов из краски, мебели или мусора, высокие уровни VOC из-за приготовления пищи, потребления пищи и выдыхаемого воздуха или потоотделения.
В качестве необработанного сигнала BME680 выводит значения сопротивления, которые изменяются из-за изменения концентрации VOC. Чем выше концентрация восстанавливающих VOC, тем ниже сопротивление и наоборот. Поскольку на этот необработанный сигнал влияют параметры, отличные от концентрации VOC (например, уровень влажности), необработанные значения преобразуются в индекс качества воздуха в помещении (IAQ) с помощью интеллектуальных алгоритмов.
Шкала IAQ варьируется от 0 (чистый воздух) до 500 (сильно загрязненный воздух). Во время работы алгоритмы автоматически калибруются и адаптируются к типичным средам, в которых работает датчик. Процесс калибровки учитывает недавнюю историю измерений, чтобы гарантировать, что IAQ 25 соответствует «типично хорошему» воздуху, а IAQ 250 указывает на «типично загрязненный» воздух.
Схема проекта
Интегрированный датчик окружающей среды BME680 имеет интерфейсы I2C и SPI. Мы рассмотрим его подключение к плате Arduino по каждому из этих интерфейсов.
Взаимодействие BME680 с Arduino с использованием интерфейса I2C
Схема подключения датчика BME680 к плате Arduino по интерфейсу I2C приведена на следующем рисунке.
Соединение между BME680 и Arduino довольно простое. Подключите вывод VCC BME680 к выводу Arduino 3.3V, а GND датчика - к GND Arduino. Аналогично подключите выводы I2C BME680, т.е. выводы SDA и SCL к выводам Arduino A4 и A5 соответственно. Более подробно про использование интерфейса I2C в плате Arduino вы можете прочитать в этой статье.
Вы можете использовать перемычки и собрать схему на макетной плате, как показано на следующем рисунке.
Взаимодействие BME680 с Arduino с использованием интерфейса SPI
Схема подключения датчика BME680 к плате Arduino по интерфейсу SPI приведена на следующем рисунке.
SPI-соединение между BME680 и Arduino довольно простое. Подключите вывод VCC BME680 к выводу Arduino 3.3V , а GND датчика - к GND Arduino. Аналогично подключите выводы SCL, SDA, SDO, CS BME680 к цифровым контактам Arduino 13, 11, 12, 10 соответственно. Более подробно про использование интерфейса SPI в плате Arduino вы можете прочитать в этой статье.
Вы можете использовать перемычки и собрать схему на макетной плате, как показано ниже.
Библиотека Adafruit BME680 для Arduino
Библиотека BME680, разработанная компанией Adafruit, может измерять температуру, влажность, давление, высоту, точку росы и газ. Библиотека упрощена и с помощью всего нескольких строк кода вы можете подключить BME680 к Arduino.
Библиотека требует другую библиотеку для компиляции под названием Adafruit Unified Sensor. Вы можете скачать ее по следующей ссылке.
Исходный код программы
Код программы для интерфейса I2C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
#include <Wire.h> #include <Adafruit_Sensor.h> #include "Adafruit_BME680.h" #define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME680 bme; // I2C void setup() { Serial.begin(9600); while (!Serial); Serial.println(F("BME680 test")); if (!bme.begin()) { Serial.println("Could not find a valid BME680 sensor, check wiring!"); while (1); } // Set up oversampling and filter initialization bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_2X); bme.setPressureOversampling(BME680_OS_4X); bme.setIIRFilterSize(BME680_FILTER_SIZE_3); bme.setGasHeater(320, 150); // 320*C for 150 ms } void loop() { if (! bme.performReading()) { Serial.println("Failed to perform reading :("); return; } float temperature = bme.temperature; float pressure = bme.pressure / 100.0; float altitude = bme.readAltitude(SEALEVELPRESSURE_HPA); float humidity = bme.humidity; float gas = bme.gas_resistance / 1000.0; double dewPoint = dewPointFast(temperature, humidity); Serial.print("Temperature = "); Serial.print(temperature); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(pressure); Serial.println(" hPa"); Serial.print("Humidity = "); Serial.print(humidity); Serial.println(" %"); Serial.print("Dew Point = "); Serial.print(dewPoint); Serial.println(" *C"); Serial.print("Approx. Altitude = "); Serial.print(altitude); Serial.println(" m"); Serial.print("Gas = "); Serial.print(gas); Serial.println(" KOhms"); Serial.println(); delay(2000); } double dewPointFast(double celsius, double humidity) { double a = 17.271; double b = 237.7; double temp = (a * celsius) / (b + celsius) + log(humidity * 0.01); double Td = (b * temp) / (a - temp); return Td; } |
Код программы для интерфейса SPI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
#include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include "Adafruit_BME680.h" #define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10 #define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); void setup() { Serial.begin(115200); while (!Serial); Serial.println(F("BME680 async test")); if (!bme.begin()) { Serial.println(F("Could not find a valid BME680 sensor, check wiring!")); while (1); } // Set up oversampling and filter initialization bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_2X); bme.setPressureOversampling(BME680_OS_4X); bme.setIIRFilterSize(BME680_FILTER_SIZE_3); bme.setGasHeater(320, 150); // 320*C for 150 ms } void loop() { // Tell BME680 to begin measurement. unsigned long endTime = bme.beginReading(); if (endTime == 0) { Serial.println(F("Failed to begin reading :(")); return; } Serial.print(F("Reading started at ")); Serial.print(millis()); Serial.print(F(" and will finish at ")); Serial.println(endTime); Serial.println(F("You can do other work during BME680 measurement.")); delay(50); // This represents parallel work. // There's no need to delay() until millis() >= endTime: bme.endReading() // takes care of that. It's okay for parallel work to take longer than // BME680's measurement time. // Obtain measurement results from BME680. Note that this operation isn't // instantaneous even if milli() >= endTime due to I2C/SPI latency. if (!bme.endReading()) { Serial.println(F("Failed to complete reading :(")); return; } Serial.print(F("Reading completed at ")); Serial.println(millis()); float temperature = bme.temperature; float pressure = bme.pressure / 100.0; float altitude = bme.readAltitude(SEALEVELPRESSURE_HPA); float humidity = bme.humidity; float gas = bme.gas_resistance / 1000.0; double dewPoint = dewPointFast(temperature, humidity); Serial.print("Temperature = "); Serial.print(temperature); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(pressure); Serial.println(" hPa"); Serial.print("Humidity = "); Serial.print(humidity); Serial.println(" %"); Serial.print("Dew Point = "); Serial.print(dewPoint); Serial.println(" *C"); Serial.print("Approx. Altitude = "); Serial.print(altitude); Serial.println(" m"); Serial.print("Gas = "); Serial.print(gas); Serial.println(" KOhms"); Serial.println(); delay(2000); } double dewPointFast(double celsius, double humidity) { double a = 17.271; double b = 237.7; double temp = (a * celsius) / (b + celsius) + log(humidity * 0.01); double Td = (b * temp) / (a - temp); return Td; } |
Тестирование и результаты
Вы можете использовать любую из вышеперечисленных схем, либо схему с I2C, либо схему с SPI. После загрузки кода в плату Arduino откройте Serial Monitor (окно монитора последовательной связи). В нем вы должны увидеть следующие результаты.
Последовательный монитор будет отображать температуру в градусах Цельсия, влажность в процентах, атмосферное давление в гПа, высоту в метрах, точку росы в градусах Цельсия и газ как значение сопротивления . Датчик используется для получения так называемого сопротивления газу, а затем рассчитывает индекс качества воздуха (IAQ) из комбинации показаний влажности и содержания газа в воздухе.
Используя код Adafruit BME680 Arduino, IAQ не может быть рассчитан. Поэтому вам нужно использовать какую-то другую библиотеку для расчета индекса качества воздуха (IAQ), что объясняется ниже.
Расчет IAQ BME680 с использованием библиотеки BSEC Arduino
Библиотека слияния BSEC была концептуализирована для обеспечения обработки сигналов более высокого уровня и слияния для BME680. Библиотека получает компенсированные значения датчика из API датчика . Она обрабатывает сигналы BME680 для предоставления запрошенных выходов датчика.
Индекс IAQ является функцией влажности, которая составляет до 25%, и концентрации газа, которая составляет до 75%. В этой текущей версии для индекса используются только влажность и концентрация газа, но добавление температуры было бы простым, поскольку слишком высокие или низкие температуры для людей добавляются к общему индексу качества воздуха вместе с влажностью и концентрацией газа.
Библиотека BSEC поддерживается на 32-, 16- и 8-битных платформах MCU. И, к сожалению, библиотека не поддерживается Arduino UNO, Nano, Pro Mini и т. д. Библиотека поддерживается только некоторыми платами Arduino, такими как Arduino MEGA 2560, Arduino Zero и Arduino Due . Загрузите библиотеку по указанной ниже ссылке и используйте ее с поддерживаемой платой Arduino.
Исходный код программы
Скопируйте следующий код и загрузите его на поддерживаемую плату Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
#include "bsec.h" // Helper functions declarations void checkIaqSensorStatus(void); void errLeds(void); // Create an object of the class Bsec Bsec iaqSensor; String output; // Entry point for the example void setup(void) { Serial.begin(115200); Wire.begin(); iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire); output = "\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix); Serial.println(output); checkIaqSensorStatus(); bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_RAW_TEMPERATURE, BSEC_OUTPUT_RAW_PRESSURE, BSEC_OUTPUT_RAW_HUMIDITY, BSEC_OUTPUT_RAW_GAS, BSEC_OUTPUT_IAQ, BSEC_OUTPUT_STATIC_IAQ, BSEC_OUTPUT_CO2_EQUIVALENT, BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); checkIaqSensorStatus(); // Print the header output = "Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent"; Serial.println(output); } // Function that is looped forever void loop(void) { unsigned long time_trigger = millis(); if (iaqSensor.run()) { // If new data is available output = String(time_trigger); output += ", " + String(iaqSensor.rawTemperature); output += ", " + String(iaqSensor.pressure); output += ", " + String(iaqSensor.rawHumidity); output += ", " + String(iaqSensor.gasResistance); output += ", " + String(iaqSensor.iaq); output += ", " + String(iaqSensor.iaqAccuracy); output += ", " + String(iaqSensor.temperature); output += ", " + String(iaqSensor.humidity); output += ", " + String(iaqSensor.staticIaq); output += ", " + String(iaqSensor.co2Equivalent); output += ", " + String(iaqSensor.breathVocEquivalent); Serial.println(output); } else { checkIaqSensorStatus(); } } // Helper function definitions void checkIaqSensorStatus(void) { if (iaqSensor.status != BSEC_OK) { if (iaqSensor.status < BSEC_OK) { output = "BSEC error code : " + String(iaqSensor.status); Serial.println(output); for (;;) errLeds(); /* Halt in case of failure */ } else { output = "BSEC warning code : " + String(iaqSensor.status); Serial.println(output); } } if (iaqSensor.bme680Status != BME680_OK) { if (iaqSensor.bme680Status < BME680_OK) { output = "BME680 error code : " + String(iaqSensor.bme680Status); Serial.println(output); for (;;) errLeds(); /* Halt in case of failure */ } else { output = "BME680 warning code : " + String(iaqSensor.bme680Status); Serial.println(output); } } } void errLeds(void) { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); delay(100); } |
Следующие параметры будут отображаться каждые 3 секунды:
1. Временная метка в миллисекундах.
2. Исходная температура в °C.
3. Давление в гПа.
4. Исходная относительная влажность в %.
5. Исходные данные с газового датчика в виде значения сопротивления в Ом.
6. Индекс качества воздуха в помещении.
7. Точность качества воздуха в помещении.
8. Температура в °C.
9. Относительная влажность в %.
10. Статическое качество воздуха в помещении.
11. Эквивалент CO2.
12. Выходной эквивалент VOC в выдыхаемом воздухе.
Начальное значение индекса BME680 IAQ составляет 25,00 и оно остается таким в течение длительного времени. Только через несколько минут значение IAQ начинает дрейфовать.