Использую cloudmqtt. При использовании другого сервиса смотрите логи этого сервиса!!!! А то получается что вы применяете косяки Жигули к Мерседесам, ну не маразм ли ? А если на вскидку с большой вероятностью отваливается по time out, если за 30 секунд не было передачи данных - отрубает связь. Для более детального ответа необходимо у модема запрашивать статус интернет сессии и уже по ситуации решать проблему.
Я тоже естественно подумал на таймаут. Всяко уже этот вопрос прошевелил. Врядли в этом дело, т.к. от момента подключения до выбрасывания, данные ведь обновляются и я сам шлю запросы, ответы от девайса приходят, поэтому таймаут, даже если как то он коряво и устанавливается на 30 сек, все равно должен сбрасываться на ноль после запросов. А он чётко от момента подключения к брокеру 30 ну +- 3 сек и CLOSED.
Проверьте параметры connect packet, возможно ваш брокер некорректно отрабатывает время удержания сессии, в любом случае не видя причину отключения это все угадайка...
И для поддержания сессии люди придумали pingreq pingresp packet
Не правильно, на модеме уровень сигнала 2.8 в ,а у вас 2.5. фильтрации питания нет вообще,на tx резистор зачем. И т д ..... Все плохо, откройте даташит
Про резистор поняла, уберу (он у меня остался от прямого подключения к Atmega328), а на счёт уровня 2,5 Вольт, минимальное 2,1 максимальное 3,1, не?
По питанию фильтрация есть, как в даташите. на моей схеме не указано
я более того скажу, смысла нет ни малейшего выше 9600 использовать. И везде по возможности стараюсь обходиться этой скоростью, особенно после того как столкнулся с жутко несоответствующим номиналу кварцем на ардуинке. На той 115200 работал с дикими и порой весьма забавными глюками.
Кстати, SoftwareSerial почему-то с SIM800 порой тоже нестабильно работает, по возможности оставьте модуль на аппаратном порту. И да, питание питание и еще раз питание. Конденсатор еще есть смысл на контакты модуля напаять если его там нет, тантал, микрофарад на 1000 хотя бы. Часть глюков отсекает.
я более того скажу, смысла нет ни малейшего выше 9600 использовать.
А мужики-то и не знают...
Мне вот явно 31250 не хватает: приходится в программе много чего накручивать, чтобы избежать переполнения буфера.
Цитата:
И везде по возможности стараюсь обходиться этой скоростью, особенно после того как столкнулся с жутко несоответствующим номиналу кварцем на ардуинке. На той 115200 работал с дикими и порой весьма забавными глюками.
А к скорости порта то это каким боком? Рассогласование скоростей - относительное, следовательно, на любой скорости будет проявляться в равной степени.
Я тоже с таким сталкивался. Итог: в коде вместо 31250 фигурирует 31500. Но по факту это те же самые 31250, только с поправкой на частоту кварца.
Напрямую: буфер переполняется, когда скорость заполнения оказывается выше скорости опустошения. А скорость опустошения - это и есть по сути скорость порта.
Легко, 2 переменных, указатель на последнюю ячейку для записи и количество занятого объема , + соответственно максимальный размер буфера. Ну а дальше тупо логика. Это кольцевой. Ну и поиск подстроки в нем начинать с конца строки.
Среднее 2.8 вольта, надёжно работает, пока сбоев не было Update. Вру, среднее 2.6, но мы делаем 2.8. И всё таки, если зависает, наверняка помехи или БП проседает на доли секунд.
Легко, 2 переменных, указатель на последнюю ячейку для записи и количество занятого объема , + соответственно максимальный размер буфера. Ну а дальше тупо логика. Это кольцевой.
Так кольцевой или не кольцевой?
В любом случае, интересует вопрос: как организовать FIFO без кольцевого буфера?
Кольцевые это когда новые данные затирают старые,хвост, а в UART если данные вы вычитывваются вовремя, вновь приходящие тупо теряются. Впрочем может это не верное определение.
Тут были примеров масса, с мобильника сложно писать, и я например отказался от progmem для хранения ответов модема, быстродействия не хватает, только отправляемые команды там храню.
А к скорости порта то это каким боком? Рассогласование скоростей - относительное, следовательно, на любой скорости будет проявляться в равной степени.
RS-232 интерфейс асинхронный, тактового провода в нем нет, линии DTR/DSR дуина по умолчанию не имеет поэтому устройство ориентируется только на старт-бит как начало посылки, а после в соответствии с предполагаемым таймингом - принимает остальные биты кодовой посылки. Тайминги же конкретно на кварц завязаны, в итоге на больших скоростях передачи (да, 115200 для 232го это уже много) на левом кварце могут вполне себе пакеты не успевать приниматься/передаваться полностью. К сожалению сейчас не могу проиллюстрировать это скринами с логического анализатора - я тогда когда просек в чем проблема даже сравнивал время передачи пакетов - у меня одна дуинка на которой кварц заявленный как 16 а по факту оказался примерно 15,2 мегагерца - конкретно "тормозила" при связи на 115200 bps - более-менее устойчивая работа начиналась только на 38400.
А вообще конечно буфер UART в 64 байта это совсем немного, тут как раз наоборот - большие скорости передачи только усугубляют проблему обработки данных. Если принимается большой объем (больше 64 байт) и нет желания/возможности увеличить буфер - то есть прямой смысл думать про обработку прерываний от UART и ухода от условия Serial.available() - что кстати на софтварном порту вроде как не реализуется, только на аппаратном.
На счёт примеров, как будет время, ткните, пожалуйста, хочу знать.
Как-то писал для SIM800L и Arduino рыбу для ответа модема и управлению им по DTMF. String не использовлась. Если интересно, то вот - https://github.com/slacky1965/alarm
Irinka, все у вас как то не логично. Зачем while внутри loop. Количество команд инициализации модема мало, поставите другой модем - будут проблемы, возьмите для пробы мой список команд из темы про mqtt. Зачем задержка 50мсек. Программа должна работать по строгой логике, инициализация, чтение смс, ответ за звонок и прочее, а у вас сборная солянка. Если хотите совсем универсально - это сложно и сотней строк кода не обоцдетесь.
А чтоб не было ошибок при приеме , даже не пытайтесь а монитор порта выводить все online принимаемое с модема - рано или поздно упретесь в недостаток быстродействия. Соответственно ваша задержка 50 мсек это тупо костыль .
Если в буфере есть байт, вы просто обязаны его вычитать вне зависимости от того есть ли место в вашем буфере! Если используется не кольцевой буфер - читаете до некоего ключевого символа, например номера отправителя СМС. Если делать универсальное решение то как вариант читать до позиции \r\n Но тогда размер буфера минимум 255 нужен. У вас задача какая стоит ? Читать СМС, звонки или что
Использую cloudmqtt. При использовании другого сервиса смотрите логи этого сервиса!!!! А то получается что вы применяете косяки Жигули к Мерседесам, ну не маразм ли ? А если на вскидку с большой вероятностью отваливается по time out, если за 30 секунд не было передачи данных - отрубает связь. Для более детального ответа необходимо у модема запрашивать статус интернет сессии и уже по ситуации решать проблему.
Картинка из даташита вам в помощь
http://arduino.ru/forum/programmirovanie/snova-mqtt-1?page=1#comment-567999
Я тоже естественно подумал на таймаут. Всяко уже этот вопрос прошевелил. Врядли в этом дело, т.к. от момента подключения до выбрасывания, данные ведь обновляются и я сам шлю запросы, ответы от девайса приходят, поэтому таймаут, даже если как то он коряво и устанавливается на 30 сек, все равно должен сбрасываться на ноль после запросов. А он чётко от момента подключения к брокеру 30 ну +- 3 сек и CLOSED.
ок , все равно, пасиб за инфу, будем копать.
Проверьте параметры connect packet, возможно ваш брокер некорректно отрабатывает время удержания сессии, в любом случае не видя причину отключения это все угадайка...
И для поддержания сессии люди придумали pingreq pingresp packet
del
Про резистор поняла, уберу (он у меня остался от прямого подключения к Atmega328), а на счёт уровня 2,5 Вольт, минимальное 2,1 максимальное 3,1, не?
По питанию фильтрация есть, как в даташите. на моей схеме не указано
Среднее 2.8 вольта, надёжно работает, пока сбоев не было
Update. Вру, среднее 2.6, но мы делаем 2.8.
И всё таки, если зависает, наверняка помехи или БП проседает на доли секунд.
Дело было в питании, макетная плата не обеспечивала хорошего контакта.
andycat, какую скорость Hardware serial используете для работы с модемом?
9600, а зачем больше? У меня не было ни одного проекта чтоб не хватало скорости, не мегабайты же с Ютуба смотреть.
я более того скажу, смысла нет ни малейшего выше 9600 использовать. И везде по возможности стараюсь обходиться этой скоростью, особенно после того как столкнулся с жутко несоответствующим номиналу кварцем на ардуинке. На той 115200 работал с дикими и порой весьма забавными глюками.
Кстати, SoftwareSerial почему-то с SIM800 порой тоже нестабильно работает, по возможности оставьте модуль на аппаратном порту. И да, питание питание и еще раз питание. Конденсатор еще есть смысл на контакты модуля напаять если его там нет, тантал, микрофарад на 1000 хотя бы. Часть глюков отсекает.
Спасибо
я более того скажу, смысла нет ни малейшего выше 9600 использовать.
А мужики-то и не знают...
Мне вот явно 31250 не хватает: приходится в программе много чего накручивать, чтобы избежать переполнения буфера.
И везде по возможности стараюсь обходиться этой скоростью, особенно после того как столкнулся с жутко несоответствующим номиналу кварцем на ардуинке. На той 115200 работал с дикими и порой весьма забавными глюками.
А к скорости порта то это каким боком? Рассогласование скоростей - относительное, следовательно, на любой скорости будет проявляться в равной степени.
Я тоже с таким сталкивался. Итог: в коде вместо 31250 фигурирует 31500. Но по факту это те же самые 31250, только с поправкой на частоту кварца.
andriano, стесняюсь спросить а как зависит скорость и переполнение буфера ? Может быть в алгоритме проблема .
Напрямую: буфер переполняется, когда скорость заполнения оказывается выше скорости опустошения. А скорость опустошения - это и есть по сути скорость порта.
скорость опустошения - это и есть по сути скорость порта.
О_О С какой стороны?
Со стороны TX.
Мда....оригинальный костыль. Впрочем хозяин-барин.
Мне самому не нравится. Но еще больше не хочется изменять размер буфера порта.
Дык обрабатывайте online каждый приходящий байт в кольцевом буфере и будет всё работать вне зависимости от размера буфера
У меня байты не приходят, они задаются музыкантом. Вот уходить не всегда успевают.
Кстати, у порта и так два кольцевых буфера, зачем еще?
Чтоб искать приходящие слова фразы типа Creg и прочее
И кстати у порта не кольцевые буферы насколько я знаю
Вот это для меня новость.
Я вообще не представляю, как можно сделать FIFO не кольцевым без нерационального увеличения потребления ресурсов.
Легко, 2 переменных, указатель на последнюю ячейку для записи и количество занятого объема , + соответственно максимальный размер буфера. Ну а дальше тупо логика. Это кольцевой. Ну и поиск подстроки в нем начинать с конца строки.
А как вы делаете 2,8? Используете выход VDDEXT?
С рождеством!
Резисторный делитель, точные номиналы сами рассчитайте или после праздников я схему просмотрю
В любом случае, интересует вопрос: как организовать FIFO без кольцевого буфера?
Не знаю, ни разу не требовался, но наверное как обычно , включить логику и все будет.
Так вот как раз по логике - иначе не будет.
Другими словами, если без извращений, то FIFO - это кольцевой буфер.
Я вот потихоньку пытаюсь уйти от String, возникли вопросы
#include <SoftwareSerial.h> SoftwareSerial MODEM(9, 10); #include <avr/wdt.h> const char AT_UART[] PROGMEM = "AT"; const char AT_SET[] PROGMEM = "AT+CCALR?"; const char AT_AOH[] PROGMEM = "AT+CLIP=1"; const char AT_UARTotv[] PROGMEM = "AT\r"; const char* const AtCommand[] PROGMEM = { AT_UART, AT_SET, AT_AOH, AT_UARTotv, }; unsigned long Time; char buffers[50]; byte pos_buf ; #define MAX_SIZE_RESP_BUF 50 void AtSend(byte nomer) { char arrayBuf[20]; strcpy_P(arrayBuf, (char*)pgm_read_word(&(AtCommand[nomer]))); MODEM.println(arrayBuf); } char AtRead(byte nomer) { char arrayBuf[20]; strcpy_P(arrayBuf, (char*)pgm_read_word(&(AtCommand[nomer]))); return arrayBuf; } void setup() { wdt_disable(); Serial.begin(9600); MODEM.begin(9600); AtSend(0); wdt_enable (WDTO_4S); } void loop() { while (1) { wdt_reset(); /* if (millis() - Time >= 3000) { Time = millis(); AtSend(1); }*/ if (Serial.available())MODEM.write(Serial.read()); if (MODEM.available() > 0) { delay(50); while (MODEM.available()) { if (pos_buf < MAX_SIZE_RESP_BUF) { byte temp = MODEM.read(); buffers[pos_buf] = temp; pos_buf++; } else { Serial.println("Bufer perepolnen"); break; } }//while Serial.print("Polucheno: "); Serial.print(pos_buf); Serial.print(" Byte"); Serial.println(""); //Serial.println(buffers); if (strstr (buffers, "AT\r") != NULL && strstr (buffers, "OK") != NULL) { Serial.println("Uart_OK"); } if (strstr (buffers, "AT+CCALR?") != NULL && strstr (buffers, "+CCALR: 1") != NULL && strstr (buffers, "OK") != NULL) { Serial.println("Set'_OK"); } while (MODEM.available())MODEM.read(); for (byte i = 0; i < pos_buf ; i++)buffers[i] = NULL; pos_buf = 0; }//if (MODEM.available() > 0) { }//while(1){ }//loopТак как ключевое АТ содержится во всех* командах, то условие на 75 строчке выполнялось бы всегда, поэтому я добавила \r
if (strstr (buffers, "AT\r") != NULL && strstr (buffers, "OK") != NULL) { Serial.println("Uart_OK"); }Почему при замене "АТ\r" на AtRead(3) условие выполняется всегда
if (strstr (buffers, AtRead(3)) != NULL && strstr (buffers, "OK") != NULL) { Serial.println("Uart_OK"); }т.е. при выполнении AT+CCALR?
я получу в монитор порта
Atread возвращает один символ, а не три.
andriano, вы пытаетесь найти абстрактное решение к непонятно какой (не описанной)задаче , опишите саму суть и нафига FIFO именно не кольцевой ?
Как собрать в строку*?
Собственно, речь не о задаче, а о Вашем утверждении:
Если не кольцевые, то какие?
Кольцевые это когда новые данные затирают старые,хвост, а в UART если данные вы вычитывваются вовремя, вновь приходящие тупо теряются. Впрочем может это не верное определение.
Как собрать в строку*?
Тут были примеров масса, с мобильника сложно писать, и я например отказался от progmem для хранения ответов модема, быстродействия не хватает, только отправляемые команды там храню.
Спасибо. Учту.
На счёт примеров, как будет время, ткните, пожалуйста, хочу знать.
А к скорости порта то это каким боком? Рассогласование скоростей - относительное, следовательно, на любой скорости будет проявляться в равной степени.
RS-232 интерфейс асинхронный, тактового провода в нем нет, линии DTR/DSR дуина по умолчанию не имеет поэтому устройство ориентируется только на старт-бит как начало посылки, а после в соответствии с предполагаемым таймингом - принимает остальные биты кодовой посылки. Тайминги же конкретно на кварц завязаны, в итоге на больших скоростях передачи (да, 115200 для 232го это уже много) на левом кварце могут вполне себе пакеты не успевать приниматься/передаваться полностью. К сожалению сейчас не могу проиллюстрировать это скринами с логического анализатора - я тогда когда просек в чем проблема даже сравнивал время передачи пакетов - у меня одна дуинка на которой кварц заявленный как 16 а по факту оказался примерно 15,2 мегагерца - конкретно "тормозила" при связи на 115200 bps - более-менее устойчивая работа начиналась только на 38400.
А вообще конечно буфер UART в 64 байта это совсем немного, тут как раз наоборот - большие скорости передачи только усугубляют проблему обработки данных. Если принимается большой объем (больше 64 байт) и нет желания/возможности увеличить буфер - то есть прямой смысл думать про обработку прерываний от UART и ухода от условия
Serial.available()- что кстати на софтварном порту вроде как не реализуется, только на аппаратном.На счёт примеров, как будет время, ткните, пожалуйста, хочу знать.
Как-то писал для SIM800L и Arduino рыбу для ответа модема и управлению им по DTMF. String не использовлась. Если интересно, то вот - https://github.com/slacky1965/alarm
Обсуждение на этом форуме было тут - http://arduino.ru/forum/proekty/sim800l-dtmf-upravlenie-golosovoe-menyu
Не претендую на гуру SIM800 и Arduino :))
Slacky, огромное спасибо, не знала про воспроизведение файлов!
Попробовала, воспроизводится)))))
А я для такого проекта хотела DFPlayer Mini прикручивать)
mySerial.print("AT+CREC=4,\"C:\\User\\"), mySerial.print(1), mySerial.println(".amr\",0,100");Вы написали что одной командой не работает
MODEM.println("AT+CREC=4,\"C:\\User\\1.amr\",1,100");Попробовала, работает.
mySerial.print("AT+CREC=4,\"C:\\User\\"), mySerial.print(1), mySerial.println(".amr\",0,100");Вы написали что одной командой не работает
MODEM.println("AT+CREC=4,\"C:\\User\\1.amr\",1,100");Попробовала, работает.
Я не помню, что я такое где-то утверждал. У меня все передается одной сторокой
void sim800PlayTrack(_track track) { strcpy_P(tmpBuffer, (char*)pgm_read_word(&(msgName[track]))); sim800WriteCmd(tmpBuffer, 0); delay(DEFAULT_DELAY_PLAY_TRACK * 1000); }Где track - номер трека, который нужно воспроизвести уже вместе с командой ...
Возникла проблемка:
#include <SoftwareSerial.h> SoftwareSerial MODEM(9, 10); #include <avr/wdt.h> const char AT_UART[] PROGMEM = "AT";//Proverka uart 0 const char AT_SET[] PROGMEM = "AT+CCALR?";//Proverka seti 1 const char AT_AOH[] PROGMEM = "AT+CLIP=1";//"Ustanovlen AON 2 const char AT_TEXTM[] PROGMEM = "AT+CMGF=1";//"Text mode 3 const char AT_DELSMS[]PROGMEM = "AT+CMGDA=\"DEL ALL\"";//Sms udaleny 4 const char AT_SBROS[]PROGMEM = "ATH";//Sbros vy`zova 5 const char* const AtCommand[] PROGMEM = { AT_UART, AT_SET, AT_AOH, AT_TEXTM, AT_DELSMS, AT_SBROS }; unsigned long Time; char buffers[50]; byte pos_buf; #define MAX_SIZE_RESP_BUF 50 void AtSend(byte nomer) { char arrayBuf[50]; strcpy_P(arrayBuf, (char*)pgm_read_word(&(AtCommand[nomer]))); MODEM.println(arrayBuf); } void setup() { wdt_disable(); Serial.begin(9600); MODEM.begin(9600); AtSend(0); wdt_enable (WDTO_4S); } void loop() { while (1) { wdt_reset(); /*if (millis() - Time >= 3000) { Time = millis(); AtSend(1); }*/ if (Serial.available())MODEM.write(Serial.read()); if (MODEM.available() > 0) { delay(50); while (MODEM.available()) { if (pos_buf < MAX_SIZE_RESP_BUF) { byte temp = MODEM.read(); buffers[pos_buf] = temp; pos_buf++; } else { Serial.println("Bufer perepolnen"); break; } }//while for (byte i = 0; i < pos_buf ; i++) { if (buffers[i] == '\r')buffers[i] = 'r'; if (buffers[i] == '\n')buffers[i] = 'n'; } Serial.print("Polucheno: "); Serial.print(pos_buf); Serial.print(" Byte"); Serial.println(""); //Serial.println(buffers); for (byte i = 0; i < pos_buf ; i++) { Serial.println(buffers[i]); } if (strstr (buffers, "+CMTI:") != NULL) { Serial.println("Polucheno SMS"); AtSend(4); } if (strstr (buffers, "AT+CMGDA=\"DEL ALL\"") != NULL && strstr (buffers, "OK") != NULL) { Serial.println("Sms udaleny"); } while (MODEM.available())MODEM.read(); for (byte i = 0; i < pos_buf ; i++)buffers[i] = NULL; pos_buf = 0; }//if (MODEM.available() > 0) { }//while(1){ }//loopЕсли я вручную отправляю +CMTI: то всё ОК, в мониторе порта вижу Polucheno SMS и Sms udaleny
Соответственно, если вручную отправляю +CMTI:"SM",1 (как приходит с модема), то так же всё ОК
+CMTI:"SM",1
Irinka, все у вас как то не логично. Зачем while внутри loop. Количество команд инициализации модема мало, поставите другой модем - будут проблемы, возьмите для пробы мой список команд из темы про mqtt. Зачем задержка 50мсек. Программа должна работать по строгой логике, инициализация, чтение смс, ответ за звонок и прочее, а у вас сборная солянка. Если хотите совсем универсально - это сложно и сотней строк кода не обоцдетесь.
Команд будеn больше, сейчас разбираюсь с логикой работы, используя char
Как по другому собрать буфер?
Иначе работает с ошибками, получаю неверные символы
http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-ni...
А чтоб не было ошибок при приеме , даже не пытайтесь а монитор порта выводить все online принимаемое с модема - рано или поздно упретесь в недостаток быстродействия. Соответственно ваша задержка 50 мсек это тупо костыль .
if (MODEM.available() > 0) { delay(3); while (MODEM.available()) { if (pos_buf < MAX_SIZE_RESP_BUF) { byte temp = MODEM.read(); buffers[pos_buf] = temp; pos_buf++; } else { Serial.println("Bufer perepolnen"); break; } }//whileПри задержке больше 5 всё ок, при меньшей получаю следующее на команду Ат
Если в буфере есть байт, вы просто обязаны его вычитать вне зависимости от того есть ли место в вашем буфере! Если используется не кольцевой буфер - читаете до некоего ключевого символа, например номера отправителя СМС. Если делать универсальное решение то как вариант читать до позиции \r\n Но тогда размер буфера минимум 255 нужен. У вас задача какая стоит ? Читать СМС, звонки или что
Я использую только звонки.