Введение
Привет, читатель, меня зовут Морозов Алексей, и в этой статье я наглядно покажу, как сделать метеостанцию! За работу.
Идея и ответы на почему
Я хочу сделать простую и модульную метеостанцию с консольным выводом данных
-
Сделать плату-опросчик, которая читает данные с датчиков и отправляет их в порт.
-
Сделать скрипт на питоне, который будет обрабатывать и выводить значения в консоль
Почему модульность?
Разделение метеостанции на два уровня, низкий(опрос датчиков) и высокий(обработка и вывод данных) позволяет быстро вносить изменения в систему, добавлять новые датчики или даже менять сами устройства.
Почему именно консольный вывод?
TUI — отличная отправная точка для вывода данных, можно быстро менять формат вывода, добавлять новые диаграммы и даже окна.
Подбор компонентов
-
В качестве платы опросчика, подойдёт
arduino nano, у неё достаточно мощности и портов, чтобы развивать метеостанцию до предела -
В качестве датчика я решил взять
htu21d, который умеет определять температуру и влажность воздуха. Отличная плата для начала, потом заменю наbmp280
Подключение
Приступим к сборке метеостанции! Вот схема подключения:
Пример сборки тут.
Код для ардуино
Вот код для считывания данных с датчика и отправки их в порт:
#include <GyverHTU21D.h>GyverHTU21D htu;void getTemp(){ Serial.print("Temp:"); Serial.print(htu.getTemperature()); Serial.print(","); Serial.print("Humd:"); Serial.println(htu.getHumidity());}void setup() { Serial.begin(115200); htu.begin();}void loop() { if (htu.readTick()) { getTemp(); }}
Если открыть вывод в ардуино иде, то мы увидим вот такую картину.
Код на питон
Вот код скрипта на питон, для парсинга и вывода данных в виде графика:
import serialimport plotext as pltimport timeser = serial.Serial('/dev/ttyUSB0', 115200)def read_and_parse(): response = ser.readline() if not response: return None, None try: decoded_response = response.decode('utf-8') input_string = decoded_response.rstrip('\n') # Разбиваем строку на пары ключ:значение pairs = input_string.split(',') if len(pairs) != 2: print("Ошибка: строка должна содержать ровно две пары ключ:значение") return None, None expected_key1 = "Temp" expected_key2 = "Humd" value1 = None value2 = None for pair in pairs: parts = pair.split(':', 1) # Разбиваем только по первому ':' if len(parts) != 2: print(f"Ошибка: некорректный формат пары: {pair}") return None, None key, value = parts[0].strip(), parts[1].strip() if key == expected_key1: value1 = value elif key == expected_key2: value2 = value else: print(f"Предупреждение: неизвестный ключ '{key}' найден в строке") # Проверяем, нашли ли оба ожидаемых значения if value1 is None or value2 is None: print("Ошибка: не найдены значения для одного или обоих ожидаемых ключей") return None, None return value1, value2 except Exception as e: print(f"Произошла ошибка при парсинге: {e}") return None, None def plot_data(temp, humd): x = ["Температура", "Влажность"] # Значения y = (float(temp), float(humd)) colors = ["cyan", "red"] plt.clear_data() plt.bar(x, y, color=colors, orientation="horizontal", width=3/5) plt.title("Данные с датчика") plt.ylabel("Значение") plt.clt() plt.show() def main(): print("Начало работы! Нажмите Ctrl+C для завершения.") try: while True: temp, humd = read_and_parse() # Рисуем только если данные успешно получены if temp is not None and humd is not None: plot_data(temp, humd) # Небольшая пауза, чтобы не нагружать процессор и дать время Arduino time.sleep(0.1) except KeyboardInterrupt: print("\nЗавершение работы...") finally: ser.close()if __name__ == "__main__": main()
Обратите внимание!
На 4 строчке, если вы работаете на windows, то нужно поменять с /dev/ttyUSB0 на COMX(заменить на номер порта куда подключена ваша плата, можно посмотреть в ардуино иде)
Тесты
Всё исправно работает!
Завершение
Всё заработало — это успех.
Идеи по доработке:
-
Поставить датчик давления(bmp280)
-
сделать GUI, например на PyQt6 + Qt creator
Спасибо за внимание!
ссылка на оригинал статьи https://habr.com/ru/articles/1055066/