ESP8266 NodeMCU. I2C. BME280
Приклад роботи ESP8266 (NodeMCU) з датчиком атмосферного тиску, температури і вологості BME280. Датчик BME280 працює по шині I2C (IIC). Шину IIC будемо використовувати для одночасної роботи з датчиком BME280 та дисплеєм SSD1306. Нагадаю, що приклад використання дисплею SSD1306 з бібліотекою UG8 був наведений у статті ESP8266 NodeMCU. SSD1306. U8G.
Датчик BME280 та BMP280
BME280 - це цифровий модуль, який містить у собі датчик атмосферного тиску, датчик температури і гігрометр. Модель іншого датчика - BMP280 дуже схожа на BME280 і відрізняється тим що не має гігрометра. Алгоритми роботи з цими датчиками майже ідентичні. Тобто, можна сказати що BMP280 + гігрометр = BME280. Ми протестуємо обидва датчики. Датчики BME280 та BMEP280 мають декілька режимів роботи (Sleep mode, Forced mode, Normal mode). Найбільш висока точність досягається при роботі у режимі Normal mode. Окремо для тиску, температури та вологості можна встановлювати oversampling (1,2,4,8,16). Чим більше oversampling тим точніше результати вимірювань. Але витрачається і більше часу для вимірювання. Також датчик має IIR_filter, який знижує шум у вихідних даних. Детальніше про ці режими можете прочитати у документації до BME280 та BMP280. Ми можемо не турбуватися про всі ці режими. Модуль bme280 NodeMCU за замовчуванням налаштує датчик для найбільш точної роботи. Корисні посилання: BME280 – датчик атмосферного тиску Повна документація по модулю NodeMCU bme280: https://nodemcu.readthedocs.io/en/master/en/modules/bme280/Функції роботи з BME280
NodeMCU має модуль для роботи з датчиком BME280. Цей модуль треба включити під час збірки NodeMCU (https://nodemcu-build.com). Оскільки BME280 використовує IIC( I2C), також треба включати модуль I2C. Ініціалізація датчика виконується функцією: bme280.init(sda, scl, [temp_oss, press_oss, humi_oss, power_mode, inactive_duration, IIR_filter]) sda - SDA pin scl - SCL pin (optional) temp_oss - Controls oversampling of temperature data. Default oversampling is 16x. (optional) press_oss - Controls oversampling of pressure data. Default oversampling is 16x. (optional) humi_oss - Controls oversampling of humidity data. Default oversampling is 16x (optional) sensor_mode - Controls the sensor mode of the device. Default sensor more is normal. (optional) inactive_duration - Controls inactive duration in normal mode. Default inactive duration is 20ms. (optional) IIR_filter - Controls the time constant of the IIR filter. Default fitler coefficient is 16. (optional) cold_start - If 0 then the BME280 chip is not initialised. Usefull in a battery operated setup when the ESP deep sleeps and on wakeup needs to initialise the driver (the module) but not the chip itself. The chip was kept powered (sleeping too) and is holding the latest reading that should be fetched quickly before another reading starts (bme280.startreadout()). By default the chip is initialised. Під час ініціалізації вказуються GPIO, які будуть використані для ліній SDA та SCL шини IIC. Решту параметрів вказувати не обов`язково. Зверніть увагу, що окремо виконувати ініціалізацію шини IIC не потрібно. Примітка: bme280.init() описана як deprecated і буде видалена у наступних версіях NodeMCU. У нових версіях треба буде використовувати bme280.setup(), а ініціалізація IIC буде виконуватися окремо. Для зчитування даних з датчика та обчислювання даних використовують наступні функції: bme280.baro() - Читає датчик і повертає тиск повітря в гектопаскалях як ціле число, помножене на 1000, або нуль, коли зчитування не вдалося. bme280.dewpoint() - Для заданої температури та відносної вологості температура роси у вигляді цілого числа, помноженого на 100. bme280.humi() - Читає датчик і повертає відносну вологість повітря у відсотках як ціле число, помножене на 100 або нуль, коли зчитування не пройшло успішно. bme280.qfe2qnh() - Для даної висоти перетворює тиск повітря на тиск повітря на рівні моря. bme280.startreadout() - Починає зчитування (переводить датчик у forced режим). bme280.temp() - Читає датчик і повертає температуру в градусах Цельсія як ціле число, помножене на 100. Докладніше про функції роботи з датчиком можна прочитати тут: https://nodemcu.readthedocs.io/en/master/en/modules/bme280/Приклад роботи з BME280
Схема підключення (для BME280 та BMP280 схема однакова): Приклад зчитування тиску, температури та вологості з датчика BME280:
-- BME280 Example
bme280.init(5, 6)
local P, T = bme280.baro()
tmr.delay(100000)
local P, T = bme280.baro()
local H, t = bme280.humi()
T = T/100
H = H/1000
print (P, T, H)
Примітка: Відразу після ініціалізації датчика bme280 я виконую зчитування і затримку на 0.1 секунду. Це необхідно, бо перше зчитування з датчика завжди хибне (читай доку по датчику). Мається на увазі перше зчитування після ввімкнення живлення.
Функція bme280.baro() повертає тиск у гектопаскалях і температуру. Перевести гектопаскалі у міліметри ртутного стовпчика можна наступним чином:
P * 0.000750061683
Примітка: Зверніть увагу, що використовуються розрахунки з плавучою комою. Тобто Вам потрібно використовувати пошивку NodeMCU float версії.
Як бачите, зчитувати данні з датчика BME280 досить просто.
Приклад роботи з BMP280
Спробуємо під`єднати датчик BMP280. BMP280 немає гігрометра, тому ми будемо зчитувати лише тиск і температуру:
-- BMP280 Example
bme280.init(5, 6)
local P, T = bme280.baro()
tmr.delay(100000)
local P, T = bme280.baro()
T = T/100
print (P, T)
BME280 + SSD1306
Тепер під`єднаємо до плати NodeMCU датчик BME280 і дисплей SSD1306 як вказано на схемі (нижче буде пояснення чому так підключати не рекомендується): Зверніть увагу, що датчик bme280 і дисплей SSD1306 працюють по шині IIC, і ми підключаємо їх до різних GPIO виводів. NodeMCU дозволяє вказати на яких GPIO використовуються SDA, SCL лінії шини IIC. Але чи все так гаразд? Скільки окремих шин IIC ми можемо використати? NodeMCU дозволяє використовувати лише одну шину. І хоча функція i2c.setup має параметр id шини, він завжди має бути 0. Так сказано в документації до NodeMCU (https://nodemcu.readthedocs.io/en/master/en/modules/i2c/). Тому нам доведеться кожного разу виконувати ініціалізацію шини IIC для датчика, зчитувати данні, потім виконувати ініціалізацію для дисплея, виводити данні і так по колу. Технічно це не дуже гарна ідея. Розглянемо приклад:
-- Don`t use this script in real project
-- it`s demonstrate wrong IIC using
-- Please see example4.lua
function round(num, numDecimalPlaces)
mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
--Init BME280
bme280.init(5, 6)
local P, T = bme280.baro()
tmr.delay(100000)
function read_and_show()
--Init BME280
bme280.init(5, 6)
local P, T = bme280.baro()
local H, t = bme280.humi()
T = T/100
H = H/1000
print (P, T, H)
-- IIC init for Display
local sda = 3
local scl = 4
local sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW)
i2c.setup(0, sda, scl, i2c.SLOW)
-- Display init
local disp = u8g.ssd1306_128x64_i2c(sla)
disp:begin()
-- Set Font
disp:setFont(u8g.font_10x20)
disp:firstPage()
file.open("t.MONO", "r")
local xbm_data_t = file.read()
file.close()
file.open("h.MONO", "r")
local xbm_data_h = file.read()
file.close()
file.open("p.MONO", "r")
local xbm_data_p = file.read()
file.close()
repeat
disp:drawXBM( 8, 0, 12, 22, xbm_data_t )
disp:drawXBM( 7, 24, 15, 22, xbm_data_h )
disp:drawXBM( 0, 48, 29, 22, xbm_data_p )
disp:setFont(u8g.font_10x20)
disp:drawStr( 40, 16, round(T,1)..` C`)
disp:drawStr( 40, 38, round(H)..` %`)
disp:drawStr( 40, 60, round(P* 0.000750061683, 0)..` mmHg`)
until disp:nextPage() == false
xbm_data_t = nil
xbm_data_h = nil
xbm_data_p = nil
collectgarbage()
end
read_and_show()
-- Start timer
tmr.register(0, 5000, tmr.ALARM_AUTO, read_and_show)
tmr.start(0)
Начебто все працює - данні зчитані і на дисплей виведені. Але насправді не зовсім все гаразд. Справа у тому, що спочатку виконується ініціалізація IIC для роботи з датчиком, а коли виконується ініціалізація шини IIC для дисплея, зв`язок з датчиком втрачається. Щоб зчитати данні з датчика наступного разу, треба знову виконувати переініціалізацію шини IIC. А коли треба вивести данні на дисплей виконувати пере-ініціалізацію дисплея. Від цього зображання на дисплеї блимає. Виглядає не дуже гарно. Взагалі, так робити не рекомендую.
Шина IIC передбачає підключення декількох приладів (теоретично до 127). З`єднаємо датчик і дисплей як вказано на схемі:
Примітка: На модулях дисплея і датчика вже встановлені підтягуючи резистори для ліній шини SDA і SCL, тому їх додавати не потрібно.
При такій схемі виконується ініціалізація всіх приладів лише один раз і подальша робота не вимагає пере-ініціалізації IIC. Таке підключення приладів, які працюють по шині IIC є коректним.
Приклад роботи датчика BME280 з дисплеєм SSD1306 та ESP8266:
function round(num, numDecimalPlaces)
mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
-- IIC init
local sda = 5
local scl = 6
local sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW)
--Init BME280
bme280.init(sda, scl)
--bme280.setup()
local P, T = bme280.baro()
tmr.delay(100000)
-- Display init
local disp = u8g.ssd1306_128x64_i2c(sla)
disp:begin()
-- Set Font
disp:setFont(u8g.font_10x20)
function read_and_show()
local P, T = bme280.baro()
local H, t = bme280.humi()
T = T/100
H = H/1000
print (P, T, H)
disp:firstPage()
file.open("t.MONO", "r")
local xbm_data_t = file.read()
file.close()
file.open("h.MONO", "r")
local xbm_data_h = file.read()
file.close()
file.open("p.MONO", "r")
local xbm_data_p = file.read()
file.close()
repeat
disp:drawXBM( 8, 0, 12, 22, xbm_data_t )
disp:drawXBM( 7, 24, 15, 22, xbm_data_h )
disp:drawXBM( 0, 48, 29, 22, xbm_data_p )
disp:setFont(u8g.font_10x20)
disp:drawStr( 40, 16, round(T,1)..` C`)
disp:drawStr( 40, 38, round(H)..` %`)
disp:drawStr( 40, 60, round(P* 0.000750061683, 0)..` mmHg`)
until disp:nextPage() == false
xbm_data_t = nil
xbm_data_h = nil
xbm_data_p = nil
collectgarbage()
end
read_and_show()
-- Start timer
tmr.register(0, 5000, tmr.ALARM_AUTO, read_and_show)
tmr.start(0)
Примітка: bme280.init() описана як deprecated і буде видалена у наступних версіях NodeMCU. У нових версіях треба буде використовувати bme280.setup(). bme280.setup() не займається ініціалізацією шиною IIC, це технічно правильно, а займається лише налаштуваннями датчика. Тобто якщо раніше ми писали:
bme280.init(5, 6)
Тепер треба:
i2c.setup(0, 5, 6, i2c.SLOW)
bme280.setup()
У цій статті ми розглянули приклад роботи з датчиком атмосферного тиску, температури і вологості BME280 і приклад роботи з датчиком атмосферного тиску і температури BMP280. Для роботи з датчиками була використана плата NodeMCU з модулем ESP-12. Плата працює під управлінням Framework NodeMCU. Приклади написані на мові програмування LUA.
Скачати всі файли, використані у цій статті можна за наступним посиланням:
https://github.com/avislab/NodeMCUExamples/tree/master/BME280_BMP280
Бажаю успіхів.
Дивись також:
- ESP8266 NodeMCU Перше знайомство. Робимо WiFi розетку
- ESP8266 NodeMCU. PWM
- ESP8266 NodeMCU. ADC
- ESP8266 NodeMCU. timer, rtc, SNTP, cron
- ESP8266 NodeMCU. файлова система, SD Card
- ESP8266 NodeMCU. UART
- GPS-трекер на базі ESP8266
- GPS-трекер + Дисплей SSD1306
- ESP8266 NodeMCU. SSD1306. U8G
- ESP-01 (ESP8266) upgrade flash memory to 4MB
- ESP8266 NodeMCU. I2C. BME280/
- Метеостанція на ESP8266
Недавні записи
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
- U-FOC - Векторне керування безколекторними моторами
Tags
esp8266 examples adc usart rfid eb-500 soldering lcd stm32 raspberry-pi python mongodb gps mpu-9250 sensors led hih-4000 foc ngnix wifi servo sms ethernet bldc 3d-printer bluetooth mpx4115a web pmsm options remap solar timer bme280 mpu-6050 avr docker flash bkp capture gpio uart meteo i2c usb rtc encoder programmator ssd1306 battery displays java-script barometer watchdog eeprom flask websocket pwm dht11 motor ssd1331 piezo smd brushless atmega books css git st-link dc-dc html nodemcu dma nvic rs-232 exti tim bmp280 max1674
Архіви