Все о SIM800L и все что с ним связано.

Oleg_I
Offline
Зарегистрирован: 04.04.2016

Здравствуйте прошу подсказать как удалось победить проблему ? Только по питанию ? 

У меня таже  сети вокруг вилит а к мтс не подключаеться 

   at+cops=?

+COPS: (1,"UMC","UMC","25501"),(3,"KYIVSTAR","UA-KS","25503"),(1,"Astelit","Astelit","25506"),,(0-4),(0-2)
 
AT+CBC
+CBC: 0,55,3846
 

at+csq

+CSQ: 0,0
 
at+cpas возвращает 2 
 
Что проверить  куда посмотреть подскажите пжл. ? 
Уже кажеться все перепробовал, может все таки проблема с модулем ?
erinaceto
Offline
Зарегистрирован: 28.04.2018

Ну, похоже на то, что было у меня. Вопрос в следующем, если подключить к модулю только питание, к сети подключается?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Oleg_I пишет:

Здравствуйте прошу подсказать как удалось победить проблему ? Только по питанию ? 

У меня таже  сети вокруг вилит а к мтс не подключаеться 

   at+cops=?

+COPS: (1,"UMC","UMC","25501"),(3,"KYIVSTAR","UA-KS","25503"),(1,"Astelit","Astelit","25506"),,(0-4),(0-2)
 
AT+CBC
+CBC: 0,55,3846
 

at+csq

+CSQ: 0,0
 
at+cpas возвращает 2 
 
Что проверить  куда посмотреть подскажите пжл. ? 
Уже кажеться все перепробовал, может все таки проблема с модулем ?

у МТС насколько я помню, код 25001

у вс такого кода нет, соответственно и не подключается

возможно 2 проблемы: в данном месте нет в принципе МТС

или у МТС нет 2G базовых станций в этом месте - модуль их не видит

Oleg_I
Offline
Зарегистрирован: 04.04.2016

Друзья, спасибо за быструю реакцию 

Сеть словило, помогла замена сим карты, хз почему, прежняя симка в телефоне нормально работает 

И перепаял напрямую все провода без бред-борда  к модулю по питанию 

 

Oleg_I
Offline
Зарегистрирован: 04.04.2016

Уважаемые форумчане прошу Вашей помощи по работе с модулем 

Использую Arduino nano  (таже проблема в мониторе порта и на меге )

