"""
MicroPython IoT Weather Station Example for Wokwi.com
To view the data:
1. Go to http://www.hivemq.com/demos/websocket-client/
2. Click "Connect"
3. Under Subscriptions, click "Add New Topic Subscription"
4. In the Topic field, type "wokwi-weather" then click "Subscribe"
Now click on the DHT22 sensor in the simulation,
change the temperature/humidity, and you should see
the message appear on the MQTT Broker, in the "Messages" pane.
Copyright (C) 2022, Uri Shaked
https://wokwi.com/arduino/projects/322577683855704658
"""
import machine # это библиотека для работы с аппаратными возможностями микроконтроллера, такими как пины GPIO, I2C, SPI и другие.
from machine import Pin, SoftI2C # Pin это класс из библиотеки machine, который используется для работы с пинами GPIO на микроконтроллере.
#SoftI2C это класс из библиотеки machine, который используется для работы с шиной I2C на микроконтроллере.
from lcd_api import LcdApi # это пользовательская библиотека, предоставляющая API для работы с текстовым дисплеем LCD.
from i2c_lcd import I2cLcd # это пользовательская библиотека, основанная на lcd_api, которая обеспечивает интерфейс для работы с LCD-дисплеем через шину I2C.
import network # это библиотека, которая предоставляет функции для работы с сетевыми возможностями, такими как подключение к Wi-Fi и работа с сетевыми сокетами.
import time # это стандартная библиотека, предоставляющая функции для работы со временем и задержками.
from machine import Pin
import dht # это библиотека для работы с датчиками температуры и влажности DHT.
import ujson #передача данных с одного устройства на другое
from umqtt.simple import MQTTClient # это библиотека для работы с протоколом MQTT (Message Queuing Telemetry Transport) для обмена сообщениями между устройствами.
from machine import Pin, PWM # это класс из библиотеки machine, который используется для работы с ШИМ (Ширина Импульса Модуляции) на микроконтроллере.
from time import sleep # это класс из библиотеки time
# MQTT параметры сервра
MQTT_CLIENT_ID = "micropython-weather-demooo"
MQTT_BROKER = "mqtt-dashboard.com"
MQTT_USER = ""
MQTT_PASSWORD = ""
MQTT_TOPIC = "mytestservo"
angle = 0 # инициализирует переменную angle со значением 0
servo_pin = 23 # Указываем номер пина, к которому подключен сигнальный провод сервопривода
servo = PWM(Pin(servo_pin), freq=50, duty=0) # Создаем объект PWM для управления сервоприводом
#Функция передвижения сервопривода
def servo_m (angle):
print('Angle',angle)
# Перемещаем сервопривод в заданное положение angle
servo.duty(int(angle))
# Дополнительная задержка для стабилизации положения
sleep(0.5)
#Функция обратного вызова для сообщений MQTT.
#- topic (str): Тема MQTT, на которой было получено сообщение.
#- msg (str): Полученное сообщение с углом в формате строки.
def mqtt_message(topic, msg):
print("Входящее сообщение:", msg) # Отправляет пользователю сообщение на сервере узла сеансов удаленных рабочих столов
try:
global angle
angle = int(msg)
except Exception as e:
print("Ошибка:", e)
# Подключение к WiFi
print("Подключение к WiFi...", end="")
import network
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect("Wokwi-GUEST", "")
while not wifi.isconnected():
sleep(0.5) # пол секунды
print(".", end="")
print("Готово")
# Подключение к брокеру MQTT
print("Подключение к MQTT...")
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER) # в этой строке создается объект MQTTClient с указанным идентификатором клиента (MQTT_CLIENT_ID) и адресом брокера (MQTT_BROKER).
client.set_callback(mqtt_message) # с помощью этого метода устанавливается функция обратного вызова (mqtt_message), которая будет вызываться при получении нового сообщения.
client.connect() # данный метод используется для подключения к брокеру MQTT.
client.subscribe(MQTT_TOPIC) # с помощью этой команды клиент подписывается на указанный топик (MQTT_TOPIC), чтобы получать все сообщения, отправленные на этот топик.
print("Подключено!")
#Основной код
while True:
# Ожидание входящих сообщений MQTT
client.check_msg() # это функция, которая проверяет, есть ли новые сообщения от клиента.
sleep(1.5) # это функция, которая приостанавливает выполнение программы на 1 секунду.
print(angle) # это функция, которая выводит значение переменной angle, на экран или консоль.
servo_m(angle) # это функция, которая управляет сервоприводом и устанавливает его в определенное положение, которое определяется значением переменной angle.
# MQTT Server Parameters
MQTT_CLIENT_ID = "micropython-weather-demooo"
MQTT_BROKER = "mqtt-dashboard.com"
MQTT_USER = ""
MQTT_PASSWORD = ""
MQTT_TOPIC = "wokwi-weather1234"
sensor = dht.DHT22(Pin(15)) # подключение дисплея lcd к пину 15
print("Connecting to WiFi", end="")
sta_if = network.WLAN(network.STA_IF) # Создает объект WLAN для режима станции (STA) (то есть устройство подключается к существующей сети).
sta_if.active(True) # Включает режим станции.
sta_if.connect('Wokwi-GUEST', '') # Подключается к WiFi-сети с именем 'Wokwi-GUEST' и без пароля (второй параметр - пустая строка).
while not sta_if.isconnected(): # Цикл ожидания, пока устройство не подключится к WiFi.
print(".", end="") # Выводит точку на каждой итерации цикла, чтобы показать процесс подключения.
time.sleep(0.1) # Задержка 0.1 секунды между итерациями цикла.
print(" Connected!")
print("Connecting to MQTT server... ", end="")
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, user=MQTT_USER, password=MQTT_PASSWORD) # Создает объект MQTTClient с указанными параметрами (идентификатор клиента, адрес брокера, имя пользователя и пароль).
client.connect() # Устанавливает соединение с MQTT-брокером.
print("Connected!")
prev_weather = "" # Переменная для хранения предыдущих данных погоды.
while True: # Бесконечный цикл для измерения и передачи данных.
print("Measuring weather conditions... ", end="")
sensor.measure() # Измеряет показания датчика (предположительно температуры и влажности).
message = ujson.dumps({ # Создает JSON-строку с измеренными значениями температуры и влажности.
"temp": sensor.temperature(),
"humidity": sensor.humidity(),
})
if message != prev_weather: # Проверяет, изменились ли данные погоды
print("Updated!")
print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC, message)) # Этот метод заменяет заполнительные скобки соответствующими значениями. В данном случае, MQTT_TOPIC и message будут вставлены вместо {} в порядке их появления в строке.
client.publish(MQTT_TOPIC, message) # Публикует сообщение на указанный MQTT-топик.
prev_weather = message # Обновляет предыдущие данные погоды.
else:
print("No change")
time.sleep(1) # Задержка 1 секунда между итерациями цикла.
from machine import Pin
import dht
d = dht.DHT22(machine.Pin(15)) # Создаем экземпляр датчика DHT22, подключенного к GPIO 15
I2C_ADDR = 0x27 # Адрес ЖК-дисплея на шине I2C
# Размеры дисплея: 2 строки и 16 колонок
totalRows = 2
totalColumns = 16
# Настраиваем пины GPIO для управления светодиодами
led1 = machine.Pin(14, machine.Pin.OUT)
led2 = machine.Pin(26, machine.Pin.OUT)
# Инициализация шины I2C с указанными пинами SCL и SDA, а также частотой
i2c = SoftI2C(scl=Pin(13), sda=Pin(12), freq=10000)
# Настройка ЖК-дисплея, работающего через интерфейс I2C
lcd = I2cLcd(i2c, I2C_ADDR, totalRows, totalColumns)
while True:
try:
sensor.measure() # Измеряем показания с датчика DHT22
temp = sensor.temperature() # Получаем температуру в градусах Цельсия с датчика
hum = sensor.humidity() # Получаем влажность в процентах с датчика
# Выводим показания температуры и влажности в консоль
print(temp)
print(hum)
except OSError as e: # используется для перехвата исключений, связанных с ошибками операционной системы
print('Failed to read sensor.') # Если при считывании данных произошла ошибка, выводим сообщение об ошибке
# Принимаем решение о состоянии первого светодиода, исходя из температуры
if 17<temp<25:
# Если температура находится в диапазоне от 17 до 25 градусов, выключаем светодиод
led1.off()
else:
led1.on() # В ином случае включаем светодиод
# Принимаем решение о состоянии второго светодиода, исходя из влажности
if 20<hum<60:
# Если влажность находится в диапазоне от 20 до 60 процентов, выключаем светодиод
led2.off()
else:
led2.on() # В ином случае включаем светодиод
lcd.clear() # Эта инструкция очищает жидкокристаллический дисплей, удаляя с него весь текст, чтобы подготовить к отображению новых данных.
lcd.putstr(f'Temp: {temp}') # Это выводит строку на LCD с использованием форматированного литерала строк, который встраивает значение переменной temp (вероятно, температура) в строку. Текст Temp: является статичным, а {temp} будет заменено текущим значением температуры.
lcd.putstr(f' \nHumidity: {hum}') # Аналогично предыдущей строке, здесь на дисплей выводится информация о влажности. \n — это специальный символ перевода строки, который говорит LCD перейти к следующей строке, перед тем как напечатать Humidity: и значение переменной hum.
prev_weathertemp = "" # Это инициализирует или сбрасывает переменную prev_weathertemp, предположительно предназначенную для хранения предыдущего значения температуры. Строка пустая, указывая на то, что нет предыдущего значения.
prev_weatherhum = "" # Аналогично с prev_weathertemp, это инициализирует или сбрасывает переменную prev_weatherhum, которая должна будет хранить предыдущее значение влажности.
messagetemp = str(d.temperature()) # Здесь предполагается, что d.temperature() возвращает текущее значение температуры от датчика или другого источника данных, а это значение приводится к строке и сохраняется в переменной messagetemp.
messagehum = str(d.humidity()) # Подобно messagetemp, этот фрагмент получает текущее значение влажности от датчика d, преобразует его в строку и сохраняет в переменной messagehum.
if (temp != prev_weathertemp) or (hum != prev_weatherhum): #Эта строка начинает условное выражение с проверкой, изменилась ли текущая температура (temp)
#по сравнению с предыдущей записанной температурой (prev_weathertemp) или изменилась ли текущая влажность (hum) по сравнению с предыдущей
# записанной влажностью (prev_weatherhum). Если любое из этих условий верно (т.е., хотя бы одно из значений изменилось), то выполняется код внутри этого блока условия.
print("Updated!") # выводит сообщение "Updated!" в консоль, что говорит о том, что новые данные обнаружены.
print("Reporting to MQTT topic") # сообщает в консоль о том, что произойдет отправка сообщения в топик MQTT.
prev_weathertemp = temp # обновляются текущими значениями temp и hum. Это необходимо для сохранения текущего состояния температуры и влажности,
prev_weatherhum = hum # чтобы при следующей итерации можно было опять проверить, изменились ли данные.
client.publish(MQTT_TOPIC, str(temp)) # этот код отправляет текущие данные о температуре и влажности на два разных MQTT топика. Вероятно, MQTT_TOPIC и
client.publish(MQTT_TOPIC1, str(hum)) # MQTT_TOPIC1 - это переменные, которые содержат названия топиков MQTT, куда должны быть отправлены значения температуры и влажности соответственно. Используется протокол MQTT, который является популярным сетевым протоколом для устройств Internet of Things (IoT).
else:
print("No change")
time.sleep(1)