Температура, влажность и давление являются основными параметрами, которые должна измерять метеорологическая станция (метеостанция). В данной статье мы рассмотрим создание метеостанции на основе платы Raspberry Pi, которая будет измерять температуру, влажность и давление и показывать их значения на экране дисплея, а также транслировать их в сеть Интернет, что позволяет получить к ним доступ из любой точки земного шара. Трансляция этих данных в сеть Интернет будет осуществляться через сервис ThingSpeak, который предоставляет хороший функционал для подобных задач и позволяет выводить измеряемые значения параметров в виде графиков. Подобный проект метеостанции мы уже рассматривали на нашем сайте на основе платы Arduino, но без измерения давления. Такие проекты сейчас принято относить к тематике интернета вещей (Internet of Things, IoT).
Для измерения значений температуры и влажности мы будем использовать датчик DHT11 (на нашем сайте мы рассматривали его подключение к плате Arduino), а для измерения атмосферного давления – датчик BM180 (подробнее о работе с ним также можно прочитать в статье про его подключение к плате Arduino).
Значения температуры и влажности окружающей среды в нашем проекте будут показываться на экране ЖК дисплея – температура будет показываться в градусах Цельсия, а влажность – в процентах. Также на экране ЖК дисплея будет показываться значение атмосферного давления в миллибарах или гектопаскалях (hPa). Также все эти данные будут передаваться на сервер ThingSpeak, откуда их можно будет просматривать из любой точки Земли, где есть доступ к сети Интернет. Более подробно работу проекта можно посмотреть на видео, приведенном в конце статьи.
Работа с сервисом ThingSpeak
Работа нашей метеостанции на основе платы Raspberry Pi будет заключаться в выполнении следующих шагов:
- сначала датчик DHT11 измеряет температуру и влажность, а датчик BM180 – атмосферное давление;
- затем плата Raspberry Pi считывает значения с датчика DHT11 с помощью однопроводного протокола (single wire protocol) и с датчика BM180 с помощью протокола I2C. После этого плата Raspberry Pi преобразует считанные значения в удобные для восприятия форматы: влажность в процентах, температура в градусах Цельсия, давление в гектопаскалях или миллибарах;
- далее эти данные передаются на сервис ThingSpeak используя встроенный в Raspberry Pi 3 Wi-Fi;
- и, наконец, сервис ThingSpeak анализирует принятые данные и показывает их в форме графиков. Также эти данные отображаются на экране ЖК дисплея.
ThingSpeak является отличным инструментом для проектов, связанных с тематикой интернета вещей. С помощью сервиса ThingSpeak мы можем просматривать данные и управлять работой системы через сеть Интернет, используя каналы (Channels) и страницы (webpages), обеспечиваемые данным сервисом. Достаточно подробно работу с сервисом ThingSpeak мы рассматривали в статье про метеостанцию на Arduino – можете ознакомиться с этой статьей если интересно, поэтому здесь мы на работе с сервисом ThingSpeak подробно останавливаться не будем.
Для начала вам необходимо создать себе аккаунт на сервисе ThingSpeak, и создать там новый канал (‘New channel’). Далее вы должны указать настройки этого канала и данные, которые вы хотите мониторить. В нашем проекте нам будет необходимо создать три поля – для значений температуры, влажности и давления.
После этого нажмите на вкладку ‘API keys’ и сохраните с нее ключи чтения и записи (Write and Read API keys), в нашем проекте мы будем использовать только ключ записи (Write key). Вам необходимо будет скопировать этот ключ в переменную ‘key’ в коде программы.
Далее нажмите на ‘Data Import/Export’ и скопируйте данные из поля Update Channel Feed чтобы получить URL, который мы далее будем использовать в программе, в нашем случае у нас получился следующий URL:
https://api.thingspeak.com/update?api_key=SIWOYBX26OXQ1WMS&field1=0
Этот URL мы будем использовать в коде программы на Python чтобы получить доступ к “api.thingspeak.com” и затем передавать данные используя этот Feed Request как строку запроса.
Но перед отправкой данных на сервис ThingSpeak нам необходимо добавить в эту строку запроса данные температуры, влажности и давления:
URL = 'https://api.thingspeak.com/update?api_key=%s' % key
finalURL = URL +"&field1=%s&field2=%s"%(humi, temp)+"&field3=%s" %(pressure)
Для считывания платой Raspberry Pi данных с датчика DHT11 мы будем использовать протокол однопроводной связи, для этого мы будем использовать библиотеку AdaFruit DHT11. Собранные данные с датчиков DHT11 и BMP180 мы будем передавать на ЖК дисплей 16x2 и сервер ThingSpeak, который будет отображать их в виде графиков, пример которых показан на следующем рисунке:
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- ЖК дисплей 16x2 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- Датчик температуры и влажности DHT11 (купить на AliExpress).
- Датчик барометрического давления BMP180 (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Схема проекта
Схема метеостанции на основе платы Raspberry Pi представлена на следующем рисунке.
Как видите, схема достаточно проста. ЖК дисплей подключен к плате Raspberry Pi в 4-битном режиме.
Настройка Raspberry Pi
Для работы нашего проекта нам необходимо установить библиотеку Adafruit для работы с датчиком DHT11 – Adafruit Python DHT Sensor Library. Для этого необходимо выполнить следующую последовательность команд:
1 2 3 4 5 6 |
sudo apt-get install git-core sudo apt-get update git clone https://github.com/adafruit/Adafruit_Python_DHT.git cd Adafruit_Python_DHT sudo apt-get install build-essential python-dev sudo python setup.py install |
После этого в настройках Raspberry Pi необходимо включить возможность работы с интерфейсом I2C, для этого заходим в настройки с помощью команды:
1 |
sudo raspi-config |
Затем заходим в ‘Advance Options’ (расширенные настройки), выбираем ‘I2C’ и ‘Enable’ (включаем его).
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Первым делом в программе нам необходимо подключить все необходимые библиотеки, инициализировать переменные и задать (определить) необходимые контакты.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import sys import RPi.GPIO as GPIO import os import Adafruit_DHT import urllib2 import smbus import time from ctypes import c_short #Register Address regCall = 0xAA ... ...... ..... ... |
В функции def main() мы будем передавать данные на сервер ThingSpeak и отображать их на экране ЖК дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def main(): print 'System Ready...' URL = 'https://api.thingspeak.com/update?api_key=%s' % key print "Wait...." while True: (humi, temp)= readDHT() (pressure) =readBmp180() lcdcmd(0x01) lcdstring("Humi#Temp#P(hPa)") lcdstring(humi+'%'+" %sC %s" %(temp, pressure)) finalURL = URL +"&field1=%s&field2=%s"%(humi, temp)+"&field3=%s" %(pressure) print finalURL s=urllib2.urlopen(finalURL); print humi+ " " + temp + " " + pressure s.close() time.sleep(10) |
Функция def lcd_init() будет использоваться для инициализации ЖК дисплея в 4-битном режиме, функция def lcdcmd(ch) – для передачи команд на ЖК дисплей, функция def lcddata(ch) – для передачи данных на ЖК дисплей, функция def lcdstring(Str) – для передачи строки на ЖК дисплей. Код этих функций приведен далее в тексте программы. Более подробно о подключении ЖК дисплея к плате Raspberry Pi вы можете прочитать в этой статье.
Функция def readDHT() используется для считывания данных с датчика DHT11.
1 2 3 |
def readDHT(): humi, temp = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, DHTpin) return (str(int(humi)), str(int(temp))) |
Функция def readBmp180 используется для считывания данных с датчика давления BM180. Датчик BM180 также измеряет и температуру, но мы в нашем проекте это его свойство не используем.
1 2 3 4 5 6 7 8 9 10 |
def readBmp180(addr=deviceAdd): value = bus.read_i2c_block_data(addr, regCall, 22) # Read calibration data # Convert byte data to word values AC1 = convert1(value, 0) AC2 = convert1(value, 2) AC3 = convert1(value, 4) AC4 = convert2(value, 6) ..... ....... ........ ...... |
Вы можете усовершенствовать данный проект метеостанции на Raspberry Pi, добавив в него измерение скорости ветра, освещенности, температуры земли, интенсивности дождя, качества воздуха и т.д.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
import sys import RPi.GPIO as GPIO import os import Adafruit_DHT import urllib2 import smbus import time from ctypes import c_short #Register Address regCall = 0xAA regMean = 0xF4 regMSB = 0xF6 regLSB = 0xF7 regPres = 0x34 regTemp = 0x2e DEBUG = 1 sample = 2 deviceAdd =0x77 humi="" temp="" #bus = smbus.SMBus(0) #for Pi1 uses 0 I2cbus = smbus.SMBus(1) # for Pi2 uses 1 DHTpin = 17 key="30BCDSRQ52AOI3UA" # введите здесь ваш Write API key с сервиса ThingSpeak GPIO.setmode(GPIO.BCM) # контакты GPIO к которым подключен ЖК дисплей LCD_RS = 18 LCD_EN = 23 LCD_D4 = 24 LCD_D5 = 16 LCD_D6 = 20 LCD_D7 = 21 GPIO.setwarnings(False) # отключаем показ любых предупреждений GPIO.setmode(GPIO.BCM) GPIO.setup(LCD_E, GPIO.OUT) GPIO.setup(LCD_RS, GPIO.OUT) GPIO.setup(LCD_D4, GPIO.OUT) GPIO.setup(LCD_D5, GPIO.OUT) GPIO.setup(LCD_D6, GPIO.OUT) GPIO.setup(LCD_D7, GPIO.OUT) def convert1(data, i): # signed 16-bit value return c_short((data[i]<< 8) + data[i + 1]).value def convert2(data, i): # unsigned 16-bit value return (data[i]<< 8) + data[i+1] def readBmp180(addr=deviceAdd): value = bus.read_i2c_block_data(addr, regCall, 22) # считываем калибровочные данные # Convert byte data to word values AC1 = convert1(value, 0) AC2 = convert1(value, 2) AC3 = convert1(value, 4) AC4 = convert2(value, 6) AC5 = convert2(value, 8) AC6 = convert2(value, 10) B1 = convert1(value, 12) B2 = convert1(value, 14) MB = convert1(value, 16) MC = convert1(value, 18) MD = convert1(value, 20) # считываем температуру bus.write_byte_data(addr, regMean, regTemp) time.sleep(0.005) (msb, lsb) = bus.read_i2c_block_data(addr, regMSB, 2) P2 = (msb << 8) + lsb # считываем давление bus.write_byte_data(addr, regMean, regPres + (sample << 6)) time.sleep(0.05) (msb, lsb, xsb) = bus.read_i2c_block_data(addr, regMSB, 3) P1 = ((msb << 16) + (lsb << 8) + xsb) >> (8 - sample) # преобразовываем значение температуры в удобный для восприятия вид X1 = ((P2 - AC6) * AC5) >> 15 X2 = (MC << 11) / (X1 + MD) B5 = X1 + X2 temperature = (B5 + 8) >> 4 # преобразовываем значение давления в удобный для восприятия вид B6 = B5 - 4000 B62 = B6 * B6 >> 12 X1 = (B2 * B62) >> 11 X2 = AC2 * B6 >> 11 X3 = X1 + X2 B3 = (((AC1 * 4 + X3) << sample) + 2) >> 2 X1 = AC3 * B6 >> 13 X2 = (B1 * B62) >> 16 X3 = ((X1 + X2) + 2) >> 2 B4 = (AC4 * (X3 + 32768)) >> 15 B7 = (P1 - B3) * (50000 >> sample) P = (B7 * 2) / B4 X1 = (P >> 8) * (P >> 8) X1 = (X1 * 3038) >> 16 X2 = (-7357 * P) >> 16 pressure = P + ((X1 + X2 + 3791) >> 4) return (str(pressure/100.0)) def readDHT(): humi, temp = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, DHTpin) return (str(int(humi)), str(int(temp))) def lcd_init(): lcdcmd(0x33) lcdcmd(0x32) lcdcmd(0x06) lcdcmd(0x0C) lcdcmd(0x28) lcdcmd(0x01) time.sleep(0.0005) def lcdcmd(ch): GPIO.output(RS, 0) GPIO.output(D4, 0) GPIO.output(D5, 0) GPIO.output(D6, 0) GPIO.output(D7, 0) if ch&0x10==0x10: GPIO.output(D4, 1) if ch&0x20==0x20: GPIO.output(D5, 1) if ch&0x40==0x40: GPIO.output(D6, 1) if ch&0x80==0x80: GPIO.output(D7, 1) GPIO.output(EN, 1) time.sleep(0.0005) GPIO.output(EN, 0) # Low bits (младшие биты) GPIO.output(D4, 0) GPIO.output(D5, 0) GPIO.output(D6, 0) GPIO.output(D7, 0) if ch&0x01==0x01: GPIO.output(LCD_D4, 1) if ch&0x02==0x02: GPIO.output(LCD_D5, 1) if ch&0x04==0x04: GPIO.output(LCD_D6, 1) if ch&0x08==0x08: GPIO.output(LCD_D7, 1) GPIO.output(EN, 1) time.sleep(0.0005) GPIO.output(EN, 0) def lcddata(ch): GPIO.output(RS, 1) GPIO.output(D4, 0) GPIO.output(D5, 0) GPIO.output(D6, 0) GPIO.output(D7, 0) if ch&0x10==0x10: GPIO.output(D4, 1) if ch&0x20==0x20: GPIO.output(D5, 1) if ch&0x40==0x40: GPIO.output(D6, 1) if ch&0x80==0x80: GPIO.output(D7, 1) GPIO.output(EN, 1) time.sleep(0.0005) GPIO.output(EN, 0) # Low bits GPIO.output(D4, 0) GPIO.output(D5, 0) GPIO.output(D6, 0) GPIO.output(D7, 0) if ch&0x01==0x01: GPIO.output(LCD_D4, 1) if ch&0x02==0x02: GPIO.output(LCD_D5, 1) if ch&0x04==0x04: GPIO.output(LCD_D6, 1) if ch&0x08==0x08: GPIO.output(LCD_D7, 1) GPIO.output(EN, 1) time.sleep(0.0005) GPIO.output(EN, 0) def lcdstring(Str): l=0; l=len(Str) for i in range(l): lcddata(ord(message[i])) lcd_init() lcdcmd(0x01) lcdstring("Circuit Digest") lcdcmd(0xc0) lcdstring("Welcomes you") time.sleep(3) # 3 second delay # main() function def main(): print 'System Ready...' URL = 'https://api.thingspeak.com/update?api_key=%s' % key print "Wait...." while True: (humi, temp)= readDHT() (pressure) =readBmp180() lcdcmd(0x01) lcdstring("Humi#Temp#P(hPa)") lcdstring(humi+'%'+" %sC %s" %(temp, pressure)) finalURL = URL +"&field1=%s&field2=%s"%(humi, temp)+"&field3=%s" %(pressure) print finalURL s=urllib2.urlopen(finalURL); print humi+ " " + temp + " " + pressure s.close() time.sleep(10) if __name__=="__main__": main() |