Решил повторить опыт  Гарачика о GSM сигнализации от сюда (http://arduinoprom.ru/arduino/276-gsm-signalizacija-dlja-dachnogo-domika-na-sim800l.html)

Программа для ардуино создана через FLProg 

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

Думал проблема в скорости порта  но я перепробовал все и ни одна не помогла как отображались крючки так и продолжают 

Есть подозрение что криво составляеться и заливаеться программа из ФЛ прог в ардуино 

Прошу глянуть специалистов поверхностно в чем может быть  проблемма что монитор порта не выводит нормальные символы 

Заранее благодарен 

#include <DFPlayerLite.h>

#include <SoftwareSerial.h>

bool GSM_In_sms;
String GSM_Phone;
String GSM_text;
bool GSM_Reject_call;
bool GSM_start;
bool GSM_Net;
int GSM_dBm;
bool GSM_Received_SMS;
String GSM_Text_sms;
String GSM_T_Nomer;
bool GSM_Sent_SMS;
bool GSM_Call;
int GSM_Number_calls;
int GSM_Error_Code;
bool GSM_start_N; //Модем прислал сообщение о том, что он стартовал 
bool GSM_final; // закончена обработка запроса
bool GSM_wait; // идет ожидание ответа на команду
bool GSM_past_SMS;
bool GSM_command_SMS;
bool GSM_past_Reject_call;
bool GSM_command_Reject_call;
//bool GSM_Call_P1;
char GSM_ch;	 //символ пришетший в ком порт
byte GSM_errorCounter; // счетчик ошибок
byte GSM_numberRepeats;
//byte GSM_Dial_response_code;
byte GSM_team_room; //номер текущей функции 
byte GSM_count; // счетчик последовальности команд
unsigned long GSM_time; //Время посылки команды
unsigned long GSM_T_millis; //Время посылки команды
unsigned long GSM_time_n; //Время последнего опроса связи с сетью.
String GSM_line; // сообщение от модуля
String GSM_reply; //Ответ модуля на команду
String GSM_Phone_T=""; //Телефон во время подачи команд на звонок или отправку смс
#define Module_Start "Call Ready"

#define GSM_TYPE_SIM800
SoftwareSerial Serial_S( 2, 3);
int GSM_DTMF;
#define GSM_INCLUSION_DTMF
 
bool GSM_Outgoing_Call;
bool GSM_Take_Call;
bool GSM_Connect;
#define GSM_INCLUSION_CALLS

int Folder;
int Track;
bool StartTrac;
bool Pause;
bool _dfstart1= 0;
bool _dfstart1I= 0;
bool _dfpause1= 0;
bool _dfpause1I= 0;
DFPlayerLite dfPlayerLite= DFPlayerLite ();
String _gtv1;
String _gtv2;
String _gtv3;
String _gtv4;
bool _gtv5 = 0;
bool _gtv6 = 0;
int _gtv7;
bool _gtv8 = 0;
bool _gtv11 = 0;
bool _gtv12 = 0;
bool _gtv13 = 0;
bool _gtv14 = 0;
bool _gtv15 = 0;
bool _gtv18 = 0;
bool _gtv20 = 0;
bool _bounseInputA2S = 0;
bool _bounseInputA2O = 0;
unsigned long _bounseInputA2P = 0UL;
bool _trgs7 = 0;
bool _trgrt4 = 0;
bool _trgrt4I = 0;
bool _changeNumber1_Out = 0;
int _changeNumber1_OLV;
int _inputNumber2_Out = 0;
String _mux2;
bool _tim2I = 0;
bool _tim2O = 0;
unsigned long _tim2P = 0UL;
bool _trgrt8 = 0;
bool _trgrt8I = 0;
String _mux1;
bool _tim1I = 0;
bool _tim1O = 0;
unsigned long _tim1P = 0UL;
bool _trgrt9 = 0;
bool _trgrt9I = 0;
bool _trgs2 = 0;
bool _trgrt12 = 0;
bool _trgrt12I = 0;
bool _trgrt5 = 0;
bool _trgrt5I = 0;
int _inputNumber3_Out = 0;
bool _bounseInputA0S = 0;
bool _bounseInputA0O = 0;
unsigned long _bounseInputA0P = 0UL;
bool _bounseInputA3S = 0;
bool _bounseInputA3O = 0;
unsigned long _bounseInputA3P = 0UL;
bool _trgrt6 = 0;
bool _trgrt6I = 0;
int _swi1;
bool _trgrt1 = 0;
bool _trgrt1I = 0;
bool _trgrt7 = 0;
bool _trgrt7I = 0;
bool _trgrt11 = 0;
bool _trgrt11I = 0;
bool _trgrt2 = 0;
bool _trgrt2I = 0;
int _inputNumber1_Out = 0;
bool _trgs3 = 0;
bool _trgrt10 = 0;
bool _trgrt10I = 0;
void setup()
{
pinMode(14, INPUT);
digitalWrite(14, HIGH);
pinMode(16, INPUT);
pinMode(17, INPUT);
digitalWrite(17, HIGH);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
pinMode(5, OUTPUT);
pinMode(4, OUTPUT);
pinMode(13, OUTPUT);

_bounseInputA2O =  digitalRead(16);
_bounseInputA3O =  digitalRead(17);
_bounseInputA0O =  digitalRead(14);
Serial_S.begin(115200);


Serial.begin (115200);
dfPlayerLite.init (&Serial);
delay(500);
dfPlayerLite.normal_mode();
delay(500);
dfPlayerLite.set_volume( 25 );
delay(500);
dfPlayerLite.set_EQ( 0 );
delay(500);

}
void loop()
{int _tempVariable_int;

bool  _bounceInputTmpA0 =  (digitalRead (14));

if (_bounseInputA0S) 
    {
     if (millis() >= (_bounseInputA0P + 40)) 
         {_bounseInputA0O= _bounceInputTmpA0; _bounseInputA0S=0;}
     }
else
    {
     if (_bounceInputTmpA0 != _bounseInputA0O )
         {_bounseInputA0S=1; _bounseInputA0P = millis();} 
      } 
bool  _bounceInputTmpA2 =  (digitalRead (16));

if (_bounseInputA2S) 
    {
     if (millis() >= (_bounseInputA2P + 40)) 
         {_bounseInputA2O= _bounceInputTmpA2; _bounseInputA2S=0;}
     }
else
    {
     if (_bounceInputTmpA2 != _bounseInputA2O )
         {_bounseInputA2S=1; _bounseInputA2P = millis();} 
      } 
bool  _bounceInputTmpA3 =  (digitalRead (17));

if (_bounseInputA3S) 
    {
     if (millis() >= (_bounseInputA3P + 40)) 
         {_bounseInputA3O= _bounceInputTmpA3; _bounseInputA3S=0;}
     }
else
    {
     if (_bounceInputTmpA3 != _bounseInputA3O )
         {_bounseInputA3S=1; _bounseInputA3P = millis();} 
      } 




//Плата:1
//Наименование:SIM800L

_gtv7 = GSM_DTMF;


GSM_In_sms = _gtv5;
GSM_Phone = _gtv4;
GSM_text = _gtv3;
GSM_Reject_call = _gtv6;
GSM_Received_SMS =0; //Сброс статутса СМС Принята
GSM_Sent_SMS =0; //Сброс статуса СМС Отправлена

if ( 1 ){
	if ( GSM_team_room==3 ){
		GSM_Number_calls =0;
		GSM_Text_sms="";
		GSM_T_Nomer =""; 
	}
}

GSM_T_millis =millis();

		while(Serial_S.available()) //Получаем данные с модема
			{GSM_ch = Serial_S.read();			
			if(GSM_ch == '\r') continue;
			if(GSM_ch == '\n') { GSM_GotLineFromNeoway(); GSM_line = ""; }
			else  GSM_line += GSM_ch;}

if (GSM_wait)//ожиание ответа на команду
	{	
	if(GSM_line.length()>0){
		if(GSM_line==F("> ")) {GSM_count++; GSM_wait=0;GSM_line = "";} }
	if(GSM_T_millis>GSM_time)	{GSM_err (2,0);}
	}

if (GSM_Call&&(GSM_team_room!=1)  ) 
	{	
	GSM_team_room=1; 	
	GSM_Number_calls=1; //сброс числа гудков
	// GSM_resetExpectations() ;	
	 }

if (GSM_start_N){if (!GSM_wait){if ( GSM_setup_comand() ){GSM_start_N=0; GSM_start =1; }}}// Инициализация

if (GSM_start)//Не работать пока не старт
	{
//______Проверка статуса сети
		if ((30000 >0)&&(GSM_team_room==0)) //проверять ли статутс сети
			{
			if((GSM_T_millis-GSM_time_n) > 30000){ GSM_team_room=3;}
			}
//______Конец Проверка статуса сети

//______Отправка СМС
	if (  GSM_In_sms  && !GSM_past_SMS  ) {  if ( GSM_number_search()) GSM_command_SMS =1; 	}	// поступление команды на отправу СМС. Проверка корректности номера
	GSM_past_SMS= GSM_In_sms;
	if ( GSM_command_SMS && (GSM_team_room==0) ) {GSM_team_room=2;  GSM_command_SMS =0;}  // начинать отправу СМС
//______Конец Отправка СМС		

//______Команда сброс вызова или разрыв разговора	
	if (  GSM_Reject_call  && !GSM_past_Reject_call  ) { GSM_command_Reject_call =1; }
	GSM_past_Reject_call=GSM_Reject_call;
//______Конец Команда сброс вызова или разрыв разговора	

	
#ifdef GSM_INCLUSION_USSD // Обработка вызова USSD запросов 
	GSM_causeProcessingUSSD();
#endif

#ifdef GSM_INCLUSION_DATA_TIME //Обработка времени, даты, оператора
	GSM_causeProcessingDataTime();
#endif

#ifdef GSM_INCLUSION_CALLS // исходящий вызов 
	if (GSM_causeProcessingCall()) {
		if( GSM_number_search()){
			GSM_wait=1; // ожитать
			GSM_time =millis() + 20000; // время ожидания			
			Serial_S.println( "ATD"+ GSM_Phone_T+";" );
			GSM_team_room=5;
	#ifdef GSM_DEBUG // отладка		
		Serial.println("Command: ATD"+ GSM_Phone_T+";" );	
	#endif
		}
	}
#endif
//________ Обработка разных процессов
	switch ( GSM_team_room ) {
	case 0:
			break;
	case 1: //Обработка входящих  вызовов 
		if (!GSM_wait){
			if ( GSM_command_Reject_call ) {
				if (  GSM_singleCommand(F("ATH0"), 10) )  {GSM_command_Reject_call=0; GSM_Call=0; GSM_count=0; GSM_final=1;}
				}	
#ifdef GSM_INCLUSION_CALLS
#ifndef GSM_TYPE_M590
		if (GSM_causeProcessingTake()){ GSM_Connect=1; GSM_team_room=5;}	
#endif	
#endif	
		}				
		if (!GSM_Call){ GSM_final =1;  GSM_T_Nomer ="";}
		break;
	case 2:	
		if (!GSM_wait){  GSM_final=GSM_sms_sent();} // отправка сообщения
		break;
	case 3:	
		if (!GSM_wait){ GSM_final=GSM_net_status();}// проверка связи с сетью
		break;
	case 4:	//приход смс
		//if (!GSM_wait){ GSM_final=1; GSM_count=0; GSM_Error_Code =0;   }// 
		break;
#ifdef GSM_INCLUSION_CALLS
	case 5:	//разговор 
		if (!GSM_wait) {	
			if ( GSM_command_Reject_call ) {
				if ( GSM_singleCommand(F("ATH0"), 10))  {GSM_command_Reject_call=0; GSM_Call=0;  GSM_count=0; GSM_Connect=0; GSM_final=1;}
			}
			GSM_count=0;			
		}
		break;
#endif
#ifdef GSM_INCLUSION_DATA_TIME
	case 6:	// дата время 
		if (!GSM_wait){if ( GSM_DataTime() ){ GSM_final =1;}}// запрос баланса
		break;
#endif
#ifdef GSM_INCLUSION_USSD
	case 7:	// USSD 
		if (!GSM_wait){ GSM_final=GSM_USSD();}// запрос баланса
		break;
#endif
	}
//________ Конец Обработка разных процессов

	if (GSM_final){GSM_team_room=0; GSM_final=0;} //должно быть последним
}

_gtv14 = GSM_Call;
digitalWrite(9, GSM_Call);
_gtv1 = GSM_T_Nomer;
_gtv2 = GSM_Text_sms;
digitalWrite(10, GSM_Net);

//Плата:2
//Наименование:Управления DTMF сигналом
digitalWrite(13, ( (_gtv12) || (_gtv11) || (_gtv13) ));
if((_gtv7) == (7)) _trgs3 = 1;
if((_gtv7) == (8)) _trgs3 = 0;
_gtv20 = _trgs3;
digitalWrite(4, !(_trgs3));
if((_gtv7) == (4)) _trgs2 = 1;
if((_gtv7) == (5)) _trgs2 = 0;
_gtv18 = _trgs2;
digitalWrite(5, !(_trgs2));
if((_gtv7) == (1)) _trgs7 = 1;
if((_gtv7) == (2)) _trgs7 = 0;
digitalWrite(8, _trgs7);
_gtv8 = _trgs7;

//Плата:3
//Наименование:Сигнализация проникнавение
_gtv11 = ( (( (_bounseInputA2O) || (_bounseInputA0O) )) && (_gtv8) );

//Плата:4
//Наименование:Пожарная сигнализация
_gtv12 = ( (!(_bounseInputA3O)) && (_gtv8) );

//Плата:5
//Наименование:Сигнализация утечки воды
_gtv13 = ( (( (analogRead (1))) < (800)) && (_gtv8) );

//Плата:6
//Наименование:Вызовы
_gtv15 = ( (((_gtv1).equals(String("+380958707374")))) || (((_gtv1).equals(String("+380958707374")))) );
GSM_Outgoing_Call = 0;
GSM_Take_Call = ( (((_gtv1).equals(String("+380958707374")))) || (((_gtv1).equals(String("+380958707374")))) );


//Плата:7
//Наименование:Голосовое сообщение
if (_gtv18) { if (_trgrt5I) { _trgrt5 = 0;} else {_trgrt5 = 1; _trgrt5I = 1;} } else {_trgrt5 = 0; _trgrt5I = 0;}; 
 if (_gtv15) { if (_trgrt4I) { _trgrt4 = 0;} else {_trgrt4 = 1; _trgrt4I = 1;} } else {_trgrt4 = 0; _trgrt4I = 0;}; 
 if (!(_gtv18)) { if (_trgrt6I) { _trgrt6 = 0;} else {_trgrt6 = 1; _trgrt6I = 1;} } else {_trgrt6 = 0; _trgrt6I = 0;}; 
 if (_gtv20) { if (_trgrt8I) { _trgrt8 = 0;} else {_trgrt8 = 1; _trgrt8I = 1;} } else {_trgrt8 = 0; _trgrt8I = 0;}; 
 if (!(_gtv20)) { if (_trgrt7I) { _trgrt7 = 0;} else {_trgrt7 = 1; _trgrt7I = 1;} } else {_trgrt7 = 0; _trgrt7I = 0;}; 
 if (_gtv8) { if (_trgrt9I) { _trgrt9 = 0;} else {_trgrt9 = 1; _trgrt9I = 1;} } else {_trgrt9 = 0; _trgrt9I = 0;}; 
 if (!(_gtv8)) { if (_trgrt10I) { _trgrt10 = 0;} else {_trgrt10 = 1; _trgrt10I = 1;} } else {_trgrt10 = 0; _trgrt10I = 0;}; 
 _inputNumber1_Out = 0;
if (_trgrt4) {_inputNumber1_Out = 1;}
if (0) {_inputNumber1_Out = 2;}
if (0) {_inputNumber1_Out = 3;}
if (0) {_inputNumber1_Out = 4;}
if (_trgrt5) {_inputNumber1_Out = 5;}
if (_trgrt6) {_inputNumber1_Out = 6;}
if (_trgrt8) {_inputNumber1_Out = 7;}
if (_trgrt7) {_inputNumber1_Out = 8;}
if (0) {_inputNumber1_Out = 9;}
if (0) {_inputNumber1_Out = 10;}
if (_trgrt9) {_inputNumber1_Out = 11;}
if (_trgrt10) {_inputNumber1_Out = 12;}
if(_gtv15)
{_swi1=_inputNumber1_Out;}
else
{_swi1=0;}
if (_changeNumber1_Out) {_changeNumber1_Out = 0;} else {_tempVariable_int = _swi1;
if (_tempVariable_int != _changeNumber1_OLV) {_changeNumber1_OLV = _tempVariable_int; _changeNumber1_Out = 1;}
}
Folder = 1;
Track = _swi1;
StartTrac = _changeNumber1_Out;
Pause = 0;

 if (StartTrac) { if (_dfstart1I) { _dfstart1 = 0;} else {_dfstart1 = 1; _dfstart1I = 1;} } else {_dfstart1 = 0; _dfstart1I = 0;};
 if( _dfstart1 == true) {dfPlayerLite.start_track ( Folder, Track );};

 if (Pause) { if (_dfpause1I) { _dfpause1 = 0;} else {_dfpause1 = 1; _dfpause1I = 1;} } else {_dfpause1 = 0; _dfpause1I = 0;};
 if( _dfpause1 == true) {dfPlayerLite.pause ();};


//Плата:8
//Наименование:Отправка SMS
if (0) { if (_trgrt1I) { _trgrt1 = 0;} else {_trgrt1 = 1; _trgrt1I = 1;} } else {_trgrt1 = 0; _trgrt1I = 0;}; 
 if (( (_gtv8) && (( (_gtv12) || (_gtv11) || (_gtv13) )) ))
{ if (_tim1I) { if (_isTimer(_tim1P, 5000)) {_tim1O = 1;}} else {_tim1I =1; _tim1P = millis();}} else {_tim1O = 0; _tim1I = 0;}
if (( (_gtv8) && (( (_gtv12) || (_gtv11) || (_gtv13) )) ))
{ if (_tim2I) { if (_isTimer(_tim2P, 10000)) {_tim2O = 1;}} else {_tim2I =1; _tim2P = millis();}} else {_tim2O = 0; _tim2I = 0;}
if (_tim2O) { if (_trgrt2I) { _trgrt2 = 0;} else {_trgrt2 = 1; _trgrt2I = 1;} } else {_trgrt2 = 0; _trgrt2I = 0;}; 
 if (( (_gtv8) && (( (_gtv12) || (_gtv11) || (_gtv13) )) )) { if (_trgrt11I) { _trgrt11 = 0;} else {_trgrt11 = 1; _trgrt11I = 1;} } else {_trgrt11 = 0; _trgrt11I = 0;}; 
 if (_tim1O) { if (_trgrt12I) { _trgrt12 = 0;} else {_trgrt12 = 1; _trgrt12I = 1;} } else {_trgrt12 = 0; _trgrt12I = 0;}; 
 _gtv5 = ( (_trgrt11) || (_trgrt12) || (_trgrt2) );
_inputNumber3_Out = 0;
if (_tim1O) {_inputNumber3_Out = 1;}
if (_tim2O) {_inputNumber3_Out = 2;}
if((_inputNumber3_Out) == 0) {_mux2 = String("+380958707374");}
if((_inputNumber3_Out) == 1) {_mux2 = String("+380958707374");}
_gtv4 = _mux2;
_inputNumber2_Out = 0;
if (_gtv11) {_inputNumber2_Out = 1;}
if (_gtv12) {_inputNumber2_Out = 2;}
if (_gtv13) {_inputNumber2_Out = 3;}
if((_inputNumber2_Out) == 0) {_mux1 = String("");}
if((_inputNumber2_Out) == 1) {_mux1 = String("Proniknovenie");}
if((_inputNumber2_Out) == 2) {_mux1 = String("Pogar");}
if((_inputNumber2_Out) == 3) {_mux1 = String("Utechka vody");}
_gtv3 = _mux1;




}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
void GSM_GotLineFromNeoway()
{
bool flag_=0; //Анализ телефонной книги
static bool isStringMessage;
#ifdef GSM_DEBUG
Serial.print("Message module: ");//Тест
Serial.println(GSM_line); //Тест
Serial.print("GSM_team_room: ");//Тест
Serial.println(GSM_team_room); //Тест
#endif

if (GSM_line.length()>0)
	{	

//Обработка входящих СМС
		if (isStringMessage){
		 	GSM_Text_sms  =  GSM_line ; //выводим текст сообщения 
			GSM_Received_SMS  =true; // Импульс приход сообщения
			isStringMessage=0;			
			return;
		}
	if (GSM_line.startsWith("+CMT")) // пришло СМС 
		{
		flag_=1; 
		GSM_resetExpectations();		 
		isStringMessage=1;	
		GSM_reply="";
		} 
//Конец Обработка входящих СМС

// Обработка входящих вызовов
	
	if (GSM_Call)
		{
		if (GSM_line.startsWith(F("+CLIP"))) {flag_=1;GSM_reply="";}
		else if (GSM_line == F("NO CARRIER")) { GSM_Call=0; }		
		}
	if (GSM_line == F("RING")){ //Входящий звонок 
				if(!GSM_Call)GSM_resetExpectations();
				GSM_Call=1; 
				GSM_Number_calls ++;				
				}
// ____ Обработка USSD sim800
#ifdef GSM_TYPE_SIM800
#ifdef GSM_INCLUSION_USSD
if (GSM_line.startsWith("+CUSD")) // пришел ответ по USSD
		{
		GSM_wait=0;
		GSM_count++;
		GSM_USSD_return  =   GSM_substring_commas(GSM_line,5) ;
		} 
#endif
#endif
//_______Конец обработки USSD SIM800


#ifdef GSM_INCLUSION_CALLS //Если добавлен блок работы со звонками
#ifdef GSM_INCLUSION_DTMF // Если добвален блок DTMF
	if ( GSM_Connect ){	if (GSM_line.startsWith(F("+DTMF"))) {GSM_ID_DTMF(GSM_line);}	}
#endif
	if (GSM_team_room==5)
		{
		if (GSM_line == F("CONNECT"))GSM_Connect=1;
		else if (GSM_line == F("BUSY")) GSM_err (505,2);
		else if (GSM_line == F("NO ANSWER")) GSM_err (506,2);
		else if (GSM_line == F("NO CARRIER")) {
				if (GSM_Connect){GSM_Connect=0; GSM_team_room=0;} 
				else GSM_err (507,2);
			}
		}
#endif
// Конец Обработка входящих вызовов
	
	
	if(GSM_line == F("ERROR")) GSM_err (1, 0);
	else if(GSM_line == F("OK")){  GSM_wait=0; GSM_count++; GSM_errorCounter=0; }
	else {
		GSM_reply+=GSM_line; 		
		}
	if (GSM_reply.length()>  160  ){GSM_reply=""; GSM_err (10100,2);}//Защита от переполнения строки


if (GSM_line == Module_Start){ GSM_start_N=1;  GSM_start=0;  GSM_err (0 , 2);  }//Сообщение от модуля о том, закончил загрузку 

if (flag_) //Получение номер телефона отправителя/звонящего
		{
		 GSM_T_Nomer =  GSM_substring_commas( GSM_line, 4) ;	
		if( GSM_T_Nomer.indexOf("+")==-1)  GSM_T_Nomer=(String( "+" ))+ GSM_T_Nomer;	
#ifdef TELEFONNAYA_BOOK // если используется телефооная книга
		int  GSM_ind_arr= GSM_StringArray( GSM_Telefon,  GSM_T_Nomer );
		if ( GSM_ind_arr>-1)  GSM_T_Nomer = GSM_Contact [  GSM_ind_arr ];
#endif
		flag_=0;
		}
#ifdef TELEFONNAYA_BOOK // если используется телефооная книга
	if (!GSM_start){
		if ( GSM_line.startsWith("+CPBF")) // пришла запись телефонной книги
			{if( GSM_index_array< GSM_Number_Contacts ){
				GSM_Telefon[  GSM_index_array ] =  GSM_substring_commas(  GSM_line, 5);
				GSM_Contact[  GSM_index_array ]=  GSM_substring_commas(  GSM_line, ( GSM_line.lastIndexOf(","))) ;
 				 GSM_index_array ++;}
			}
	}
#endif
}
// Получили строку ответа от Neoway. Любые ответы приходят в виде
// либо одной, либо нескольких строк, так что единица, которой мы должны
// оперировать - именно строка
// F("") -Хранить строку в Флеш памяти


}
void GSM_AT_Command(const __FlashStringHelper* str, String str2, byte _numRep)
{
 GSM_numberRepeats=_numRep;
 GSM_reply="";//Сброс содержимого прошлого ответа модуля
 GSM_wait=1; // ожитать
 GSM_time =millis() + 20000; // время ожидания
Serial_S.write("AT+");
Serial_S.print(str);
Serial_S.print(str2);
Serial_S.write("\"\r\n");



#ifdef GSM_DEBUG // отладка
	Serial.write("Command: AT+");
	Serial.print(str);
	Serial.print(str2);
	Serial.write("\"\r\n");	
#endif




}
bool GSM_net_status()
{
switch (  GSM_count ) {
case 0:	
	 GSM_count ++;	
	break;
case 1:	
	 GSM_AT_Command(F("CREG?") , 5);	//Проверка регистрации в сети		
	break;
case 2:	
	if ( GSM_analysisResponse(F("+CREG") )){ 
		if( ( GSM_reply.endsWith("1")) || ( GSM_reply.endsWith("5"))) { GSM_Net =1;} // 1-В домашней сети, 5- в роуминге
		else { GSM_Net =0;}
		}	
	break;		
case 3: // Проверка уровня сигнала 
	 GSM_AT_Command(F("CSQ") , 5 ) ;	
	break;
case 4:		
	if ( GSM_analysisResponse(F("+CSQ") )){				// 
		int t1= GSM_reply.indexOf(": ");
		if(t1>-1)    GSM_dBm  =(( ( ( GSM_reply.substring(t1+2,t1+4) ).toInt())*(2) )-(113));			
		if(  GSM_dBm >0)   GSM_dBm =-120; //нет сети		
		}		
	break;
case 5:	
	 GSM_count=0;
	 GSM_time_n=millis();// время последнего опроса	
	 GSM_Error_Code =0; //Сброc ошибки
	return 1;
	break;
}
return 0;
}
bool GSM_sms_sent()
{
switch (  GSM_count ) {
case 0:	
	 GSM_count ++;	
	break;
case 1:	
	 GSM_AT_Command(F("CMGF=1"),1);		// Перевод сообщенй в текстовый режим	
	break;
case 2:	
	 GSM_AT_Command(F("CMGS=\""),  GSM_Phone_T ,1 ); // Отправка команды на начальный этап  отправки СМС
	break;
case 3: // передача текста СМС и отправка сообщения
	if (  GSM_errorCounter ){  GSM_err( (200+ GSM_count) , 2);  break; }// выход из посылки команд если достигнуто придельное колличество ошибок
	Serial_S.println( GSM_text +String( (char)26 ));		
	 GSM_wait=1; // ожитать
	 GSM_time =millis() + 20000; // время ожидания
#ifdef GSM_DEBUG // отладка
	Serial.println( GSM_text +String( (char)26 ));		
#endif
	break;
case 4:	
	 GSM_count=0;	
	 GSM_Sent_SMS =1;
	 GSM_Error_Code =0; //Сброc ошибки
	return 1;	
	break;	
}
return 0;
}
String GSM_substring_commas(String text_analyze, int position)
{
int t1=text_analyze.indexOf("\"", position);
int t2=text_analyze.indexOf("\"",(t1+1));
if(t1>-1){
	if(t2>-1)  return text_analyze.substring(t1+1,t2);
	else return text_analyze.substring(t1+1);}	
return "";
}
bool GSM_number_search()
{
if ( GSM_Phone.length() <4) {GSM_Error_Code =10005; return 0;}
GSM_Phone_T = GSM_Phone ;

#ifdef TELEFONNAYA_BOOK
int ind_arr;
ind_arr= GSM_StringArray( GSM_Contact ,  GSM_Phone  );
if (ind_arr>-1)  GSM_Phone_T = GSM_Telefon [ ind_arr ];
else if(GSM_White_list ) {GSM_Error_Code =10006; return 0;}	
#endif
	
return 1;
}
void GSM_resetExpectations()
{
//сброс текущей операции 
GSM_wait=0; //сброс ожидания ответа
GSM_count=0; //Сброс состояний обработки других функций
GSM_time_n=GSM_T_millis;//отсрочка проверки статуса сети
GSM_team_room=0; 

}
void GSM_err(int error, byte _ret)
{
GSM_errorCounter++ ;
GSM_reply=""; //Сброс содержимого прошлого ответа модуля
GSM_wait =0;
if (_ret==0){
	if ( GSM_errorCounter >GSM_numberRepeats){ 
		error = GSM_team_room*100+ GSM_count;
		_ret=2;}
	else return;
}
if ( _ret==1)  GSM_count--;
else if (_ret==2 ){
	GSM_errorCounter=0;
	GSM_Error_Code =error;
	if (GSM_team_room==3){GSM_Net =0;GSM_dBm =-120;}
	GSM_resetExpectations();	
}

}
void GSM_AT_Command(const __FlashStringHelper* str, byte _numRep)
{
#ifdef GSM_DEBUG // отладка	
	Serial.write("AT+ _ ");	
#endif
Serial_S.write("AT+");
 GSM_Command( str,_numRep  ) ;


}
bool GSM_analysisResponse(const __FlashStringHelper* response)
{
#ifdef GSM_DEBUG
Serial.print("Expected Answer: ");//Тест
Serial.println(response); //Тест
Serial.print("Real  Answer: ");//Тест
Serial.println(GSM_reply); //Тест
#endif

if (GSM_reply.startsWith(response)){GSM_count++; return 1; }
GSM_err(0,1);
return 0;	
}
bool GSM_singleCommand(const __FlashStringHelper* str, byte _numRep)
{
switch ( GSM_count ) {
case 0:	
	GSM_Command(str, _numRep) ;
	break;
case 1:	
	GSM_count=0;	
	GSM_Error_Code =0; //Сброc ошибки
	return 1;	
	break;
}
return 0;
}
void GSM_Command(const __FlashStringHelper* str, byte _numRep)
{
GSM_reply=""; //Сброс содержимого прошлого ответа модуля
GSM_numberRepeats=_numRep;
GSM_wait=1; // ожитать
GSM_time =millis() + 20000; // время ожидания
Serial_S.println(str);


#ifdef GSM_DEBUG // отладка
	Serial.write("Command: ");	
	Serial.println(str);
#endif

}
bool GSM_setup_comand()
{
switch (  GSM_count ) {
case 0:	
	 GSM_count ++;	
	break;
case 1:
	 GSM_Command(F("ATE0") ,2 ) ; //отключение эхо ответа
	break;
case 2:		
	 GSM_AT_Command(F("CPAS"),4);			// проверка готовности модуля к работе 
	break;
case 3:	
	 GSM_analysisResponse(F("+CPAS: 0") );		
	break;
case 4:	
	 GSM_AT_Command(F("CREG?"),10);	//Проверка регистрации в сети		
	break;
case 5:	
	if ( GSM_analysisResponse(F("+CREG") )){ 
		if( ( GSM_reply.endsWith("1")) || ( GSM_reply.endsWith("5"))) { GSM_Net =1;} // 1-В домашней сети, 5- в роуминге
		else { GSM_err(0,1);  GSM_count--; }			
		}	
	break;
case 6:	
	 GSM_AT_Command(F("CSCB=1") ,2 ) ;	 	// Отключение приема широковещательных сообщений 
	break;	
case 7:	
	 GSM_AT_Command(F("CLIP=1") ,2 ) ;	 	// настройки автоматического определения номера
	break;
case 8:
	 GSM_AT_Command(F("CMGF=1") ,2 ) ; //настройки формата SMS сообщений, текстовый
	break;
case 9:	
	 GSM_AT_Command(F("CSCS=\"GSM\"") ,2 ) ; 	// выбора кодировки текста, кодировка ASCII
	break;
case 10:
	 GSM_AT_Command(F("CNMI=2,2,0,0,0") ,2 ) ; //выдовать смс в терминал и не сохранять в память
	break;
case 11:
#ifdef GSM_INCLUSION_DTMF // Если добвален блок DTMF
	GSM_AT_Command(F("DDET=1") ,5 ); // Включение работы с DTMF
#else
	GSM_count ++;
#endif	 
	break; 
#ifdef TELEFONNAYA_BOOK // Если использовать телефонну книгу
case 12:
	 GSM_AT_Command(F("CPBS?"),2);			
	break;
case 13:
	 GSM_analysisResponse(F("+CPBS: \"SM\"") );			
	break;	
case 14:
	 GSM_AT_Command(F("CPBF=\""), GSM_Name_Contact , 2 ) ;
	 GSM_index_array =0;
	break;
case 15:
#else //Если не использовать телефонную книгу
case 12:
#endif //Окнчание выбора по телефонной книге	
	 GSM_count=0;	
	 GSM_Error_Code =0; //Сброc ошибки	
	return 1;
	break;
}
return 0;
}
void GSM_ID_DTMF(String st)
{
int www=(int(st.charAt(7)));
switch ( www ) {
case 35:	
	 GSM_DTMF =14;	
	break;
case 42:		
	 GSM_DTMF =15;	
	break;
case 65:
	 GSM_DTMF =10;
	break;
case 66:	
	 GSM_DTMF =11;
	break;	
case 67:
	 GSM_DTMF =12;
	break;
case 68:	
	 GSM_DTMF =13;
	break;	
 default: 
if (www>47 && www<58) GSM_DTMF =www-48;
}

}
bool GSM_causeProcessingCall()
{
static bool past_Outgoing_Call=0;
static bool command_Outgoing_Call=0;

if (  GSM_Outgoing_Call   && !past_Outgoing_Call   )  command_Outgoing_Call  =1; 
past_Outgoing_Call  = GSM_Outgoing_Call ;
if (  command_Outgoing_Call  && (GSM_team_room==0) )	 { 	 command_Outgoing_Call  =0;  return 1;} // начинать запрос времени 
return 0;
}
bool GSM_causeProcessingTake()
{
static bool past_Take_Call;
static bool command_Take_Call;

if (   GSM_Take_Call    && !past_Take_Call    )  { command_Take_Call=1;  }
	past_Take_Call   =  GSM_Take_Call;
if (  command_Take_Call    ) { 
	switch (  GSM_count ) {
	case 0:	
	 	GSM_count++;
		break;
	case 1:	
	 	GSM_Command(F("ATA"), 5);	// Поднять трубку
	#ifdef GSM_DEBUG // отладка		
		Serial.println("Command: ATA" );	
	#endif
		break;
	case 2:	
		GSM_count=0;
		command_Take_Call  =0;
		return 1;
		break;	
 	}
}
return 0;
}

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Поверхностно на эту простыню не взглянешь, да и про flprog тут уже было мнение что добавление и исправление чего либо сильно сложно, вы бы сами попытались написать - гораздо полезнее.

Oleg_I
Offline
Зарегистрирован: 04.04.2016

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Я бы для начала скорость serial уменьшил до 9600

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Строка 143

Oleg_I
Offline
Зарегистрирован: 04.04.2016

andycat пишет:
Я бы для начала скорость serial уменьшил до 9600

пробовал, не помогло

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

А если в МК тупой скетч вписать он вообще serial print нормально отображает?

Oleg_I
Offline
Зарегистрирован: 04.04.2016

да, другие тестовые примеры с sim800 в сериал нормально выводят инфо

alexpetro000
Offline
Зарегистрирован: 17.11.2013

Снова пришлось использовать эти модули. Проблему нашел - косяк модуля/несовместимость с местной сетью. Так же перезагружался после команды SMS Ready. Спасло:
AT+CBAND="DCS_MODE"
AT&W

После этого все заработало идеально

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

в итоге получился скетч чтения русских и / или длинных СМС. состоит из трех файлов.

1

#include <avr/wdt.h>
#include <avr\pgmspace.h>
#include "s800str.h"

#include <SoftwareSerial.h>
SoftwareSerial gsm(GSM_TX, GSM_RX); // установка контактовGSM_TX->RX и GSM_RX->TX для программного порта

byte modem_step = 100; // current work mode mode in table of command
// static steps:
// 100 - delay 30 sec for registration modem in net
// 101 - not wait response, wait incomming call or other commands
unsigned long current_millis; // main timer
#define period_read_sms 120971UL // read sms every ~2 min
unsigned long timer_read_sms = 0; // timer read sms
#define period_fixed_wait 60000UL // max time wait response
unsigned long timer_reg_modem = 0; // timer registration modem in net and timer response
char resp_buf[maxSizeATcommandANDresponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define max_resp_count_on_one_type_cmd 5 // max 5 response text by one command and one type
byte fl_true_Rresp[max_resp_count_on_one_type_cmd];
byte fl_true_Oresp[max_resp_count_on_one_type_cmd];
byte startFlag = 1;
byte rresp, oresp;

// part for sms
byte smsStep = 0;
//99 start new sms
byte smsOriginalSize;
byte smsOriginalPosByte;
byte smsTmpByte;
byte smsSizePhone;
byte smsBodyPosByte;
byte smsTPMTICO;
byte smsTPUDHI;
#define max_size_sms_sender 12 // 11 + stopbyte;
char smsSender[max_size_sms_sender];
byte smsTPOA;
byte smsTmpSize;
byte smsTPDCS;
byte smsPrevDecodeByte;
byte smsIdxCurrentChar;
byte smsUDHL;
byte smsIEDL;
byte smsIED;

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

void setup() {
  MCUSR = 0;
  wdt_disable();
  Serial.begin(115200);
  Serial.println("Power ON or WDT reset");
  gsm.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  randomSeed(analogRead(A2));
  pinMode(ledRed_pin, OUTPUT);
  pinMode(ledGre_pin, OUTPUT);
  pinMode(relay1_pin, OUTPUT);
  pinMode(relay2_pin, OUTPUT);
  pinMode(relay3_pin, OUTPUT);
  LEDREDOFF;  LEDGREOFF;
  RELAY1OFF; RELAY2OFF; RELAY3OFF;
  wdt_enable(WDTO_8S);
}

void loop() {
  wdt_reset();
  //delay(9000); // test WDT
  current_millis = millis();
  if (((current_millis - timer_read_sms) >= period_read_sms) && (modem_step == 101)) {
    timer_read_sms = current_millis; modem_step = 3; sendATcmd();
  }
  if (modem_step == 100) {
    LEDGREOFF;
    if ((current_millis - timer_reg_modem) >= 30000UL) { // wait 30 sec registration modem
      modem_step = 0; sendATcmd();
    }
  } else if (modem_step == 101) {
    LEDGREOFF;
    if (startFlag) {
      LEDREDOFF;
      startFlag = 0;
      Serial.println("Ready");
    }
    // nothing do
    loadDataFromModem();
  } else if (modem_step < 100) {
    LEDGREON;
    if ((rresp == 0) && (oresp == 0)) { // go to next cmd
      modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
    } else {
      if ((current_millis - timer_reg_modem) >= period_fixed_wait) {
        if (rresp > 0) {
          resetModem();
        } else if (oresp > 0) { // go to next cmd
          modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd();
        }
      } else {
        // main work
        loadDataFromModem();
      }
    }
  }
}

byte doCmdForModem(byte inByte) {
  byte flGood, flResp;
  char respCmd[maxSizeATcommandANDresponse];
  if (modem_step < 100) {
    if (rresp > 0) {
      flGood = 0;
      flResp = 0;
      for (byte i = 0; i < rresp; ++i) {
        if (fl_true_Rresp[i] == 0) {
          s800getRespByNum(0, modem_step, i, respCmd);
          if (findRespFromBuf(respCmd)) {
            fl_true_Rresp[i] = 1;
            if ((rresp == 1) || (i == (rresp - 1))) flGood = 1;
            flResp = 1;
          }
          break;
        }
      }
      if (flGood) {
        // go to next cmd
        modem_step = s800getNextStepCmdByNum(modem_step);
        if (modem_step < 100) sendATcmd(); return 1;
      }
      if (flResp) {
        clearRespBuf(); return 1;
      }
    }
    // manual processing response
    switch (modem_step) {
      case 3: { // read sms
          if (smsStep >= 99) {
            doSMSbody(inByte);
          } else if (smsStep == 1) {
            if (findRespFromBuf("\r\n")) {
              doSMShead(); clearRespBuf(); return 1;
            }
          } else {
            if (findRespFromBuf("+CMGL:")) {
              smsStep = 1; clearRespBuf(); return 1;
            }
          }
          break;
        }
      default: {}
    }
  } else { // mode 101
    // find ring or other cmd
  }
  return 0;
}

byte findRespFromBuf(char* textResp) {
  if (resp_buf[pos_buf] > 0) {
    byte idxBuf = pos_buf;
    byte idxResp = 0;
    byte lenResp = strlen(textResp);
l1: if (resp_buf[idxBuf] == textResp[idxResp]) {
      byte flRigth = 1;
      while ((idxResp < lenResp) && (idxBuf != pos_buf)) {
        if ((textResp[idxResp]) != (resp_buf[idxBuf])) {
          flRigth = 0; break;
        }
        ++idxResp;
        if ((++idxBuf) >= maxSizeATcommandANDresponse) idxBuf = 0;
      }
      if (!flRigth) {
        if ((++idxBuf) >= maxSizeATcommandANDresponse) idxBuf = 0;
        if (idxBuf == pos_buf) return 0;
        idxResp = 0;
        goto l1;
      } else return 1;
    } else {
      if ((++idxBuf) >= maxSizeATcommandANDresponse) idxBuf = 0;
      if (idxBuf == pos_buf) return 0;
      idxResp = 0;
      goto l1;
    }
  } else if (pos_buf > 0) {
    if (strPos(resp_buf, textResp) >= 0) {
      return 1;
    }
  }
  return 0;
}

void sendATcmd() {
  char cmdAT[maxSizeATcommandANDresponse];
  s800getTextCmdByNum(modem_step, cmdAT);
  gsm.print(cmdAT);
  timer_reg_modem = current_millis;
  //Serial.print(cmdAT);
  rresp = s800getCountRrespCmdByNum(modem_step);
  oresp = s800getCountOrespCmdByNum(modem_step);
  for (byte i = 0; i < max_resp_count_on_one_type_cmd; ++i) {
    fl_true_Rresp[i] = 0; // max 5 response text by one command and one type
    fl_true_Oresp[i] = 0;
  }
  // manual setting
  clearRespBuf();
}

void clearRespBuf() {
  for (byte i = 0; i < maxSizeATcommandANDresponse; ++i) resp_buf[i] = 0;
  pos_buf = 0;
}

void loadDataFromModem() {
  if (gsm.available()) {
    while (gsm.available()) {
      byte readByte = gsm.read();
      if (readByte > 0) {
        //if (modem_step != 3) Serial.write(readByte);
        resp_buf[pos_buf] = readByte;
        ++pos_buf;
        if (pos_buf >= maxSizeATcommandANDresponse) pos_buf = 0;
        if (doCmdForModem(readByte) == 1) break;
      }
    }
  }
}

void resetModem() {
  LEDREDON;
  // reset modem
  pinMode(reset_sim800_pin, OUTPUT);
  digitalWrite(reset_sim800_pin, LOW);
  delay(115);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  // new init modem and start new main loop
  timer_reg_modem = current_millis;
  modem_step = 100;
  startFlag = 1;
}

void doSMShead() {
  // get length body sms
  byte posSbyte = 0;
  byte posBbyte = (pos_buf - 3);
  while ((resp_buf[posBbyte] >= 0x30) && (resp_buf[posBbyte] <= 0x39)) {
    if (posSbyte == 0) smsOriginalSize = (resp_buf[posBbyte] - 0x30);
    else if (posSbyte == 1) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 10;
    else if (posSbyte == 2) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 100;
    ++posSbyte;
    --posBbyte;
  }
  smsOriginalPosByte = 0;
  smsStep = 99;
}

void doSMSbody(byte readByte) {
  // get byte from buf
  ++smsOriginalPosByte;
  switch (smsStep) {
    case 99: { // get size sms centr
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte);
          smsStep = 100;
        }
        break;
      }
    case 100: { // skip num sms centr
        if (!bitRead(smsOriginalPosByte, 0)) {
          if ((--smsSizePhone) == 0) {
            smsStep = 101;
            smsBodyPosByte = 0;
          }
        }
        break;
      }
    case 101: { // get TP-MTI & Co
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsTPMTICO = getByteFromTwoChar(smsTmpByte, readByte);
          ++smsBodyPosByte;
          // analize TP-MTI & Co
          smsTPUDHI = bitRead(smsTPMTICO, 6);
          if ((bitRead(smsTPMTICO, 0) == 0) && (bitRead(smsTPMTICO, 1) == 0)) smsStep = 102; else smsStep = 0;
        }
        break;
      }
    case 102: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte);
          if (bitRead(smsSizePhone, 0)) smsTmpSize = smsSizePhone + 1; else smsTmpSize = smsSizePhone;
          ++smsBodyPosByte;
          smsStep = 103;
        }
        break;
      }
    case 103: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsTPOA = getByteFromTwoChar(smsTmpByte, readByte);
          ++smsBodyPosByte;
          smsSender[0] = 0;
          smsStep = 104;
        }
        break;
      }
    case 104: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // processing sender
          byte ts;
          if (bitRead(smsSizePhone, 0)) ts = smsSizePhone + 1; else ts = smsSizePhone;
          byte tp = ts - smsTmpSize;
          if ((bitRead(smsTPOA, 6) == 1) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) &&
              (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 0)) {
            // char sender
            // ignore sms
            smsStep = 0;
            break;
          } else if ((bitRead(smsTPOA, 6) == 0) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) &&
                     (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 1)) {
            // number phone
            if (tp < max_size_sms_sender) smsSender[tp] = readByte;
            ++tp;
            if (tp < max_size_sms_sender) smsSender[tp] = smsTmpByte;
            if ((ts > smsSizePhone) && (smsTmpSize <= 2)) {
              if (tp < max_size_sms_sender) smsSender[tp] = 0;
            } else {
              if ((tp + 1) < max_size_sms_sender) smsSender[tp + 1] = 0;
            }
          } else {
            smsStep = 0;
            break;
          }
          // ---
          if ((smsTmpSize -= 2) == 0) smsStep = 105;
        }
        break;
      }
    case 105: { // TP-PID
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          smsStep = 106;
        }
        break;
      }
    case 106: { // TP-DCS
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          smsTPDCS = getByteFromTwoChar(smsTmpByte, readByte);
          smsStep = 107;
          smsTmpSize = 7;
        }
        break;
      }
    case 107: { // TP-SCTS - skip 7 byte
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          if ((--smsTmpSize) == 0) smsStep = 108;
        }
        break;
      }
    case 108: { // TP-UDL
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          smsTmpSize = getByteFromTwoChar(smsTmpByte, readByte);
          if (smsTPUDHI == 0) {
            Serial.println(smsSender);
            smsPrevDecodeByte = 0;
            smsIdxCurrentChar = 0;
            smsStep = 109;
          } else {
            // long sms
            smsStep = 110;
          }
        }
        break;
      }
    case 109: { // body sms
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          byte tb = getByteFromTwoChar(smsTmpByte, readByte);
          if (smsTPDCS == 0) {
            // decode 7 bit
            getDecode7bitChar(smsPrevDecodeByte, tb);
            smsPrevDecodeByte = tb;
          } else {
            // decode UCS2
            if ((smsPrevDecodeByte == 0x04) && (tb >= 0x10) && (tb <= 0x4F)) {
              // rus unicode
              if (tb >= 0x40) {
                Serial.write(0xD1);
                Serial.write(0x40 + tb);
              } else {
                Serial.write(0xD0);
                Serial.write(0x80 + tb);
              }
            } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x01)) {
              Serial.write(0xD0); Serial.write(0x01);
            } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x51)) {
              Serial.write(0xD1); Serial.write(0x91);
            } else if ((smsPrevDecodeByte == 0x00) && (tb >= 0x20) && (tb < 0x7F)) {
              // ascii
              Serial.write(tb);
            }
            smsPrevDecodeByte = tb;
          }
          if ((++smsBodyPosByte) >= smsOriginalSize) {
            // end sms
            smsStep = 0;
            if (smsTPUDHI == 0) {
              Serial.write('\r');
              Serial.write('\n');
            } else if (smsIED = smsIEDL) {
              Serial.write('\r');
              Serial.write('\n');
            }
          }
        }
        break;
      }
    case 110: { // TP-UDH
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          smsUDHL = getByteFromTwoChar(smsTmpByte, readByte) - 1;
          smsStep = 111;
        }
        break;
      }
    case 111: { // EIDL
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          if ((--smsUDHL) == 0) {
            smsIEDL = getByteFromTwoChar(smsTmpByte, readByte);
            smsStep = 112;
          }
        }
        break;
      }
    case 112: { // EID
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          smsIED = getByteFromTwoChar(smsTmpByte, readByte);
          if (smsIED == 1) Serial.println(smsSender);
          smsPrevDecodeByte = 0;
          smsIdxCurrentChar = 6;
          smsStep = 109;
        }
        break;
      }
    default: {}
  }
}

