Датчик температуры Raspberry Pi с выводом на ЖК-экран

Отобразим текущую температуру окружающей среды и среднее значение в течение определенного дня на ЖК-дисплее с помощью Raspberry Pi.

Что нам понадобится?

Аппаратные средства/комплектующие:

  • Raspberry Pi 3 Модель B+ (примерно $60)
  • Аналоговый датчик температуры (примерно $8)
  • Модуль преобразователя AD/DA (примерно $9)
  • ЖК-экран LCD1602 (примерно $12)

Все эти комплектующие нам помогут отобразить текущую температуру окружающей среды и средний показатель за определенный день на ЖК-дисплее, используя Raspberry Pi, aWhere API и библиотеки SunFounder.

Датчик температуры Raspberry Pi

В уроке использован Sensor Kit V2.0 от SunFounder, который поставляется с аналоговым температурным датчиком, и их PCF8591, который является устройством сбора данных. Мы использовали схему проекта от SunFounder, как показано ниже:

После правильной сборки схемы используйте код для проверки конфигурации. Вы можете скачать его на официальной странице здесь. Их код идет как на Python, так и на C, мы будем использовать Python.

Если вы делаете всё дистанционно, вы можете загрузить код на свой компьютер и использовать FileZilla, чтобы перенести его на свой Raspberry Pi.

Чтобы протестировать схему, запустите файл "18_thermistor.py". Результат должен выглядеть примерно так.

Использование ЖК-дисплея Raspberry Pi

Дисплей, который был использован, имеет только четыре провода. Оставьте датчик температуры подключенным. Используя схему ниже, предоставленную SunFounder, подключите ЖК-дисплей.

ЖК-дисплей и датчик температуры перекрываются на контактах «SDA1» и «SCL1». Он работает с этими контактами.

Чтобы отобразить текущую температуру на ЖК-дисплее, создайте новый каталог, например «LCDTemp», и скопируйте два файла, выделенные ниже на рисунке из каталога кода SunFounder, в ваш новый каталог. Это библиотеки, специфичные для оборудования SunFounder Kit (мы не тестировали их работу с другими датчиками).

Теперь, когда у вас есть эти библиотеки, настало время начать писать код для отображения текущей температуры на ЖК-дисплее:

#*****dispTemp.py*****#
from decimal import Decimal
import RPi.GPIO as GPIO
import PCF8591 as ADC
import math
import time
import LCD1602 as LCD

tempPin = 11  # temperature D0 pin
GPIO.setmode(GPIO.BOARD)  # reference pins using BOARD numbers


# *****Initialize Pins*****#
def setup():
    ADC.setup(0x48)  # set up analog converter
    GPIO.setup(tempPin, GPIO.IN)  # set pin to input
    LCD.init(0x27, 1)  # init(slave address, background light)


def loop():
    while True:
        analogVal = ADC.read(0)  # read temperature sensor value
        # Calculations to convert to Celsius, from SunFounder
        Vr = 5 * float(analogVal) / 255
        Rt = 10000 * Vr / (5 - Vr)
        temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
        temp = Decimal(temp - 273.15)  # convert to Decimal Type
        temp = round(temp, 1)  # round to 1 decimal point
        LCD.write(0, 0, 'Temp: {} C'.format(temp))  # write to top row and farthest left column of LCD
        time.sleep(1)  # update every second

# *****MAIN*****#
if __name__ == '__main__':
    try:
        setup()
        loop()
    except KeyboardInterrupt:
        pass

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

Получение исторических данных погоды с использованием API aWhere

Самый простой бесплатный API, который получилось найти для получения средних исторических температур для определенного местоположения, - использовать aWhere. С помощью aWhere вы можете получать всевозможные исторические данные о погоде.

Вы можете получить на бесплатную учетную запись на сайте aWhere здесь. Зарегистрировавшись, перейдите в «Моя учетная запись» (англ. - My Account) в верхнем правом углу и нажмите на «Мои приложения» (англ. - My apps). Внутри «Мои приложения» нажмите синюю кнопку «Добавить новое приложение» (англ. - Add a new App), как показано ниже:

Создав приложение, вы получите ключ «Consumer Key» и «Consumer Secret», мы будем использовать их, чтобы получить токен аутентификации в приведенном ниже коде.

Создание поля

Ощущение, что сервис aWhere больше направлен на сельскохозяйственное направление, поэтому, естественно, чтобы указать местоположение, чтобы получить температуру, нам нужно «добавить поле» (англ. - add a field) в наше приложение.

Документацию для добавления поля можно найти по ссылке. Сначала мы попробовали два разных способа, используя запросы «requests» и «urllib», но не смогли заставить всё работать. Единственный пример Python, который был найден, который работал, был в разделе ответов здесь, и именно на этом основан код ниже:

#*****addField.py*****#
import json
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

url = 'https://api.awhere.com/v2/fields'
consumer_key = '' # key
consumer_secret = '' # secret

# body of request, change to wherever you would like
body = {
    "id": "CN_Tower",
    "name": "Toronto",
    "farmId": "accr",
    "centerPoint": {
        "latitude": 43.642465, # can get these from Google maps
        "longitude": -79.386488
    }
}

