Raspberry Pi

Русский сайт по микрокомпьютеру
Предложить пост

Вход








Регистрация | Забыли пароль?

Поиск



По всему сайту
По тэгам
По тэгам и заголовкам

Рубрики

  • Проекты и статьи
  • Модели
  • Новости
  • Мысли
  • Рейтинг

  • 1. Хакеры могут атаковать устройства Apple через Bluetooth и Raspberry Pi
  • 2. Новая операционная система для государства Российского!
  • 3. Настройка приёма цифрового телевещания dvb-t2 на компьютере Raspberry PI
  • 4. Используем старую кассету в качестве корпуса под Raspberry Pi
  • 5. Умное ружьё "Калашников" на базе Raspberry Pi
  • Облако тэгов

    raspberry pi 3, raspbian, windows, ubuntu, linux, умный дом, windows 10, osmc, игры, python, gpio, установка ос, raspberry pi 2, raspberry pi zero, raspberry pi zero w, слежение, самолёт, http, diy, 1c-битрикс, оружие, сеть, кластер, бесперебойник, акустика

    Боковое меню

  • RSS-канал
  • Карта сайта
  • Обратная связь
  • Пользователи


    Top.Mail.Ru
  • Кроссплатформенная разработка погодной станции для Raspberry Pi

    Как известно, что ни делай под Raspberry Pi, получится либо медиаплеер, либо метеостанция. Постигла эта участь и меня — когда после очередного ливня датчик метеостанции залило, настала пора или купить новую, или сделать самому.

    От метеостанции нужны были следующие функции:

    отображение температуры
    отображение графика атмосферного давления
    прогноз дождя
    синхронизация времени (в случае обычной метеостанции, по DCF77, если уж на устройстве есть часы, они должны показывать точное время)


    Из покупных, по сочетанию «дизайн-цена-функции» не понравилась ни одна — либо нет одного, либо другого, либо слишком громоздко и дорого. В итоге решено было задействовать Raspberry Pi с TFT-экраном, и сделать те функции, которые нужны.

    Получилось примерно так:



    Получение данных погоды

    Первое, с чем нужно было определиться — это получение данных погоды. Здесь есть 2 варианта, либо использовать свои датчики, либо брать погоду из интернета. Первое интереснее, но есть несколько «но»:

    Сделать датчик «абы как» несложно, но сделать датчик хорошо, чтобы он например год работал от одного комплекта батареек, задача уже не столь тривиальная. Есть конечно сейчас и малопотребляющие процы, и радиомодули, но потратить на это месяц было бы лень.
    Нужно заморачиваться с корпусом, влагозащитой и прочими мелочами (3д-принтера у меня нет).
    Балкон выходит на солнечную сторону, так что погрешность измерения температуры в первую половину дня была бы слишком большой.


    Альтернативным вариантом была покупка готового метеомодуля с датчиками для Raspberry Pi.
    Увы, поиск показал что в продаже есть всего 2 варианта:

    — Raspberry Pi sense hat



    Плата имеет «на борту» термометр, барометр, датчик влажности, гироскоп и акселерометр — но чем думали разработчики, ставя такой «экран» 8х8 светодиодов, непонятно — ничего внятного на нем вывести нельзя. Желаю разработчикам этого модуля всю жизнь UI под матрицу 8х8 писать :)

    — Raspberry Pi weather hat



    Ничего кроме светодиодов здесь нет вообще.

    В общем, как ни странно, но нормального готового шилда для метеостанции с хорошим экраном и хорошим набором датчиков так никто и не сделал. Краудсорсеры, ау — рыночная ниша пропадает :)

    В итоге, не паримся и делаем по-простому — берем погоду из Интернета и выводим на обычный TFT. Как подсказал гугл, самое развитое API сейчас у https://openweathermap.org/api, его и будем использовать.

    В комментариях был вопрос про точность интернет-данных. Как можно видеть в коде ниже, для вывода температуры и атмосферного давления используется запрос на получение текущих (current weather data), а не прогнозируемых данных. Их точность можно считать вполне достаточной для бытовых целей, более того, скорее всего она даже выше, чем точность уличного термометра/датчика, размещенного за окном или на балконе.

    Регистрация

    Для получения данных погоды с openweathermap нужен ключ, его можно получить бесплатно, зарегистрировавшись на вышеупомянутом сайте. Ключ выглядит примерно так «dadef5765xxxxxxxxxxxxxx6dc8». Большинство функций доступны бесплатно, платные API нам не понадобятся. Для бесплатных функций есть ограничение на 60 запросов в минуту, нам этого достаточно.

    Чтение данных

    Чтение данных весьма просто благодаря библиотеке pyowm.

    Получение погоды на данный момент (Python):

    import pyowm

    owm = pyowm.OWM(apiKey)
    observation = owm.weather_at_coords(lat, lon)
    w = observation.get_weather()
    dtRef = w.get_reference_time(timeformat='date')
    t = w.get_temperature('celsius')
    temperatureVal = int(t['temp'])

    p = w.get_pressure()
    pVal = int(p['press'])


    Получение прогноза погоды для отображения осадков:

    fc = owm.three_hours_forecast_at_coords(lat, lon)
    rain = fc.will_have_rain()
    snow = fc.will_have_snow()
    rains = fc.when_rain()


    На выходе получаем массив данных со списком дождей и их интенсивностью. Несмотря на название функции three_hours_forecast_at_coords, дожди прописаны на 2-3 дня вперед.

    Можно использовать GET-запросы напрямую, например так. Это может пригодиться, например при портировании кода на MicroPython под ESP.

    Получение координат пользователя

    Как можно видеть выше, для получения данных нужны широта и долгота. Получение координат также весьма просто, и делается в 3 строчки кода:

    import geocoder

    g = geocoder.ip('me')
    lat = g.latlng[0]
    lon = g.latlng[1]


    UI

    Собственно, самая сложная часть. На Raspberry Pi используется TFT-дисплей от Adafruit, поддерживающий систему команд ILI9340. Библиотеки под него найти несложно, однако отлаживать код на Raspberry Pi не очень удобно. В итоге было принято решение написать высокоуровневый набор контролов, которых нужно было всего 3 — изображения, текст и линии. При запуске на Raspberry Pi контрол будет рисовать себя на TFT, при запуске на десктопе будет использоваться встроенная в Python библиотека tkinter. В итоге, код будет работать везде — и на Raspberry Pi, и на Windows, и на OSX.

    Код одного контрола выглядит примерно так:

    class UIImage:
    def __init__(self, image = None, x = 0, y = 0, cId = 0):
    self.x = x
    self.y = y
    self.width = 0
    self.height = 0
    self.cId = cId
    self.tkID = None
    self.tftImage = None
    self.tkImage = None
    self.useTk = utils.isRaspberryPi() is False
    if image is not None:
    self.setImage(image)

    def setImage(self, image):
    width, height = image.size
    if self.useTk:
    self.tkImage = ImageTk.PhotoImage(image)
    self.tftImage = image
    self.width = width
    self.height = height

    def draw(self, canvas = None, tft = None):
    if tft != None:
    tft.draw_img(self.tftImage, self.x, self.y, self.width, self.height)
    elif canvas != None and self.tkImage != None:
    if self.tkID == None or len(canvas.find_withtag(self.tkID)) == 0:
    self.tkID = canvas.create_image(self.x, self.y, image=self.tkImage , anchor=tkinter.NW)
    else:
    canvas.itemconfigure(self.tkID, image=self.tkImage)


    Класс «FakeTFT» создает обычное окно программы:

    class FakeTFT:
    def __init__(self):
    self.tkRoot = tkinter.Tk()
    self.tkRoot.geometry("500x300")

    self.screenFrame = tkinter.Frame(self.tkRoot, width=330, height=250, bg="lightgray")
    self.screenFrame.place(x=250 - 330 / 2, y=5)

    self.tkScreenCanvas = tkinter.Canvas(self.tkRoot, bg = 'white', width = 320, height = 240, highlightthickness=0)
    self.tkScreenCanvas.focus_set()
    self.tkScreenCanvas.place(x=250 - 320 / 2, y=10)

    self.controls = []

    def draw(self):
    for c in self.controls:
    c.draw(self.tkScreenCanvas)


    Класс «LCDTFT» использует «настоящий» дисплей (фрагмент кода):

    class LCDTFT:
    def __init__(self, spidev, dc_pin, rst_pin=0, led_pin=0, spi_speed=16000000):
    # CE is 0 or 1 for RPI, but is actual CE pin for virtGPIO
    # RST pin. 0 means soft reset (but reset pin still needs holding high (3V)
    # LED pin, may be tied to 3V (abt 14mA) or used on a 3V logic pin (abt 7mA)
    # and this object needs to be told the GPIO and SPIDEV objects to talk to
    global GPIO
    self.SPI = spidev
    self.SPI.open(0, 0)
    self.SPI.max_speed_hz = spi_speed

    self.RST = rst_pin
    self.DC = dc_pin
    self.LED = led_pin

    self.controls = []

    def draw(self):
    for c in self.controls:
    c.draw(tft = self)


    При инициализации автоматически выбирается нужный дисплей, в зависимости от того, где запускается программа:

    def lcdInit():
    if utils.isRaspberryPi():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)

    DC = 25
    LED = 18
    RST = 0
    return LCDTFT(spidev.SpiDev(), DC, RST, LED)
    else:
    return FakeTFT()


    Все это позволяет полностью абстрагироваться от «железа», и писать код типа такого:

    self.labelPressure = libTFT.UILabel("Pressure", 18,126, textColor=self.tft.BLACK, backColor=self.tft.WHITE, fontS = 7)
    self.tft.controls.append(self.labelPressure)
    self.labelRain = libTFT.UILabel("Rain", 270,126, textColor=self.tft.BLUE, backColor=self.tft.WHITE, fontS = 7)
    self.tft.controls.append(self.labelRain)


    Собственно UI выглядит так:



    На экране отображаются текущая температура, график атмосферного давления за сегодняшний день (в следующей версии будет добавлен график температуры), также в случае прогноза дождя, его время отмечается на графике вертикальной синей чертой (на данной картинке дождей нет). Также выводятся время последнего обновления данных и IP-адрес, если понадобится подключиться к устройству.

    Желающие ознакомиться с исходником подробнее, могут посмотреть его на guthub.

    Установка на Raspberry Pi

    Для тех, кто не хочет заморачиваться описанным выше, короткая инструкция по установке:

    — Скачиваем исходники с github:
    git clone github.com/dmitryelj/RPi-Weather-Station.git

    — Если не установлен Python3, ставим:
    sudo apt-get install python3

    — Ставим дополнительные библиотеки (они нужны для работы с дисплеем):
    sudo pip3 install numpy pillow spidev

    — Добавляем в автозапуск (sudo nano /etc/rc.local)

    python3 /home/pi/Documents/RPi-Weather-Station/weather.py &

    — Пробуем запустить

    python3 weather.py

    Если все работает, то перезагружаемся (sudo reboot) и пользуемся.

    В плане добавить еще что-нибудь полезное, например отображение карты облачности, API на openweathermap для этого есть.

    Продолжение следует.

    Источник

    07.10.2017 в 00:26, Просмотров: 4157

    метеостанция, python

    ID: 16