void getDecode7bitChar(byte byte1, byte byte0) {
  byte posIdx = smsIdxCurrentChar % 8;
  byte byteOut;
  if (posIdx > 0) {
    byteOut =  byte0 << posIdx;
    byte b2 = byte1 >> (8 - posIdx);
    byteOut = byteOut | b2;
    byteOut = byteOut & 0x7F;
    if (byte1) Serial.write(byteOut);
    if (posIdx == 6) {
      byteOut =  byte0 >> 1;
      Serial.write(byteOut);
      ++smsIdxCurrentChar;
    }
  } else {
    byteOut = byte0;
    byteOut = byteOut & 0x7F;
    Serial.write(byteOut);
  }
  ++smsIdxCurrentChar;
}

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;
}

2

//--s800str.h--
#include <avr\pgmspace.h>

#define maxSizeATcommandANDresponse 24
#define countATcmdDict 13

const char at0cmdAT[] PROGMEM = "AT\r\n";
const char at1cmdHTTPACTION[] PROGMEM = "AT+HTTPACTION=0\r\n";
const char at1rsp1[] PROGMEM = "+HTTPACTION:";
const char at1rsp2[] PROGMEM = ",";
const char at2cmdSAPBR11[] PROGMEM = "AT+SAPBR=1,1\r\n";
const char at2rsp1[] PROGMEM = "ration not allowed\r\n";
const char at3cmdREADSMS[] PROGMEM = "AT+CMGL=4\r\n"; // "AT+CMGL=\"ALL\"\r\n";
const char at3rsp1[] PROGMEM = "+CMGL:";
const char at4cmdDDET[] PROGMEM = "AT+DDET=1\r\n";
const char at5cmdATE0[] PROGMEM = "ATE0\r\n";
const char at6cmdCLIP1[] PROGMEM = "AT+CLIP=1\r\n";
const char at7cmdATS0[] PROGMEM = "ATS0=0\r\n";
const char at8cmdATV1[] PROGMEM = "ATV1\r\n";
const char at9cmdATCMEE2[] PROGMEM = "AT+CMEE=2\r\n";
const char at10cmdATCMGF1[] PROGMEM = "AT+CMGF=0\r\n";
const char at11cmdATCREG[] PROGMEM = "AT+CREG?\r\n";
const char at11rsp1[] PROGMEM = "+CREG:";
const char at11rsp2[] PROGMEM = ",1";
const char at12cmdDELSMS[] PROGMEM = "AT+CMGDA=6\r\n"; // "AT+CMGDA=\"DEL ALL\"\r\n";

