Wi-Fi является неотъемлемой частью любого DIY-проекта Internet of Things (IoT), но наш любимый Arduino не поставляется с Wi-Fi, а добавление щита Wi-Fi может привести к общей стоимости около 40 долларов. Что если я скажу вам, что есть Arduino-совместимая dev-плата со встроенным Wi-Fi менее чем за 10 долларов? Ну, есть.
Встречайте убийцу Ардуино: ESP8266. Это был лишь вопрос времени, когда корона была украдена у блестящей головы нашей дорогой платы разработки Arduino. Можно ли влюбиться в печатную плату?
Помимо броских имен, ESP8266 (также известный как NodeMCU) первоначально продавался как дешевый Wi-Fi-надстройка для плат Arduino, пока сообщество хакеров не осознало, что вы можете полностью исключить Arduino из этого уравнения.
Менее чем за год ESP8266 завоевал популярность, и теперь он так хорошо поддерживается и развивается, что если вы в настоящее время используете Arduino, вам нужно встать и принять к сведению. Купите сейчас , а затем следуйте этому руководству, чтобы начать программировать свой ESP8266 — и все это в знакомой среде Arduino IDE.
Конечно, вы не ограничены использованием Arduino IDE — они совместимы и с Lua (который выглядит как укороченный Python для моих глаз новичка), но, поскольку мы решаем эту проблему с точки зрения тех из нас, кто научился на Arduino это то, что мы расскажем исключительно сегодня.
В настоящее время существует довольно много моделей ESP8266, но я собираюсь пойти дальше и порекомендовать эту: ESP-12E (также известный как NodeMCU 1.0 или его новейший родной NodeMCU 2.0).
Это немного дороже, чем другие (6,50 долл. По сравнению с 4 долл.!), Но включает в себя драйвер последовательного интерфейса, необходимый для программирования чипа, и имеет встроенный регулятор мощности, а также множество выводов ввода-вывода. Он широко поддерживается и на самом деле ничего не нужно, кроме USB-соединения для программирования или питания, поэтому с ним проще всего работать. Если вы покупаете какую-либо другую плату ESP8266, вам может понадобиться отдельный стабилизатор питания 3,3 В и подходящее соединение FTDI для программирования.
Начало работы с ESP8266-12E и Arduino
Сначала установите драйверы для этой платы. Возможно, вам придется отключить подпись KEXT, если вы используете El Capitan из-за новых систем безопасности.
Далее нам нужно включить поддержку ESP8266 от менеджера плат Arduino IDE. Откройте «Настройки» и введите следующий URL-адрес, на котором написано « Дополнительные URL-адреса менеджера доски объявлений» :
Нажмите Ok, затем откройте Boards Manager из меню Tools -> Board , найдите esp8266 и установите платформу. Теперь вы должны увидеть выбор для NodeMCU 1.0.
Оставьте процессор и загрузите скорость как есть, и выберите ваш вновь установленный последовательный порт. На Mac это выглядит как cu.SLAB_USBtoUART .
В качестве первой программы я бы предложил простой сканер Wi-Fi — найдите его в меню Файл -> Примеры -> ESP8266WiFi -> WifiScan . Обратите внимание, что загрузка происходит довольно медленно, но в конечном итоге будет сказано «завершена загрузка», и в этот момент (не раньше или вы прервете процесс загрузки) вы можете открыть монитор последовательного порта. Вы должны увидеть что-то похожее на это:
Успех! Теперь давайте попробуем подключиться к одному.
Вот абсолютно простой код для подключения к сети Wi-Fi. Он не делает ничего, кроме подключения, но вы можете добавить его позже. Просто не забудьте изменить YOUR_SSID и YOUR_PASSWORD на свои данные Wi-Fi. Загрузите, откройте консоль Serial и вы увидите, что она подключается.
#include const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; WiFiClient wifiClient; void setup() { Serial.begin(115200); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void loop() { }
Разве это не здорово, как это просто смешно?
Прежде чем мы продолжим, вот схема распиновки — она может пригодиться позже. Обратите внимание, что номера контактов, указанные в коде, являются номерами GPIO, а не D0-16, вероятно, написанными на вашей печатной плате. Если вы абсолютно точно не можете понять, почему датчик не работает, вы, вероятно, перепутали номера выводов.
Быстрый Умный Дом Датчик с MQTT и DHT11
Вот практический пример, который вы можете сразу использовать для наблюдения за своим домом. Мы добавим датчик температуры и влажности DHT11, а затем сообщим о значениях по протоколу MQTT по сети Wi-Fi, в моем случае, в систему домашней автоматизации OpenHAB DIY (если нет, вы можете прочитать наше руководство для начинающих по на Raspberry Pi , часть 2, посвященная установке сервера MQTT. )
Со стороны проводки подключите датчик DHT к GND , 3,3 В и ~ D4 (или GPIO 2). Это все, что нам нужно на данный момент.
Загрузите эти библиотеки MQTT и DHT . Даже если они у вас уже есть , все равно загрузите их, сделайте резервную копию того, что у вас есть, и перезапишите их. Последняя библиотека DHT11 от Adafruit использует автоматический алгоритм для определения скорости, с которой данные считываются с датчика, но в ESP8266 она глючит и 90% времени приводит к ошибкам чтения.
В старой версии 1.0 библиотеки, которую я включил в загрузку, вы можете вручную изменить время: 11 лучше всего подходит для этих плат ESP2866. Я также просмотрел множество копий библиотеки MQTT, пытаясь найти одну хорошую функцию обратного вызова , и, наконец, приземлился на включенную. Вам нужно будет перезапустить Arduino IDE после их замены.
Вот полный код проекта . Вверху находятся все переменные, которые необходимо изменить, включая сведения о Wi-Fi, MQTT-сервер (вместо него можно использовать URL-адрес, если используется облачный сервер, хотя аутентификация не установлена) и каналы для публикации данных.
/ * ESP8266 + MQTT Узел влажности и температуры | |
* Можно также получать команды; настроить функцию messageReceived () | |
* См. .com для полного руководства по сборке и инструкций | |
* / | |
#include <MQTTClient.h> | |
#include <ESP8266WiFi.h> | |
#include <DHT.h> | |
const char * ssid = "YOUR_SSID"; | |
const char * password = "YOUR_PASSWORD!"; | |
char * subscribeTopic = "openhab / родительская комната / входящий"; // подписаться на эту тему; все отправленное здесь будет передано в функцию messageReceived | |
char * tempTopic = "openhab / родительская комната / температура"; // тема для публикации показаний температуры | |
char * влажностьTopic = "openhab / родительская комната / влажность"; // публикуем показания влажности | |
const char * server = "192.168.1.99"; // сервер или URL брокера MQTT | |
String clientName = "parentbedroom-"; // просто имя, используемое для общения с брокером MQTT | |
длинный интервал = 60000; // (мс) - 60 секунд между отчетами | |
unsigned long resetPeriod = 86400000; // 1 день - это период, после которого мы перезагружаем процессор, чтобы справиться с нечетными ошибками утечки памяти | |
#define DHTTYPE DHT11 // DHT11 или DHT22 | |
#define DHTPIN 2 | |
долгое время без подписи; | |
DHT dht (DHTPIN, DHTTYPE, 11); | |
плавать h, t; | |
WiFiClient wifiClient; | |
Клиент MQTTClient; | |
Строка macToStr (const uint8_t * mac) | |
{ | |
Строковый результат; | |
для (int i = 0; i <6; ++ i) { | |
результат + = строка (mac [i], 16); | |
если (я <5) | |
результат + = ':'; | |
} | |
вернуть результат; | |
} | |
void setup () { | |
Serial.begin (115200); | |
dht.begin (); | |
client.begin (сервер, wifiClient); | |
Serial.print («Подключение к»); | |
Serial.println (SSID); | |
WiFi.begin (ssid, пароль); | |
while (WiFi.status ()! = WL_CONNECTED) { | |
задержки (500); | |
Serial.print ( ""); | |
} | |
Serial.println ( ""); | |
Serial.println («WiFi подключен»); | |
Serial.println («IP-адрес:»); | |
Serial.println (WiFi.localIP ()); | |
// Генерируем имя клиента на основе MAC-адреса и последних 8 бит микросекундного счетчика | |
uint8_t mac [6]; | |
WiFi.macAddress (Mac); | |
clientName + = macToStr (mac); | |
clientName + = "-"; | |
clientName + = String (micros () & 0xff, 16); | |
Serial.print («Подключение к»); | |
Serial.print (сервер); | |
Serial.print («как»); | |
Serial.println (CLIENTNAME); | |
if (client.connect ((char *) clientName.c_str ())) { | |
Serial.println («Подключен к MQTT-брокеру»); | |
Serial.print («Подписано на:»); | |
Serial.println (subscribeTopic); | |
client.subscribe (subscribeTopic); | |
} | |
еще { | |
Serial.println («Ошибка подключения MQTT»); | |
Serial.println («Сброс и попытка снова ...»); | |
преждевременное прекращение (); | |
} | |
prevTime = 0; | |
} | |
void loop () { | |
статический int counter = 0; | |
if (prevTime + interval <millis () || prevTime == 0) { | |
prevTime = миллис (); | |
Serial.println («проверка снова»); | |
Serial.println (prevTime); | |
h = dht.readHumidity (); | |
t = dht.readTempera (); | |
h = h * 1,23; | |
t = t * 1,1; | |
// Проверить, не удалось ли выполнить какое-либо чтение, и завершить работу рано (чтобы повторить попытку). | |
if (isnan (h) || isnan (t)) { | |
Serial.println («Не удалось прочитать с датчика DHT!»); | |
} | |
иначе если (! client.connected ()) { | |
Serial.println («Соединение с брокером потеряно; повторная попытка»); | |
} | |
еще { | |
char * tPayload = f2s (t, 0); | |
char * hPayload = f2s (h, 0); | |
Serial.println (т); | |
Serial.println (ч); | |
Serial.println (TPayload); | |
Serial.println (hPayload); | |
client.publish (tempTopic, tPayload); | |
client.publish (влажность, топика, hPayload); | |
Serial.println («опубликованные данные об окружающей среде»); | |
} | |
} | |
client.loop (); | |
// сброс через день, чтобы избежать утечек памяти | |
если (Миллис ()> resetPeriod) { | |
ESP.restart (); | |
} | |
} | |
/ * плавать в строку | |
* f - это число, превращающееся в строку | |
* p - точность (количество десятичных знаков) | |
* вернуть строковое представление с плавающей точкой. | |
* / | |
char * f2s (float f, int p) { | |
char * pBuff; // используем, чтобы запомнить, какую часть буфера использовать для dtostrf | |
const int iSize = 10; // количество буферов, по одному на каждое число с плавающей запятой перед переносом | |
статический символ sBuff [iSize] [20]; // пробел для 20 символов, включая терминатор NULL для каждого числа с плавающей запятой | |
static int iCount = 0; // сохраняем вкладку следующего места в sBuff для использования | |
pBuff = sBuff [iCount]; // используем этот буфер | |
if (iCount> = iSize -1) {// проверка на перенос | |
iCount = 0; // если упаковка начинается снова и сбрасывается | |
} | |
еще { | |
iCount ++; // продвигаем счетчик | |
} | |
вернуть dtostrf (f, 0, p, pBuff); // вызов функции библиотеки | |
} | |
void messageReceived (тема String, полезная нагрузка String, байты char *, длина без знака int) { | |
Serial.print («входящий:»); | |
Serial.print (тема); | |
Serial.print ("-"); | |
Serial.print (полезная нагрузка); | |
Serial.println (); | |
} |
Вот как это работает и несколько заметок:
- Сначала мы подключаемся к Wi-Fi, затем к серверу MQTT, затем начинаем основной цикл ().
- В цикле мы опрашиваем датчик DHT каждые 60 секунд и публикуем показания на соответствующие каналы MQTT. Опять же, если вы обнаружите, что большинство показаний приводит к сообщению об ошибке, у вас неверная версия библиотеки DHT - понизьте ее до версии 1.0.
- client.loop () передает управление библиотеке MQTT, позволяя ей реагировать на входящие сообщения.
- Есть функция messageReceived (), в которой мы обрабатываем входящие сообщения - просто сделайте простой оператор if, чтобы сравнить полезную нагрузку с ожидаемым сообщением. Вы можете использовать это, например, для активации реле.
- После их запуска в течение нескольких дней я обнаружил, что они случайно перестали работать - я предполагаю, что это какая-то утечка памяти, но, учитывая, что у меня нет навыков программирования, чтобы справиться с этим, и это может быть с основными библиотеками, я выбрал простой мягкий сброс каждый день. Ровно через день после того, как узлы датчиков будут активированы в первый раз, они сами перезагрузятся.
- При питании этих дешевых модулей DHT11 от 3,3 В значения влажности намного ниже, чем должны быть. Я решил это простым умножением и откалибровал по коммерческому датчику. Я бы посоветовал вам подтвердить также против вашего собственного известного источника, прежде чем полагаться на показания. В качестве альтернативы, подайте на них напряжение 5 В, но вы должны установить переключатель логического уровня 5–3,3 В между контактом данных и ESP8266, иначе вы можете его повредить .
Если все прошло хорошо, теперь вы должны получать показания датчиков в вашем брокере MQTT и можете подключить их к OpenHAB, как подробно описано в части 2 нашего руководства начинающих в , где я также показал вам, как построить график данных.
Прощай, Ардуино, мы так тебя любили. Просто шучу: не везде в моем доме можно даже получить Wi-Fi, поэтому для этих мест мне все равно понадобится ячеистая сеть с Arduino и радиочастотными приемниками.
Для увлекательного проекта, узнайте, как сделать кнопку Wi-Fi с ESP8266
Но что вы будете делать с ESP8266? Какие проекты, использующие ESP8266, вы хотели бы видеть написанными на ? Дайте нам знать об этом в комментариях!