После отправки 0xC0 0x00 0x1A из порта модема получаю 0xFF 0xC0 0x00 0x1A. Т.е. на сколько я понимаю наружу ничего не уходит.
Что значит из "порта модема получаю" - это откуда?
Сложно судить, вы бы скетч весь выложили, посмотрим. А ещё проще - тупо для испытания - напишите простенький скетч с последовательностью АТ команд что выше было - они то гарантированно наружу шлют данные. И будет понятно где косяк.
И вы так и не выложили что отвечает модем и лог брокера.
Update : я так понимаю вам модем в ответ дублирует посланную команду - отключите нафиг чтоб не мешало разбираться.
По поводу пинга - каждый коннект к брокер сотовый оператор считает за новое подключение, соответственно если у вас лимитный интернет и коннктится каждые N секунд - трафик весь быстро закончится. Пинг пакеты на то и придуманы в mqtt чтоб коннктится раз например в сутки, и постоянно проверять связь через M секунд.
с чего вы взяли что ответ от брокера стабильно через 100 миллисекунд придёт, а например не через секунду.
Делэй поставил уже от безисходности, кстати ставил setTimeout на порт 10000 - эффект нет.. И вообще модем должен что то внятное пинуть в порт после отправки пакета, я его жду. При отправке паблиша или подписки сразу получаю "SEND OK, а тут нифига. Видимо я всё же как то не правильно формирую пакет.
Вижу два варианта :
1 сменить брокера - возможно он что то шлёт не так
2 взять наконец то нормальный пример с последовательность АТ команд и делать по аналогии
ЗЫ. Чудес не бывает.
Update :
3. Пересмотреть всю логику работы с модемом - переходить на конечные автоматы или их подобие, т е каждая отправлена команда подразумевает ожидание некоего ответа и или какие то действия и в зависимости от условия - переходить на другие действия.
нет команд настройки режима обмена CIPQSEND CIPMODE
нет команды закрытия сессии CIPSHUT
рекомендую все таки сообщать модему сколько будет отправлено байт в команде CIPSEND, а не слать в конце байт 26, это во первых надежнее, во вторых если у вас в передаче будет этот байт - все сломается
Вобщем опять работает, отвечает как положено 0xD0 0x00. От чего завист и какого чёрта надо серверу - закономерности без бутылки не нашёл. Просто раз несколько переконнектился и заработало.
А че их искать - cipshut добавили? Похоже что нет, естественно он будет несколько раз пытаться запустить новую сессию не закрыв старую, в итоге по таймауту все сбрасывается и опять работает.
ЗЫ. Вот поэтому у нас и ракеты падают и заказчики скетч не могут запустить и т.д. - потому что разработчик сказал "и так сойдёт, ведь законнектилось в итоге" (
Тьфу...блин, разбирайтесь сами, я в теме, у меня мой код по вышеперечисленным книжкам работает исправно, а вы вместо того чтоб прислушаться и хоть чуть попытаться изменить свой скетч только и делайте что троллите.
закончил небольшой проект, работа SIM800L + MQTT подключение к двум брокерам через два сокета, список команд модема ниже, вдруг кому пригодится.
- инициализация
AT
OK
AT+CIPSHUT
SHUT OK
AT+DDET=0
OK
ATE0
OK
AT+CLIP=0
OK
ATS0=0
OK
ATV1
OK
AT+CMEE=2
OK
AT+CMGF=1
OK
AT+CSCLK=0
OK
AT+CIPMODE=0
OK
AT+CIPMUX=1
OK
AT+CIPHEAD=0
OK
AT+CIPSRIP=0
OK
AT+CSTT="internet"
OK
AT+CIICR
OK
AT+CIPSTATUS
OK
STATE: IP GPRSACT
AT+CIFSR
t▒b▒IRU*R▒('LK▒▒,",▒9%J▒▒
C: 2,,"","","","INITIAL"
C: 3,,"","","","INITIAL"
C: 4,,"","","","INITIAL"
C: 5,,"","","","INITIAL"
100.70.64.195
OK
STATE: IP STATUS
Ready
- подключение к брокерам CIPSTART=X, закрытие сокета для его потом повторного подключения CIPCLOSE=X, или переподключение между брокерами для работы в попеременном режиме
Последовательность команд SIM800L работы с MQTT брокером, устройство работает 24/7, в случае проблем переподключается между серверами.
// начало работы
Start!
// начало модуля первоначальной настройкой модема
// ждем ответ на команды в течении 5 секунд, в случае отсутствия - перезагрузка модема
ATZ // сбросим настройки модема в default
OK
ATE0 // отключение ЭХО, т е модем в обратку не дублирует команды
OK
ATV1 // развернуты подробный ответ от модема
OK
AT+CMEE=2 // вывод подробных описаний ошибок
OK
AT+CIPSHUT // закрыть все интернет сессии
SHUT OK // этот ответ лучше ждать подольше, до 10 секунд
AT+CLIP=0 // отключение АОН
OK
ATS0=0 // модем не берет трубку при входящем звонке
OK
AT+CMGF=1 // обычный режим вывода SMS
OK
AT+CSCLK=0 // отключение работы энергосберегающего режима через пин DTR
OK
AT+CIPHEAD=0 // не добавлять заголовок при приеме данных
OK
AT+CIPRXGET=0 // автоматический вывод принятых данных
OK
AT+CIPSRIP=0 // не показывать данные отправителя при приеме данных
OK
AT+CSPN? // получить имя оператора из SIM карты
+CSPN: "M2M Express",0 // парсим ответ, в зависимости от того, чья карта стоит, будем использовать разные APN
OK
// инициализация основная закончилась
// переходим в режим регистрации модема у оператора
AT+CREG? // каждые 5 секунд запрашиваем статус
+CREG: 0,2
OK
SMS Ready
// ответ ждем в течении 2х минут, если за это время не зарегестрировались - перезагрузка модема
AT+CREG?
+CREG: 0,3
OK
AT+CREG?
+CREG: 0,3
OK
AT+CREG?
+CREG: 0,3
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,0
OK
AT+CREG?
+CREG: 0,5 // успешно зарегестрировались
OK
AT+COPS? // запрашиваем имя оператора
+COPS: 1,0,"MegaFon" // парсим ответ - заносим имя оператора в переменную - потом отдадим на сервер для статистики
OK
AT+CSQ? // запрашиваем уровень связи
+CSQ: 12,0 // парсим ответ, потом отдадим серверу для статистики
OK
AT+CIPMODE=0 // командный режим передачи данных
OK
AT+CMGDA="DEL ALL" // удаление всех SMS на SIM карте
OK
// закончилась полная инициализация модема
// начало модуля соединения с mqtt сервером
// ответы на команды, просто отвечающие ОК, без глобальных изменений так же ждем 5 секунд, в случе отсутствия - проблема - перезагружаем модем
AT+CIPSTATUS // запрашиваем статус сессии
OK
STATE: IP INITIAL
AT + CSTT = "internet.emt.ee" // прописываем APN в зависимости от установленной SIM карты
OK
AT+CIPSTATUS // запрашиваем статус
OK
STATE: IP START
AT+CIICR // активируем контекст, по даташиту команда выполняется до 62 секунд, оптимально 35 секунд ждать ответ
OK
AT+CIPSTATUS // запрашиваем статус
OK
STATE: IP GPRSACT
AT+CIFSR // получаем адрес
0.137.119.101
OK
STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",***** // коннектимся к серверу
OK
AT+CIPSTATUS // запрашиваем статус
OK
STATE: TCP CONNECTING
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
//
// в течении 10 секунд ждем подключения к серверу, иначе или меняем сервер на резервный или опять поднимаем заново интернет сессию
// общее время ожидания к mqtt серверу ждем в течении 2 минут, иначе перезагрузка модема
//
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK
OK
STATE: CONNECT OK // успешное подключение
// начинаем работать с брокером
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ****** xC ******* // connect packet
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1 x2 x1 // подписываемся на нужные топики
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12 // отправляем на сервер данные о подключении
23
0
x90 x3
x1
SEND OK // после каждой отправки ждем данное подтверждение в течении 8 секунд, в случае отсутствия - переподключаемся к серверу
AT+CIPSEND // каждае 240 секунд (время удержания соединения, меньшее, чем указано в connect packet)
>xC0 x0 // шлем PING REQ , потом ждем 14 секунд PING RESP
SEND OK
xD0 /*пришел PING RESP, если не дождались - реконнект к серверу*/ AT+CIPSEND
>xC0 x0
SEND OK
xD0 AT+CIPSTATUS
OK
STATE: CONNECT OK
AT+CIPCLOSE // принудительно разорвали связь или увидели ответ CLOSED
CLOSE OK
AT+CIPSTATUS // запускаем заново модуль соединения к серверу
OK
STATE: TCP CLOSED // который в зависимости от статуса
AT+CIPSHUT // согласно даташита шлет нужную команду
SHUT OK
AT+CIPSTATUS
OK
STATE: IP INITIAL
AT + CSTT = "internet.emt.ee"
OK
AT+CIPSTATUS
OK
STATE: IP START
AT+CIICR
OK
AT+CIPSTATUS
OK
STATE: IP GPRSACT
AT+CIFSR
0.137.201.64S
OK
STATE: IP STATUS
AT+CIPSTART="TCP","m20.cloudmqtt.com",***** // коннектимся к резервному серверу
OK
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
// .......... ждем коннекта
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK
OK
STATE: CONNECT OK
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ****** xC *******
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1 x2
SEND OK
AT+CIPSEND
>x82 xC x0 xA x0 x7 log/srvx1 x90 x3
x1
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12
23
7
x90 x3
x1
SEND OK
AT+CIPSTATUS
OK
STATE: CONNECT OK
AT+CIPCLOSE // опять принудительно разрываем связь
CLOSE OK
AT+CIPSTATUS
OK
STATE: TCP CLOSED
AT+CIPSHUT
SHUT OK
AT+CIPSTATUS
OK
STATE: IP INITIAL
AT + CSTT = "internet.emt.ee"
OK
AT+CIPSTATUS
OK
STATE: IP START
AT+CIICR
OK
AT+CIPSTATUS
OK
STATE: IP GPRSACT
AT+CIFSR
0.149.212.52S
OK
STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",****** // теперь уже соединяемся с основным сервером
OK
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
// ...... ждем соединения
AT+CIPSTATUS
OK
STATE: TCP CONNECTING
AT+CIPSTATUS
CONNECT OK
OK
STATE: CONNECT OK
AT+CIPSEND
>x10 3x0 x4 MQTTx4 xC0 x0 xFD x0 xF Qw37Tu89u78-91px0 x8 ******* xC ********
SEND OK
AT+CIPSEND
>x82 x1C x0 xA x0 x17 smd/Qw37Tu89u78-91p/cmdx1 x2 x1
SEND OK
AT+CIPSEND
>05x0 xB log/connectx0 x0 Qw37Tu89u78-91p - connected;MegaFon;12
23
0
x90 x3
x1
SEND OK
0x1D x17 smd/Qw37Tu89u78-91p/cmdcmd1AT+CIPSEND // пришла команда в подписанный топик, выполнили ее
>0"x0 x18 smd/Qw37Tu89u78-91p/respx0 x0 resp12 // отправили подтверждающий ответ
SEND OK
AT+CIPSEND
>xC0 x0 // бесконечно крутимся в цикле PING REQ
SEND OK
xD0 // PING RESP
-
часть кода, обработка интернет сессии по даташиту
-
void processStatus(byte inBt) { // основной анализ статусов, логика строго по даташиту
static unsigned long timerConnecting; // таймер для замера времени коннекта к брокеру
if (findRespFromBuf((char *) "IP INITIAL\r\n", inBt)) { // если начальный статус // 0
needCloseConnect = false; // разрывать связь не надо
// прописываем APN
gprsATcmdByIdx(0, false);
gprsATcmd((char *)getAPNname(opsCard), false);
gprsATcmd((char *)"\"\r", true);
currentGprsModem = waitOKcmd; // ждем ОК
} else if (findRespFromBuf((char *) "IP START\r\n", inBt)) { // следующий статус // 1
gprsATcmdByIdx(1, true); // активируем контекст
currentGprsModem = waitCIICRcmd; // ждем ОК
} else if (findRespFromBuf((char *) "IP GPRSACT\r\n", inBt)) { // следующий статус // 3
if (needCloseConnect) { // если нужно свзь разорвать
gprsATcmdByIdx(2, true); // отключаем контекст
currentGprsModem = waitOKcmd; // ждем ОК
} else { // если подключаем связь
gprsATcmdByIdx(3, true); // получаем адрес
currentGprsModem = waitRNcmd; // ждем вывода
}
} else if (findRespFromBuf((char *) "IP STATUS\r\n", inBt)) { // дальше // 4
if (needCloseConnect) { // если рвем связь
gprsATcmdByIdx(2, true); // отключаем контекст
} else { // продолжаем подключение
gprsATcmdByIdx(4, false); // коннектимся к серверу
if (mainMQTTserver) { // выбор сервера и отправка соотвествующего имени в зависимости от режима
#ifdef DEBUG_MODE
gprsATcmd((char *)"m20.cloudmqtt.com", false); gprsATcmd((char *)"\",", false); gprsATcmd((char *)"*****", false);
#else
char strServer[maxSizeBrokerID];
strcpy(strServer, (char *)mqttServer2); gprsATcmd((char *)strServer, false); gprsATcmd((char *)"\",", false);
strcpy(strServer, (char *)mqttPort2); gprsATcmd((char *)strServer, false);
#endif
} else { // основной сервер
#ifdef DEBUG_MODE
gprsATcmd((char *)"m23.cloudmqtt.com", false); gprsATcmd((char *)"\",", false); gprsATcmd((char *)"*****", false);
#else
char strServer[maxSizeBrokerID];
strcpy(strServer, (char *)mqttServer1); gprsATcmd((char *)strServer, false); gprsATcmd((char *)"\",", false);
strcpy(strServer, (char *)mqttPort1); gprsATcmd((char *)strServer, false);
#endif
}
gprsATcmd((char *)"\r", true); // шлем окончание команды
timerConnecting = currentMillis; // обнуляем таймер ожидания коннекта
}
currentGprsModem = waitOKcmd; // ждем ок
} else if (findRespFromBuf((char *) "CONNECT OK\r\n", inBt)) { // приконнектилось // 6
if (needCloseConnect) { // если нужен разрыв
gprsATcmdByIdx(5, true); // закрываем контекст
currentGprsModem = waitOKcmd; // ждем ОК
} else { // если подключаемся
currentGprsModem = serverConnected; // успешно выходим
}
} else if (findRespFromBuf((char *) "TCP CONNECTING\r\n", inBt)) { // в процессе подключения // 5
if (needCloseConnect) { // если нужно разорвать связь
gprsATcmdByIdx(2, true); // гасим
currentGprsModem = waitOKcmd; // ждем ОК
} else { // ждем подключения
if ((currentMillis - timerConnecting) >= gprsPeriodConnecting) { // если время вышло
if (mainMQTTserver) mainMQTTserver = 0; else mainMQTTserver = 1; // меняем сервер
++totalReconnectMQTT; // увеличиваем счетчик смены брокеров
gprsATcmdByIdx(2, true); // гасим контекст
currentGprsModem = waitOKcmd; // ждем ОК
} else { // если продолжыется подключение
currentGprsModem = sendCipStatus; // запрашиваем статус
}
}
} else if (findRespFromBuf((char *) "IP CONFIG\r\n", inBt)) { // шаг // 2
currentGprsModem = sendCipStatus; // запрос статуса
} else if (findRespFromBuf((char *) "TCP CLOSING\r\n", inBt)) { // шаг // 7
currentGprsModem = sendCipStatus; // запрос статуса
} else if (findRespFromBuf((char *) "TCP CLOSED\r\n", inBt)) { // отключились от сервера // 8
gprsATcmdByIdx(2, true); // гасим сессию
currentGprsModem = waitOKcmd; // ждем ОК
} else if (findRespFromBuf((char *) "DPD DEACT\r\n", inBt)) { // отключилась сессия // 9
currentGprsModem = sendCipStatus; // запрос статуса
} else if (findRespFromBuf((char *) "CONNECT FAIL\r\n", inBt)) { // ошибка соединения
gprsATcmdByIdx(2, true); // гасим сессию
currentGprsModem = waitOKcmd; // ждем ОК
}
}
-
к сожалению, какая бы не была хорошая схема, в среднем один из 20и модемов SIM800L зависает наглухо один раз в 50....70 дней, на команды отвечает, а по факту данные не передает. Поэтому рекомендую в схему добавить эл.ключ/реле, в случае принудительной перезагрузки третий раз за 15 минут, тупо отрубать питание. И конечно для стабильной работы строго использовать Hardware UART atmega328p.
просто с правильным SoftwareSerial видимо никто не экспериментировал...
А что, в природе такое бывает?
IMHO, SoftwareSerial - костыль, который, возможно, может быть в некоторых экзотических случаях использован для отладки, но который обязательно должен быть удален из финального кода.
аппаратная реализация сериала конечно лучше программной...
я знаю как минимум пяток реализаций программного, недостатки того, что из коробки...
захватывает все прерывания PCINT и нет поддержки параметров число бит данных, контроль, стоп биты
первый решился бы разработкой библиотеки менеджера прерываний, второй решен в одной из библиотек, но
только для ограниченного набора частот кварца
смотрю профессиональные девайсы, а там используется SIM300... более стабилен в работе?
а что в вашем понятии профессиональные девайсы? мой последний проект/заказ c SIM800L развернут на нескольких тысяч устройств, в планах 200000+ , но считать его профессиональным я например не могу.
и да, соглашусь с мнением выше, использовать software serial из коробки можно только для вывода какого нибудь не критичного лога. Если у вас он стабильно работает, могу только поздравить.
но считать его профессиональным я например не могу.
Интересно, почему ?
потому что я не профессиональный программист/электронщик и не имею соответствующего сертификата как у какого нибудь КБ с кучей специалистов разной направленности :)
но да, устройства работают хорошо и стабильно, поэтому конечно вопрос спорный что считать проф.устройством.
использовать software serial из коробки можно только для вывода какого нибудь не критичного лога.
Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial его положит. Список его авторов я уже дето выкладывал. Этих уродов регулярно упоминаю в проклятиях. Надо быть последним фашистским человеконенавистником чтоб такое нахерячить. И да - тех кого устраивает как оно работает - дальше хелоуворда не пробовали. Он просто не может стабильно работать не убив все вокруг.
Температура, влажность, давление на BME280+ESP8266(WeMos D1 mini), отправляемые на MQTT сервер.
Код сборная солянка, страшненький, написан наспех на коленке, но работает стабильно.
При включении подключается в течении 2 минут к WiFi точке доступа, в случае облома запускает сервер куда вбиваются данные WiFi и MQTT. Далее получает данные, отправлет и засыпает на 25 минут.
Потребление через понижайку от аккумулятора 18650 ~1.5мА в спящем режиме
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#define SEALEVELPRESS_HPA (1013.25)
Adafruit_BME280 bme;
char srvssid[] = "ESterm06";
char srvpass[] = "ESterm06";
ESP8266WebServer server(80);
/* Just a little test message. Go to http://192.168.4.1 in a web browser
connected to this access point to see it.
*/
byte wifiset = 0; byte mqttset = 0;
#define eep_max_len_param 0x40
#define eep_max_count_params 7
#define eep_pos_wifi_p1 0x10
#define eep_pos_wifi_p2 0x30
#define eep_pos_mqtt_p1 0x60
#define eep_pos_mqtt_p2 0x80
#define eep_pos_mqtt_p3 0xA0
#define eep_pos_mqtt_p4 0xC0
#define eep_pos_mqtt_p5 0xE0
char eep_str[eep_max_len_param];
#define period_enable_http_server 300000UL // 5min
unsigned long timer_enable_http_server = 0;
#define size_response_buf 0x40
char mqtt_response_buf[size_response_buf];
byte pos_response_mqtt = 0;
#define errTemp 1111
word currTemp = errTemp;
word currHum = errTemp;
word currPres = errTemp;
byte deviceMode = 10; // main mode work device
// 0 connect wifi
// 1 wait connect wifi
// 2 repeat connect wifi
// 3 connect to mqtt server
// 7 load data mqtt
// 8 wifi access point + http server - several minuts after start
// 9 wait get/post answer
// 10 get temp/hum/press
// 11 sleep device
char ssid[eep_max_len_param];
char password[eep_max_len_param];
#define period_test_wifi_connect 500UL
unsigned long timer_test_wifi_connect = 0;
#define period_timeout_wifi_connect 30000UL // 30sec
unsigned long timer_timeout_wifi_connect = 0;
#define period_repeat_wifi_connect 30000UL // 30sec and MQTT repeat
unsigned long timer_repeat_wifi_connect = 0;
WiFiClient client;
char mqtt_server[eep_max_len_param];
int mqtt_port;
char mqtt_user[eep_max_len_param];
char mqtt_pass[eep_max_len_param];
char mqtt_device[eep_max_len_param];
char mqtt_realhard[] = "Pogreb01-CatVil";
char mqtt_topic_temp[] = "/pog";
char mqtt_topic_hum[] = "/hum";
char mqtt_topic_pres[] = "/pre";
unsigned long currentMillis;
#define LEDON digitalWrite(LED_BUILTIN,LOW)
#define LEDOFF digitalWrite(LED_BUILTIN,HIGH)
void ledFlash(byte countFlash) {
for (byte i = 0; i < countFlash; ++i) {
LEDON; delay(100); LEDOFF; delay(100);
}
delay(400);
}
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
LEDOFF; EEPROMinit();
Serial.begin(115200); Serial.println("Reset Serial");
ledFlash(1); loadDataWiFiEEPROM(); loadDataMqttEEPROM();
}
void processMainWork() {
switch (deviceMode) {
case 0: { // connect wifi
WiFi.disconnect(true);
Serial.print("Connect to WiFi AP "); Serial.println(ssid);
WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); ++deviceMode; timer_timeout_wifi_connect = currentMillis; timer_test_wifi_connect = currentMillis; break;
}
case 1: { // wait connect wifi
if ((currentMillis - timer_test_wifi_connect) >= period_test_wifi_connect) {
timer_test_wifi_connect = currentMillis;
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi connected"); deviceMode = 3; // connect ok
ledFlash(3);
} else {
Serial.print(".");
if ((currentMillis - timer_timeout_wifi_connect) >= period_timeout_wifi_connect) {
Serial.println("WiFi timeout connection"); timer_repeat_wifi_connect = currentMillis; deviceMode = 8; WiFi.disconnect(); // problem connect
}
}
} break;
}
case 3: { // connect to mqtt server
if (client.connect(mqtt_server, mqtt_port)) {
Serial.println("MQTT connected"); deviceMode = 5; // connect ok
} else {
Serial.println("Error MQTT connect"); timer_repeat_wifi_connect = currentMillis; deviceMode = 4; // problem connect
} break;
}
case 4: { // repeat connect mqtt
if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) {
if (WiFi.status() == WL_CONNECTED) {
deviceMode = 3;
} else {
deviceMode = 0;
}
} break;
}
case 5: { // send conneck packet and subscribe
sendConnectPacket(); Serial.println(""); deviceMode = 6; timer_repeat_wifi_connect = currentMillis; break;
}
case 6: { // wait response - pause 3 sec
if ((currentMillis - timer_repeat_wifi_connect) >= 3000UL) {
deviceMode = 7;
} else {
if (client.available()) {
while (client.available()) {
byte inByte = client.read();
if ((inByte < 0x20) || (inByte >= 0x7F)) {
Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
} else {
Serial.write(inByte);
}
}
} // end avail
} // -
break;
}
case 7: { // send data
Serial.println(" Need send current temp! ");
sendPubTemp(); Serial.println("");
Serial.println(" Need send current hum! ");
sendPubHum(); Serial.println("");
Serial.println(" Need send current pres! ");
sendPubPres(); Serial.println("");
deviceMode = 11; // sleep
break;
}
case 8: { // start wifi and http server
WiFi.disconnect(true);
Serial.print("Configuring access point...");
WiFi.softAP(srvssid, srvpass);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.on("/", handleRoot);
server.on("/setup", HTTP_GET, handleSetupGet);
server.on("/setup", HTTP_POST, handleSetupPost);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
deviceMode = 9;
timer_enable_http_server = currentMillis;
break;
}
case 9: {
server.handleClient();
if (server.hasArg("action")) {
if (!wifiset) {
if (((server.arg("action").indexOf("savewifi")) >= 0) && (server.hasArg("ssid")) && (server.hasArg("pass"))) {
wifiset = 1;
Serial.println("There are new WiFi data");
// save data to eeprom
byte l = server.arg("ssid").length() + 1;
server.arg("ssid").toCharArray(eep_str, l); eep_str[l] = 0;
byte i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_wifi_p1 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_wifi_p1 + i, 0);
l = server.arg("pass").length() + 1;
server.arg("pass").toCharArray(eep_str, l); eep_str[l] = 0;
i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_wifi_p2 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_wifi_p2 + i, 0);
EEPROM.commit();
EEPROM.end();
EEPROMinit();
loadDataWiFiEEPROM();
}
}
if (!mqttset) {
if (((server.arg("action").indexOf("mqttset")) >= 0) && (server.hasArg("host")) && (server.hasArg("port")) && (server.hasArg("user")) && (server.hasArg("pass")) && (server.hasArg("devname"))) {
mqttset = 1;
Serial.println("There are new MQTT data");
// save data to eeprom
byte l = server.arg("host").length() + 1;
server.arg("host").toCharArray(eep_str, l); eep_str[l] = 0;
byte i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_mqtt_p1 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_mqtt_p1 + i, 0);
l = server.arg("port").length() + 1;
server.arg("port").toCharArray(eep_str, l); eep_str[l] = 0;
i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_mqtt_p2 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_mqtt_p2 + i, 0);
l = server.arg("user").length() + 1;
server.arg("user").toCharArray(eep_str, l); eep_str[l] = 0;
i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_mqtt_p3 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_mqtt_p3 + i, 0);
l = server.arg("pass").length() + 1;
server.arg("pass").toCharArray(eep_str, l); eep_str[l] = 0;
i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_mqtt_p4 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_mqtt_p4 + i, 0);
l = server.arg("devname").length() + 1;
server.arg("devname").toCharArray(eep_str, l); eep_str[l] = 0;
i = 0; while (eep_str[i] > 0) {
EEPROM.write(eep_pos_mqtt_p5 + i, eep_str[i]); ++i;
} EEPROM.write(eep_pos_mqtt_p5 + i, 0);
EEPROM.commit();
EEPROM.end();
EEPROMinit();
loadDataMqttEEPROM();
}
}
}
if ((currentMillis - timer_enable_http_server) >= period_enable_http_server) {
Serial.println("Stop HTTP server");
server.stop();
WiFi.disconnect(true);
deviceMode = 11; // sleep
}
break;
}
case 10: { // get temp hum press
if (!bme.begin(0x76)) {
Serial.println("BME280 problem!");
} else {
currTemp = ((word)(bme.readTemperature() * 10)) + 2000;
currHum = bme.readHumidity();
currPres = (word)(bme.readPressure() / 133.322368421);
ledFlash(2);
}
deviceMode = 0; // connect to wifi
break;
}
case 11: { // wait 5 sec and sleep
timer_repeat_wifi_connect = currentMillis;
++deviceMode;
break;
}
default: { // wait 5 sec
if ((currentMillis - timer_repeat_wifi_connect) >= 5000UL) {
// 12 sleep device
Serial.println(" sleep device ");
WiFi.disconnect(true);
ESP.deepSleep(1500e6); // sleep 25min
} else {
if (client.available()) {
while (client.available()) {
byte inByte = client.read();
if ((inByte < 0x20) || (inByte >= 0x7F)) {
Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
} else {
Serial.write(inByte);
}
}
} // end avail
} // -
}
}
}
void loop() {
// put your main code here, to run repeatedly:
currentMillis = millis();
// main work
processMainWork();
// end loop
}
void sendConnectPacket() {
byte sizeDevice = strlen(mqtt_realhard); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass);
// fixed header
sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000
sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)0x04); // Length LSB (4)
sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name
sendByteToMQTTclient((byte)0x04); // Protocol Level byte
sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable + retain +will flag
sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0)
sendByteToMQTTclient((byte)0x28); // Keep Alive LSB (10) - 40 sec
// payload
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_realhard[i]));
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user
for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i]));
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass
for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i]));
}
void sendByteToMQTTclient(byte inByte) {
client.write((byte)(inByte));
if ((inByte < 0x20) || (inByte >= 0x7F)) {
Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" ");
} else {
Serial.write(inByte);
}
}
void sendPubTemp() {
char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currTemp;
if (currTemp == errTemp) {
textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
} else {
if (absTemp >= 2000) {
textTemp[textPos] = '+'; absTemp -= 2000;
} else {
textTemp[textPos] = '-';
} ++textPos;
//word bt = absTemp * 0.023; absTemp = absTemp + bt; // correct to true temp
if (absTemp >= 1000) {
textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 100) {
textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 10) {
textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
}
textTemp[textPos] = '.'; ++textPos; textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
}
textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = '`'; ++textPos; textTemp[textPos] = 'C'; ++textPos; textTemp[textPos] = 0;
byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp); byte sizeData = strlen(textTemp);
// fixed header
sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i]));
sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
// payload
for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}
void sendPubHum() {
char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currHum;
if (currHum == errTemp) {
textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
} else {
if (absTemp >= 1000) {
textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 100) {
textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 10) {
textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
}
textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
}
textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = '%'; ++textPos; textTemp[textPos] = 0;
byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_hum); byte sizeData = strlen(textTemp);
// fixed header
sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_hum[i]));
sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
// payload
for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}
void sendPubPres() {
char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currPres;
if (currPres == errTemp) {
textTemp[textPos] = 'n'; ++textPos; textTemp[textPos] = 'o'; ++textPos;
} else {
if (absTemp >= 1000) {
textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 100) {
textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
} else if (absTemp >= 10) {
textTemp[textPos] = (absTemp / 10) + '0'; ++textPos;
}
textTemp[textPos] = (absTemp % 10) + '0'; ++textPos;
}
textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = 'm'; ++textPos; textTemp[textPos] = 'm'; ++textPos; textTemp[textPos] = 0;
byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_pres); byte sizeData = strlen(textTemp);
// fixed header
sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags
sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_pres[i]));
sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
// payload
for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}
byte getByteFromTwoChar(byte byte1, byte byte0) {
byte resultB;
if (byte1 >= 0x41) resultB = (byte1 - 0x37) * 16; else resultB = (byte1 - 0x30) * 16;
if (byte0 >= 0x41) resultB = resultB + (byte0 - 0x37); else resultB = resultB + (byte0 - 0x30);
return resultB;
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void handleRoot() {
wifiset = 0; mqttset = 0;
server.send(200, "text/html", "<h1>You are connected</h1>");
}
void handleSetupGet() {
String message = "<html lang='ru'>\
<head>\
<meta charset='utf - 8'>\
<title>ESP temperature Server</title>\
</head>\
<body>\
<h1>WiFi Acces Point data</h1>\
<form action='?' method='post'>\
<div>\
<label for='ssid'>WiFi SSID: <input type='text' name='ssid' id='ssid' value='";
message += ssid;
message += "'></label>\
</div>\
<div>\
<label for='pass'>WiFi Password: <input type='password' name='pass' id='pass' value='";
message += password;
message += "'></label>\
</div>\
<p></p>\
<input type='hidden' name='action' value='savewifi'>\
<input type='submit' value='Save'>\
</div>\
</form>\
<form action='?' method='post'>\
<div>\
<label for='host'>Host: <input type='text' name='host' id='host' value='";
message += mqtt_server;
message += "'></label>\
</div>\
<div>\
<label for='port'>Port: <input type='text' name='port' id='port' value='";
message += mqtt_port;
message += "'></label>\
</div>\
<p></p>\
<div>\
<label for='user'>User: <input type='text' name='user' id='user' value='";
message += mqtt_user;
message += "'></label>\
</div>\
<div>\
<label for='pass'>Password: <input type='password' name='pass' id='pass' value='";
message += mqtt_pass;
message += "'></label>\
</div>\
<p></p>\
<div>\
<label for='devname'>Topic name: <input type='text' name='devname' id='devname' value='";
message += mqtt_device;
message += "'></label>\
</div>\
<p></p>\
<input type='hidden' name='action' value='mqttset'>\
<input type='submit' value='Set'>\
</form>\
<p></p>\
<a href='../'>Return to main page</a>\
</body>\
</html>";
server.send(200, "text/html", message);
}
void handleSetupPost() {
server.send(200, "text/html", "<html lang='ru'>\
<head>\
<meta charset='utf - 8'>\
<title>ESP temperature Server</title>\
</head>\
<body>\
<h1>OK</h1>\
<p></p>\
<a href='../'>Return to main page</a>\
</body>\
</html>");
}
char* LastPos(char *str1, char *str2) { // find substring in string
int L1 = strlen(str1);
int L2 = strlen(str2);
for (int i = L1 - L2; i >= 0; i--)
{
int j = 0;
for (; j < L2; j++)
if ((str1[i + j] != str2[j]))
break;
if (j == L2)
return str1 + i;
}
return 0;
}
int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
char*p = LastPos(str11, str22);
int n = p - str11;
return n;
}
void loadDataWiFiEEPROM() {
byte i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p1 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(ssid, eep_str);
i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p2 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(password, eep_str);
}
void EEPROMinit() {
EEPROM.begin(eep_max_len_param * eep_max_count_params);
}
void loadDataMqttEEPROM() {
byte i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p1 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(mqtt_server, eep_str);
i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p2 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
mqtt_port = atoi(eep_str);
i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p3 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(mqtt_user, eep_str);
i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p4 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(mqtt_pass, eep_str);
i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_mqtt_p5 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0;
strcpy(mqtt_device, eep_str);
}
Добрый день. Подскажите пожалуйста в чем может быть проблема? Сделал sim800+arduino, брокер был cloudmqtt.com. Все работало стабильно.Решил перенести на другой брокер,www.dioty.co. Возникли трудности. Опубликовать в паблик могу, все передается на брокер, но как только пытаюсь подписаться на топик, сразу закрывает соединение
использовать software serial из коробки можно только для вывода какого нибудь не критичного лога.
Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial его положит. Он просто не может стабильно работать не убив все вокруг.
Есть еще CustomSoftwareSerial, SomeSerial, я их использую
А какая, собственно, разница?
Любая программная реализация последовательного порта будет конфликтовать с прерываниями. Вопрос лишь в том, что раньше отвалится - сам COM-порт или все остальное оборудование, требующее прерываний.
PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.
Любая программная реализация последовательного порта будет конфликтовать с прерываниями. Вопрос лишь в том, что раньше отвалится - сам COM-порт или все остальное оборудование, требующее прерываний.
PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.
использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные, DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))
использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные,
Ну переписали мы таким образом библиотеку. Ну пошли у нас прерывания со стороны. И вот тут каждое устройство стало тянуть одеяло на себя. И кто-то из них в этом перетягивании однозначно проиграет. Чудес не бывает: либо с софтсериал полезут ошибки, либо другое устройство будет работать ненормально со всеми вытекающими.
Цитата:
DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))
Вот именно - при правильном! А отключить часть пинов от pcint и думать, что все проблемы уже решены - подход явно неправильный.
И кому это? если мне, то не интересно - я все это читал.
В логах брокера что нибудь вразумительное есть? Модем корректно отвечает на все команды? отправка успешна у модема?
После отправки 0xC0 0x00 0x1A из порта модема получаю 0xFF 0xC0 0x00 0x1A. Т.е. на сколько я понимаю наружу ничего не уходит.
После отправки 0xC0 0x00 0x1A из порта модема получаю 0xFF 0xC0 0x00 0x1A. Т.е. на сколько я понимаю наружу ничего не уходит.
Что значит из "порта модема получаю" - это откуда?
Сложно судить, вы бы скетч весь выложили, посмотрим. А ещё проще - тупо для испытания - напишите простенький скетч с последовательностью АТ команд что выше было - они то гарантированно наружу шлют данные. И будет понятно где косяк.
И вы так и не выложили что отвечает модем и лог брокера.
Update : я так понимаю вам модем в ответ дублирует посланную команду - отключите нафиг чтоб не мешало разбираться.
После вызова функции в терминале вижу:
К брокеру ессенно в это время подключен, паблиши улетают как положено.
А что касаемо лога, а что лог... в нём не пишется ничего из обена, там просто коннект, дисконнект и всего то...
Я чё думаю: может не морочится с пингом. пустой паблиш туда кадать какой нибудь до таймута да и всё, по сути эффект будет тот же.
Вот смотрю я на код, а с чего вы взяли что ответ от брокера стабильно через 100 миллисекунд придёт, а например не через секунду.
Может быть я не прав, но уже писал - такая архитектура скетча с delay и не дожидаться ответов от модемов и без их анализа - неработоспособна!
По поводу пинга - каждый коннект к брокер сотовый оператор считает за новое подключение, соответственно если у вас лимитный интернет и коннктится каждые N секунд - трафик весь быстро закончится. Пинг пакеты на то и придуманы в mqtt чтоб коннктится раз например в сутки, и постоянно проверять связь через M секунд.
Делэй поставил уже от безисходности, кстати ставил setTimeout на порт 10000 - эффект нет.. И вообще модем должен что то внятное пинуть в порт после отправки пакета, я его жду. При отправке паблиша или подписки сразу получаю "SEND OK, а тут нифига. Видимо я всё же как то не правильно формирую пакет.
Вижу два варианта :
1 сменить брокера - возможно он что то шлёт не так
2 взять наконец то нормальный пример с последовательность АТ команд и делать по аналогии
ЗЫ. Чудес не бывает.
Update :
3. Пересмотреть всю логику работы с модемом - переходить на конечные автоматы или их подобие, т е каждая отправлена команда подразумевает ожидание некоего ответа и или какие то действия и в зависимости от условия - переходить на другие действия.
И ещё команда cipsend имеет несколько режимов работы, я отправляю с указанием количества отправояемых байт, а вы как настроили свой модем?)
Пока скетч не выложите - сложно далее что либо обсуждать.
Весь скетч
нет команд настройки режима обмена CIPQSEND CIPMODE
нет команды закрытия сессии CIPSHUT
рекомендую все таки сообщать модему сколько будет отправлено байт в команде CIPSEND, а не слать в конце байт 26, это во первых надежнее, во вторых если у вас в передаче будет этот байт - все сломается
Читать до просветления:
http://forum.cxem.net/index.php?/topic/195209-%D0%BD%D0%B0%D1%81%D1%82%D...
http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540
Вот старенький пример, комментариев нет, функционал - ранняя версия, только отправка и то с одним неприятным косяком.
Вобщем опять работает, отвечает как положено 0xD0 0x00. От чего завист и какого чёрта надо серверу - закономерности без бутылки не нашёл. Просто раз несколько переконнектился и заработало.
.
А че их искать - cipshut добавили? Похоже что нет, естественно он будет несколько раз пытаться запустить новую сессию не закрыв старую, в итоге по таймауту все сбрасывается и опять работает.
ЗЫ. Вот поэтому у нас и ракеты падают и заказчики скетч не могут запустить и т.д. - потому что разработчик сказал "и так сойдёт, ведь законнектилось в итоге" (
А причём здесь вообще cipshut ?? Сервер соединение рвёт при отправке пинга. Вы вообще здесь, в теме?
Тьфу...блин, разбирайтесь сами, я в теме, у меня мой код по вышеперечисленным книжкам работает исправно, а вы вместо того чтоб прислушаться и хоть чуть попытаться изменить свой скетч только и делайте что троллите.
код для этого примера
http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540
Andycat, а зачем сохраняем в mcusr_mirror , если потом не используем? Или я проглядел?
Это кусок кода для работоспособности wdt на arduino nano
Я понял что это не mqtt. Но это же переменная не используется потом вроде?
На форуме была целая тема по поводу этого кода и он вроде из Даташита, и если я правильно помню, концы смотреть в #include <avr/wdt.h>
Щас гуру подтянутся - разьяснят.
Последовательность команд SIM800L работы с MQTT брокером, устройство работает 24/7, в случае проблем переподключается между серверами.
-
часть кода, обработка интернет сессии по даташиту
-
-
к сожалению, какая бы не была хорошая схема, в среднем один из 20и модемов SIM800L зависает наглухо один раз в 50....70 дней, на команды отвечает, а по факту данные не передает. Поэтому рекомендую в схему добавить эл.ключ/реле, в случае принудительной перезагрузки третий раз за 15 минут, тупо отрубать питание. И конечно для стабильной работы строго использовать Hardware UART atmega328p.
плюсую, также сделал в проекте управления webasto - суровое реле питание рубит.
просто с правильным SoftwareSerial видимо никто не экспериментировал...
просто с правильным SoftwareSerial видимо никто не экспериментировал...
А что, в природе такое бывает?
IMHO, SoftwareSerial - костыль, который, возможно, может быть в некоторых экзотических случаях использован для отладки, но который обязательно должен быть удален из финального кода.
аппаратная реализация сериала конечно лучше программной...
я знаю как минимум пяток реализаций программного, недостатки того, что из коробки...
захватывает все прерывания PCINT и нет поддержки параметров число бит данных, контроль, стоп биты
первый решился бы разработкой библиотеки менеджера прерываний, второй решен в одной из библиотек, но
только для ограниченного набора частот кварца
смотрю профессиональные девайсы, а там используется SIM300... более стабилен в работе?
смотрю профессиональные девайсы
а что в вашем понятии профессиональные девайсы? мой последний проект/заказ c SIM800L развернут на нескольких тысяч устройств, в планах 200000+ , но считать его профессиональным я например не могу.
и да, соглашусь с мнением выше, использовать software serial из коробки можно только для вывода какого нибудь не критичного лога. Если у вас он стабильно работает, могу только поздравить.
ЗЫ. И вообще ветка про MQTT.
Sim300 применяется в ВЭРС-ПК к примеру, имеет все необходимые сертификаты, можно почистить флуд...
но считать его профессиональным я например не могу.
Интересно, почему ?
но считать его профессиональным я например не могу.
Интересно, почему ?
потому что я не профессиональный программист/электронщик и не имею соответствующего сертификата как у какого нибудь КБ с кучей специалистов разной направленности :)
но да, устройства работают хорошо и стабильно, поэтому конечно вопрос спорный что считать проф.устройством.
использовать software serial из коробки можно только для вывода какого нибудь не критичного лога.
Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial его положит. Список его авторов я уже дето выкладывал. Этих уродов регулярно упоминаю в проклятиях. Надо быть последним фашистским человеконенавистником чтоб такое нахерячить. И да - тех кого устраивает как оно работает - дальше хелоуворда не пробовали. Он просто не может стабильно работать не убив все вокруг.
Температура, влажность, давление на BME280+ESP8266(WeMos D1 mini), отправляемые на MQTT сервер.
Код сборная солянка, страшненький, написан наспех на коленке, но работает стабильно.
При включении подключается в течении 2 минут к WiFi точке доступа, в случае облома запускает сервер куда вбиваются данные WiFi и MQTT. Далее получает данные, отправлет и засыпает на 25 минут.
Потребление через понижайку от аккумулятора 18650 ~1.5мА в спящем режиме
Установленные железки в реальных условиях
смотреть логи брокера - искать что ему не нравиться
Не подскажите каким образом это делается?
Обычно - глазами.
использовать software serial из коробки можно только для вывода какого нибудь не критичного лога.
Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial его положит. Он просто не может стабильно работать не убив все вокруг.
Есть еще CustomSoftwareSerial, SomeSerial, я их использую
использовать software serial из коробки можно только для вывода какого нибудь не критичного лога.
Даже для этого нельзя, если софт интенсивно прерывания юзает. software serial его положит. Он просто не может стабильно работать не убив все вокруг.
Есть еще CustomSoftwareSerial, SomeSerial, я их использую
А какая, собственно, разница?
Любая программная реализация последовательного порта будет конфликтовать с прерываниями. Вопрос лишь в том, что раньше отвалится - сам COM-порт или все остальное оборудование, требующее прерываний.
PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.
А какая, собственно, разница?
Любая программная реализация последовательного порта будет конфликтовать с прерываниями. Вопрос лишь в том, что раньше отвалится - сам COM-порт или все остальное оборудование, требующее прерываний.
PS. Лично я программный COM-порт не использую. Где-то при отладке - еще может быть, а в готовом изделии - никогда.
использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные, DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))
использует PCINT однако, только захватывает все прерывания, править библиотеку приходится освобождая ненужные,
Ну переписали мы таким образом библиотеку. Ну пошли у нас прерывания со стороны. И вот тут каждое устройство стало тянуть одеяло на себя. И кто-то из них в этом перетягивании однозначно проиграет. Чудес не бывает: либо с софтсериал полезут ошибки, либо другое устройство будет работать ненормально со всеми вытекающими.
DetSimen написал библиотеку для радиолюбителей использующую софтовый сериал, всё работает при правильном подходе )))
Вот именно - при правильном! А отключить часть пинов от pcint и думать, что все проблемы уже решены - подход явно неправильный.
Подскажите как использовать Willmessage. После установки флагов как указать топик и сообщение?