const char rspOK[] PROGMEM = "OK\r\n";
const char rspEndLine[] PROGMEM = "\r\n";

const char * const at_list_cmd[] PROGMEM = { // text command
  at0cmdAT, at1cmdHTTPACTION, at2cmdSAPBR11, at3cmdREADSMS, at4cmdDDET,
  at5cmdATE0, at6cmdCLIP1, at7cmdATS0, at8cmdATV1, at9cmdATCMEE2,
  at10cmdATCMGF1, at11cmdATCREG, at12cmdDELSMS
};

const PROGMEM  uint8_t at_rresp_cmd[] = { // 0-count right response
  1, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1
};

const PROGMEM  uint8_t at_oresp_cmd[] = { // 1-count other response - need manual action by response
  0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

const PROGMEM  uint8_t at_move_cmd[] = { // step after action cmd
  4, 0, 0, 12, 5, 6, 7, 8, 9, 10, 11, 12, 101
};

const char * const at_list_rresp[] PROGMEM = {
  rspOK, // at0
  rspOK, at1rsp1, at1rsp2, rspEndLine, // at1
  rspOK, // at3
  rspOK, // at4
  rspOK, // at5
  rspOK, // at6
  rspOK, // at7
  rspOK, // at8
  rspOK, // at9
  rspOK, // at10
  at11rsp1, at11rsp2, rspOK, // at11
  rspOK, // at12
};

const char * const at_list_oresp[] PROGMEM = {
  rspOK, at2rsp1 // at2
};

void s800getTextCmdByNum(byte numCmd, char* textCmd);
byte s800getCountRrespCmdByNum(byte numCmd);
byte s800getCountOrespCmdByNum(byte numCmd);
void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd);
byte s800getNextStepCmdByNum(byte numCmd);

#define GSM_RX 3 // пин RX на модуле подключаем к указаному пину на Ардуино TX
#define GSM_TX 2 // пин TX на модуле подключаем к указаному пину на Ардуино RX

#define WORK_LEVEL_LED 0      // 1 if HIGH level ON led, else 0
#define WORK_LEVEL_RELAY 0    // 1 if HIGH level ON relay, else 0

#define reset_sim800_pin 4 // pin for reset modem

#define relay1_pin 6 // pin relay 1
#define relay2_pin 5 // pin relay 2
#define relay3_pin 9 // pin relay 3

#define ledRed_pin 7 // pin RED led
#define ledGre_pin 8 // pin GREEN led

#if (WORK_LEVEL_LED == 0)
#define LEDREDON digitalWrite(ledRed_pin,LOW)
#define LEDGREON digitalWrite(ledGre_pin,LOW)
#define LEDREDOFF digitalWrite(ledRed_pin,HIGH)
#define LEDGREOFF digitalWrite(ledGre_pin,HIGH)
#else
#define LEDREDON digitalWrite(ledRed_pin,HIGH)
#define LEDGREON digitalWrite(ledGre_pin,HIGH)
#define LEDREDOFF digitalWrite(ledRed_pin,LOW)
#define LEDGREOFF digitalWrite(ledGre_pin,LOW)
#endif

#if (WORK_LEVEL_RELAY == 0)
#define RELAY1ON digitalWrite(relay1_pin,LOW)
#define RELAY2ON digitalWrite(relay2_pin,LOW)
#define RELAY3ON digitalWrite(relay3_pin,LOW)
#define RELAY1OFF digitalWrite(relay1_pin,HIGH)
#define RELAY2OFF digitalWrite(relay2_pin,HIGH)
#define RELAY3OFF digitalWrite(relay3_pin,HIGH)
#else
#define RELAY1ON digitalWrite(relay1_pin,HIGH)
#define RELAY2ON digitalWrite(relay2_pin,HIGH)
#define RELAY3ON digitalWrite(relay3_pin,HIGH)
#define RELAY1OFF digitalWrite(relay1_pin,LOW)
#define RELAY2OFF digitalWrite(relay2_pin,LOW)
#define RELAY3OFF digitalWrite(relay3_pin,LOW)
#endif

char* LastPos(char *str1, char *str2);
int strPos(char *str11, char *str22);

3

//--s800str.cpp--
#include "Arduino.h"
#include "s800str.h"

void s800getTextCmdByNum(byte numCmd, char* textCmd) {
  const char * addrStroki = pgm_read_word_near((int)(at_list_cmd + numCmd));
  strcpy_P(textCmd, addrStroki);
}

byte s800getCountRrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_rresp_cmd + numCmd);
}

byte s800getCountOrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_oresp_cmd + numCmd);
}

byte s800getNextStepCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_move_cmd + numCmd);
}

void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd) {
  byte startPos = 0;
  if (numCmd > 0) for (byte i = 1; i <= numCmd; ++i) {
      switch (typeResp) {
        case 0: {
            startPos += pgm_read_byte_near(at_rresp_cmd + i - 1);
            break;
          }
        case 1: {
            startPos += pgm_read_byte_near(at_oresp_cmd + i - 1);
            break;
          }
        default : {}
      }
    }
  switch (typeResp) {
    case 0: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_rresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    case 1: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_oresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    default : {}
  }
}

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;
}

 

Скетч использует 6782 байт (22%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 423 байт (20%) динамической памяти, оставляя 1625 байт для локальных переменных. Максимум: 2048 байт.


Power ON or WDT reset
Ready
7920*****46
Short SMS 
7920*****46
Short SMS 
7920*****46
Русская короткая SMS! 
7920*****46
Это пробная СМСка из 2 Х или трех штук, будем пробовать объедение, 
 но не факт конечно что получиться. Но стараться надо. Part SMS on 
English. В середине часть латиницей. 

 

Paruzma
Offline
Зарегистрирован: 27.06.2018

Привет, где расписано мигание светодиода на sim-800l?  У меня мигает -7-9-7-9- раз, питание нормальное.

Oleg_I
Offline
Зарегистрирован: 04.04.2016

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

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Paruzma пишет:

Привет, где расписано мигание светодиода на sim-800l?  У меня мигает -7-9-7-9- раз, питание нормальное.

Не поверишь - в даташите.

Oleg_I
Offline
Зарегистрирован: 04.04.2016

у меня модуль был в бред борде и пока напрямую провода не припаял сеть не мог словить и еще в момент регистрации просадка напряжения была пока от бп и dc-dc step down не запитал

Paruzma
Offline
Зарегистрирован: 27.06.2018

DIYMan пишет:

Не поверишь - в даташите.

не поверю, даташит на 70 листов перечитал, там мигание по соединению только, не по проблеммам

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

У меня часто мигает при установке gprs сессии

slider
Offline
Зарегистрирован: 17.06.2014

попался ликбез про GSM модули и в частности sim800L , особенности питания и  подключения

будет познавательно для тех кто не в теме 

https://youtu.be/6hi-wMx6T9A

 

b707
Offline
Зарегистрирован: 26.05.2017

slider пишет:

попался ликбез про GSM модули и в частности sim800L , особенности питания и  подключения
 

очередной Дима осипов :) Без майки незачет

Керил
Offline
Зарегистрирован: 10.03.2018

Привет всем, делаю автозапуск в машину. SIM800L и NANO корректно работают, но релюшки срабатывают немного не так. Работать должно так - если я звоню на сим, то замыкается реле зажигания, через некоторое время замыкается реле стартера на 2,5 секунды и сразу размыкается. Далее через 10 секунд выключается реле зажигания (через 10 секунд после замыкания) Написал вот код, только работает так - после заливки скетча реле зажигания замыкается(или размыкается) после чего через несколько секунд снова делает это и все стоит. Когда звоню - реле зажигания замыкается, замыкается и отключается через 2с реле стартера, при отключении реле стартера сразу же отключается и реле зажигания. нужна помощь, думаю что то не так в скетче

#include <SoftwareSerial.h>                     // Библиотека програмной реализации обмена по UART-протоколу
SoftwareSerial SIM800(4, 3);                    // RX, TX

String _response = "";                          // Переменная для хранения ответа модуля
unsigned long int timeMillis;  //переменные для подсчета интервала задержки


void setup() {
  Serial.begin(9600);                           // Скорость обмена данными с компьютером
  SIM800.begin(9600);                           // Скорость обмена данными с модемом
  Serial.println("Start!");
  pinMode(5, OUTPUT); // Объявляем пин реле как выход
  digitalWrite(5, HIGH); // Выключаем реле - посылаем высокий сигнал
  pinMode(6, OUTPUT); // Объявляем пин реле как выход
  digitalWrite(6, HIGH); // Выключаем реле - посылаем высокий сигнал
  sendATCommand("AT+IPR=9600", true);                    // Отправили AT для настройки скорости обмена данными

  // Команды настройки модема при каждом запуске
  _response = sendATCommand("AT+CLIP=1", true);  // Включаем АОН
  //_response = sendATCommand("AT+DDET=1", true);  // Включаем DTMF
}

String sendATCommand(String cmd, bool waiting) {
  String _resp = "";                            // Переменная для хранения результата
  Serial.println(cmd);                          // Дублируем команду в монитор порта
  SIM800.println(cmd);                          // Отправляем команду модулю
  if (waiting) {                                // Если необходимо дождаться ответа...
    _resp = waitResponse();                     // ... ждем, когда будет передан ответ
    // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
    if (_resp.startsWith(cmd)) {                // Убираем из ответа дублирующуюся команду
      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
    }
    Serial.println(_resp);                      // Дублируем ответ в монитор порта
  }
  return _resp;                                 // Возвращаем результат. Пусто, если проблема
}

String waitResponse() {                         // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                            // Переменная для хранения результата
  long _timeout = millis() + 10000;             // Переменная для отслеживания таймаута (10 секунд)
  while (!SIM800.available() && millis() < _timeout)  {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
  if (SIM800.available()) {                     // Если есть, что считывать...
    _resp = SIM800.readString();                // ... считываем и запоминаем
  }
  else {                                        // Если пришел таймаут, то...
    Serial.println("Timeout...");               // ... оповещаем об этом и...
  }
  return _resp;                                 // ... возвращаем результат. Пусто, если проблема
}

void loop() {
  if (SIM800.available())   {                   // Если модем, что-то отправил...
    _response = waitResponse();                 // Получаем ответ от модема для анализа
    _response.trim();                           // Убираем лишние пробелы в начале и конце
    Serial.println(_response);                  // Если нужно выводим в монитор порта
    String whiteListPhones = "+79507395422"; // Белый список телефонов
    if (_response.startsWith("RING")) {         // Есть входящий вызов
      int phoneindex = _response.indexOf("+CLIP: \"");// Есть ли информация об определении номера, если да, то phoneindex>-1
      String innerPhone = "";                   // Переменная для хранения определенного номера
      if (phoneindex >= 0) {                    // Если информация была найдена
        phoneindex += 8;                        // Парсим строку и ...
        innerPhone = _response.substring(phoneindex, _response.indexOf("\"", phoneindex)); // ...получаем номер
        Serial.println("Number: " + innerPhone); // Выводим номер в монитор порта
      }
      // Проверяем, чтобы длина номера была больше 6 цифр, и номер должен быть в списке
      if (innerPhone.length() >= 7 && whiteListPhones.indexOf(innerPhone) >= 0) {
         sendATCommand("ATH", true);        // Если да, то -отвечаем на вызов
       digitalWrite(5, LOW); // Включаем реле - посылаем низкий уровень сигнала
       delay(5000);
       digitalWrite(6, LOW); // Включаем реле - посылаем низкий уровень сигнала
       delay(2500);
       digitalWrite(6, HIGH); // Включаем реле - посылаем высокий уровень сигнала
        timeMillis = millis();    //постоянно сохраняем текущее время работы системы
      }
      
      else {
        sendATCommand("ATH", true);        // Если нет, то отклоняем вызов
      }
    }
  }
   if(timeMillis >= 300)  //сверяем текущее время с последним сохраненным
  {
      //если прошло больше 5000 мс
     
        digitalWrite(5, HIGH); // Включаем реле - посылаем низкий уровень сигнала
      }
  if (Serial.available())  {                    // Ожидаем команды по Serial...
    SIM800.write(Serial.read());                // ...и отправляем полученную команду модему
  };
}

 

Думаю, что закралась какая то ошибка в этой части

 

     if (innerPhone.length() >= 7 && whiteListPhones.indexOf(innerPhone) >= 0) {
         sendATCommand("ATH", true);        // Если да, то -отвечаем на вызов
       digitalWrite(5, LOW); // Включаем реле - посылаем низкий уровень сигнала
       delay(5000);
       digitalWrite(6, LOW); // Включаем реле - посылаем низкий уровень сигнала
       delay(2500);
       digitalWrite(6, HIGH); // Выключаем реле - посылаем высокий уровень сигнала
        timeMillis = millis();    //постоянно сохраняем текущее время работы системы
      }
      
      else {
        sendATCommand("ATH", true);        // Если нет, то отклоняем вызов
      }
    }
  }
   if(timeMillis >= 300)  //сверяем текущее время с последним сохраненным
  {
      //если прошло больше 300 мс
     
        digitalWrite(5, HIGH); // Выключаем реле - посылаем высокий уровень сигнала
      }

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Просьба подсказать по аккумуляторному питанию SIM800.

Задумал железку для своих нужд, что бы не городить лишних стабилизаторов, планирую подключить по ниже приведенной схеме. Модем SIM800L подключить напрямую параллельно аккумулятору 18650, фактически на выходе модуля заряда TP4056.

Учитывая что буду использовать голый atmega328p  - его бы аналогично параллельно и модему и аккумулятору запитал.

Насколько жизнеспособно это будет?

kontulavittu
Offline
Зарегистрирован: 06.12.2018

Moй опыт по использованию sim800l :

1. Модули очень капризные по питанию. Для sim800L минимум 3,7 Вольта, чтобы он вообще адекватно мог реагировать на простые AT-команды и нужно максимум 4,2 В для полноценной работы. Но(!), тут ещё 2 параметра вступают в игру: ток и делители по шине данных Rx и Тх. 

2. Очень мнохо бахвальства на тему прямого подключения Rx и Tx -шины напрямую к Ардуино. Не скажу за все модели, но если подключить напрямую к Nano, то гарантированно летит к чертям шина управление gsm-модуля. Если не в течении минуты-часа, то через пару дней стабильно будет пробой, и модуль начинает жить своей жизнью.

