Введение
Привет, читатель, меня зовут Морозов Алексей, и в этой статье я наглядно покажу, как сделать метеостанцию! За работу.
Идея и ответы на почему
Я хочу сделать простую и модульную метеостанцию с консольным выводом данных
Сделать плату-опросчик, которая читает данные с датчиков и отправляет их в порт.
Сделать скрипт на питоне, который будет обрабатывать и выводить значения в консоль
Почему модульность?
Разделение метеостанции на два уровня, низкий(опрос датчиков) и высокий(обработка и вывод данных) позволяет быстро вносить изменения в систему, добавлять новые датчики или даже менять сами устройства.
Почему именно консольный вывод?
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 serial import plotext as plt import time ser = 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
Спасибо за внимание!