# get Authentication token
client = BackendApplicationClient(client_id = consumer_key)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url='https://api.awhere.com/oauth/token', client_id=consumer_key, client_secret=consumer_secret)

# post body to url
client = OAuth2Session(consumer_key, token=token)
field_response = client.post(url, json=body)
print(field_response.json())

После выполнения кода выше, если вы успешно добавили поле, результат должен выглядеть примерно так (в зависимости от выбранного вами местоположения):

Получение исторических данных о погоде

Теперь, когда вы успешно создали поле, вы можете извлекать исторические данные о погоде для географического местоположения. Здесь можно найти документацию от aWhere.

Этот шаг довольно прост, приведенный ниже код должен только вернуть среднюю температуру за этот день за последние 10 лет.

#*****histWeather.py*****#
import requests, json, base64

id = 'CN_Tower' # field id
date = '05-23' # month and day that you would like 10 year average for
key = ''
secret = ''

# *****Get aWhere security token*****#
def getToken():
    combination = key+':'+secret.encode()
    auth = base64.b64encode(combination).decode('utf8')

    credential = auth
    response = requests.post('https://api.awhere.com/oauth/token',
                             data='grant_type=client_credentials',
                             headers={'Content-Type': 'application/x-www-form-urlencoded',
                                      'Authorization': 'Basic {}'.format(credential)}).json()

    if 'access_token' and 'expires_in' in response.keys():
        print(response['access_token'])
        return response['access_token']
    else:
        raise ValueError(response)


token = getToken()  # get auth token

headers = {"Authorization": "Bearer " + token,
           "Content-Type": "application/json"}
response = requests.get('https://api.awhere.com/v2/weather/fields/'+id+'/norms/'+date, headers=headers)
data = response.json()
print(str(data['meanTemp']['average']))
print(response)

Результат должен выглядеть примерно так:

Цифра 15 на рисунке выше - средняя температура в градусах Цельсия.

Собираем всё вместе

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

Код предназначен для обновления температуры окружающей среды каждую секунду, но средняя температура - только один раз в день. Он сравнивает день с помощью счетчика «currDay»:

#*****LCDTemp.py*****#
from decimal import Decimal
import RPi.GPIO as GPIO
import PCF8591 as ADC
import math
import time
import LCD1602 as LCD
import requests, json, base64, datetime

tempPin = 11  # temperature D0 pin
GPIO.setmode(GPIO.BOARD)  # reference pins using BOARD numbers
key = ''  # Consumer Key
secret = ''  # Consumer Secret


# *****Initialize Pins*****#
def setup():
    ADC.setup(0x48)  # set up analog converter
    GPIO.setup(tempPin, GPIO.IN)  # set pin to input
    LCD.init(0x27, 1)  # init(slave address, background light)


# *****Main Loop, sets temperatures*****#
def loop():
    currDay = 0  # use currDay as variable to keep track of last numeric day
    while True:
        now = datetime.datetime.now()  # create datetime object called now
        if currDay == now.day:  # if currDay and now.day are equal, only update ambient temperature
            analogVal = ADC.read(0)  # read temperature sensor value
            # Calculations to convert to Celsius, from SunFounder
            Vr = 5 * float(analogVal) / 255
            Rt = 10000 * Vr / (5 - Vr)
            temp = 1 / (((math.log(Rt / 10000)) / 3950) + (1 / (273.15 + 25)))
            temp = Decimal(temp - 273.15)  # convert to Decimal Type
            temp = round(temp, 1)  # round to 1 decimal point
            LCD.write(0, 0, 'Temp: {} C'.format(temp))  # write to top row and farthest left column of LCD
            time.sleep(1)  # update every second

        else:  # if date has changed
            avgTemp = getHistTemp(now.strftime('%m-%d'))  # get average historical temperature for that day
            avgTemp = round(Decimal(avgTemp), 1)  # convert to decimal and round
            LCD.write(0, 1, 'Avg Temp: ' + str(avgTemp) + ' C')  # write to second row of lcd
            currDay = now.day  # update current day


# *****Get aWhere security token*****#
def getToken():
    combination = key + ':' + secret.encode()
    auth = base64.b64encode(combination).decode('utf8')

    credential = auth
    response = requests.post('https://api.awhere.com/oauth/token',
                             data='grant_type=client_credentials',
                             headers={'Content-Type': 'application/x-www-form-urlencoded',
                                      'Authorization': 'Basic {}'.format(credential)}).json()

    if 'access_token' and 'expires_in' in response.keys():  # if response contains access token
        print(response['access_token'])
        return response['access_token']  # return access token
    else:
        raise ValueError(response)


# ***** use aWhere to get historical temperature for certain day*****#
def getHistTemp(date):
    token = getToken()
    headers = {"Authorization": "Bearer " + token,
               "Content-Type": "application/json"}
    response = requests.get('https://api.awhere.com/v2/weather/fields/Toronto/norms/' + date, headers=headers)
    data = response.json()
    return (data['meanTemp']['average'])


# *****MAIN*****#
if __name__ == '__main__':
    try:
        setup()
        loop()
    except KeyboardInterrupt:
        pass

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

На этом пока всё. Больше о проектах на Raspberry в следующих публикациях.

Ардуино+