3. Сложности начинаются, когда идёт приём звонка или дозвон. Тут сюрпризом великое множество. Можно сутками биться на решением проблемы внезапной перезагрузки модуля при поступлении на симку звонка. И напряжения ОК, и блок питания более 2А, и конденсатор параллельно цепи питания модуля - хоть тресни, если модуль взумал сбрасыватся при входящих - это приговор.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Это вы батенька их готовить не умеете.
Несколько десятков устройств ездит по стране вообще без проблем.
Завтра посторяюсь выложить схему соединения nano и sim800 какую я использую - все отлично работает в любых режимах.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

1 стоит стабилизатор на 2 ампера 4 вольта
2 обычные резисторные делитель - это сложно?
3 фильтры на питание модуля - дроссель и 4 конденсатора согласно даташита

kontulavittu
Offline
Зарегистрирован: 06.12.2018

andycat пишет:
1 стоит стабилизатор на 2 ампера 4 вольта 2 обычные резисторные делитель - это сложно? 3 фильтры на питание модуля - дроссель и 4 конденсатора согласно даташита

1. стабилизатор стоит в DC-DC понижающем , куда уж больше?

2. делитель давно стоит, и не в них дело.

3. вообше непонятно, куда ещё больше стабилизации, мало уже стабилизатора по току, так ещё и дополнительные фильтры?  Это лишь подтверждает, что модули настолько капризны, что как не дунешь - сразу в перезагрузку.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Ну сравните работу с модулями a6, впрочем дело вкуса, у тысяч людей все работает, у вас нет, выводы делайте сами.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
kontulavittu
Offline
Зарегистрирован: 06.12.2018

Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала? 

Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

kontulavittu пишет:

Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала? 

Поставить-то можно, только будет ли от этого лучше?

Установка нескольких параллельных конденсаторов обычно практикуется в цепях питания, при этом все причины, по которым это делается, обычно можно объединить в две большие группы:

- из-за неидеальности конденсаторов,

- из-за неидеальности проводников.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

kontulavittu пишет:

Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала? 

Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.

В даташите на модем нарисованы схемы подключения питания для модема и там же написано почему это сделано, в том числе и для фильтрации высокочастиотных помех.

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

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

andriano пишет:

Поставить-то можно, только будет ли от этого лучше?

будет лучше, проверено на себе.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

andycat пишет:

andriano пишет:

Поставить-то можно, только будет ли от этого лучше?

будет лучше, проверено на себе.

На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

andriano пишет:

andycat пишет:

andriano пишет:

Поставить-то можно, только будет ли от этого лучше?

будет лучше, проверено на себе.

На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?

Нет, я поставил конденсаторы согласно даташита и стало лучше, один большей ёмкости не пробовал, но интернет читал, в институте предметы изучал и сомневаюсь что один большой конденсатор защитит от всех видов помех.
ЗЫ. Никому ничего утверждать не собираюсь, прежде всего я практик а не теоретик.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Так а что именно Вы "проверяли на себе"?

kontulavittu
Offline
Зарегистрирован: 06.12.2018

После внимательного изучения номиналось конденсаторов стало понятно, почему параллельно стоят. Гасители высокочастотных помех.  Раз такое ставят, тогда тем более очевидно, что модуль капризный и на любое малейшее колебание по U ,начинает бесноваться...

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Очередной скетч без практического применения, из серии "дурная голова рукам покоя не дает", вдруг кому пригодиться для SIM800.

Чтение СМС, выполнение команд из СМС, получение температур с нескольких DS18B20, отправка http запроса каждые N минут, при использовании OLED 128*64 и нажатии на кнопку отправляет модем в спячку, на 20 секунд выводит инфу на дисплей и выводит модем в рабочий режим.

#include <avr/wdt.h>
#include <avr\pgmspace.h>
#include "s800str.h"
#include "s800sms.h"

/*12.03.2019 Версия smsdshttp13
  Нет, смысл обработки команд приводит к увеличенному расходу памяти,
  т.е. от чего пытался уйти, к это му же и пришел.
  Учитывая что если команды шлются в коротком тексте - смысла нет менять.*/

/* 11.03.2019 Версия smsdshttp12
  вытянул все что можно из RealTime обработки каждого входящего
  байта из СМС. Обрабатывается хорошо, но как только в длинных СМС
  появляется команда к выполнению - быстродействия уже не хватает.
  Или руки у меня кривые. Учитывая что одновременной отправки и
  приема сообщений быть не может, а буфер отправки sms_buf простаивает,
  решил со следующей версии сделать прием в этот буфер с последующей
  обработкой, соотвественно увеличил max_size_out_sms до 128 байт,
  значит и максимальный размер отправляемой и принимаемой СМС
  максимум 126 символов текста.*/

#define USE_IIC_OLED
#define USE_UART_LOG
#define USE_DS18B20

#define max_size_imei 20
char original_imei_code[max_size_imei];

#ifdef USE_DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
#define pin_ds18b20 A0 // пин подключения термодатчика DS18B20
#define TEMPERATURE_PRECISION 9 // точность получения значения темературы
OneWire oneWire(pin_ds18b20); // объект 1Ware
DallasTemperature sensors(&oneWire); // объект  датчика температуты
byte dsCount; // количество датчиков температуры
#define max_ds_count 3 // максимальное количество датчиков
DeviceAddress massTherm[max_ds_count]; // массив адресов датчиков ds18b20
#define period_get_temp 89968UL // получение температуры каждые 1.5 min
unsigned long timer_get_temp; // таймер получения температуры
word massTemper[max_ds_count]; //массив температур
byte requestTemp = 1; // запрос температуры
#endif

#ifdef USE_IIC_OLED
#include <Wire.h>
#include <OzOLED.h>
#define period_show_info 20000UL // max time show info
unsigned long timer_show_info = 0; // timer show info on oled
#define oled_show_pin 11 // key pin for enable OLED 128*64, active level = 0
#endif

#include <SoftwareSerial.h>
SoftwareSerial gsm(GSM_TX, GSM_RX); // установка контактовGSM_TX->RX и GSM_RX->TX для программного порта

