Перейти к содержанию
    

Модуль SIM800 не отвечает на команды

4 hours ago, ARV said:

Мда... ужос. Еще больше убеждаюсь, что в данном контексте асинхронность - злейшее зло, поллинг наше все.

Ужас происходит от избытка инф-ии. 

Начните с простого, выделение из потока байт пар <CR><LF> которые являются разделителями.

То, что принято из потока ранее разделителя - укладывается в строковую переменную (или их массив).

Если Вы сделаете такой "разборщик-парсер" вывода для одной AT-команды, то для остальных (ATкоманд) все будет намного проще (принцип один).

Фактически, sscanf работает как универсальный настраиваемый парсер входного массива по правилам, указанным в строке формата.

Вам универсальность не требуется, но надо для "вывода" каждой AT-команды создать свой "умный" sscanf + анализатор результата. 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, k155la3 сказал:

Если Вы сделаете такой "разборщик-парсер"

Да сделал я это... Только, подозреваю, перемудрил. Говорю же: мой парсер полностью асинхронно отрабатывает все уведомления модуля... Да только асинхронность эта для СМС приема и передачи боком выходит. 

// сообщение DTMF-кнопки
CMD_HOOK(DTMF){
	// транслировать символ в главную задачу
	//str = DTMF: 1
	//            ^
	//      01234567
	send_to_main(MSG_KEY, str[6]);
}

// ответ на запрос баланса
CMD_HOOK(CUSD){
	// находим первую кавычку в строке - это начало сообщения
	char *start = strchr(str,'"')+1;
	// находим последнюю кавычку - это конец сообщения
	char *end = strchr(start,'"');
	*end = 0;
	if((start[0] == '0') && (start[1] == '0')){
		// это UCS2-кодировка
		ucs2_to_text(start); // функция оставляет только латинские символы, цифры и знаки
		strstr(start, " .p")[3] = 0; // хак - отбросим лишний хвост
		debug_i(max_avail());
		mem_reduce(str, strlen(str)+2);
		debug_i(max_avail());
	}
	// вычисляем реальную длину полезных данных
	uint8_t sz = strlen(start);
	char *sms = mem_alloc(sz+1);
	// копируем данные в отдельную область
	strncpy(sms, start, sz);
	// отправлем эту СМС
	sms_send(cfg.mstr_phone, sms);
	// освобождаем память отправленной смс
	mem_free(sms);
}

Вот из примерно таких обработчиков состоит мой код. А вот так выглядит отправка СМС:

void sms_send(uint8_t n, const __memx char *send_sms){
	if(n == 0) return;
	// выделяем память под команду
	char *cmd = mem_alloc(TEL_LEN + 2 + COUNTRY_CODE_LEN + 26);
	if(!cmd) return;
	debug_s(send_sms);
	// формируем команду
	strcpy_P(cmd, PSTR("+CMGS=\""));
	strncat(cmd, cfg.country, COUNTRY_CODE_LEN);
	strncat(cmd, cfg.phone[n-1], TEL_LEN);
	strcat(cmd,"\"");
	// отправляем команду
	gsm_at_cmd(cmd);
	// освобождаем память
	mem_free(cmd);
	//Task_Sleep(1000);
	// выводим тело сообщения
	while(*send_sms) gsm_send_char(*send_sms++);
	// завершаем сообщение
	Task_Sleep(10);
	gsm_send_char(SMS_END);
}

Видите - Task_Sleep в разных местах? Это борьба с асинхронностью, потоу как прием "промпта" в мою концепцию не укладывается. Хотя если постараться, можно упихать. Просто никак не могу решить: надо ли корячиться, или плюнуть на асинхронность? Просто уже очень много сделано...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, rx3apf сказал:

А что сложного с PDU ?

Сложного - ничего, но сообщение в этом формате может быть слишком большим - много памяти надо, ведь никогда не знаешь, кто и что там пришлет, потому закладываться придется на максимальную длину... А реальной необходимости в приеме мультиязычных и мультисимвольных сообщений нет, достаточно и латиницы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

sms_send(cfg.mstr_phone, sms);

Ваше void sms_send( ) Ситуации могут быть разны, от отсутствия сети до отключенного телефона у абонента и мало ли чего там еще может быть.

Хотябы 2 кода - успешно выполнена операция или нет.

