Добрый день коллеги,
Я в разработке проектов и приложений с/для Ардуино совсем новичок (с недельным стажем).
Просьба помочь советом/решением следующего примитивного (на первый взгляд) вопроса:
На Arduino Uno "надет" GSM shield SIM900. Переключатели TX/RX установлены в положении SW. При загрузке комплект устанавливает GPRS соеденение и шлет GET запрос на сервер. В ответ получает конкретные "текстовые" указания (1 или 0) на основе которых надо включить или отключить диодную лампочку. Установка соеденения, отправка запроса и прием проходит как запланировано (в логах веб-сервера виден запрос/ответ). Надо на основе "приема" включить/отключить лампу. Нужна промежуточная "процедура" считывания и присвоения переменной ledcmd ответа выдаваемое в консоль после вызова AT+HTTPREAD (1 или 0). В "ручном" режиме (ручном вводе АТ комманд) после AT+HTTPREAD выдается результат:
+HTTPREAD:1
1
OK
Основной код програмы ниже.
#include "SIM900.h"
#include <SoftwareSerial.h>
int ledpin = 11;
char ledcmd;
void setup()
{
pinMode(ledpin, OUTPUT);
Serial.begin(9600);
Serial.println("GSM Shield testing.");
if (gsm.begin(9600)) Serial.println("\nstatus=READY");
else Serial.println("\nstatus=IDLE");
Serial.println("Setting up GPRS");
gsm.SimpleRead();
gsm.SimpleWriteln(("AT+SAPBR=3,1,\"Contype\",\"GPRS\""));
delay(100);
gsm.SimpleWriteln(("AT+SAPBR=3,1,\"APN\",\"internet.beeline.am\""));
delay(100);
gsm.SimpleWriteln(("AT+SAPBR =1,1"));
delay(100);
gsm.SimpleWriteln(("AT+HTTPINIT"));
delay(100);
gsm.SimpleWriteln(("AT+HTTPPARA=\"CID\",1"));
delay(100);
delay(100);
gsm.SimpleWriteln(("AT+HTTPACTION=0"));
delay(100);
gsm.SimpleWriteln(("AT+HTTPREAD"));
};
void loop()
{
if (ledcmd=="1")
{
digitalWrite(ledpin, HIGH);
}
else
{
digitalWrite(ledpin, LOW);
}
delay (2000);
}
На просторах интернета есть подобные задачи и решения, но уже который день тестирую их: ни с одним не удалось достичь результата.
Заранее спасибо за любую помошь и совет.
А в чтении Вы тоже "совсем новичок (с недельным стажем)"? Или Вы просто не сочли нужным прочесть правила форума, прежде, чем в него писать?
В чтетии у меня "стаж" более 30 лет и прошу прощения если кого-то "обидел" своим необдуманным действием не ознакомившись до конца со всеми правилами. Ниже код в "приемлемом" формате (не нашел как отредактировать старое сообщение):
Вот сами подумайте, ну вот захочу я сейчас сказать Вам где у Вас ошибка. И что мне говорить? В строке № .. эээ ... ХЗ?
Без номеров строк обсуждать невозможно. Вставьте как следует и привыкайте так вставлять.
Евгений, раз формат (функционал) портала (форума) позволяет мне постить код с специальной опцией "Убрать вертикальный выравниватель и номерацию строк" то речи быть не может о неприемлемости. Другое дело что указанный вами формат более удобен для указания конкретных ошибок (в общих случаях). С этим не спорю. В будущем (для более объемных задач) именно так и буду делать. Но в данном случае: не думаю что есть что указывать. Я тут не нерабочий код постил чтоб искать что где не работает. Это вырезка из рабочего кода с иллюстрацией как устанавливается соедение и как планирую "проверять" ответ с сервера. Мне нужно дописать процедуру типа readresponce() в которой ledcmd будет приписыватся 1 или 0. Но если указанный вами формат (с нумерацией) поможет решению моей проблемы: пожалуйста...
П.С. строка 27 содержит URL, который преобразовывается в линк на форуме. Может сразу и как боротся с этим подскажете? ;)
раз формат (функционал) портала (форума) позволяет мне постить код с специальной опцией "Убрать вертикальный выравниватель и номерацию строк" то речи быть не может о неприемлемости.
Ну, раз собачки в парке какают и дероьмо валяется, то и речи быть не может, что в него не стоит вступать.
Я пытаюсь Вам помочь, сделать так, чтобы Ваш код кто-то прочитал и кто-то захотел посмотреть на суть дела. Если Вам это не нужно - я не настаиваю :)))))
Мне как раз это и нужно - чтоб кто-то помог. Но думаю если кто-то будет смотреть этот топик и по прошествии 5-7-и постов не увидит ничего дельного (кроме как указаний и соблюдений тех или иных правил и повторения того же кода в 3-х разных форматах) то шансов на решение куда меньше чем если осталось бы как есть и между строк (как совет) было бы выдано мне (как новичку форума) мол так писать намного удобнее. В любом случае, все еще надеюсь что кто нибудь вникнет в суть дела и даст дельный совет. И Вам спасибо Евгений, что помогли мне с советом как гулять в парках где много собак (да и с правилами форума ознакомили - это уже без иронии)...
Мне как раз это и нужно - чтоб кто-то помог. Но думаю если кто-то будет смотреть этот топик и по прошествии 5-7-и постов не увидит ничего дельного (кроме как указаний и соблюдений тех или иных правил и повторения того же кода в 3-х разных форматах) то шансов на решение куда меньше
Вы правы, читать вашу перепалку с Евгением куда как интереснее, чем разбираться в скетче.
Что касается вопроса - на такие вопросы здесь отвечать не принято. Почему? - потому что ваш вопрос предполагает, что кто-то возьмет и напишет вам недостающий код. А это неправильно.
На этом форуме принято отвечать на вопросы "Найдите ошибку?". а не "Помогите сделать?". Это предполагпет, что спрашивающий сначала сам попытается решить проблему, напишет код (пусть не работающий, но свой) - а на форум придет задавать вопросы о ошибках в коде, а не о том, как вообще это делается. Для ответов на вопрос "Как?" есть учебники и Гугль.
Вряд ли тебе здесь помогут. Раньше Квон таким как ты помогал, но сейчас ему, похоже, надоело.
А так здесь помогают тем, кто делает сам, т.е. тем, кто пишет что-то типа: "Я вот написал процедуру, но она в таких-то случаях неправильно работает, подскажите где накосячил".
А тем, кто сам не делает, а пишет
Нужна промежуточная "процедура"
Здесь отвечают что-нибудь типа "всем нужна, иди в раздел "Ищу исполнителя" и заказывай на коммерческой основе".
Надо на основе "приема" включить/отключить лампу. Нужна промежуточная "процедура" считывания и присвоения переменной ledcmd ответа выдаваемое в консоль после вызова AT+HTTPREAD (1 или 0). В "ручном" режиме (ручном вводе АТ комманд) после AT+HTTPREAD выдается результат:
А что выдает программа? После команды
Какой ответ получаете?
И опять же после каждой из команд модему приходит ответ? Если вы не дожидаясь ответа отправляете следующую команду то результат будет непредсказуем :-( На время выполнения отводится 0,1 скеунда "delay(100)", я в настройках GPRS не силен, но вот если смс отправляю модем иногда и на 1-2 секунды задумывается. То есть сначала надо убедится что на все команды SIM900 реагирует как вам надо, а потом уже парсить тот ответ что вам нужен.
С ручным вводом все понятно, там вы ввели и ждете визуально ответ, а в скетче вы его не ждете, а думаете что за 0,1 сек придет ответ ОК для каждой из команд.
Коллеги, я специально не запостил десятки (без преувеличения) версии той процедуры которую написал/модифицировал и которая не дает результат а оставил место между setup и loop чтоб кто-то без мусора (в моем коде) помог написать эти 10 строк. Кстати, с которым думаю сталкивался практически любой начинающий разработчик связки Arduino/GSM Shield (коим я не являюсь и волей судьбы столкнулся с конкретной задачей) или же дал совет куда копать (пользоватся Гуглом тоже умею - не туда путь искал обращаясь сюда). Что до "спрашивающий сначала сам попытается решить проблему": уже неделю как столкнулся с этими платами именно над этим и тружусь (может вам и историю браузера выложить тут?) и по прошествии недели решил обратися к более опытным. Но даже и не думал что некоторые из них вместо того чтоб давать советы (если могут) будут гнатся за формальностями как в ЖКХ - бланки, бумаги, форматы и порядки постановки вопроса. Что до "Вряд ли тебе здесь помогут" и "на такие вопросы здесь отвечать не принято": не хочешь отвечать: пройди мимо. Кто-то может и поможет, буду благодарен. Сам найду ответ, выложу тут. Может кому-то как я понадобится. По крайней мере я не сижу сложа руки пока кто-то тут выложит код. Более того: из-за этой "перепалки с Евгением" к которой стягивается масса указывающих на образ жизни и так теряю достаточно времени которую мог бы потратить на что-то приближающее меня к решению задач.
Итог: не можешь помочь, не мешай...
Сам найду ответ, выложу тут. Может кому-то как я понадобится.
Итог: не можешь помочь, не мешай...
Помогаю.
Вы правы насчет того, что с вашей проблемой сталкивается любой начинающий разработчик связки Arduino/GSM Shield. И потому ваша задача разобрана в инете десятки раз. Каждый мало-мальский серьезный проектс с использованием ГСМ-модема содержит пример нужного вам кода.
Спасибо Андрей за ответ. Да, после каждой команды приходит ответ. delay (100) это один из этапов модификаций кода. На практике вплоть до 10сек задержку ставил именно предпалагаю что может быть опоздание ответа. В ручном режиме ответ выдается сразу же (может через секунду). Что получаю в консоли в ручном режиме: писал...
Помогаю.
Вы правы насчет того, что с вашей проблемой сталкивается любой начинающий разработчик связки Arduino/GSM Shield. И потому ваша задача разобрана в инете десятки раз. Каждый мало-мальский серьезный проектс с использованием ГСМ-модема содержит пример нужного вам кода.
Вот и я об этом писал. В инете сотни РАЗНЫХ реализаций моей задачи. Неделю именно их и перебирал, модифицировал, делал свое на их основе. Результат всегда разный и какой-то не правильный (в прошлом сообщении написал: думаю что-то не то с serial привязкой). Поэтому и попросил тут помочь: чтоб кто-то предложил конкретно проверенный вариант и на основе его и продолжили общение (если самому не удастся подогнать его под себя).
выкладывайте код, как "разными способами" присваивали переменной.
До вас никак не дойдет, что без вашего кода разговора не будет.
Спасибо Андрей за ответ. Да, после каждой команды приходит ответ. delay (100) это один из этапов модификаций кода. На практике вплоть до 10сек задержку ставил именно предпалагаю что может быть опоздание ответа. В ручном режиме ответ выдается сразу же (может через секунду). Что получаю в консоли в ручном режиме: писал...
Готового решения никто не предложит. Ваш код загрузил в IDE ну и соответственно ошибки полезли. Да это ладно. Все равно на работе SIM 900 нету.
Как вариант чтобы помогли надо привести код который компилируется. Ну и что выдаются какието цифры буквы но не те что надо. Тогда может кто либо и поможет как вам уже и выше писали.
А готовое решение тут никто не выложит, времени нет разбираться и писать код, а комммерсы из "Ищу исполнителя" тоже не будут его писать по вполне понятным причинам.
Так что будет один глумеж. Выход один выкладываете то что у вас выводит непонятные цифры буквы при парсинге, тогда может и будут разбираться.
Ниже полный код одного из версий попытки считывания. Давайте обсуждать его...
В serialread() считываю порты.
В clearbuffer() сбрасываю то что считалось (обнуляю после каждой AT комманды кроме последней)
В loop-е помимо проверки для контроля вывожу то что считалось. По идее должно быть послений вывод (AT+HTTPREAD) но на выводе получается что-то из предпоследних (лобо что-то миксированное):
clearbuffer не работает никогда.
В конце serialread (в строке 67) Вы устанавливаете count d 0. Соответственно, цикл в строках 72-75 не выполняется ни разу, т.к. i (рвыное 0) с самого начала НЕ МЕНЬШЕ count, тоже равного 0.
ТС, вам принципиально (только мое ИМХО) нужно менять логику: не пытаться вытащить ответы от модема и понять что он отвечает, а сделать некую таблицу (в голове / на бумаге, а потом уже в МК) - недавно обсуждали подобие "робот состояний".
Например:
команда Х может выдать ответы Y Z C, т.е. послали команду, в цикле посмоянно смотрите ответ его парсите и уже в зависимости от ответа делайте действия.
и так далее, не нужно надеяться что после некой команды придет ответ именно на нее, может придти ответ на предыдущую или первую команду....
не нужно надеяться что после некой команды придет ответ именно на нее, может придти ответ на предыдущую или нервую комнду....
Поддерживаю.
И в первую очередь не стоит рассчитывать, что на каждую вашу команду вы будете получать "ОК".
А вы сейчас в своем коде даже этого не проверяете - просто стираете ответ модема и идете дальше.
Спасибо Евгений за замечание. Это случилось после того как вынес очистку буфера отдельной процедурой.
Принудительно поменял
clearbuffer не работает никогда.
В конце serialread (в строке 67) Вы устанавливаете count d 0. Соответственно, цикл в строках 72-75 не выполняется ни разу, т.к. i (рвыное 0) с самого начала НЕ МЕНЬШЕ count, тоже равного 0.
Насколько я понимаю можно упростить
Думаю так будет достаточно.
ТС, вам принципиально (только мое ИМХО) нужно менять логику: не пытаться вытащить ответы от модема и понять что он отвечает, а сделать некую таблицу (в голове / на бумаге, а потом уже в МК) - недавно обсуждали подобие "робот состояний".
Прежде чем строить какую-то логику мне пока нужно "вытащить ответы от модема". Я на этом этапе "застрял". Не могу вытащить то что нужно. А как дальше с ним обращатся: это уже другое дело (дело логики).
и так далее, не нужно надеяться что после некой команды придет ответ именно на нее, может придти ответ на предыдущую или первую команду....
А что более непредсказуемо, может прийти звонок входящий или смс, тогда вообще путаница получится :)
И об этом тоже не надо забывать, я о том и писал что не delay(ххх) надо писать, а именно парсить ответ.
Ну тут бы пока разобраться с чтением UART.
А что более непредсказуемо, может прийти звонок входящий или смс, тогда вообще путаница получится :)
И об этом тоже не надо забывать, я о том и писал что не delay(ххх) надо писать, а именно парсить ответ.
Ну тут бы пока разобраться с чтением UART.
Вот именно. Перебирать конечную модель с учетом всех погодных условий пока рано. Мне бы пока запарсить то что идет в serial-е (в ответ на последную AT команду) без каких-либо форс-мажорных обстоятельст (звонок, смс, ответ модема не OK и т.д.)
Вот такая конструкция точно работать не будет
по одной простой причине, UART может не успеть вам отдать всю строку сразу, и вы получите не все символы из ответа.
То есть gsmserial.available() возвращает количество символов в буфере на момент когда вы обратились там 1 символ вы его считали и вышли из while(gsmserial.available()) в буфере у вас 1 символ, а остальное пройдет мимо кассы. Отсюда и микс.
Вот тут есть небольшая статья как приянть строку из Srerial. То есть надо читать до символа конец строки ('\n'). И тогда у вас в буфере будет именно строка ответа, а не ее часть. Ну при условии что SIM900 завершает строку \r\n по сути это в установках по умолчанию.
Принудительно поменял
Current buffer is:
Похоже все-таки не успевает. То есть к моменту подачи команды HTTPREAD модем еще только выдает ответ на HTTPACTION. Попробуйте после подачи всех команд читать ответ не один раз, как у вас в программе - а в в бесконечном цикле, выводя все полученное в Сериал.
Вы почему-то считаете, что мы бюрократы и "гноимся за формальностями", когда требуем от Вас публиковать вопросы правильно.
Я поменял только то, что опубликовал (параметры в цикле for).
Но для верности вот полный код (посто не хотел раз за разом в топик заливать тот же длинный код)
Похоже все-таки не успевает. То есть к моменту подачи команды HTTPREAD модем еще только выдает ответ на HTTPACTION. Попробуйте после подачи всех команд читать ответ не один раз, как у вас в программе - а в в бесконечном цикле, выводя все полученное в Сериал.
Сейчас попробую как посоветовали. А может еще и delay после всех AT увеличить раз не успевает?
Кстати, увеличение скорости serial-ов до 19200 выдает вообще пустой результат.
Сейчас попробую как посоветовали. А может еще и delay после всех AT увеличить раз не успевает?
Нет, задержку увеличивать не надо - это неверный путь. Правильнее все-таки знать, какая строка должна придти в ответ - и парсить ответ от модема на предмет получение этой строки. Тогда у вас не будет ситуации, что вы на команду получаете отклик от предыдущей. Совет от Andrey12 ждать конца строки вам задает правильное направление , надо только учитывать, что у вас модем отвечает несколькими строчками и конец строки не всегда конец сообщения.
Сейчас попробую как посоветовали. А может еще и delay после всех AT увеличить раз не успевает?
Кстати, увеличение скорости serial-ов до 19200 выдает вообще пустой результат.
Увеличение скорости выше 9600 у софтового UART у меня вообще не работает, ну в смысле нормально. Хотя на форуме писали, что стабильно работает до 38400.
Совет от Andrey12 ждать конца строки вам задает правильное направление , надо только учитывать, что у вас модем отвечает несколькими строчками и конец строки не всегда конец сообщения.
Это да, но дальше уже тема парсинга, а пока пытаемся прочитать правильно.
Нет, задержку увеличивать не надо - это неверный путь.
Согласен, но установив везде delay в 5 секунд получил то что надо:
Увеличение скорости выше 9600 у софтового UART у меня вообще не работает, ну в смысле нормально. Хотя на форуме писали, что стабильно работает до 38400.
Именно delay и помог. Но как-то не комфортно так работать. Слишком долго ждать. Будем искать другой путь. Что до скорости модема: честно говоря не знаю. Как сказал только неделю назад волей судьбы пришлось столкнутся с Arduino+SIM900. Если подскажете где смотреть: посмотрю.
Согласен, но установив везде delay в 5 секунд получил то что надо:
Как вариант с костылем попробуйте
про скорость
Как вариант с костылем попробуйте
не помогло...
про скорость
это все равно "костыль".
Парсинг ответов - единственный правильный путь.
не помогло...
Получается +IPR: 9600
Ну костыли на то и костыли что помогают не всегда.
У меня стоит 0, то есть автоопределение скорости, работает пока нормально.
Парсинг ответов - единственный правильный путь.
+100500!
И если не терять время на костыли, то его давно уже можно было сделать.
Спасибо всем за советы. Сегодня попробую сделать парсинг до требуемой строки. На стороне сервера могу сделать так же чтоб вместо 0 или 1 выдавал что-то определенное с ключем: типа LED:0 или LED:1. Буду искать слово LED в ответах. По ходу буду отписыватся...
Вот, для себя делал функцию для парсинга ответа модема.
Пользоваться примерно вот так
Первый параметр - команда, которую шлем
Второй - какой ответ ожидаем
Третий - столько раз шлем команду за тот период времени, который указан в четвертом параметре.
Четвертый параметр - максимальный срок ожидания корректноего ответа. То-есть, вы можете задать период ожидания скажем 2000 миллисекунд, но модем ответил правильно через 200, значит и функция завершится сразу посде получения ожидаемого ответа, возвращая true.
Но, если ответ модема не тот, что мы ожидаем, то функция будет продолжать ожидать до конца строка и завершится через 2000 миллисекунд, возвращаю false.
Если вам не нравится поведение функции, вы вольны менять ее по своему усмотрению. ))
Фактически, третий параметр, нормально, должен быть равен 1, но повторная отправка команды несколько раз, за некий период времени, иногда бывает полезна, как в случае команды AT, когда модем в режиме автоматического выбора скорости. Вверху как раз такой случай.
Или вот:
ПС. К гуру: Да, это быдлокод, да, я тоже еще только учусь. ))