byte modem_step = 100; // current work mode mode in table of command
// static steps:
// 100 - delay 15 sec for registration modem in net
// 101 - not wait response, wait incomming call or other commands
// 102 - show info on display by press key and/or sleep modem
// 103 - get temp from ds 18b20
byte next_modem_command; // next command
unsigned long current_millis; // main timer
#define period_read_sms 120971UL // read sms every ~2 min
unsigned long timer_read_sms = 0; // timer read sms
#define period_send_sms 10971UL // send sms every ~10 sec
unsigned long timer_send_sms = 0; // timer send sms
#define period_fixed_wait 20000UL // max time wait response
unsigned long timer_reg_modem = 0; // timer registration modem in net and timer response
char resp_buf[maxSizeResponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define max_resp_count_on_one_type_cmd 5 // max 5 response text by one command and one type
byte fl_true_Rresp[max_resp_count_on_one_type_cmd];
char text_Rresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte fl_true_Oresp[max_resp_count_on_one_type_cmd];
char text_Oresp[max_resp_count_on_one_type_cmd][maxSizeResponse];
byte startFlag = 1;
byte rresp, oresp;
byte gprsON = 0;
byte gprsAllow = 1; // 1 -> ON Internet GPRS
#define period_http_send 3000000UL // read http page every 50 min
unsigned long timer_http_send = 0; // timer http
extern byte smsStep;
word modemVin = 999;
byte qNet = 99;
#define period_read_vin 150691UL // read vin modem
unsigned long timer_read_vin = 0; // get modem power level
#define max_size_operator_name 10
char operator_name[max_size_operator_name];
#define period_get_qnet 237923UL // get quality net
unsigned long timer_get_qnet = 0; // timer get net
float Vdel = 0.096; // R2/(R1+R2)  0.99кОм / (9.88кОм + 0.99кОм)
byte resetTimeModem = 0; // count time auto reset modem
byte ussdMode;
char ussdChar[4];
byte ussdStep;

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

void setup() {
  MCUSR = 0; wdt_disable();
#if defined(SHOW_SMS) || defined(USE_UART_LOG)
  Serial.begin(115200); Serial.println("Power ON or WDT reset");
#endif
  gsm.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  pinMode(dtr_sim800_pin, OUTPUT); digitalWrite(dtr_sim800_pin, LOW); // normal mode modem
  randomSeed(analogRead(A2)); analogReference(INTERNAL); getVinModem();
  pinMode(ledRed_pin, OUTPUT); pinMode(ledGre_pin, OUTPUT);
  pinMode(relay1_pin, OUTPUT); pinMode(relay2_pin, OUTPUT); pinMode(relay3_pin, OUTPUT);
  LEDREDOFF;  LEDGREOFF; RELAY1OFF; RELAY2OFF; RELAY3OFF;
#ifdef USE_IIC_OLED
  pinMode(oled_show_pin, INPUT); digitalWrite(oled_show_pin, HIGH); // key
  Wire.begin(); OzOled.init();  //initialze OLED display
  OzOled.setNormalDisplay();       //Set display to Normal mode
  OzOled.setHorizontalMode();      //Set addressing mode to Horizontal Mode
  OzOled.setPowerOff();
#endif
  operator_name[0] = 0; smsClearOut(); next_modem_command = 0; ussdMode = 0; original_imei_code[0] = 0;
#ifdef USE_DS18B20
  sensors.begin(); // инициировать датчики температуры
  dsCount = sensors.getDeviceCount(); // получить количество датчиков
#ifdef USE_UART_LOG
  Serial.print("Found DS18B20 = "); Serial.println(dsCount, DEC); // вывести количество
#endif
  if (dsCount > max_ds_count) dsCount = max_ds_count; // если датчиков больше чем максимальное - уменьшаем
  oneWire.reset_search(); // сброс шины поиска датчиков
  byte i = 0; while (i < dsCount) { // цикл по всем датчикам
    if (sensors.getAddress(massTherm[i], i)) { // получение адреса
#ifdef USE_UART_LOG
      printAddress(massTherm[i]); Serial.println();
#endif
      sensors.setResolution(massTherm[i], TEMPERATURE_PRECISION); // настраиваем разрешение
    } ++i; // следующий цикл
  }
#endif
  wdt_enable(WDTO_8S);
}

void loop() {
  wdt_reset();
  //delay(9000); // test WDT
  current_millis = millis();
  if ((next_modem_command > 0) && (modem_step == 101)) {
    switch (next_modem_command) {
      case 1: {
          modem_step = 28; sendATcmd(0, 0); break;
        }
      case 2: {
          smsClearOut();
          smsPrepareText(operator_name); smsPrepareText(' '); smsPrepareText(194); smsPrepareText(' ');
          smsPrepareText(240); smsPrepareText(224); smsPrepareText(225); smsPrepareText(238); smsPrepareText(242);
          smsPrepareText(229); smsPrepareText(' ');
          byte bu = getDaysUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(228); smsPrepareText(237); smsPrepareText('.');
          bu = getHoursUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(247); smsPrepareText('.');
          bu = getMinsUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(236); smsPrepareText('.');
          smsPrepareOut(); break;
        }
      case 3: {
          smsClearOut();
          smsPrepareText((modemVin / 100) + '0'); smsPrepareText('.');
          smsPrepareText((modemVin % 100) / 10 + '0'); smsPrepareText((modemVin % 100) % 10 + '0');
          smsPrepareText('V'); smsPrepareText(' ');
          byte bu = getDaysUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(228); smsPrepareText(237); smsPrepareText('.');
          bu = getHoursUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(247); smsPrepareText('.');
          bu = getMinsUptime();
          if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(236); smsPrepareText('.');
          smsPrepareOut(); break;
        }
      case 4: {
#ifdef USE_DS18B20
          if (dsCount) {
            smsClearOut();
            for (byte i = 0; i < dsCount; ++i) {
              smsPrepareText('t'); smsPrepareText(i + '0'); smsPrepareText('='); word tt = massTemper[i];
              if (tt >= 2000) {
                smsPrepareText('-'); tt -= 2000;
              } word ts = tt / 10;
              if (ts >= 100) {
                smsPrepareText((ts / 100) + '0'); ts = ts % 100;
              }
              if (ts >= 10) {
                smsPrepareText((ts / 10) + '0'); ts = ts % 10;
              }
              smsPrepareText(ts + '0'); smsPrepareText('.');
              smsPrepareText((tt % 10) + '0'); smsPrepareText(' ');
            }
            byte bu = getDaysUptime();
            if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(228); smsPrepareText(237); smsPrepareText('.');
            bu = getHoursUptime();
            if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(247); smsPrepareText('.');
            bu = getMinsUptime();
            if (bu > 9) smsPrepareText((bu / 10) + '0'); smsPrepareText((bu % 10) + '0'); smsPrepareText(236); smsPrepareText('.');
            smsPrepareOut();
          }
#endif
          break;
        }
      default: {}
    } next_modem_command = 0;
  }
#ifdef USE_IIC_OLED
  if ((!digitalRead(oled_show_pin)) && (modem_step == 101)) {
    timer_show_info = current_millis; OzOled.setPowerOn();
    showInfoOled(); sleepModem(); // test for power off modem
    modem_step = 102;
  }
  if (((current_millis - timer_show_info) >= period_show_info) && (modem_step == 102)) {
    OzOled.setPowerOff(); wakeupModem(); // end test for power off modem
    resetAllTimers(); modem_step = 101;
  }
#endif
  if (((current_millis - timer_read_sms) >= period_read_sms) && (modem_step == 101)) {
    timer_read_sms = current_millis; modem_step = 3; sendATcmd(0, 0);
  }
  if (((current_millis - timer_send_sms) >= period_send_sms) && (modem_step == 101) && (doHaveSendSms())) {
    timer_send_sms = current_millis; modem_step = 26; sendATcmd(0, 1);
  }
  if (((current_millis - timer_get_qnet) >= period_get_qnet) && (modem_step == 101)) {
    timer_get_qnet = current_millis; modem_step = 25; sendATcmd(0, 0);
  }
  if (((current_millis - timer_read_vin) >= period_read_vin) && (modem_step == 101)) {
    timer_read_vin = current_millis; getVinModem();
  }
#ifdef USE_DS18B20
  // get temper // каждое N время получаем температуру со всех датчиков
  if (((current_millis - timer_get_temp) >= period_get_temp) && ((modem_step == 101) || (modem_step == 103))) {
    if (requestTemp) {
      modem_step = 103; sensors.requestTemperatures(); requestTemp = 0;
    } else if ((current_millis - timer_get_temp) >= (period_get_temp + 200UL)) { // for 9 bit PRECISION
      timer_get_temp = current_millis; requestTemp = 1;
      byte i = 0; while (i < dsCount) {
        float tct = sensors.getTempC(massTherm[i]);
        if (tct < 0) massTemper[i] = ((-tct) * 10) + 2000; else massTemper[i] = (tct * 10);
#ifdef USE_UART_LOG
        Serial.print("t"); Serial.print(i, DEC); Serial.print(" = "); Serial.println(massTemper[i], DEC);
#endif
        ++i;
      } modem_step = 101;
    }
  }
#endif
  if (((current_millis - timer_http_send) >= period_http_send) && (modem_step == 101) && (gprsAllow)) {
    timer_http_send = current_millis;
    if (gprsON) modem_step = 17; else modem_step = 2; sendATcmd(0, 0);
  }
  if (modem_step == 100) {
    LEDGREOFF;
    if ((current_millis - timer_reg_modem) >= 15000UL) { // wait 15 sec registration modem
      modem_step = 0; sendATcmd(0, 0);
    }
  } else if (modem_step == 101) {
    LEDGREOFF;
    if (startFlag) {
      LEDREDOFF; startFlag = 0;
#ifdef USE_UART_LOG
      Serial.println("Ready");
#endif
      digitalWrite(LED_BUILTIN, HIGH);
    }
    // nothing do
    loadDataFromModem();
  } else if (modem_step < 100) {
    LEDGREON;
    if ((rresp == 0) && (oresp == 0)) { // go to next cmd
      modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd(0, 0);
    } else {
      if ((current_millis - timer_reg_modem) >= period_fixed_wait) {
        if (rresp > 0) {
          resetModem();
        } else if (oresp > 0) { // go to next cmd
          modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd(0, 0);
        }
      } else {
        // main work
        loadDataFromModem();
      }
    }
  }
  /*#ifdef USE_UART_LOG
    unsigned long lms = millis() - current_millis;
    if (lms > 40) {
      Serial.print("F..C! It's very big delay! = "); Serial.println(lms, DEC);
    }
    #endif*/
}

byte doCmdForModem(byte inByte) {
  byte flGood, flResp;
  if (modem_step < 100) {
    if (rresp) {
      flGood = 0; flResp = 0;
      for (byte i = 0; i < rresp; ++i) {
        if (fl_true_Rresp[i] == 0) {
          if (findRespFromBuf(text_Rresp[i])) {
            fl_true_Rresp[i] = 1;
            if ((rresp == 1) || (i == (rresp - 1))) flGood = 1; flResp = 1;
          } break;
        }
      }
      if (flGood) {
        // manual processing response for good cmd
        switch (modem_step) {
          case 28: { // end ussd -> send SMS
              if (ussdMode == 101) {
                ussdMode = 0; smsPrepareOut();
              } break;
            }
          default: {}
        }
        // go to next cmd
        modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd(0, 0); return 1;
      }
      if (flResp) {
        clearRespBuf(); return 1;
      }
    } else if (oresp) {
      for (byte i = 0; i < oresp; ++i) {
        if (findRespFromBuf(text_Oresp[i])) {
          fl_true_Oresp[i] = 1;
          // part of response
          switch (modem_step) {
            case 2: { // gprs ON
                gprsON = 1;
                // go to next cmd
                modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd(0, 0); return 1;
              }
            case 3: { // read sms
                // go to next cmd
                modem_step = s800getNextStepCmdByNum(modem_step); if (modem_step < 100) sendATcmd(0, 0); return 1;
              }
            default: {
                clearRespBuf(); return 1;
              }
          }
        }
      }
    }
    // manual processing response
    switch (modem_step) {
      case 29: { // imei
          if ((inByte >= '0') and (inByte <= '9')) {
            byte bl = strlen(original_imei_code);
            if (bl < (max_size_imei - 1)) {
              original_imei_code[bl] = inByte;
            }
          } break;
        }
      case 25: { // qnet
          if (inByte == '+') {
            ussdStep = 1; qNet = 0;
          } else if ((ussdStep == 1) && (inByte == ' ')) {
            ussdStep = 2;
          } else if (ussdStep == 2) {
            if (inByte == ',') {
              ussdStep = 3;
            } else {
              if ((inByte >= '0') and (inByte <= '9')) {
                if (qNet) {
                  qNet = qNet * 10; qNet = qNet + (inByte - 0x30);
                } else {
                  qNet = inByte - 0x30;
                }
              }
            }
          } break;
        }
      case 24: { // operator name
          if (inByte == '+') {
            ussdStep = 1; operator_name[0] = 0;
          } else if ((ussdStep == 1) && (inByte == '"')) {
            ussdStep = 2;
          } else if (ussdStep == 2) {
            if (inByte == '"') {
              ussdStep = 3;
            } else {
              byte sl = strlen(operator_name);
              if (sl < (max_size_operator_name - 1)) {
                operator_name[sl] = inByte; operator_name[sl + 1] = 0;
              }
            }
          } break;
        }
      case 28: { // read ussd balance Megafon and send sms
          if (ussdMode < 100) {
            if (findRespFromBuf("CUSD")) ussdMode = 100;
          } else if ((ussdMode == 100) && (inByte == '"')) {
            ussdMode = 101; ussdStep = 0; smsClearOut();
          } else if ((ussdMode == 101) && (((inByte >= '0') && (inByte <= '9')) || ((inByte >= 'A') && (inByte <= 'F')))) {
            switch (ussdStep) {
              case 0: {
                  ussdChar[ussdStep] = inByte; ++ussdStep; break;
                }
              case 1: {
                  ussdChar[ussdStep] = inByte; ++ussdStep; break;
                }
              case 2: {
                  ussdChar[ussdStep] = inByte; ++ussdStep; break;
                }
              default: {
                  ussdChar[ussdStep] = inByte; ussdStep = 0;
                  byte tb = getByteFromTwoChar(ussdChar[2], ussdChar[3]);
                  if ((ussdChar[1] == '0') && (tb >= 0x20) && (tb < 0x7F)) {
                    // ascii
                    smsPrepareText(tb); return 1;
                  } else if ((ussdChar[1] == '4') && (tb >= 0x10) && (tb <= 0x4F)) {
                    // rus win1251
                    tb += 0xB0; smsPrepareText(tb); return 1;
                  } else {
                    smsPrepareText(' '); return 1;
                  }
                }
            }
          } break;
        }
      case 3: { // read sms
          if (smsStep >= 99) {
            doSMSbody(inByte);
          } else if (smsStep == 1) {
            if (findRespFromBuf("\r\n")) {
              doSMShead(); clearRespBuf(); return 1;
            }
          } else {
            if (findRespFromBuf("+CMGL:")) {
              smsStep = 1; clearRespBuf(); return 1;
            }
          } break;
        }
      default: {}
    }
  } else { // mode 101
    // find ring or other cmd
  }
  return 0;
}

byte findRespFromBuf(char* textResp) {
  if (resp_buf[pos_buf] > 0) {
    byte idxBuf;
    if (pos_buf == 0) idxBuf = maxSizeResponse - 1; else idxBuf = pos_buf - 1;
    byte lenResp = strlen(textResp); byte idxResp = lenResp - 1; byte cntResp = 0;
    for (byte i = 0; i < maxSizeResponse; ++i) {
      if (resp_buf[idxBuf] == 0) break;
      if (resp_buf[idxBuf] == textResp[idxResp]) {
        --idxResp;
        if ((++cntResp) == lenResp) return 1;
      } else {
        cntResp = 0; idxResp = lenResp - 1;
      }
      if ((--idxBuf) == 0) idxBuf = maxSizeResponse - 1;
    }
  } else if (pos_buf > 0) {
    if (strPos(resp_buf, textResp) >= 0) return 1;
  }
  return 0;
}

void sendATcmd(byte addBefor, byte addAfter) {
  char cmdAT[maxSizeATcommand]; s800getTextCmdByNum(modem_step, cmdAT);
  switch (addBefor) {
    case 1: break;
    default: {}
  }
  switch (modem_step) { // manual processing AT cmd
    case 27: { // send body sms
        byte tb;
        while ((tb = smsOutPackedByte()) > 0) if (tb < 0xFF) {
            gsm.write(tb);
#ifdef USE_UART_LOG
            Serial.write(tb);
#endif
          }
        gsm.write(26);
#ifdef USE_UART_LOG
        Serial.println("");
#endif
        smsClearOut(); break;
      }
    default: {
        gsm.print(cmdAT);
#ifdef USE_UART_LOG
        Serial.print(cmdAT);
#endif
      }
  }
  timer_reg_modem = current_millis;
  switch (addAfter) {
    case 1: { // send size sms packet
        byte bdl = smsGetSizePDU();
        if (bdl > 99) {
          byte bhs = (bdl / 100) + '0';
          gsm.write(bhs);
#ifdef USE_UART_LOG
          Serial.write(bhs);
#endif
          bhs = (bdl % 100) / 10 + '0';
          gsm.write(bhs);
#ifdef USE_UART_LOG
          Serial.write(bhs);
#endif
          bhs = (bdl % 100) % 10 + '0';
          gsm.write(bhs);
#ifdef USE_UART_LOG
          Serial.write(bhs);
#endif
        } else {
          byte bhs = (bdl / 10) + '0';
          gsm.write(bhs);
#ifdef USE_UART_LOG
          Serial.write(bhs);
#endif
          bhs = (bdl % 10) + '0';
          gsm.write(bhs);
#ifdef USE_UART_LOG
          Serial.write(bhs);
#endif
        }
        gsm.print("\r\n");
#ifdef USE_UART_LOG
        Serial.print("\r\n");
#endif
        break;
      }
    default: { }
  }
  rresp = s800getCountRrespCmdByNum(modem_step); oresp = s800getCountOrespCmdByNum(modem_step);
  for (byte i = 0; i < max_resp_count_on_one_type_cmd; ++i) {
    fl_true_Rresp[i] = 0; fl_true_Oresp[i] = 0; // max 5 response text by one command and one type
  }
  if (rresp) {
    for (byte i = 0; i < rresp; ++i) {
      s800getRespByNum(0, modem_step, i, text_Rresp[i]);
    }
  }
  if (oresp) {
    for (byte i = 0; i < oresp; ++i) {
      s800getRespByNum(1, modem_step, i, text_Oresp[i]);
    }
  }
  clearRespBuf(); cmdClearBuf();
}

void clearRespBuf() {
  memset(resp_buf, 0, maxSizeResponse); pos_buf = 0;
}

void loadDataFromModem() {
  if (gsm.available()) {
    while (gsm.available()) {
      byte readByte = gsm.read();
      if (readByte > 0) {
#ifdef USE_UART_LOG
        if ((modem_step != 3) && (modem_step != 28) && (modem_step != 21)) Serial.write(readByte);
#endif
        resp_buf[pos_buf] = readByte; ++pos_buf;
        if (pos_buf >= maxSizeResponse) pos_buf = 0;
        wdt_reset();
        if (doCmdForModem(readByte) == 1) break;
      }
    }
  }
}

void resetModem() {
  LEDREDON; ++resetTimeModem;
  // reset modem
  pinMode(reset_sim800_pin, OUTPUT); digitalWrite(reset_sim800_pin, LOW); delay(115);
  pinMode(reset_sim800_pin, INPUT); digitalWrite(reset_sim800_pin, LOW);
  // new init modem and start new main loop
  timer_reg_modem = current_millis;
  modem_step = 100; startFlag = 1; gprsON = 0; operator_name[0] = 0;
  modemVin = 999; qNet = 99; smsClearOut(); next_modem_command = 0;
}

void sleepModem() {
  digitalWrite(dtr_sim800_pin, HIGH); modem_step = 102;
}

void wakeupModem() {
  digitalWrite(dtr_sim800_pin, LOW); resetAllTimers();
  delay(115); modem_step = 101; ussdMode = 0;
}

void getVinModem() {
  float Vbat = (analogRead(power_level_pin) * 1.1) / 1023;
  float Vin = Vbat / Vdel; modemVin = Vin * 100;
}

void resetAllTimers() {
#ifdef USE_IIC_OLED
  timer_show_info = current_millis;
#endif
  timer_read_sms = current_millis; timer_reg_modem = current_millis;
  timer_http_send = current_millis; timer_read_vin = current_millis;
  timer_get_qnet = current_millis;
#ifdef USE_DS18B20
  timer_get_temp = current_millis; requestTemp = 1;
#endif
}

#ifdef USE_IIC_OLED
void showInfoOled() {
  OzOled.clearDisplay(); //clear the screen and set start position to top left corner
  OzOled.printString(operator_name); OzOled.printString(" ");
  OzOled.printNumber((long)qNet);
  OzOled.setCursorXY(0, 1); OzOled.printString("Power: ");
  OzOled.printNumber((long)(modemVin / 100)); OzOled.printString(",");
  OzOled.printNumber((long)(modemVin % 100));
  OzOled.setCursorXY(0, 2); OzOled.printString("UT: ");
  byte days = current_millis / 86400000UL;
  if (days < 10) {
    OzOled.printNumber((long)days);
  } else {
    OzOled.printNumber((long)(days / 10)); OzOled.printNumber((long)(days % 10));
  }
  OzOled.printString("d"); days = (current_millis % 86400000UL) / 3600000UL;
  if (days < 10) {
    OzOled.printNumber((long)days);
  } else {
    OzOled.printNumber((long)(days / 10)); OzOled.printNumber((long)(days % 10));
  }
  OzOled.printString("h"); days = ((current_millis % 86400000UL) % 3600000UL) / 60000UL;
  if (days < 10) {
    OzOled.printNumber((long)days);
  } else {
    OzOled.printNumber((long)(days / 10)); OzOled.printNumber((long)(days % 10));
  }
  OzOled.printString("m");
  OzOled.setCursorXY(0, 3); OzOled.printString("Reset: ");
  OzOled.printNumber((long)resetTimeModem);
#ifdef USE_DS18B20
  if (dsCount) {
    OzOled.setCursorXY(0, 4);
    for (byte i = 0; i < dsCount; ++i) {
      OzOled.printString("t"); OzOled.printNumber((long)i);
      OzOled.printString("="); word tt = massTemper[i];
      if (tt >= 2000) {
        OzOled.printString("-"); tt -= 2000;
      }
      word ts = tt / 10; OzOled.printNumber((long)ts);
      OzOled.printString("."); ts = tt % 10;
      OzOled.printNumber((long)ts); OzOled.printString(" ");
    }
  }
#endif
}
#endif

void execExtCmd(byte numCmd) {
  if (!foundSenderPhoneFromList()) return;
  switch (numCmd) {
    case 0: {
        next_modem_command = 2; break;
      }
    case 1: {
        next_modem_command = 3; break;
      }
    case 2: { // get balance megafon
        next_modem_command = 1; break;
      }
    case 3: { // get temp DS18B20
        next_modem_command = 4; break;
      }
    default: {}
  }
}

byte getDaysUptime() {
  return (current_millis / 86400000UL);
}

byte getHoursUptime() {
  return ((current_millis % 86400000UL) / 3600000UL);
}

byte getMinsUptime() {
  return (((current_millis % 86400000UL) % 3600000UL) / 60000UL);
}

#ifdef USE_DS18B20
// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++) {
    // zero pad the address if necessary
#ifdef USE_UART_LOG
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
#endif
  }
}
#endif




//--s800sms.h--

#define SHOW_SMS

#define max_size_sms_sender 12 // 11 + stopbyte;
#define max_size_cmd 16 // maximum size external command
#define max_size_out_sms 64 // maximum size out SMS by WIN1251 chars

void getDecode7bitChar(byte byte1, byte byte0);
byte getByteFromTwoChar(byte byte1, byte byte0);
void doSMSbody(byte readByte);
void doSMShead();
void cmdClearBuf();
byte findCmdInBuf(byte inByte);
byte findCmdFromBuf(char* textCmd);
void smsClearOut();
void smsPrepareSender(char* textSender);
void smsPrepareText(char* textText);
void smsPrepareText(byte inByte);
void smsPrepareOut();
byte smsOutPackedByte();
byte smsGetSizePDU();
byte doHaveSendSms();
byte foundSenderPhoneFromList();



//--s800sms.cpp--
#include "Arduino.h"
#include "s800str.h"
#include "s800sms.h"

#define count_ext_cmd 4
char* ext_cmd_list[] = {"getuptime", "getpower", "getbalmegafon", "getdsdata"};

#define count_staf_phone 3
char* staf_phone_list[] = {"7**********" /*admin phone*/, "7**********", "7**********"};

extern void execExtCmd(byte numCmd);
extern byte pos_buf;
extern char resp_buf[maxSizeResponse];
byte pos_cmd;
char cmd_buf[max_size_cmd];

char sms_buf[max_size_out_sms];
byte sms_out_size_packet;
byte sms_out_pos_sender;
byte sms_out_pos_string;
byte sms_out_pos_other;
byte sms_out_pos_mode;
byte smsLenSender;
byte smsLenString;
byte smsUDL;

byte smsStep = 0;
//99 start new sms
byte smsOriginalSize;
byte smsOriginalPosByte;
byte smsTmpByte;
byte smsSizePhone;
byte smsBodyPosByte;
byte smsTPMTICO;
byte smsTPUDHI;
char smsSender[max_size_sms_sender];
byte smsTPOA;
byte smsTmpSize;
byte smsTPDCS;
byte smsPrevDecodeByte;
byte smsIdxCurrentChar;
byte smsUDHL;
byte smsIEDL;
byte smsIED;

byte foundSenderPhoneFromList() { // 0 - no match 1 - exist 2 - admin phone
  for (byte i = 0; i < count_staf_phone; ++i) {
    if (strPos(smsSender, staf_phone_list[i])) {
      if (!i) return 1; else return 2;
    }
  }
  return 0;
}

void cmdClearBuf() {
  memset(cmd_buf, 0, max_size_cmd); pos_cmd = 0;
}

byte findCmdInBuf(byte inByte) {
  cmd_buf[pos_cmd] = inByte; ++pos_cmd;
  if (pos_cmd >= (max_size_cmd - 1)) pos_cmd = 0;
  for (byte i = 0; i < count_ext_cmd; ++i) {
    if (findCmdFromBuf(ext_cmd_list[i])) {
      cmdClearBuf(); return (i + 1);
    }
  } return 0;
}

byte findCmdFromBuf(char* textCmd) {
  if (cmd_buf[pos_cmd] > 0) {
    byte idxBuf;
    if (pos_cmd == 0) idxBuf = max_size_cmd - 1; else idxBuf = pos_cmd - 1;
    byte lenResp = strlen(textCmd); byte idxResp = lenResp - 1; byte cntResp = 0;
    for (byte i = 0; i < max_size_cmd; ++i) {
      if (cmd_buf[idxBuf] == 0) break;
      if (cmd_buf[idxBuf] == textCmd[idxResp]) {
        --idxResp;
        if ((++cntResp) == lenResp) return 1;
      } else {
        cntResp = 0; idxResp = lenResp - 1;
      }
      if ((--idxBuf) == 0) idxBuf = max_size_cmd - 1;
    }
  } else if (pos_cmd > 0) {
    if (strPos(cmd_buf, textCmd) >= 0) return 1;
  } return 0;
}

