Последняя версия для атом - отправленная в офис

master
SmartUaWIn 2021-03-10 19:13:24 +02:00
parent 3f9ef8347b
commit 4196da49c3
7 changed files with 703 additions and 70 deletions

View File

@ -63,7 +63,7 @@ bool mqttSendFlag = false;
int reqCounter = 0; int reqCounter = 0;
long rssi = 0; long rssi = 0;
byte MapAngle, SetAngle, SpeedAngle=10; byte MapAngle, SetAngle, SpeedAngle = 10;
char bufTopic[140], bufWillTopic[150], bufAngleTopic[150]; char bufTopic[140], bufWillTopic[150], bufAngleTopic[150];
@ -71,14 +71,16 @@ char bufTopic[140], bufWillTopic[150], bufAngleTopic[150];
void setup() void setup()
{ {
M5.begin(true, false, true); M5.begin(true, false, true);
M5.Power.begin(); M5.Power.begin();
M5.Lcd.clear(WHITE); M5.Lcd.clear(WHITE);
M5.Lcd.setTextSize(4); M5.Lcd.setTextSize(4);
M5.Lcd.setTextColor(BLACK); M5.Lcd.setTextColor(BLACK);
servoAir.attach(17); pinMode(25, OUTPUT);
digitalWrite(25, LOW);
servoAir.attach(25);
String topicTemp = "/aastudio/" + macc; String topicTemp = "aastudio/" + macc;
String willTopicTemp = topicTemp + "/status"; String willTopicTemp = topicTemp + "/status";
String angleTopicTemp = topicTemp + "/setangle"; String angleTopicTemp = topicTemp + "/setangle";
@ -90,7 +92,6 @@ void setup()
willTopicTemp.toCharArray(bufWillTopic, willTopicTemp.length() + 1); willTopicTemp.toCharArray(bufWillTopic, willTopicTemp.length() + 1);
angleTopicTemp.toCharArray(bufAngleTopic, angleTopicTemp.length() + 1); angleTopicTemp.toCharArray(bufAngleTopic, angleTopicTemp.length() + 1);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
Serial.begin(115200); Serial.begin(115200);
//Serial.setDebugOutput(true); //Serial.setDebugOutput(true);
@ -107,6 +108,7 @@ void setup()
wm.setMenu(menu); wm.setMenu(menu);
wm.setClass("invert"); wm.setClass("invert");
wm.setConfigPortalTimeout(90); // auto close configportal after n seconds wm.setConfigPortalTimeout(90); // auto close configportal after n seconds
wm.setWiFiAutoReconnect(true);
bool res; bool res;
res = wm.autoConnect("AirAnglePortal", "12345678"); // Подключение к анонимной точке доступа res = wm.autoConnect("AirAnglePortal", "12345678"); // Подключение к анонимной точке доступа
if (!res) if (!res)
@ -122,7 +124,6 @@ void setup()
//Запрос IP сервера MQTT и установка сервера //Запрос IP сервера MQTT и установка сервера
setMqttServer(); setMqttServer();
reqNtpTime(); reqNtpTime();
macc = getMacAddress();
} }
//Установка сервера и порта //Установка сервера и порта
@ -162,6 +163,66 @@ void setServCall(IPAddress SetIpaddr)
MqttClient.setCallback(callback); MqttClient.setCallback(callback);
} }
void moveServo(int SetAngleTmp, int SpeedAngleTmp, int posServoTmp)
{
if ((SetAngleTmp >= 0 && SetAngleTmp <= 100) && (SpeedAngleTmp >= 0 && SpeedAngleTmp <= 50))
{
MapAngle = map(SetAngleTmp, 0, 100, 2, 178);
// 544 мкс — для 0° и 2400 мкс — для 180°.
if (posServoTmp < MapAngle)
{
for (int tok = posServoTmp; tok <= MapAngle; tok++)
{
servoAir.write(tok);
delay(SpeedAngleTmp);
}
}
else
{
for (int tok = posServoTmp; tok >= MapAngle; tok--)
{
servoAir.write(tok);
delay(SpeedAngleTmp);
}
}
//servoAir.write(SetAngle);
posServo = (int)MapAngle;
SpeedAngle = SpeedAngleTmp;
SetAngle = SetAngleTmp;
OTApreferences.begin(spacePref, false);
OTApreferences.putString("stateangle", String(MapAngle));
OTApreferences.putString("percent", String(SpeedAngle));
OTApreferences.putString("us", String(SetAngle));
Serial.print("OTApreferences.getString(stateangle): ");
Serial.println(OTApreferences.getString("stateangle"));
OTApreferences.end();
drawLcd();
}
}
void drawLcd()
{
M5.Lcd.clear(WHITE);
M5.Lcd.setCursor(20, 50);
M5.Lcd.setTextColor(BLACK);
M5.Lcd.print(posServo);
M5.Lcd.println("<");
M5.Lcd.setCursor(20, 120);
M5.Lcd.setTextColor(BLACK);
M5.Lcd.print(SetAngle);
M5.Lcd.println("%");
M5.Lcd.setCursor(150, 120);
M5.Lcd.setTextColor(BLACK);
M5.Lcd.print(SpeedAngle);
M5.Lcd.println("uS");
}
//Функция получения данных из MQTT если мы подпишемся на топики //Функция получения данных из MQTT если мы подпишемся на топики
void callback(char *topic, byte *payload, unsigned int length) void callback(char *topic, byte *payload, unsigned int length)
{ {
@ -185,61 +246,23 @@ void callback(char *topic, byte *payload, unsigned int length)
return; return;
} }
// {"angle":20} // {"percent":50,"speed":20}
//сделать проверку на байті //сделать проверку на байті
SetAngle = docResult["percent"]; SetAngle = docResult["percent"];
SpeedAngle = docResult["speed"]; //0-100 SpeedAngle = docResult["speed"]; //0-100
// byte isTimer = docResult["timer"]; // byte isTimer = docResult["timer"];
// byte isTimerAngle = docResult["timerangle"]; // byte isTimerAngle = docResult["timerangle"];
Serial.println(SetAngle); Serial.println(SetAngle);
if (SetAngle >= 0 || SetAngle <= 100) moveServo(SetAngle, SpeedAngle, posServo);
{
MapAngle = map(SetAngle, 0, 100, 2, 178);
// 544 мкс — для 0° и 2400 мкс — для 180°.
if (posServo < MapAngle)
{
for (int tok = posServo; tok <= MapAngle; tok++)
{
servoAir.write(tok);
delay(SpeedAngle);
}
}
else
{
for (int tok = posServo; tok >= MapAngle; tok--)
{
servoAir.write(tok);
delay(SpeedAngle);
}
}
//servoAir.write(SetAngle);
posServo = (int)MapAngle;
OTApreferences.begin(spacePref, false);
OTApreferences.putString("stateangle", String(MapAngle));
//char anglePref[4] = OTApreferences.getString("stateangle");
Serial.println("OTApreferences.getString(stateangle)");
Serial.println(OTApreferences.getString("stateangle"));
OTApreferences.end();
}
// Serial.println(isTimer);
// Serial.println(isTimerAngle);
Serial.println();
} }
// Serial.println(isTimer);
// Serial.println(isTimerAngle);
//Запрос времени NTP и установка локлаьного времени //Запрос времени NTP и установка локлаьного времени
void reqNtpTime() void reqNtpTime()
{ {
@ -380,23 +403,23 @@ void OTAUpdate()
void ledset(char color, bool blink = false) void ledset(char color, bool blink = false)
{ {
// M5.dis.setBrightness(120); //Половина яркости // M5.dis.setBrightness(120); //Половина яркости
switch (color) switch (color)
{ {
case 'g': case 'g':
// M5.dis.drawpix(0, 0xf00000); //Зеленый // M5.dis.drawpix(0, 0xf00000); //Зеленый
break; break;
case 'r': case 'r':
// M5.dis.drawpix(0, 0x00f000); //Красный // M5.dis.drawpix(0, 0x00f000); //Красный
break; break;
case 'b': case 'b':
// M5.dis.drawpix(0, 0x0000f0); //Синий // M5.dis.drawpix(0, 0x0000f0); //Синий
break; break;
case 'w': case 'w':
// M5.dis.drawpix(0, 0x707070); //Белый // M5.dis.drawpix(0, 0x707070); //Белый
break; break;
default: default:
// M5.dis.clear(); // M5.dis.clear();
break; break;
} }
} }
@ -419,7 +442,7 @@ void SendMqttReq()
// doc["mac"] = String(getMacAddress()); // doc["mac"] = String(getMacAddress());
doc["swver"] = VersionSW; doc["swver"] = VersionSW;
doc["anglestate"] = String(servoAir.read()); doc["anglestate"] = String(servoAir.read());
doc["percent"] = SetAngle; doc["percent"] = SetAngle;
doc["rssi"] = rssi; doc["rssi"] = rssi;
doc["lasterror"] = errorID; doc["lasterror"] = errorID;
@ -437,14 +460,6 @@ void SendMqttReq()
MqttClient.publish(bufTopic, resultString, true); MqttClient.publish(bufTopic, resultString, true);
//Serial.println("SentToTopic - ok"); //Serial.println("SentToTopic - ok");
} }
M5.Lcd.clear(WHITE);
M5.Lcd.setCursor(50, 50);
M5.Lcd.setTextColor(BLACK);
M5.Lcd.print(posServo); M5.Lcd.println(" <");
M5.Lcd.setCursor(50, 150);
M5.Lcd.setTextColor(BLACK);
M5.Lcd.print(SetAngle); M5.Lcd.println(" %");
} }
//Переподключение при петери связи с MQTT //Переподключение при петери связи с MQTT
@ -509,6 +524,36 @@ void loop()
reconnectMqtt(); reconnectMqtt();
} }
if (M5.BtnA.wasPressed())
{
if (SetAngle >= 0 && SetAngle < 100)
{
SetAngle += 1;
moveServo(SetAngle, SpeedAngle, posServo);
}
}
if (M5.BtnB.wasPressed())
{
if (SetAngle > 0 && SetAngle <= 100)
{
SetAngle -= 1;
moveServo(SetAngle, SpeedAngle, posServo);
}
}
if (M5.BtnC.wasPressed())
{
SpeedAngle += 5;
if (SpeedAngle > 50)
{
SpeedAngle = 0;
}
drawLcd();
}
//Если не определен IP то и не будет отправки. //Если не определен IP то и не будет отправки.
// 40 секунд и происходит сброс настроек WIFI // 40 секунд и происходит сброс настроек WIFI
// if (M5.Btn.wasReleasefor(40000)) // if (M5.Btn.wasReleasefor(40000))