//Task_Sleep(1000);

Посмотрите в Вашей ОС (кстати какая ? "нЭ узнаЛ") наличие мьютексов и семафоров.

В том месте, где Вы хотели использовать Task_Sleep() можно поставить ожидание флага MyMutex.wait(4000);

В асинхронном потоке, соответственно, Вы устанавливаете-lock и сбрасываете-unlock флаг (mutex)

поток В 

while(1) 
{
 if( parse_code != 0 )
	{
		switch( parse_code )
		{
			case CMD_SET_REG:
				. . . .
				break;

			case CMD_GET_REG:
				. . . .
				break;

			case CMD_SEND_SMS_A:  // разбор ответа модема на фазу "А" - ждем промпт или что-то еще
				MyMutex.lock() // установить блокировку 1 "блокировка установлена"  
				retc = modem_Get();
				. . . .
				MyMutex.unlock() // снимаем блокировку, тк от модема получен (или не получен, те ошибка) блок инф-ии
				break;
		
			case ... case ...case ...case ...
		}//sw
		parse_code = 0;
		}//if
 else
		sleep(10);

} //while

поток A (основной алгоритм, который остановлен для ожидания выполнения операции в потоке B)
 

retc = sendSMS("122245");
if( retc == OK )
{
    retc = MyMutex.wait(4000);  // здесь "залипаем" на ожидание выполнения операции в потоке A - не более чем на 4000мс
	. . . . здесь или истек таймаут в 4000мс или операция завершилась (сбросился lock в потоке A) - см. retc
	. . . . 
}
else
    display("error");

При залипанни на wait OS не тормозится, это такой sleep(x) c встроенным таймером и анализом условия.

(Как синхронизировать асинхронность) .

ps Я не претендую на "истину и правильность", нас поправят и наставят на путь истинный старшие товарисчи :)

psps  - TC, с каким объемом RAM имеем дело ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, ARV сказал:

 А реальной необходимости в приеме мультиязычных и мультисимвольных сообщений нет, достаточно и латиницы.

А потом захочется узнать баланс, а там вдруг оператор решит, что это надо именно в PDU передать... Что же это за платформа такая, что за каждый байт RAM жаться приходится (я вообще лишнего не привлекал, есть рабочий буфер для разных нужд, им и пользуюсь). Не, дело хозяйское, конечно...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, rx3apf сказал:

А потом захочется узнать баланс, а там вдруг оператор решит, что это надо именно в PDU передать...

Оператор и так это решил :) но ответ на запрос баланса короткий даже в PDU, я из него тупо выдергиваю символы, которые кодируются 00ХХ, т.е. с лидирующим нулем (латиница) и все остальное отбрасываю - баланс цифрами и знаками остается :)

8 часов назад, k155la3 сказал:

можно поставить ожидание флага MyMutex.wait(4000);

Принципиально это ожидание от Task_Sleep отличается мало, как и от тупого delay()... и все это как-то неприятно.

Что касается сути моих вопросов, то, пожалуй, я окончательно решил пока что не заниматься переделками, а оставить все, как уже работает и проверить необходимость задержек в реальном железе, т.к. велика вероятность, что их необходимость обусловлена смешением реальности с виртуальностью.

9 часов назад, k155la3 сказал:

Ситуации могут быть разны, от отсутствия сети до отключенного телефона у абонента

На счет отсутствия сети - об этом стоит подумать... Пока не очень понимаю, как это простыми средствами выяснить (просто по ERROR этого не поймешь, надо подробности узнавать, а это пока что представляется какими-то лишними телодвижениями). Но это не большая проблема - разберусь по документации. А выключенный телефон у абонента, как я понимаю, обнаружить при отправке СМС невозможно, да и не нужно - если СМС не дошла быстро, необходимость в ней пропадает - кому надо узнать, что на даче лопнула труба и все залито вдой спустя 3 дня? Об этом с тем же успехом можно и весной узнать по приезду :)

9 часов назад, rx3apf сказал:

Что же это за платформа такая

Самая что ни наиесть простейшая - atmega128. RAM 4K, RTOS - FunkOS (с небольшими собственными доделками).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, ARV said:

Что касается сути моих вопросов, то, пожалуй, я окончательно решил пока что не заниматься переделками, а оставить все, как уже работает и проверить необходимость задержек в реальном железе, т.к. велика вероятность, что их необходимость обусловлена смешением реальности с виртуальностью. . . . 

Если сформулировать в контексте толерантности, то будет излишним настаивать в применении иных технических и мировоззренческих решений :biggrin:

ps

Не знаю, есть ли JTAG и аппаратная отладка для  atmega128. Если ее (вдруг) нет - бросайте ЭТО вмести с виртуальностью и переходите на норм. современную платформу - ARM или что-то с возможностью прямой отладки софта в железе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А абсолютно толерантен к советам, более того, я их ищу. И очень благодарен всем, кто готов их мне давать.

Но любой совет я рассматриваю через призму целесообразности применения. У меня сейчас есть задержки в смешении с асинхронностью, причем асинхронность реалзована более удачно (имхо), нежели мне советовли. В частности, у меня нет цикла, в котором я зависаю при ожидании асинхронного сообщения от модуля, т.е. нет одной задачи в контексте RTOS. Все советы, данные мне, не избавялют меня ни от задержек, ни от каши из синхронно-асинхронных подходов. Поэтому я не вижу принципиальной выгоды переделывать все уже работающее. Логично? Если доведется в будущем что-то делать снова с таким модулем, возможно, уже буду изначально поступать иначе...

Только что, k155la3 сказал:

переходите на норм. современную платформу - ARM или что-то с возможностью прямой отладки софта в железе

А вот это не тот совет, в котором я нуждаюсь. Что изменилось за последние 4-5 лет, что вдруг едва ли не один из самых крутых среди доступных МК стал никуда не годным? Лень разработчика выросла? Или USART вдруг стал 32-битным и бешено скоростным? Или мода поменялась?

Не желаю идти на поводу у мнимого "прогресса".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, ARV сказал:

Самая что ни наиесть простейшая - atmega128. RAM 4K

У меня была 644 (в которой больше половины осталось). Какой-то дополнительной оперативки для PDU не потребовалось...

33 минуты назад, ARV сказал:

Или USART вдруг стал 32-битным и бешено скоростным? Или мода поменялась?

 

Но вообще-то FIFO или DMA на UART точно не повредил, несколько досадно отдавать ресурсы на обработку каждого байта, особенно если и UARTов два. Если работать только с модемом, да и на 9600 - ясное дело, что проблем не будет. На 115200 уже несколько сложнее. Да и производительность CPU невысока, если работаем от 3.6...4.2, то выше 7.3728 уже и не прыгнешь. Мне, впрочем, вполне хватало - но там был чистый asm.

 

Очень люблю AVR, не знаю, к сожалению, ARM - но в данном случае ARM кажется предпочтительнее. Да и дешевле они, существенно.

Изменено пользователем rx3apf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, rx3apf сказал:

Какой-то дополнительной оперативки для PDU не потребовалось...

Так понимаете ли в чем дело... Я стал заложником выбранного (и по высказанным советам не факт, что верного) пути: RTOS. На каждую задачу под стек от 128 до 460 байт (подобрано минимальное значение в протеусе), на кольцевой буфер каждого USART еще по 64 байта... Еще под кучу буфер... И в итоге уже задумываешься: стоит ли статически выделять под буфер еще порядка 360 байт на PDU или не стоит...

Только что, rx3apf сказал:

несколько досадно отдавать ресурсы на обработку каждого байта

Считаете, отдать их на Sleep или Mutex.wait менее досадно ? ;)

Только что, rx3apf сказал:

Если работать только с модемом, да и на 9600 - ясное дело, что проблем не будет.

На это и уповаю :) МК сейчас работает на 8МГц и основную часть времени проводит в Task_Idle. А те задачи, что помимо обмена с модемом и т.п., у меня не требуют какой-то выдающейся реакции или быстродействия. Собственно, как практически все задачи, которые могут прийти в голову любителю домашней автоматики.

 

Только что, rx3apf сказал:

ARM кажется предпочтительнее

Не думаю, что на эту тему стоит дискутировать вообще и в данной теме в частности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, ARV said:

... Я стал заложником выбранного (и по высказанным советам не факт, что верного) пути: RTOS. . . . 

"Заложником" можно стать, если вы изготовили партию плат с "неправильным" hardware. А так .... 

