diff --git a/AAOffice_vent.ino b/AAOffice_vent.ino index c3e7130..aa5f08e 100644 --- a/AAOffice_vent.ino +++ b/AAOffice_vent.ino @@ -63,7 +63,7 @@ bool mqttSendFlag = false; int reqCounter = 0; long rssi = 0; -byte MapAngle, SetAngle, SpeedAngle=10; +byte MapAngle, SetAngle, SpeedAngle = 10; char bufTopic[140], bufWillTopic[150], bufAngleTopic[150]; @@ -71,14 +71,16 @@ char bufTopic[140], bufWillTopic[150], bufAngleTopic[150]; void setup() { M5.begin(true, false, true); - M5.Power.begin(); + M5.Power.begin(); M5.Lcd.clear(WHITE); - M5.Lcd.setTextSize(4); - M5.Lcd.setTextColor(BLACK); + M5.Lcd.setTextSize(4); + 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 angleTopicTemp = topicTemp + "/setangle"; @@ -90,7 +92,6 @@ void setup() willTopicTemp.toCharArray(bufWillTopic, willTopicTemp.length() + 1); angleTopicTemp.toCharArray(bufAngleTopic, angleTopicTemp.length() + 1); - WiFi.mode(WIFI_STA); Serial.begin(115200); //Serial.setDebugOutput(true); @@ -107,6 +108,7 @@ void setup() 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) @@ -122,7 +124,6 @@ void setup() //Запрос IP сервера MQTT и установка сервера setMqttServer(); reqNtpTime(); - macc = getMacAddress(); } //Установка сервера и порта @@ -162,6 +163,66 @@ void setServCall(IPAddress SetIpaddr) 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 если мы подпишемся на топики void callback(char *topic, byte *payload, unsigned int length) { @@ -185,61 +246,23 @@ void callback(char *topic, byte *payload, unsigned int length) return; } - // {"angle":20} + // {"percent":50,"speed":20} //сделать проверку на байті SetAngle = docResult["percent"]; SpeedAngle = docResult["speed"]; //0-100 - + // byte isTimer = docResult["timer"]; // byte isTimerAngle = docResult["timerangle"]; Serial.println(SetAngle); - if (SetAngle >= 0 || SetAngle <= 100) - { - 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(); + moveServo(SetAngle, SpeedAngle, posServo); } +// Serial.println(isTimer); +// Serial.println(isTimerAngle); + //Запрос времени NTP и установка локлаьного времени void reqNtpTime() { @@ -380,23 +403,23 @@ void OTAUpdate() void ledset(char color, bool blink = false) { - // M5.dis.setBrightness(120); //Половина яркости + // M5.dis.setBrightness(120); //Половина яркости switch (color) { case 'g': - // M5.dis.drawpix(0, 0xf00000); //Зеленый + // M5.dis.drawpix(0, 0xf00000); //Зеленый break; case 'r': - // M5.dis.drawpix(0, 0x00f000); //Красный + // M5.dis.drawpix(0, 0x00f000); //Красный break; case 'b': - // M5.dis.drawpix(0, 0x0000f0); //Синий + // M5.dis.drawpix(0, 0x0000f0); //Синий break; case 'w': - // M5.dis.drawpix(0, 0x707070); //Белый - break; + // M5.dis.drawpix(0, 0x707070); //Белый + break; default: - // M5.dis.clear(); + // M5.dis.clear(); break; } } @@ -419,7 +442,7 @@ void SendMqttReq() // doc["mac"] = String(getMacAddress()); doc["swver"] = VersionSW; - doc["anglestate"] = String(servoAir.read()); + doc["anglestate"] = String(servoAir.read()); doc["percent"] = SetAngle; doc["rssi"] = rssi; doc["lasterror"] = errorID; @@ -437,14 +460,6 @@ void SendMqttReq() MqttClient.publish(bufTopic, resultString, true); //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 @@ -509,6 +524,36 @@ void loop() 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 то и не будет отправки. // 40 секунд и происходит сброс настроек WIFI // if (M5.Btn.wasReleasefor(40000)) diff --git a/AAOffice_ventatom/1.bin b/AAOffice_ventatom/1.bin new file mode 100644 index 0000000..c31dc78 Binary files /dev/null and b/AAOffice_ventatom/1.bin differ diff --git a/AAOffice_ventatom/AAOffice_ventatom.ino b/AAOffice_ventatom/AAOffice_ventatom.ino new file mode 100644 index 0000000..02f0c63 --- /dev/null +++ b/AAOffice_ventatom/AAOffice_ventatom.ino @@ -0,0 +1,564 @@ +/* +Управление сервоприводом MQTT +*/ +#include // https://github.com/tzapu/WiFiManager +#include //Сохранение настроек хеша прошивки + +#include +#include //Библиотека ОТА обновлений +#include "M5Atom.h" //Библиотека атома для функции Led и Кнопки, можно упразднить и убрать + +#include //Udp клиент +#include //NTP запрос времени +#include //Внутреннее время +#include //Библиотека дял I2C + +#include //Mtqq +#include //Упакова в JSon - удобная библиотека +#include +#include + +//Наша кнопочка при нажатии на которую произойдет вызов 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 = "
One
Two
Three"; + new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input + wm.addParameter(&custom_field); + wm.setSaveParamsCallback(saveParamCallback); + std::vector 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; +} \ No newline at end of file diff --git a/AAOffice_ventatom/AAOffice_ventatom.ino.m5stick_c.bin b/AAOffice_ventatom/AAOffice_ventatom.ino.m5stick_c.bin new file mode 100644 index 0000000..fa07824 Binary files /dev/null and b/AAOffice_ventatom/AAOffice_ventatom.ino.m5stick_c.bin differ diff --git a/AAOffice_ventatom/~$кумент Microsoft Word.docx b/AAOffice_ventatom/~$кумент Microsoft Word.docx new file mode 100644 index 0000000..c654af8 Binary files /dev/null and b/AAOffice_ventatom/~$кумент Microsoft Word.docx differ diff --git a/AAOffice_ventatom/Документ Microsoft Word.docx b/AAOffice_ventatom/Документ Microsoft Word.docx new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 9206076..e22d2b9 100644 --- a/README.md +++ b/README.md @@ -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мА. Чем меньше скорость движения сервы, тем меньше ток. Быстрая скорость = большой бросок напряжения. - - Сервопривод не имеет обратной связи по углу (для программы), поэтому при запуске будет “резко” повёрнут на стартовый угол (“в ноль” по умолчанию или на указанный в attach(pin, target) \ No newline at end of file +Питание на Core от девайса. +Питание на Atom разделено. + +Полный тест драйв сервы на ютубе: + https://www.youtube.com/watch?v=qz3iyydPDCU \ No newline at end of file