В данной статье мы рассмотрим, как создать веб-сервер реального времени с использованием микроконтроллера Raspberry Pi Pico W и датчика температуры и влажности DHT11. Объединив возможности микроконтроллера Raspberry Pi Pico и способность датчика DHT11 измерять температуру и влажность, мы можем создать простую, но эффективную систему для мониторинга условий окружающей среды. Мы рассмотрим процесс настройки оборудования, написания кода и создания веб-сервера, который отображает данные о температуре и влажности в режиме реального времени.
В предыдущей статье на нашем сайте мы рассматривали веб-сервер на Raspberry Pi Pico W для мигания светодиодом.
Также на нашем сайте мы рассматривали подключение датчика температуры и влажности DHT11 к другим микроконтроллерам (платам):
- к плате Arduino;
- к плате Raspberry Pi;
- к микроконтроллеру PIC;
- к модулю ESP8266;
- к модулю ESP32;
- к плате STM32 Blue Pill.
Необходимые компоненты
- Плата Raspberry Pi Pico W (купить на AliExpress).
- Датчик температуры и влажности DHT11 (купить на AliExpress).
Датчик влажности и температуры DHT11
Датчик DHT11 — популярный и недорогой цифровой датчик температуры и влажности. Он обычно используется в различных проектах и приложениях, требующих мониторинга или контроля уровня температуры и влажности в окружающей среде. Датчик обеспечивает надежные и точные измерения, что делает его подходящим как для любителей, так и для профессиональных проектов.
Распиновка модуля DHT11
VCC - этот вывод используется для подачи питания на датчик. Обычно он подключается к источнику питания 5 В.
Data - вывод данных используется для двунаправленной связи между датчиком и микроконтроллером. Для передачи данных используется однопроводной последовательный интерфейс.
GND - подключается к земле или опорному сигналу 0 В источника питания.
Компоненты модуля DHT11
В модуле DHT11 очень мало деталей, включая сам датчик DHT11, подтягивающий резистор, который не виден под этим углом, и светодиод питания.
Принципиальная схема модуля DHT11
DHT11 состоит из подтягивающего резистора, который добавлен к выводу данных. Один светодиод используется с токоограничивающим резистором 1 кОм, а конденсатор используется для фильтрации сигналов от датчика dht11.
Работа датчика влажности и температуры DHT11
Датчик DHT11 работает с использованием емкостного датчика влажности и датчика температуры на основе термистора. Микроконтроллер инициирует измерение, отправляя сигнал запуска сенсорному модулю. Модуль реагирует и передает на микроконтроллер 40-битный поток данных, содержащий показания влажности и температуры. Микроконтроллер вычисляет контрольную сумму для проверки целостности данных, интерпретирует полученные данные и преобразует их в реальные значения температуры и влажности. Сенсорный модуль DHT11 упрощает интеграцию, обеспечивая цифровой выход, устраняя необходимость аналого-цифрового преобразования и абстрагируя сложность протокола связи, что упрощает его использование для приложений измерения температуры и влажности.
Часто задаваемые вопросы о DHT11
Как следует обрабатывать ошибки или несоответствия показаний датчика DHT11?
Датчик DHT11 может иногда давать неправильные или противоречивые показания. Чтобы повысить точность, вы можете реализовать методы проверки ошибок и усреднения, такие как получение нескольких показаний и вычисление среднего значения или сравнение показаний с заранее заданными пороговыми значениями для выявления аномалий.
Как часто я могу считывать данные с датчика DHT11?
Датчик DHT11 имеет ограниченную частоту обновления, обычно около 1 Гц. Это означает, что вы можете считывать данные с датчика раз в секунду. Более частое считывание данных может привести к неточным показаниям.
Могу ли я использовать датчик DHT11 вне помещения?
Датчик DHT11 не предназначен для использования вне помещений или воздействия агрессивных сред. Рекомендуется использовать его внутри помещений, где он может быть защищен от влаги и экстремальных температур.
Схема проекта
Схема веб-сервера мониторинга температуры и влажности на Raspberry Pi Pico W и датчике DHT11 приведена на следующем рисунке.
Чтобы подключить датчик DHT11 к Raspberry Pi Pico вам потребуется установить необходимые соединения. Начните с подключения контакта Vcc (питание) датчика DHT11 к выходному контакту 3V3 Raspberry Pi Pico. Это соединение обеспечивает датчик необходимым питанием.
Затем подключите контакт Gnd (земля) датчика DHT11 к контакту заземления (GND) Raspberry Pi Pico. Это соединение обеспечивает общее заземление между датчиком и микроконтроллером, обеспечивая правильную привязку сигнала.
Наконец, подключите контакт данных датчика DHT11 к контакту 16 платы Raspberry Pi Pico. Этот контакт будет использоваться для связи с датчиком и получения данных о температуре и влажности. Он служит интерфейсом между датчиком и микроконтроллером.
Объяснение кода программы
Сначала вам нужно скачать файл dht.py и открыть его в Thonny IDE. Потом нажмите File>Save as («Файл» > «Сохранить как»). Когда появится диалог, показанный на рисунке ниже, нажмите raspberry pi pico W и сохраните файл с именем «dht.py».
Файловая система должна выглядеть так, как показано на рисунке ниже. Main.py — это файл веб-сервера, который вам необходимо сохранить таким же образом. Сейчас мы углубимся в объяснение его кода.
Замена SSID и паролей в следующей строке на значения для своей WiFi сети.
1 |
wlan.connect("SSID", "password") |
Веб-серверу необходимо подключиться к точке доступа вашего телефона, чтобы отобразить значения dht11, и для этого вам необходимо заменить SSID и пароль на свои собственные.
Сначала импортируем модули и библиотеки, необходимые для работы программы.
1 2 3 4 5 6 7 8 |
from machine import Pin import socket import math import utime import network import time import json from dht import DHT11, InvalidChecksum |
Следующий код устанавливает и подключается к сети Wi-Fi с указанными SSID и паролем.
1 2 3 |
wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("SSID", "password") |
В нашем проекте мы используем контакт 16 как контакт GPIO для подключения датчика DHT11. Затем создается экземпляр класса DHT11, которому передается используемый контакт в качестве параметра.
1 2 |
dhtPIN = 16 sensor = DHT11(Pin(dhtPIN, Pin.OUT, Pin.PULL_UP)) |
Следующий цикл ожидает установления соединения с Wi-Fi. Он проверяет состояние соединения Wi-Fi и ждет максимум 10 секунд.
1 2 3 4 5 6 7 |
wait = 10 while wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break wait -= 1 print('waiting for connection...') time.sleep(1) |
Если соединение Wi-Fi установлено успешно, производится получение IP-адреса и вывод его значения на экран.
1 2 3 4 5 6 |
if wlan.status() != 3: raise RuntimeError('WiFi connection failed') else: print('Connected') ip = wlan.ifconfig()[0] print('IP:', ip) |
Следующая функция считывает значения температуры и влажности с датчика DHT11.
1 2 3 4 5 |
def read_dht(): sensor.measure() temperature = sensor.temperature humidity = sensor.humidity return temperature, humidity |
Следующая функция создает веб-страницу HTML, содержащую заполнители для значений температуры и влажности. Он также включает код JavaScript для динамического обновления значений каждые 5 секунд с использованием запроса на выборку к конечной точке '/data'.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def webpage(temperature, humidity): html = f""" <!DOCTYPE html> <html> <body> <head>Raspberry pi pico W web server </head> <p>Temperature: <span id="temp">{temperature}</span> degrees Celsius</p> <p>Humidity: <span id="hum">{humidity}</span> %</p> <script> setInterval(function() {{ fetch('/data') .then(response => response.json()) .then(data => {{ document.getElementById('temp').innerHTML = data.temperature; document.getElementById('hum').innerHTML = data.humidity; }}); }}, 5000); </script> </body> </html> """ return html |
Следующая функция обрабатывает клиентские соединения и выдает соответствующий ответ на основе полученного HTTP-запроса. Если запрос «/data», он считывает температуру и влажность.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def serve(connection): while True: client = connection.accept()[0] request = client.recv(1024) request = str(request) try: request = request.split()[1] except IndexError: pass print(request) if request == '/data': temperature, humidity = read_dht() print("temp :"+str(temperature)) print(" humidity :"+str(humidity)) response = {'temperature': temperature, 'humidity': humidity} client.send(json.dumps(response)) else: html = webpage(0, 0) # Initial values for temperature and humidity client.send(html) client.close() |
Доступ к веб-серверу Raspberry Pi
Сначала вам нужно запустить код, открыв main.py в Thonny IDE, затем нажать кнопку run current script («Запустить текущий скрипт») в левом верхнем углу и запустить точку доступа вашего телефона. Не забудьте заменить «SSID» и пароль вашей точки доступа WiFi в коде программы.
В окне вывода данных после этого вы можете видеть, что Pico W подключена к вашему смартфону. Он печатает ваш IP-адрес, а затем постоянно отправляет данные на веб-страницу HTML в режиме реального времени.
Теперь откройте свой смартфон и введите свой IP-адрес в адресную строку (каждый IP-адрес различен, поэтому сначала проверьте свой - его наша программа выводит в окне).
Экран вывода должен выглядеть следующим образом и обновляться в режиме реального времени каждые 5 секунд.
Следуя этому руководству, вы сможете создать систему мониторинга температуры и влажности в реальном времени с использованием платы Raspberry Pi Pico W и датчика DHT11. Этот проект демонстрирует мощность и универсальность микроконтроллера Raspberry Pi Pico W в сочетании с популярным датчиком, открывая возможности для различных приложений интернета вещей (IoT). С помощью веб-сервера, работающего в режиме реального времени, вы можете легко отслеживать условия окружающей среды и интегрировать эти данные в свои проекты или системы.
Исходный код программы
Все необходимые файлы для этого проекта вы можете скачать по следующей ссылке. Также код программы приведен в листинге ниже.
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 |
from machine import Pin import socket import math import utime import network import time import json from dht import DHT11, InvalidChecksum wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("SSID", "password") dhtPIN = 16 sensor = DHT11(Pin(dhtPIN, Pin.OUT, Pin.PULL_UP)) # Wait for connect or fail wait = 10 while wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break wait -= 1 print('waiting for connection...') time.sleep(1) # Handle connection error if wlan.status() != 3: raise RuntimeError('WiFi connection failed') else: print('Connected') ip = wlan.ifconfig()[0] print('IP:', ip) def read_dht(): sensor.measure() temperature = sensor.temperature humidity = sensor.humidity return temperature, humidity def webpage(temperature, humidity): html = f""" <!DOCTYPE html> <html> <body> <head>Raspberry pi pico W web server </head> <p>Temperature: <span id="temp">{temperature}</span> degrees Celsius</p> <p>Humidity: <span id="hum">{humidity}</span> %</p> <script> setInterval(function() {{ fetch('/data') .then(response => response.json()) .then(data => {{ document.getElementById('temp').innerHTML = data.temperature; document.getElementById('hum').innerHTML = data.humidity; }}); }}, 5000); </script> </body> </html> """ return html def serve(connection): while True: client = connection.accept()[0] request = client.recv(1024) request = str(request) try: request = request.split()[1] except IndexError: pass print(request) if request == '/data': temperature, humidity = read_dht() print("temp :"+str(temperature)) print(" humidity :"+str(humidity)) response = {'temperature': temperature, 'humidity': humidity} client.send(json.dumps(response)) else: html = webpage(0, 0) # Initial values for temperature and humidity client.send(html) client.close() def open_socket(ip): # Open a socket address = (ip, 80) connection = socket.socket() connection.bind(address) connection.listen(1) print(connection) return connection try: if ip is not None: connection = open_socket(ip) serve(connection) except KeyboardInterrupt: machine.reset() |