Вот, промежуточный вариант между "циклом" и ОС  ТУТ  - псевдо-ОС без отдельных стеков для задач. "Кооператив".

Если Вы вернете софт на цикл, то следующим этапом можете попробовать упорядочить проект с использованием Protothreads.

В прерывания вывести буферизацию USART и таймер ms.

Примеры - ТУТ

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, k155la3 сказал:

А так ....

Ну как бы порядка 3 десятков файлов с общим количеством строк больше 100 тысяч тоже жалко... Что-то, конечно, уцелеет, старался обеспечить независимость модулей, но все равно работы много. И переходить на новую парадигму вообще сложно - еще и сознание надо перестроить. В RTOS просто эйфорию испытал от возможности пользоваться готовыми очередями, хоть ничего сложного в них нет и можно всегда реализовать аналог. 

Кооператив вообще не хочется даже обдумывать, потоу как возможность не ограничивать себя в длительности циклов дорогого стоит.

Все ж хочется сделать с минимумом усилий, и RTOS как бы дает на это надежду... Да и не пробовал RTOS до этого ни разу на МК.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 minutes ago, ARV said:

. . .  В RTOS просто эйфорию испытал от возможности пользоваться готовыми очередями, хоть ничего сложного в них нет и можно всегда реализовать аналог. . . 

Попробуйте в небольшом тестовом проекте поработать с мютексами. Есть некоторая вероятность, что их использование в Вашем проекте уменьшит кол-во кода и позволит уйти от граблей с синхронизацией, в частности - с сессиями обмена с модемом. IMHO

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 часа назад, ARV сказал:

    // находим первую кавычку в строке - это начало сообщения
    char *start = strchr(str,'"')+1;
    // находим последнюю кавычку - это конец сообщения
    char *end = strchr(start,'"');
    *end = 0;

А здесь видимо повисаем или чё-нить портим если вдруг в строке не оказалось кавычек или кавычка оказалась одна.

22 часа назад, ARV сказал:

    if((start[0] == '0') && (start[1] == '0')){

А здесь видимо лезем за пределы строки, если пришла пустая строка "".

Очень всё коряво....  :russian_ru:

2 часа назад, rx3apf сказал:

Но вообще-то FIFO или DMA на UART точно не повредил, несколько досадно отдавать ресурсы на обработку каждого байта

У автора обработка так неоптимально написана, что DMA будет мёртвому припарка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, k155la3 сказал:

Попробуйте в небольшом тестовом проекте поработать с мютексами

Мьютекс мне представляется менее удачным решением.

Смотрите, как сделано сейчас у меня.

Главная задача-дспетчер имеет очередь сообщений. По прерываниям от GSM-модуля USART я принимаю заранее определенный набор его уведомлений, и посылаю строку с одним из этих уведомлений в главную задачу. Там происходит выбор соответствующей функции-обработчика и т.п. Помимо сообщений от GSM, в очередь поступают и другие, так что как бы отдельного "зависания в ожидании" для модема нет. Когда в очередь попадает сообщение с требованием что-то послать в модем, получается чуть хуже: послать-то я посылаю легко прямо из основной задачи, но когда требуется получить ответ (например, текст СМС), приходится перенастраивать обработку прерываний USART так, чтобы байты попадали не в кольцевой буфер (он мал - 64 байта), а в заранее выделенный большой линейный буфер, и потом ждать, пока прием не закончится (или таймер не истечет), восстанавливать работу по кольцу и т.п. О том, что прием закончился, я узнаю снова через сообщение из очереди. Только в этом моменте небольшая заковыка - и таймер ожидания задействован, и освобождение памяти не в том месте, где выделение... короче, тут некрасиво. Но работает. Хоть и не предусмотрено прибытие вместо ожидаемых данных какого-то уведомления (что, конечно, не хорошо).

С мьютексами я просто сведу обработку сообщений в главной задаче в цикл ожидания мьютексов, и эта задача по сути станет заблокированной на все время, пока я жду - очередь обрабатываь она не сможет. Что не очень хорошо, как я понимаю...

Только что, jcxz сказал:

А здесь видимо повисаем или чё-нить портим если вдруг в строке не оказалось кавычек или кавычка оказалась одна.

Я подумаю и отвечу, но не сразу, а позже.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...