BIN
AAOffice_ventatom/1.bin Normal file

Binary file not shown.

View File

@ -0,0 +1,564 @@
/*
Управление сервоприводом MQTT
*/
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#include <Preferences.h> //Сохранение настроек хеша прошивки
#include <HTTPClient.h>
#include <ESP32httpUpdate.h> //Библиотека ОТА обновлений
#include "M5Atom.h" //Библиотека атома для функции Led и Кнопки, можно упразднить и убрать
#include <WiFiUdp.h> //Udp клиент
#include <NTPClient.h> //NTP запрос времени
#include <TimeLib.h> //Внутреннее время
#include <Wire.h> //Библиотека дял I2C
#include <PubSubClient.h> //Mtqq
#include <ArduinoJson.h> //Упакова в JSon - удобная библиотека
#include <ESPmDNS.h>
#include <ESP32Servo.h>
//Наша кнопочка при нажатии на которую произойдет вызов wifi менеджера и перезагрузка в станцию
#define TRIGGER_PIN 39
#define SERVO_PIN 33
unsigned int VersionSW = 4; //65536 Версия прошивки
//2 поиск по metrics local
//3 -
//4 - тестовая для проверки загрузки прошивки
Servo servoAir;
int posServo = 0;
int posServoLast = 0;
byte errorID = 0;
WiFiManager wm; // обьект менеджера
WiFiManagerParameter custom_field;
Preferences OTApreferences; //Обьект хранения настроек хеша прошивки
String JsonData;
StaticJsonDocument<200> doc, docResult;
WiFiClient espClient;
PubSubClient MqttClient(espClient);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "0.ua.pool.ntp.org", 7200, 60000); //Собственно сервер времени смещение и частоат запроса, но он вручную
const char *spacePref = "ota-config";
const PROGMEM char *mqttHostName = "metrics"; //Хостнейм брокера 192.168.89.210 cctv.automation.art:8889
unsigned int mqttPort = 1883; //Порт брокера 1883
const PROGMEM char *mqttLogin = NULL, //Логин пароль - необходимо сменить код при connect()
*mqttPass = NULL;
const char *mqttIPHost; //тут хранится IP хоста по хостнейму
unsigned long timingUpdate, timingReqSensor, timingSendMqtt, timingAjaxUpdate; //Таймеры для millis()
int PROGMEM nextM5Update = 450000; //каждые 7.5 минут запрос обновления с сервера
String getMacAddress();
String macc = getMacAddress();
bool mqttSendFlag = false;
int reqCounter = 0;
long rssi = 0;
byte MapAngle, SetAngle, SpeedAngle = 10;
char bufTopic[140], bufWillTopic[150], bufAngleTopic[150];
void ledset(char color, bool blink = false)
{
M5.dis.setBrightness(60); //Половина яркости
switch (color)
{
case 'g':
M5.dis.drawpix(0, 0xf00000); //Зеленый
break;
case 'r':
M5.dis.drawpix(0, 0x00f000); //Красный
break;
case 'b':
M5.dis.drawpix(0, 0x0000f0); //Синий
break;
case 'w':
M5.dis.drawpix(0, 0x707070); //Белый
break;
default:
M5.dis.clear();
break;
}
}
//Настройки
void setup()
{
M5.begin(true, false, true);
pinMode(SERVO_PIN, OUTPUT);
digitalWrite(SERVO_PIN, LOW);
String topicTemp = "aastudio/" + macc;
String willTopicTemp = topicTemp + "/status";
String angleTopicTemp = topicTemp + "/setangle";
Serial.println(topicTemp);
Serial.println(willTopicTemp);
Serial.println(angleTopicTemp);
topicTemp.toCharArray(bufTopic, topicTemp.length() + 1);
willTopicTemp.toCharArray(bufWillTopic, willTopicTemp.length() + 1);
angleTopicTemp.toCharArray(bufAngleTopic, angleTopicTemp.length() + 1);
WiFi.mode(WIFI_STA);
Serial.begin(115200);
Serial.setDebugOutput(true);
delay(100);
Serial.println("\n Starting station");
pinMode(TRIGGER_PIN, INPUT);
//int customFieldLength = 40;
const char *custom_radio_str = "<br/><label for='customfieldid'>Custom Field Label</label><input type='radio' name='customfieldid' value='1' checked> One<br><input type='radio' name='customfieldid' value='2'> Two<br><input type='radio' name='customfieldid' value='3'> Three";
new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input
wm.addParameter(&custom_field);
wm.setSaveParamsCallback(saveParamCallback);
std::vector<const char *> menu = {"wifi", "info", "param", "sep", "restart", "exit"};
wm.setMenu(menu);
wm.setClass("invert");
wm.setConfigPortalTimeout(90); // auto close configportal after n seconds
wm.setWiFiAutoReconnect(true);
bool res;
res = wm.autoConnect("AirAnglePortal", "12345678"); // Подключение к анонимной точке доступа
if (!res)
{
Serial.println("Failed to connect or hit timeout");
ESP.restart();
}
else
{
Serial.println("connected client - OK");
}
//Запрос IP сервера MQTT и установка сервера
setMqttServer();
reqNtpTime();
firstStart();
}
//Установка сервера и порта
void setMqttServer()
{
mdns_init();
IPAddress IpMqtt, ipaddr;
ipaddr = MDNS.queryHost(mqttHostName); // .local omitted
// Serial.println(ipaddr.toString());
if (ipaddr.toString() == "0.0.0.0")
{
Serial.println("Trying again to resolve mDNS");
ledset('r');
int err = WiFi.hostByName(mqttHostName, IpMqtt);
if (err == 1)
{
delay(50);
setServCall(IpMqtt);
ledset('w');
}
else
{
Serial.print("Error code hostByName(): ");
Serial.println(err);
ledset('r');
}
}
else
{
setServCall(ipaddr);
ledset('w');
}
}
void setServCall(IPAddress SetIpaddr)
{
MqttClient.setServer(SetIpaddr, mqttPort);
MqttClient.setCallback(callback);
}
void firstStart()
{
OTApreferences.begin(spacePref, true);
posServo = OTApreferences.getString("stateangle").toInt();
SetAngle = OTApreferences.getString("percent").toInt();
SpeedAngle = OTApreferences.getString("us").toInt();
OTApreferences.end();
Serial.println(SpeedAngle);
Serial.println(SetAngle);
Serial.println(posServo);
moveServo((int)SetAngle, (int)SpeedAngle, posServo);
SendMqttReq();
}
void moveServo(int SetAngleTmp, int SpeedAngleTmp, int posServoTmp)
{
servoAir.attach(SERVO_PIN);
if ((SetAngleTmp >= 0 && SetAngleTmp <= 100) && (SpeedAngleTmp >= 0 && SpeedAngleTmp <= 50))
{
MapAngle = map(SetAngleTmp, 0, 100, 2, 178);
// 544 мкс — для 0° и 2400 мкс — для 180°.
if (posServoTmp < MapAngle)
{
for (int tok = posServoTmp; tok <= MapAngle; tok++)
{
servoAir.write(tok);
delay(SpeedAngleTmp);
}
}
else
{
for (int tok = posServoTmp; tok >= MapAngle; tok--)
{
servoAir.write(tok);
delay(SpeedAngleTmp);
}
}
//servoAir.write(SetAngle);
posServo = (int)MapAngle;
SpeedAngle = SpeedAngleTmp;
SetAngle = SetAngleTmp;
OTApreferences.begin(spacePref, false);
OTApreferences.putString("stateangle", String(posServo));
OTApreferences.putString("us", String(SpeedAngle));
OTApreferences.putString("percent", String(SetAngle));
Serial.println(SpeedAngle);
Serial.println(SetAngle);
Serial.println(posServo);
OTApreferences.end();
}
servoAir.detach();
}
//Функция получения данных из MQTT если мы подпишемся на топики
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
char jsonResult[250];
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
jsonResult[i] = (char)payload[i];
}
DeserializationError error = deserializeJson(docResult, jsonResult);
if (error)
{
Serial.print(F("deserializeJson() failed: "));
//Serial.println(String(error));
return;
}
// {"percent":50,"speed":20}
//сделать проверку на байті
SetAngle = docResult["percent"];
SpeedAngle = docResult["speed"]; //0-100
// byte isTimer = docResult["timer"];
// byte isTimerAngle = docResult["timerangle"];
// Serial.println(SetAngle);
moveServo(SetAngle, SpeedAngle, posServo);
}
// Serial.println(isTimer);
// Serial.println(isTimerAngle);
//Запрос времени NTP и установка локлаьного времени
void reqNtpTime()
{
timeClient.update();
setTime(timeClient.getEpochTime());
// Serial.println(timeClient.getEpochTime());
// Serial.println("<=ntp====now=>");
//time_t t = now();
// Serial.println(t);
}
//Нажатие кнопки для сброса
void checkButton()
{
disconnectMQTT();
wm.resetSettings();
ESP.restart();
}
void saveParamCallback()
{
Serial.println("[CALLBACK] saveParamCallback fired");
Serial.println("PARAM customfieldid = " + getParam("customfieldid"));
}
String getParam(String name)
{
String value;
if (wm.server->hasArg(name))
{
value = wm.server->arg(name);
}
return value;
}
//Обновление прошивки, происходит проверка и загрузка
//Делается Get запрос на хостинг проверяется хеш, если хеш
void OTAUpdate()
{
Serial.println("OTAUpdate()");
bool flagOTA = false;
String keyOTA;
String payload;
OTApreferences.begin(spacePref, false);
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
String serverPath = "http://meteosence.s-host.net/airqa/airquality.php?meteopas=6v567t5pDU2UDH7eBydb&mac=" + macc + "&meteodata=gethash";
http.begin(serverPath.c_str());
int httpResponseCode = http.GET();
if (httpResponseCode > 0)
{
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
Serial.println(payload);
if (payload != "errno" || payload != "errfi")
{
keyOTA = OTApreferences.getString("md5HashOTA");
if (keyOTA.length() <= 0)
{
OTApreferences.putString("md5HashOTA", "undifined");
}
keyOTA = OTApreferences.getString("md5HashOTA");
if (payload != keyOTA)
{
flagOTA = true;
OTApreferences.putString("md5HashOTA", payload);
Serial.println("flagOTA = true;");
}
}
else
{
Serial.println("Hosting return error HASH or error REQUEST");
}
}
else
{
Serial.print("Error code HTTP: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
else
{
Serial.println("WiFi Disconnected");
}
if (flagOTA == true)
{
flagOTA = false;
Serial.println("flagOTA = false;");
ledset('b');
t_httpUpdate_return ret = ESPhttpUpdate.update("http://meteosence.s-host.net/airqa/servo/servoatoms.bin");
//После update ничего не происходит, такая вот особенность.
//Если все прошло хорошо, перезагрузка на новую прошивку
Serial.print("ret ");
Serial.println(ret);
switch (ret)
{
case HTTP_UPDATE_FAILED:
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
Serial.println(ESPhttpUpdate.getLastError());
Serial.println(ESPhttpUpdate.getLastErrorString().c_str());
Serial.println("HTTP_UPDATE_FAILD Error");
delay(3000);
ESP.restart();
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("HTTP_UPDATE_NO_UPDATES");
delay(3000);
ESP.restart();
break;
case HTTP_UPDATE_OK:
Serial.println("HTTP_UPDATE_OK");
delay(3000);
ESP.restart();
break;
}
}
OTApreferences.end();
}
//Получение мак адреса
String getMacAddress()
{
uint8_t baseMac[6];
esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
char baseMacChr[18] = {0};
sprintf(baseMacChr, "%02X%02X%02X%02X%02X%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
return String(baseMacChr);
}
//Отправка данных по MQTT
void SendMqttReq()
{
ledset('g');
Serial.println("Data in SendMqttReq()");
rssi = WiFi.RSSI();
// doc["mac"] = String(getMacAddress());
doc["swver"] = VersionSW;
servoAir.attach(SERVO_PIN);
doc["anglestate"] = posServo;
servoAir.detach();
doc["percent"] = SetAngle;
doc["rssi"] = rssi;
doc["lasterror"] = errorID;
doc["time"] = now();
char resultString[200];
String JsonData = "";
serializeJson(doc, JsonData);
Serial.println(JsonData); //Вывод JSON строки в консоль
JsonData.toCharArray(resultString, JsonData.length() + 1);
if (mqttSendFlag == true)
{
MqttClient.publish(bufTopic, resultString, true);
//Serial.println("SentToTopic - ok");
}
}
//Переподключение при петери связи с MQTT
//10 раз проверили и вернулись в общий цикл что бы вдруг что втянуть обновления
void reconnectMqtt()
{
//clientId += String(random(0xffff), HEX);
//clientId.c_str()
//MqttClient.connect(macc.c_str(), mqttLogin, mqttPass
byte circle = 0;
while (!MqttClient.connected())
{
ledset('r');
Serial.println("MQTT reconnect...");
circle++;
if (circle == 2)
{
break;
}
const char *clientId = macc.c_str();
//macc += String(random(0xffff), HEX);
if (MqttClient.connect(clientId, bufWillTopic, 2, true, "OFFLINE")) //mqttLogin, mqttPass
{
MqttClient.publish(bufTopic, "CONNECTED", true);
MqttClient.publish(bufWillTopic, "ONLINE", true);
MqttClient.subscribe(bufAngleTopic);
mqttSendFlag = true;
}
else
{
Serial.print("MqttClient.state() = ");
Serial.println(MqttClient.state());
/*
-4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time
-3 : MQTT_CONNECTION_LOST - the network connection was broken
-2 : MQTT_CONNECT_FAILED - the network connection failed
-1 : MQTT_DISCONNECTED - the client is disconnected cleanly
0 : MQTT_CONNECTED - the client is connected
1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT
2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected
5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
*/
mqttSendFlag = false;
delay(3000);
}
}
}
void loop()
{
//Проверка старта сервера
M5.update();
if (!MqttClient.connected())
{
reconnectMqtt();
}
// 40 секунд и происходит сброс настроек WIFI
if (M5.Btn.wasReleasefor(40000))
{
checkButton();
}
//По таймеру запруск обновления прошивки
if (millis() - timingUpdate > nextM5Update)
{
reqNtpTime();
OTAUpdate();
Serial.print("OTAUpdate() ");
// Serial.println(millis());
timingUpdate = millis();
}
if (posServo != posServoLast)
{
SendMqttReq();
posServoLast = posServo;
}
MqttClient.loop();
}
int disconnectMQTT()
{
MqttClient.publish(bufTopic, "DISCONNECTED", true);
MqttClient.disconnect();
return 0;
}

Binary file not shown.

Binary file not shown.

View File

@ -3,10 +3,34 @@
управление задвижкой вентиляции управление задвижкой вентиляции
Точка доступа: AirAnglePortal пароль 12345678
Топики и данные Топики и данные
aastudio/24A1605421B8 - данные
Пример: {"swver":1,"anglestate":19,"percent":10,"rssi":-64,"lasterror":0,"time":1615391892}
"swver" - версия прошивки
"anglestate" - угол сервы в углах 2-178 градусов
"percent" - процент открытия 0-100%
"rssi"- сигнал сети
"lasterror":0 - последняя ошибка
"time" - время
aastudio/24A1605421B8/status - статус Online/Offline
aastudio/24A1605421B8/setangle - установка угла
Пример: {"percent":50,"speed":5}
"percent": - процент 0-100
"speed":5 - скорость в милисекундах между установкой угла. от 1 до 50.
Дешевые сервы (а тем более - дешевые клоны дешевых серв) - они не для точного поградусного движения. Более того - нет никакой гарантии, что они будут двигаться на разные градусы с одной и той же скоростью. Дешевые сервы (а тем более - дешевые клоны дешевых серв) - они не для точного поградусного движения. Более того - нет никакой гарантии, что они будут двигаться на разные градусы с одной и той же скоростью.
Сервопривод не имеет обратной связи по углу (для программы), поэтому при запуске будет “резко” повёрнут на стартовый угол (“в ноль” по умолчанию или на указанный в attach(pin, target)
Ток при полном залипании превышает 500мА-600мА. В атоме установлен предохранитель на 500мА. Чем меньше скорость движения сервы, тем меньше ток. Быстрая скорость = большой бросок напряжения.
Питание на Core от девайса.
Сервопривод не имеет обратной связи по углу (для программы), поэтому при запуске будет “резко” повёрнут на стартовый угол (“в ноль” по умолчанию или на указанный в attach(pin, target) Питание на Atom разделено.
Полный тест драйв сервы на ютубе:
https://www.youtube.com/watch?v=qz3iyydPDCU