void getDecode7bitChar(byte byte1, byte byte0) {
  byte posIdx = smsIdxCurrentChar % 8;
  byte byteOut;
  if (posIdx > 0) {
    byteOut =  byte0 << posIdx;
    byte b2 = byte1 >> (8 - posIdx);
    byteOut = byteOut | b2;
    byteOut = byteOut & 0x7F;
    if (byte1) {
#ifdef SHOW_SMS
      Serial.write(byteOut);
#endif
      // find external command
      byte bc = findCmdInBuf(byteOut);
      if (bc) execExtCmd(bc - 1);
    }
    if (posIdx == 6) {
      byteOut =  byte0 >> 1;
#ifdef SHOW_SMS
      Serial.write(byteOut);
#endif
      // find external command
      byte bc = findCmdInBuf(byteOut);
      if (bc) execExtCmd(bc - 1);
      ++smsIdxCurrentChar;
    }
  } else {
    byteOut = byte0; byteOut = byteOut & 0x7F;
#ifdef SHOW_SMS
    Serial.write(byteOut);
#endif
    // find external command
    byte bc = findCmdInBuf(byteOut);
    if (bc) execExtCmd(bc - 1);
  } ++smsIdxCurrentChar;
}

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 doSMShead() {
  // get length body sms
  byte posSbyte = 0; byte posBbyte = (pos_buf - 3);
  while ((resp_buf[posBbyte] >= 0x30) && (resp_buf[posBbyte] <= 0x39)) {
    if (posSbyte == 0) smsOriginalSize = (resp_buf[posBbyte] - 0x30);
    else if (posSbyte == 1) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 10;
    else if (posSbyte == 2) smsOriginalSize = smsOriginalSize + (resp_buf[posBbyte] - 0x30) * 100;
    ++posSbyte; --posBbyte;
  }
  smsOriginalPosByte = 0; smsStep = 99;
}

void doSMSbody(byte readByte) {
  // get byte from buf
  ++smsOriginalPosByte;
  switch (smsStep) {
    case 99: { // get size sms centr
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte); smsStep = 100;
        } break;
      }
    case 100: { // skip num sms centr
        if (!bitRead(smsOriginalPosByte, 0)) {
          if ((--smsSizePhone) == 0) {
            smsStep = 101; smsBodyPosByte = 0;
          }
        } break;
      }
    case 101: { // get TP-MTI & Co
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsTPMTICO = getByteFromTwoChar(smsTmpByte, readByte); ++smsBodyPosByte;
          // analize TP-MTI & Co
          smsTPUDHI = bitRead(smsTPMTICO, 6);
          if ((bitRead(smsTPMTICO, 0) == 0) && (bitRead(smsTPMTICO, 1) == 0)) smsStep = 102; else smsStep = 0;
        } break;
      }
    case 102: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsSizePhone = getByteFromTwoChar(smsTmpByte, readByte);
          if (bitRead(smsSizePhone, 0)) smsTmpSize = smsSizePhone + 1; else smsTmpSize = smsSizePhone;
          ++smsBodyPosByte; smsStep = 103;
        } break;
      }
    case 103: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          smsTPOA = getByteFromTwoChar(smsTmpByte, readByte);
          ++smsBodyPosByte; smsSender[0] = 0; smsStep = 104;
        } break;
      }
    case 104: { // get TP-OA - sender
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // processing sender
          byte ts;
          if (bitRead(smsSizePhone, 0)) ts = smsSizePhone + 1; else ts = smsSizePhone;
          byte tp = ts - smsTmpSize;
          if ((bitRead(smsTPOA, 6) == 1) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) &&
              (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 0)) {
            // char sender
            // ignore sms
            smsStep = 0; break;
          } else if ((bitRead(smsTPOA, 6) == 0) && (bitRead(smsTPOA, 5) == 0) && (bitRead(smsTPOA, 4) == 1) &&
                     (bitRead(smsTPOA, 3) == 0) && (bitRead(smsTPOA, 2) == 0) && (bitRead(smsTPOA, 1) == 0) && (bitRead(smsTPOA, 0) == 1)) {
            // number phone
            if (tp < max_size_sms_sender) smsSender[tp] = readByte;
            ++tp;
            if (tp < max_size_sms_sender) smsSender[tp] = smsTmpByte;
            if ((ts > smsSizePhone) && (smsTmpSize <= 2)) {
              if (tp < max_size_sms_sender) smsSender[tp] = 0;
            } else {
              if ((tp + 1) < max_size_sms_sender) smsSender[tp + 1] = 0;
            }
          } else {
            smsStep = 0; break;
          }
          // ---
          if ((smsTmpSize -= 2) == 0) smsStep = 105;
        } break;
      }
    case 105: { // TP-PID
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte; smsStep = 106;
        } break;
      }
    case 106: { // TP-DCS
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte; smsTPDCS = getByteFromTwoChar(smsTmpByte, readByte);
          smsStep = 107; smsTmpSize = 7;
        } break;
      }
    case 107: { // TP-SCTS - skip 7 byte
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte; if ((--smsTmpSize) == 0) smsStep = 108;
        } break;
      }
    case 108: { // TP-UDL
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte; smsTmpSize = getByteFromTwoChar(smsTmpByte, readByte);
          if (smsTPUDHI == 0) {
#ifdef SHOW_SMS
            Serial.println(smsSender);
#endif
            smsPrevDecodeByte = 0; smsIdxCurrentChar = 0; smsStep = 109;
          } else {
            // long sms
            smsStep = 110;
          }
        } break;
      }
    case 109: { // body sms
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          byte tb = getByteFromTwoChar(smsTmpByte, readByte);
          if (smsTPDCS == 0) {
            // decode 7 bit
            getDecode7bitChar(smsPrevDecodeByte, tb);
            smsPrevDecodeByte = tb;
          } else {
            // decode UCS2
            if ((smsPrevDecodeByte == 0x04) && (tb >= 0x10) && (tb <= 0x4F)) {
              // rus unicode
#ifdef SHOW_SMS
              if (tb >= 0x40) {
                Serial.write(0xD1); Serial.write(0x40 + tb);
              } else {
                Serial.write(0xD0); Serial.write(0x80 + tb);
              }
#endif
            } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x01)) {
#ifdef SHOW_SMS
              Serial.write(0xD0); Serial.write(0x01);
#endif
            } else if ((smsPrevDecodeByte == 0x04) && (tb == 0x51)) {
#ifdef SHOW_SMS
              Serial.write(0xD1); Serial.write(0x91);
#endif
            } else if ((smsPrevDecodeByte == 0x00) && (tb >= 0x20) && (tb < 0x7F)) {
              // ascii
#ifdef SHOW_SMS
              Serial.write(tb);
#endif
              // find external command
              byte bc = findCmdInBuf(tb); if (bc) execExtCmd(bc - 1);
            } smsPrevDecodeByte = tb;
          }
          if ((++smsBodyPosByte) >= smsOriginalSize) {
            // end sms
            smsStep = 0;
#ifdef SHOW_SMS
            if (smsTPUDHI == 0) {
              Serial.write('\r'); Serial.write('\n');
            } else if (smsIED = smsIEDL) {
              Serial.write('\r'); Serial.write('\n');
            }
#endif
          }
        } break;
      }
    case 110: { // TP-UDH
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          smsUDHL = getByteFromTwoChar(smsTmpByte, readByte) - 1; smsStep = 111;
        } break;
      }
    case 111: { // EIDL
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          if ((--smsUDHL) == 0) {
            smsIEDL = getByteFromTwoChar(smsTmpByte, readByte); smsStep = 112;
          }
        } break;
      }
    case 112: { // EID
        if (bitRead(smsOriginalPosByte, 0)) {
          smsTmpByte = readByte;
        } else {
          ++smsBodyPosByte;
          // get num and count sms and show sender
          smsIED = getByteFromTwoChar(smsTmpByte, readByte);
#ifdef SHOW_SMS
          if (smsIED == 1) Serial.println(smsSender);
#endif
          smsPrevDecodeByte = 0; smsIdxCurrentChar = 6; smsStep = 109;
        } break;
      }
    default: {}
  }
}

void smsClearOut() {
  sms_buf[0] = 0; sms_out_size_packet = 0;
}

void smsPrepareSender(char* textSender) {
  strcpy(smsSender, textSender);
}

void smsPrepareText(char* textText) {
  if ((strlen(sms_buf) + strlen(textText)) < (max_size_out_sms - 1)) strcat(sms_buf, textText);
}

void smsPrepareText(byte inByte) {
  byte st = strlen(sms_buf);
  if (st < (max_size_out_sms - 1)) {
    sms_buf[st] = inByte; sms_buf[st + 1] = 0;
  }
}

void smsPrepareOut() {
  sms_out_pos_sender = 0; sms_out_pos_string = 0;
  sms_out_pos_other = 0; sms_out_pos_mode = 0;
  // calculate size all fields SMS by PDU format
  sms_out_size_packet = 3; // SCA + PDU Type + MR
  smsLenSender = strlen(smsSender);
  byte lenSender = smsLenSender;
  if (bitRead(lenSender, 0)) ++lenSender;
  sms_out_size_packet += 2; // lenght + format sender
  sms_out_size_packet += (lenSender / 2); // sender
  sms_out_size_packet += 3; // PID + DCS + VP(null) +UDL
  smsLenString = strlen(sms_buf); smsUDL = (smsLenString * 2);
  sms_out_size_packet += smsUDL; // UD
  --sms_out_size_packet; // -SCA
}

byte smsOutPackedByte() {
  switch (sms_out_pos_mode) {
    case 0: { // SCA
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return '0';
        } else {
          ++sms_out_pos_other; return '0';
        } break;
      }
    case 1: { // PDU Type
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return '1';
        } else {
          ++sms_out_pos_other; return '0';
        } break;
      }
    case 2: { // MR
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return '0';
        } else {
          ++sms_out_pos_other; return '0';
        } break;
      }
    case 3: { // DA
        if (sms_out_pos_other < 2) { // lenght sender
          // lenth to HEX
          if (sms_out_pos_other) {
            ++sms_out_pos_other; byte tb = (smsLenSender % 16);
            if (tb > 9) return (tb + 0x37); else return (tb + '0');
          } else {
            ++sms_out_pos_other; return ((smsLenSender / 16) + '0');
          }
        } else if (sms_out_pos_other < 4) { // format sender = 91
          if (sms_out_pos_other == 2) {
            ++sms_out_pos_other; return '9';
          } else {
            ++sms_out_pos_other; return '1';
          }
        } else { // sender
          if (sms_out_pos_sender < smsLenSender) {
            ++sms_out_pos_other; ++sms_out_pos_sender;
            if (bitRead(sms_out_pos_sender, 0)) {
              if ((sms_out_pos_sender >= smsLenSender) && (bitRead(smsLenSender, 0)))
                return ('F'); else
                return (smsSender[sms_out_pos_sender]);
            }  else  {
              return (smsSender[sms_out_pos_sender - 2]);
            }
          } else {
            sms_out_pos_other = 0; ++sms_out_pos_mode;
            if (bitRead(smsLenSender, 0))
              return (smsSender[smsLenSender - 1]);
            else return 0xFF;
          }
        } break;
      }
    case 4: { // PID
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return '0';
        } else {
          ++sms_out_pos_other; return '0';
        } break;
      }
    case 5: { // DCS
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return '8';
        } else {
          ++sms_out_pos_other; return '0';
        } break;
      }
    case 6: { // UDL
        if (sms_out_pos_other) {
          ++sms_out_pos_mode; sms_out_pos_other = 0; byte uh = smsUDL % 16;
          if (uh > 9) return (uh + 0x37); else return (uh + '0');
        } else {
          ++sms_out_pos_other; byte uh = smsUDL / 16;
          if (uh > 9) return (uh + 0x37); else return (uh + '0');
        } break;
      }
    case 7: { // UD
        if (sms_out_pos_string < smsLenString) {
          byte outChar = sms_buf[sms_out_pos_string]; byte bpos = (sms_out_pos_other % 4);
          switch (bpos) {
            case 0: {
                ++sms_out_pos_other; return '0';
              }
            case 1: {
                ++sms_out_pos_other; if (outChar < 0x7F) return '0'; else return '4';
              }
            case 2: {
                ++sms_out_pos_other;
                if (outChar < 0x7F) {
                  // ascii
                  outChar = (outChar / 16);
                  if (outChar > 9) return (outChar + 0x37); else return (outChar + '0');
                } else {
                  // win1251
                  switch (outChar) {
                    case 168: return '0';
                    case 184: return '5';
                    default: {
                        outChar -= 0xB0; outChar = (outChar / 16);
                        if (outChar > 9) return (outChar + 0x37); else return (outChar + '0');
                      }
                  }
                } break;
              }
            case 3: {
                ++sms_out_pos_other; ++sms_out_pos_string;
                if (outChar < 0x7F) {
                  // ascii
                  outChar = (outChar % 16);
                  if (outChar > 9) return (outChar + 0x37); else return (outChar + '0');
                } else {
                  // win1251
                  switch (outChar) {
                    case 168: return '1';
                    case 184: return '1';
                    default: {
                        outChar -= 0xB0;
                        outChar = (outChar % 16);
                        if (outChar > 9) return (outChar + 0x37); else return (outChar + '0');
                      }
                  }
                } break;
              }
            default: {}
          }
        } else {
          ++sms_out_pos_mode; sms_out_pos_other = 0; return 0; // 0xFF for next step
        } break;
      }
    default: {
        return 0;
      };
  }
}

byte smsGetSizePDU() {
  return sms_out_size_packet;
}

byte doHaveSendSms() {
  if ((sms_buf[0] > 0) && (sms_out_size_packet) && (smsSender[0] > 0)) return 1; else return 0;
}



//--s800str.h--
#include <avr\pgmspace.h>

#define maxSizeATcommand 40
#define maxSizeResponse 24

const char at0cmdAT[] PROGMEM = "AT\r\n";
const char at1cmdHTTPACTION[] PROGMEM = "AT+HTTPACTION=0\r\n";
const char at1rsp1[] PROGMEM = "+HTTPACTION:";
const char at1rsp2[] PROGMEM = ",";
const char at2cmdSAPBR11[] PROGMEM = "AT+SAPBR=1,1\r\n";
const char at2rsp1[] PROGMEM = "allowed";
const char at3cmdREADSMS[] PROGMEM = "AT+CMGL=4\r\n"; // "AT+CMGL=\"ALL\"\r\n";
const char at4cmdDDET[] PROGMEM = "AT+DDET=1\r\n";
const char at5cmdATE0[] PROGMEM = "ATE0\r\n";
const char at6cmdCLIP1[] PROGMEM = "AT+CLIP=1\r\n";
const char at7cmdATS0[] PROGMEM = "ATS0=0\r\n";
const char at8cmdATV1[] PROGMEM = "ATV1\r\n";
const char at9cmdATCMEE2[] PROGMEM = "AT+CMEE=2\r\n";
const char at10cmdATCMGF1[] PROGMEM = "AT+CMGF=0\r\n";
const char at11cmdATCREG[] PROGMEM = "AT+CREG?\r\n";
const char at11rsp1[] PROGMEM = "+CREG:";
const char at11rsp2[] PROGMEM = ",1\r\n";
const char at12cmdDELSMS[] PROGMEM = "AT+CMGDA=6\r\n"; // "AT+CMGDA=\"DEL ALL\"\r\n";
const char at13cmdSAPBR311[] PROGMEM = "AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n";
const char at14cmdSAPBR312[] PROGMEM = "AT+SAPBR=3,1,\"APN\",\"internet\"\r\n";
const char at15cmdSAPBR313[] PROGMEM = "AT+SAPBR=3,1,\"USER\",\"\"\r\n";
const char at16cmdSAPBR314[] PROGMEM = "AT+SAPBR=3,1,\"PWD\",\"\"\r\n";
const char at17cmdSAPBR21[] PROGMEM = "AT+SAPBR=2,1\r\n";
const char at17rsp1[] PROGMEM = "+SAPBR:";
const char at17rsp2[] PROGMEM = ",1,\"";
const char at18cmdHTTPINIT[] PROGMEM = "AT+HTTPINIT\r\n";
const char at19cmdHTTPCID[] PROGMEM = "AT+HTTPPARA=\"CID\",1\r\n";
const char at20cmdHTTPURL[] PROGMEM = "AT+HTTPPARA=\"URL\",\"www.ya.ru\"\r\n";
const char at21cmdHTTPREAD[] PROGMEM = "AT+HTTPREAD\r\n";
const char at22cmdHTTPTERM[] PROGMEM = "AT+HTTPTERM\r\n";
const char at23cmdCSCLK1[] PROGMEM = "AT+CSCLK=1\r\n"; // =1 if use DTR pin modem
const char at24cmdGETOPS[] PROGMEM = "AT+COPS?\r\n"; // get operator
const char at24rsp1[] PROGMEM = "+COPS:";
const char at24rsp2[] PROGMEM = "\"\r\n";
const char at25cmdCSQ[] PROGMEM = "AT+CSQ\r\n"; // get net
const char at26cmdCMGS[] PROGMEM = "AT+CMGS="; // begin send sms
const char at26rsp1[] PROGMEM = ">"; // begin send sms
const char at27cmdCMGS[] PROGMEM = "none"; // text sms
const char at27rsp1[] PROGMEM = "+CMGS:"; // text sms
const char at28cmdBALMEG[] PROGMEM = "AT+CUSD=1,\"*100#\"\r\n"; // get balance megafon
const char at28rsp1[] PROGMEM = "+CUSD:";
const char at28rsp2[] PROGMEM = ", 72\r\n";
const char at29cmdIMEI[] PROGMEM = "AT+GSN\r\n";

const char rspOK[] PROGMEM = "OK\r\n";
const char rspEndLine[] PROGMEM = "\r\n";

