iobroker - недорогое решение - подключение Infodisplay на основе ESP8266
santos
iobroker - недорогое решение - подключение Infodisplay на основе ESP8266
Привет. Как я отписался в теме про «умный дом IOBROKER на RASPBERRY“, захотелось мне сделать небольшой экранчик, на который выводятся нужные мне данные из iobroker.
Критерии были такие:
- Экранчик должен стоять в домике для инструментов, который редко закрывается. Тоесть при потере/краже быть недорогим, либо вообще не вызывать желание украсть.
- небольшой, только для некольких значений
- слабое потребление тока
- только отображение информации
Планшет я принципиально не захотел, хотя было бы наверно проще с ним.
Приведу пример – стою в я домике, под ним зарыта бочка с дождевой водой, а уровень воды я не знаю, для этого надо из хлама отрыть крышку, открыть её. Или пойти в дом и посмотреть на планшете на стене, какой уровень. Так как в бочку я уже интегрировал модуль/сонар ультразвуковой, который меряет расстояние до воды. Может как нибудь опишу в другой статье.
(Все линки/ссылки для примера, некоторые с моих покупок. Я никаким образом не связан с продавцами или получаю выгоду с этого).
В итоге, для этого на пробу приобрел вот такую приблуду «ESP8266 development board OLED 0.96 inch WIFI» за 12,30€ вот здесь.
Хотелось, чтобы информация выдавалась в таком примерно виде.
Питаться должно от маленького преобразавателя 5 вольт,
Но тут на форуме отсоветовали, сказали что OLED «выгорает» со временем, лучше на другой основе.
Для этого в Китае были прииобретены следующие девайсы:
и экран TFT 2.4“ Touch
По цене обошлось даже дешевле, вместе около 12€. И кстати, они просто втыкаются друг в друга, никакий проводов или шлейфов.
Пришло как обычно, несколько недель ждал. Советую заказать сразу 2-3 Wemos, так как цена копеечная, а для поиска неисправностей помогает. Я, например, один спалил, повезло еще парочка лежала.
Потом начал искать примеры, как все это в моем проекте реализовать. Находил только похожие проекты, с другими экранами. Но там и другое программирование, другие данные и команды экрана. Самый похожий проект был здесь, его брал за основу.
https://www.smarthome-tricks.d…fuer-iobroker-ueber-mqtt/
Так как я в Ардуино новичок, заняло у меня «сборка и отладка» кода несколько вечеров и некоторое количества нервов. Но зато теперь это готовое решение, которое может собрать почти любой.
Проект состоит из двух частей – подготовка передающей стороны (иоброкер и значения для передачи) и приёмной стороны – сам ESP8266 модуль.
Начал я с второй части, она казалась сложней.
1. Для начала, припаиваяем штекеры к Wemos D1 mini, и втыкаем его в экран. Внимание на правильную распиновку, все ножки на обоих платах подписанны.
2. Установил Ардуино, загрузил в него нужные библиотеки. Это «Adafruit GFX Library» общая библиотека для экранов, «Adafruit_ILI9341»- библиотека для моего экрана. Также нужна PubSubClient библиотека MQTT клиента, так как из брокера данные передаются по протоколу MQTT.
3. Для того, что бы наша плата распознавалась в Ардуино, нужно обновить список плат из источника http://arduino.esp8266.com/sta…age_esp8266com_index.json. Для этого идём в Menü Datei/Voreinstellungen. В поле "Zusätzliche Boardverwalter-URLs" вставляем предыдущий линк.
4. Теперь в Menü Werkzeuge/Board/Boardverwalter. Находим наш тип платы ESP8266, в моём случае это Wemos D1 mini. После этого надо выставить правильный порт. Все, подготовка завершена.
5. Вставляем этот код в новый скетч, в поле const char* ssid = "наш ВЛАН"; const char* password = "наш пароль"; const char* mqtt_server = "IP Adresse нашего сервера с Iobroker"; В конце кода, где в моём случае стоят слова типа «Terasse, Ventil, Regen, Wasser и прочее типа хххххх» - тут можно поэксперементировать со своими текстами.
#include <Adafruit_ILI9341.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define TFT_CS D0 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_DC D8 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_RST -1 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TS_CS D3 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
String _DisplayLine1 = "";
String _DisplayLine2 = "";
String _DisplayLine3 = "";
String _DisplayLine4 = "";
String _DisplayLine5 = "";
String _DisplayLine6 = "";
String _DisplayLine7 = "";
String _DisplayLine8 = "";
String _DisplayLine9 = "";
String _DisplayLine10 = "";
String _DisplayLine11 = "";
String _DisplayLine12 = "";
String _DisplayLine13 = "";
String _DisplayLine14 = "";
String _DisplayLine15 = "";
String _DisplayLine16 = "";
String _DisplayLine17 = "";
String _DisplayLine18 = "";
String _DisplayLine19 = "";
String _DisplayLine20 = "";
const char* ssid = "xxxxxxxxx";
const char* password = "xxxxxxxxx";
const char* mqtt_server = "192.168.1.32";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
if ( strcmp( topic, "display_line1" ) == 0 )
{
_DisplayLine1 = "";
for (int i = 0; i < length; i++) { _DisplayLine1 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line2" ) == 0 )
{
_DisplayLine2 = "";
for (int i = 0; i < length; i++) { _DisplayLine2 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line3" ) == 0 )
{
_DisplayLine3 = "";
for (int i = 0; i < length; i++) { _DisplayLine3 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line4" ) == 0 )
{
_DisplayLine4 = "";
for (int i = 0; i < length; i++) { _DisplayLine4 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line5" ) == 0 )
{
_DisplayLine5 = "";
for (int i = 0; i < length; i++) { _DisplayLine5 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line6" ) == 0 )
{
_DisplayLine6 = "";
for (int i = 0; i < length; i++) { _DisplayLine6 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line7" ) == 0 )
{
_DisplayLine7 = "";
for (int i = 0; i < length; i++) { _DisplayLine7 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line8" ) == 0 )
{
_DisplayLine8 = "";
for (int i = 0; i < length; i++) { _DisplayLine8 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line9" ) == 0 )
{
_DisplayLine9 = "";
for (int i = 0; i < length; i++) { _DisplayLine9 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line10" ) == 0 )
{
_DisplayLine10 = "";
for (int i = 0; i < length; i++) { _DisplayLine10 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line11" ) == 0 )
{
_DisplayLine11 = "";
for (int i = 0; i < length; i++) { _DisplayLine11 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line12" ) == 0 )
{
_DisplayLine12 = "";
for (int i = 0; i < length; i++) { _DisplayLine12 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line13" ) == 0 )
{
_DisplayLine13 = "";
for (int i = 0; i < length; i++) { _DisplayLine13 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line14" ) == 0 )
{
_DisplayLine14 = "";
for (int i = 0; i < length; i++) { _DisplayLine14 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line15" ) == 0 )
{
_DisplayLine15 = "";
for (int i = 0; i < length; i++) { _DisplayLine15 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line16" ) == 0 )
{
_DisplayLine16 = "";
for (int i = 0; i < length; i++) { _DisplayLine16 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line17" ) == 0 )
{
_DisplayLine17 = "";
for (int i = 0; i < length; i++) { _DisplayLine17 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line18" ) == 0 )
{
_DisplayLine18 = "";
for (int i = 0; i < length; i++) { _DisplayLine18 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line19" ) == 0 )
{
_DisplayLine19 = "";
for (int i = 0; i < length; i++) { _DisplayLine19 += (char)payload[i]; }
}
if ( strcmp( topic, "display_line20" ) == 0 )
{
_DisplayLine20 = "";
for (int i = 0; i < length; i++) { _DisplayLine20 += (char)payload[i]; }
}
UpdateDisplay();
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.subscribe("display_line1");
client.subscribe("display_line2");
client.subscribe("display_line3");
client.subscribe("display_line4");
client.subscribe("display_line5");
client.subscribe("display_line6");
client.subscribe("display_line7");
client.subscribe("display_line8");
client.subscribe("display_line9");
client.subscribe("display_line10");
client.subscribe("display_line11");
client.subscribe("display_line12");
client.subscribe("display_line13");
client.subscribe("display_line14");
client.subscribe("display_line15");
client.subscribe("display_line16");
client.subscribe("display_line17");
client.subscribe("display_line18");
client.subscribe("display_line19");
client.subscribe("display_line20");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void UpdateDisplay()
{
tft.begin();
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print("Regenwasser: ");
tft.setTextColor(ILI9341_YELLOW);
tft.print(_DisplayLine1.c_str());
tft.setTextSize(1);
tft.println(" Liter");
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print("Distanz/Median: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine2.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Temp. outdoor: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine3.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Max.Temp. heute: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine4.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Akku Ladnroid: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine5.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Regen heute? ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine6.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine7.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine8.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine9.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine10.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine11.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("xxxxxxxxx: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine12.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Licht Terrasse: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine13.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Licht Garage: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine14.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Garten_LED: ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine15.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Pumpe aktiv: ");
tft.setTextColor(ILI9341_GREEN);
tft.println(_DisplayLine16.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Ventil 1 (Quadrat): ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine17.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Ventil 2 (Streifen):");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine18.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Ventil 3 (Hochbeet):");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine19.c_str());
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1); tft.print("Ventil 4 (Leitung): ");
tft.setTextColor(ILI9341_YELLOW);
tft.println(_DisplayLine20.c_str());
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1884);
client.setCallback(callback);
tft.begin();
//display.clearDisplay();
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
//display.display();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
Начинаем загружать код в Ардуино, нажав кнопку Upload. Если все нормально прошло и ошибок в коде нет, соединение установленно – код загрузится, наш экран начнет соединятся с WLAN и iobroker. Так как мы еще не подготовили iobroker, то никаких значений не отобразится.
Для этого переходим к другой части, к iobroker.
Для начала, если стоит Windows 10, то советую отобразить MQTT Box, может облегчить поиск ошибок, но вообще не обязателен, можно попробовать сначала без него.
1. Идем в брокер, устанавливаем новый адаптер MQTT Server. Картинка 1
2. Идём в настройки адаптера- ставим typ -> server. Про порт: у меня стоит уже адаптер sonoff, который тоже работает по протоколлу MQTT через стандартный порт 1883. Чтобы оба адаптера друг другу не мешали – я поставил для MQTT Server порт 1884, этот же порт надо указать в ардуино-скетче, в моём примере он уже стоит.
3. Пароль/юзер я не использовал, пропустил. Во второй вкладке настоей я все оставил по умолчанию, можно потом поигратся с настройками, интервалами обновления и т.д.
4. Адаптер светится жёлтым, иногда зелёным, это нормально.
5. По идее, если в ESP8266 залит скетч и адаптер MQTT правильно сконфигурирован – в iobroker/objekte в папке mqtt.0 должны появится 20 строчек, которые передаются на ESP8266. Тип данных каждой строчки стоит у меня на „Zeichenkette“, некоторые значение на „Logikwert“ – там, где мне надо значение true/false. Картинка 2
6. Если был установлен MQTT Box, то там (после прописки адресса/порта) тоже должны отображатся все события, которые передаются по протоколлу MQTT.
7. Предпоследний шаг – я в Blockly написал простейший скрипт, который в эти 20 строчек кода вставляет данные из iobroker, если они обновляются. Картинка 3
8. Ну теперь я припаял преобразователь напряжения 230v->5v
9. Пока в процессе создания корпуса- рисую его как 3D Modell и попозже распечатаю. Но в принципе, можно придумать корпус по желанию.
Пара линков, которые мне помогли понять принцип Arduino & ESP8266:
https://wiki.wemos.cc/products…ni_shields:tft_2.4_shield
https://wiki.wemos.cc/tutorial…arted_with_tft_2.4_shield
http://stefanfrings.de/esp8266/
Я знаю, что в тексте наделал кучу ошибок. Но чукча не писатель – чукча больше читатель!
Может что то забыл, пишите, дополню.