Отобразим текущую температуру окружающей среды и среднее значение в течение определенного дня на ЖК-дисплее с помощью 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 в следующих публикациях.