const char * const at_list_cmd[] PROGMEM = { // text command
  at0cmdAT, at1cmdHTTPACTION, at2cmdSAPBR11, at3cmdREADSMS, at4cmdDDET,
  at5cmdATE0, at6cmdCLIP1, at7cmdATS0, at8cmdATV1, at9cmdATCMEE2,
  at10cmdATCMGF1, at11cmdATCREG, at12cmdDELSMS, at13cmdSAPBR311,
  at14cmdSAPBR312, at15cmdSAPBR313, at16cmdSAPBR314, at17cmdSAPBR21,
  at18cmdHTTPINIT, at19cmdHTTPCID, at20cmdHTTPURL, at21cmdHTTPREAD, at22cmdHTTPTERM,
  at23cmdCSCLK1, at24cmdGETOPS, at25cmdCSQ, at26cmdCMGS, at27cmdCMGS,
  at28cmdBALMEG, at29cmdIMEI
};

const PROGMEM  uint8_t at_rresp_cmd[] = { // 0-count right response
  1, 4, 0, 0, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3 /*24*/, 1, 1, 2, 3, 2
};

const PROGMEM  uint8_t at_oresp_cmd[] = { // 1-count other response - need manual action by response
  0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

const PROGMEM  uint8_t at_move_cmd[] = { // step after action cmd
  4, 21, 17, 12, 5, 6, 7, 8, 9, 10, 11, 13, 101, 14, 15, 16, 23, 18, 19, 20, 1, 22, 101, 24, 29, 101, 27, 101, 101, 12
};

const char * const at_list_rresp[] PROGMEM = {
  rspOK, // at0
  rspOK, at1rsp1, at1rsp2, rspEndLine, // at1
  //rspOK, // at3 // read sms
  rspOK, // at4
  rspOK, // at5
  rspOK, // at6
  rspOK, // at7
  rspOK, // at8
  rspOK, // at9
  rspOK, // at10
  at11rsp1, at11rsp2, rspOK, // at11
  rspOK, // at12
  rspOK, // at13
  rspOK, // at14
  rspOK, // at15
  rspOK, // at16
  at17rsp1, at17rsp2, rspOK, // at17
  rspOK, // at18
  rspOK, // at19
  rspOK, // at20
  rspOK, // at21
  rspOK, // at22
  rspOK, // at23
  at24rsp1, at24rsp2, rspOK, // at24 ?
  rspOK, // at25
  at26rsp1, // at26
  at27rsp1, rspOK, // at27
  rspOK, at28rsp1, at28rsp2, // at28
  rspEndLine, rspOK // at29
};

const char * const at_list_oresp[] PROGMEM = {
  rspOK, at2rsp1, // at2
  rspOK // at3
};

void s800getTextCmdByNum(byte numCmd, char* textCmd);
byte s800getCountRrespCmdByNum(byte numCmd);
byte s800getCountOrespCmdByNum(byte numCmd);
void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd);
byte s800getNextStepCmdByNum(byte numCmd);

#define GSM_RX 3 // пин RX на модуле подключаем к указаному пину на Ардуино TX
#define GSM_TX 2 // пин TX на модуле подключаем к указаному пину на Ардуино RX

#define WORK_LEVEL_LED 0      // 1 if HIGH level ON led, else 0
#define WORK_LEVEL_RELAY 0    // 1 if HIGH level ON relay, else 0

#define reset_sim800_pin 4 // pin for reset modem
#define dtr_sim800_pin 10 // pin DTR for sleep mode

#define power_level_pin A6 // input power level for control

#define relay1_pin 6 // pin relay 1
#define relay2_pin 5 // pin relay 2
#define relay3_pin 9 // pin relay 3

#define ledRed_pin 7 // pin RED led
#define ledGre_pin 8 // pin GREEN led

#if (WORK_LEVEL_LED == 0)
#define LEDREDON digitalWrite(ledRed_pin,LOW)
#define LEDGREON digitalWrite(ledGre_pin,LOW)
#define LEDREDOFF digitalWrite(ledRed_pin,HIGH)
#define LEDGREOFF digitalWrite(ledGre_pin,HIGH)
#else
#define LEDREDON digitalWrite(ledRed_pin,HIGH)
#define LEDGREON digitalWrite(ledGre_pin,HIGH)
#define LEDREDOFF digitalWrite(ledRed_pin,LOW)
#define LEDGREOFF digitalWrite(ledGre_pin,LOW)
#endif

#if (WORK_LEVEL_RELAY == 0)
#define RELAY1ON digitalWrite(relay1_pin,LOW)
#define RELAY2ON digitalWrite(relay2_pin,LOW)
#define RELAY3ON digitalWrite(relay3_pin,LOW)
#define RELAY1OFF digitalWrite(relay1_pin,HIGH)
#define RELAY2OFF digitalWrite(relay2_pin,HIGH)
#define RELAY3OFF digitalWrite(relay3_pin,HIGH)
#else
#define RELAY1ON digitalWrite(relay1_pin,HIGH)
#define RELAY2ON digitalWrite(relay2_pin,HIGH)
#define RELAY3ON digitalWrite(relay3_pin,HIGH)
#define RELAY1OFF digitalWrite(relay1_pin,LOW)
#define RELAY2OFF digitalWrite(relay2_pin,LOW)
#define RELAY3OFF digitalWrite(relay3_pin,LOW)
#endif

char* LastPos(char *str1, char *str2);
int strPos(char *str11, char *str22);



//--s800str.cpp--
#include "Arduino.h"
#include "s800str.h"

void s800getTextCmdByNum(byte numCmd, char* textCmd) {
  const char * addrStroki = pgm_read_word_near((int)(at_list_cmd + numCmd));
  strcpy_P(textCmd, addrStroki);
}

byte s800getCountRrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_rresp_cmd + numCmd);
}

byte s800getCountOrespCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_oresp_cmd + numCmd);
}

byte s800getNextStepCmdByNum(byte numCmd) {
  return pgm_read_byte_near(at_move_cmd + numCmd);
}

void s800getRespByNum(byte typeResp, byte numCmd, byte numResp, char* textCmd) {
  byte startPos = 0;
  if (numCmd > 0) for (byte i = 1; i <= numCmd; ++i) {
      switch (typeResp) {
        case 0: {
            startPos += pgm_read_byte_near(at_rresp_cmd + i - 1);
            break;
          }
        case 1: {
            startPos += pgm_read_byte_near(at_oresp_cmd + i - 1);
            break;
          }
        default : {}
      }
    }
  switch (typeResp) {
    case 0: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_rresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    case 1: {
        const char * addrStroki = pgm_read_word_near((int)(at_list_oresp + startPos + numResp));
        strcpy_P(textCmd, addrStroki);
        break;
      }
    default : {}
  }
}

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;
}


Скетч использует 19208 байт (62%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1309 байт (63%) динамической памяти, оставляя 739 байт для локальных переменных. Максимум: 2048 байт.


Power ON or WDT reset
Found DS18B20 = 1
28FF3C6F5317049B
AT

OK
AT+DDET=1

OK
ATE0

OK
AT+CLIP=1

OK
ATS0=0

OK
ATV1

OK
AT+CMEE=2

OK
AT+CMGF=0

OK
AT+CREG?

+CREG: 0,1

OK
AT+SAPBR=3,1,"CONTYPE","GPRS"

OK
AT+SAPBR=3,1,"APN","internet"

OK
AT+SAPBR=3,1,"USER",""

OK
AT+SAPBR=3,1,"PWD",""

OK
AT+CSCLK=1

OK
AT+COPS?

+COPS: 0,0,"MegaFon"

OK
AT+GSN

867856037506554

OK
AT+CMGDA=6

OK
Ready
t0 = 230

+CMTI: "SM",1
AT+CMGL=4
AT+CMGDA=6

OK

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0
t0 = 230

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

RING

+CLIP: "+79384426398",145,"",0,"",0

NO CARRIER

+CMTI: "SM",1

+CMTI: "SM",2
AT+CSQ

+CSQ: 15,0

OK
AT+CMGL=4
AT+CMGDA=6

OK
t0 = 230
t0 = 230
AT+CMGL=4
AT+CMGDA=6

OK
t0 = 230
AT+CSQ

+CSQ: 14,0

OK
AT+CMGL=4
AT+CMGDA=6

OK
t0 = 230
AT+CMGL=4
AT+CMGDA=6

OK
t0 = 225
AT+CSQ

+CSQ: 16,0

OK
t0 = 230
AT+CMGL=4
AT+CMGDA=6

OK
t0 = 230

+CMTI: "SM",1

+CMTI: "SM",2
AT+CMGL=4
79009698478
Просто длинное сообщение, состоящее из 2х. It is long message. PDU 
mode. Режим  PDU! 
AT+CMGDA=6

OK
t0 = 230

+CMTI: "SM",1
AT+CSQ

+CSQ: 15,0

OK
AT+CMGL=4
79009698478
Команда запрос баланса getbalmegafon МЕГАФОН. 
AT+CMGDA=6

OK
t0 = 230

+CMTI: "SM",1
t0 = 230
AT+CMGL=4
79009698478
Ещё раз getbalmegafon пробуем 
AT+CMGDA=6

OK

+CMTI: "SM",1
t0 = 235
AT+CSQ

+CSQ: 14,0

OK
AT+CMGL=4
79009698478
Команда getuptime время работы 
AT+CMGDA=6

OK
AT+CMGS=69

>0001000B919700698974F8000838004D0065006700610046006F006E002004120020044004300431043E04420435002000300434043D002E00300447002E00320030043C002E
 
+CMGS: 120

OK
t0 = 235

+CMTI: "SM",1
AT+CMGL=4
79009698478
Команда getdsdata получить температуру всех датчиков. 
AT+CMGDA=6

OK
AT+CMGS=51

>0001000B919700698974F800082600740030003D00320033002E0035002000300434043D002E00300447002E00320032043C002E
 
+CMGS: 121

OK
t0 = 230

+CMTI: "SM",1

+CMTI: "SM",2

AT+CSQ

+CSQ: 14,0

OK
t0 = 230
AT+CMGL=4
AT+CMGDA=6

OK

+CMTI: "SM",1
t0 = 230
AT+CMGL=4
79009698478
Напряжение getpower модема. 
AT+CMGDA=6

OK
AT+CMGS=47

>0001000B919700698974F80008220033002E003900370056002000300434043D002E00300447002E00320036043C002E
 
+CMGS: 122

OK

 

vlad072
Offline
Зарегистрирован: 01.08.2017

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

Ток потребления ~30-40mA, с резкими короткими скачками до >1А при сетевой активности. Источник питания лучше импульсный с большой частотой ШИМ и быстрой реакцией, тот же mini360 не вывозит, частые глюки, даже при параллельном включении кондёра 3300uF и обвязки из керамики.

При несоблюдении прокола по UART последствия непредказуемые, вплоть до необходимости сброса в заводские установки. Послал команду, не дождавшись ответа послал вторую - жди сюрприз, т.е. неблокирующие алгоритмы малоприменимы. Пример:

>AT+BTPOWER=1 // включаем блютуз, на практике время ответа до 7 сек
// не дождавшись "ОК" шлём
>AT+CIPSEND        // отправка пакета через GPRS
// получаем как минимум потерю регистрации в сети оператора

Вот такой он китай-модем. Впрочем как "звонилка" с учётом копеечной стоимости вполне себе годный

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

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

в серьезных проектах на питании не экономят

vlad072 пишет:
 
 тот же mini360 не вывозит
 
 
LM2596S
 
vlad072 пишет:
 
даже при параллельном включении кондёра 3300uF и обвязки из керамики.
 
 
читайте даташит - там 4 конденсатора и не только 
 
vlad072 пишет:
 
При несоблюдении прокола 
 
 
соблюдайте протокол
 
vlad072 пишет:
 
 на практике время ответа до 7 сек
// не дождавшись "ОК" шлём
 
 
не использовать delay, писать с учетом анализа ЛЮБОГО ответа от модема
 
P.S. Так что все проблемы надуманы....
 
 
vlad072
Offline
Зарегистрирован: 01.08.2017

Хотел просто ничего не отвечать, дабы не разводить палемику, ну да ладно, по пунктам:

1. Здесь имелась ввиду блокирующая задержка  а не питание. Про питание было сказано как про один из "капризов" SIM'a

2. LM2596S обладает ещё вдвое меньшим быстродействием чем mp23070 на которой собран mini360.

3. Про "4 кондёра" действительно поржал. Так вот оно что, дело в количестве? ))) На сколько я понимаю принципов байпаса по питанию Вы не представляете, просто скажу что для МОДУЛЯ (платки с обвязкой) эффективность 10pF и 33pF мягко говоря нулевая. Да и в случе с отдельным чипом это как бы перестраховка от влияния на "соседей" СВЧ трансивера.

4. При "соблюдении" протокола в однопоточном цикле опять же появляются зачастую недопустимые задержки. Ведь нам кроме как "держать вязь" с модемом нужно ещё что то обрабатывать, правда? А события в контролируемых цепях хотелось бы хоть как то держать в синхроне с управлением этими цепями.Идеальным вариантом было бы некое подобие DMA, но к сожалению его нет.

5. delay не использую без крайней необхдимости никогда.

 

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

дабы не разводить палемику

вот и не разводите срач, я только одно напишу:

У меня и тысяч других пользователей модуль работает просто отлично, а у вас и других теоретиков он капризный - вот и делайте выводы сами, у кого руки и/или голова кривые.

vlad072
Offline
Зарегистрирован: 01.08.2017

В шапке топика конктерный список вопросов по модулю, я по списку высказал свою точку зрения. А срач из этого как раз раздули Вы.

kontulavittu
Offline
Зарегистрирован: 06.12.2018

Без участия в мелкосрачке, добавлю - были бы модули не такими капризными, стоили бы тогда раза в 3-4 дороже. Ходит байка, дескать, он на базе Б/У-радиомодулей собирают. Сам в это не верю, но всё же такая "капризность" в поведении наводит на мысль, что их собирают из отбракованных серий.

kolyn
Offline
Зарегистрирован: 18.01.2019

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

SIM 800 имеет 3 режима работы: AT+CFUN=0 - минимальная функциональность, для чего этот режим - не понял;

                                                   AT+CFUN=1 - полная функциональность,  режим установлен по умолчанию;

                                                   AT+CFUN=4 - режим "полет".

Кроме этого командой AT+CSCLK можно выбирать способ перевода модуля в спящий режим:

                                                   AT+CSCLK=0 - никогда не переходить в спящий режим; установлен по умолчанию; 

                                                   AT+CSCLK=1 - переходит в спящий режим при подаче на пин DTR "1"и просыпается при подаче "0"

                                                   AT+CSCLK=2 - переходит в спящий режим автоматически через 5 сек бездействия (нет звонка\СМС или в порт модема нет команд); просыпается после приема в порт команды (первая команда не дойдет до модуля, а просто "разбудит")

Подробнее о спящем режиме: в этом режиме значительно  падает энергопотребление(<1мА). При этом модем способен принимать звонки и СМС (если установлен AT+CFUN=1). Однако  посл. порт недоступен - ответить на звонок невозможно.  Если поступил входящий/пришла СМС на выводе RING появляется "0", этот сигнал можно отследить программой и подав на DTR "0" (AT+CSCLK=1) или АТ-команду ( AT+CSCLK=2) вывести модем в"полный функционал".

ВАЖНО. Модем просыпается не мгновенно! По ДШ 50 мсек, на деле задержка до 200 мсек.

Теперь о потреблении тока. Измерения стрелочным прибором Ц4315, на метрологическую точность не претендуют, позволяют оценить лишь порядок потребления модема. Напряжение 4 В.                                                              Режимы:   AT+CFUN=1 ;    AT+CSCLK=0 :                                                                                                              Загрузка -                                 0.1А с бросками до 0.4А (на самом деле больше, стрелка не успевает;                        Нашел сеть,ждем звонка           14мА с бросками до 20 мА                                                                                    Разговор -                                 плавает 90 - 200 мА

Режимы:   AT+CFUN=1 ;    AT+CSCLK=1 :                                                                                                              Загрузка -                                 0.1А с бросками до 0.4А (на самом деле больше, стрелка не успевает;                           Нашел сеть,ждем звонка           14мА с бросками до 20 мА                                                                                      Перешел в спящий режим          0.9 мА !!! ПОТРЕБЛЕНИЕ УПАЛО В 15.6 раза!!!                                                        Поступил входящий, не отвечаем    90 -100 мА                                                                                                        Разговор                                    плавает 100 -200 мА                                                                                              Отбой, спящий режим                0.9 мА.

Вывод - 0.9 мА в спящем режиме - достойный результат. При питании от аккумулятора стоит применять.

alexbmd
Offline
Зарегистрирован: 15.01.2016

добрый день.

в ДШ упоминается PWRKEY пин. но на выводах сим800 такого нету.  есть варианты как можно программно его выключать /включать ?

b707
Offline
Зарегистрирован: 26.05.2017

alexbmd пишет:

добрый день.

в ДШ упоминается PWRKEY пин. но на выводах сим800 такого нету

есть, ищите. Может называться PWR или похоже

alexbmd
Offline
Зарегистрирован: 15.01.2016

pinout