Сама схема не запустилась, в поисках причины решил посмотреть в монитор порта, что там отображаеться но там старословянские маты одни квадратики и буквы кирилицы, и то только при запуске самой ардуины и все больше в порт ничего не приходит
Думал проблема в скорости порта но я перепробовал все и ни одна не помогла как отображались крючки так и продолжают
Есть подозрение что криво составляеться и заливаеться программа из ФЛ прог в ардуино
Прошу глянуть специалистов поверхностно в чем может быть проблемма что монитор порта не выводит нормальные символы
Заранее благодарен
#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;
}
Поверхностно на эту простыню не взглянешь, да и про flprog тут уже было мнение что добавление и исправление чего либо сильно сложно, вы бы сами попытались написать - гораздо полезнее.
спасибо, согласен, самому полезнее. Но тут всю простынь и аннализировать наверное нет смысла т.к. суть в том что ардуина даже без обвеса после прошивки в монитор порта выдает иероглифы, т.е. скорее проблема в написании именно строк связаных с сериалом
Снова пришлось использовать эти модули. Проблему нашел - косяк модуля/несовместимость с местной сетью. Так же перезагружался после команды SMS Ready. Спасло:
AT+CBAND="DCS_MODE"
AT&W
//--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. В середине часть латиницей.
у меня модуль был в бред борде и пока напрямую провода не припаял сеть не мог словить и еще в момент регистрации просадка напряжения была пока от бп и dc-dc step down не запитал
Привет всем, делаю автозапуск в машину. 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); // Выключаем реле - посылаем высокий уровень сигнала
}
Просьба подсказать по аккумуляторному питанию SIM800.
Задумал железку для своих нужд, что бы не городить лишних стабилизаторов, планирую подключить по ниже приведенной схеме. Модем SIM800L подключить напрямую параллельно аккумулятору 18650, фактически на выходе модуля заряда TP4056.
Учитывая что буду использовать голый atmega328p - его бы аналогично параллельно и модему и аккумулятору запитал.
1. Модули очень капризные по питанию. Для sim800L минимум 3,7 Вольта, чтобы он вообще адекватно мог реагировать на простые AT-команды и нужно максимум 4,2 В для полноценной работы. Но(!), тут ещё 2 параметра вступают в игру: ток и делители по шине данных Rx и Тх.
2. Очень мнохо бахвальства на тему прямого подключения Rx и Tx -шины напрямую к Ардуино. Не скажу за все модели, но если подключить напрямую к Nano, то гарантированно летит к чертям шина управление gsm-модуля. Если не в течении минуты-часа, то через пару дней стабильно будет пробой, и модуль начинает жить своей жизнью.
3. Сложности начинаются, когда идёт приём звонка или дозвон. Тут сюрпризом великое множество. Можно сутками биться на решением проблемы внезапной перезагрузки модуля при поступлении на симку звонка. И напряжения ОК, и блок питания более 2А, и конденсатор параллельно цепи питания модуля - хоть тресни, если модуль взумал сбрасыватся при входящих - это приговор.
Это вы батенька их готовить не умеете.
Несколько десятков устройств ездит по стране вообще без проблем.
Завтра посторяюсь выложить схему соединения nano и sim800 какую я использую - все отлично работает в любых режимах.
1 стоит стабилизатор на 2 ампера 4 вольта
2 обычные резисторные делитель - это сложно?
3 фильтры на питание модуля - дроссель и 4 конденсатора согласно даташита
1 стоит стабилизатор на 2 ампера 4 вольта 2 обычные резисторные делитель - это сложно? 3 фильтры на питание модуля - дроссель и 4 конденсатора согласно даташита
1. стабилизатор стоит в DC-DC понижающем , куда уж больше?
2. делитель давно стоит, и не в них дело.
3. вообше непонятно, куда ещё больше стабилизации, мало уже стабилизатора по току, так ещё и дополнительные фильтры? Это лишь подтверждает, что модули настолько капризны, что как не дунешь - сразу в перезагрузку.
Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.
Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Поставить-то можно, только будет ли от этого лучше?
Установка нескольких параллельных конденсаторов обычно практикуется в цепях питания, при этом все причины, по которым это делается, обычно можно объединить в две большие группы:
Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.
В даташите на модем нарисованы схемы подключения питания для модема и там же написано почему это сделано, в том числе и для фильтрации высокочастиотных помех.
Соберите схему как у меня и проведите эксперимент - позвоните на модем и послушайте фон - его не будет, потом уберите конденсаторы и дроссель и позвоните/сравните.
И что значит промышленное или нет, да, это можно сказать образец для нескольких десятков устройств которые уже собраны, но в любом случае вы как разработчик должны стремиться к идеально работающему устройству.
Поставить-то можно, только будет ли от этого лучше?
будет лучше, проверено на себе.
На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?
Поставить-то можно, только будет ли от этого лучше?
будет лучше, проверено на себе.
На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?
Нет, я поставил конденсаторы согласно даташита и стало лучше, один большей ёмкости не пробовал, но интернет читал, в институте предметы изучал и сомневаюсь что один большой конденсатор защитит от всех видов помех.
ЗЫ. Никому ничего утверждать не собираюсь, прежде всего я практик а не теоретик.
После внимательного изучения номиналось конденсаторов стало понятно, почему параллельно стоят. Гасители высокочастотных помех. Раз такое ставят, тогда тем более очевидно, что модуль капризный и на любое малейшее колебание по U ,начинает бесноваться...
Там ещё важны материалы из чего конденсаторы сделаны, электролит керамика металлопреночный и ещё какой то, не помню, я в схеме маркировки старался привести, если нужно точнее - в понедельник конкретику напишу.
Очередной скетч без практического применения, из серии "дурная голова рукам покоя не дает", вдруг кому пригодиться для 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
Скажу за SIM800C. Крайне глючная какашка, требующая исключительно хорошего питания и строгого соблюдения протокола обмена, что в реальных серьёзных проетах не всегда возможно.
Ток потребления ~30-40mA, с резкими короткими скачками до >1А при сетевой активности. Источник питания лучше импульсный с большой частотой ШИМ и быстрой реакцией, тот же mini360 не вывозит, частые глюки, даже при параллельном включении кондёра 3300uF и обвязки из керамики.
При несоблюдении прокола по UART последствия непредказуемые, вплоть до необходимости сброса в заводские установки. Послал команду, не дождавшись ответа послал вторую - жди сюрприз, т.е. неблокирующие алгоритмы малоприменимы. Пример:
>AT+BTPOWER=1 // включаем блютуз, на практике время ответа до 7 сек
// не дождавшись "ОК" шлём
>AT+CIPSEND // отправка пакета через GPRS
// получаем как минимум потерю регистрации в сети оператора
Вот такой он китай-модем. Впрочем как "звонилка" с учётом копеечной стоимости вполне себе годный
Хотел просто ничего не отвечать, дабы не разводить палемику, ну да ладно, по пунктам:
1. Здесь имелась ввиду блокирующая задержка а не питание. Про питание было сказано как про один из "капризов" SIM'a
2. LM2596S обладает ещё вдвое меньшим быстродействием чем mp23070 на которой собран mini360.
3. Про "4 кондёра" действительно поржал. Так вот оно что, дело в количестве? ))) На сколько я понимаю принципов байпаса по питанию Вы не представляете, просто скажу что для МОДУЛЯ (платки с обвязкой) эффективность 10pF и 33pF мягко говоря нулевая. Да и в случе с отдельным чипом это как бы перестраховка от влияния на "соседей" СВЧ трансивера.
4. При "соблюдении" протокола в однопоточном цикле опять же появляются зачастую недопустимые задержки. Ведь нам кроме как "держать вязь" с модемом нужно ещё что то обрабатывать, правда? А события в контролируемых цепях хотелось бы хоть как то держать в синхроне с управлением этими цепями.Идеальным вариантом было бы некое подобие DMA, но к сожалению его нет.
5. delay не использую без крайней необхдимости никогда.
У меня и тысяч других пользователей модуль работает просто отлично, а у вас и других теоретиков он капризный - вот и делайте выводы сами, у кого руки и/или голова кривые.
Без участия в мелкосрачке, добавлю - были бы модули не такими капризными, стоили бы тогда раза в 3-4 дороже. Ходит байка, дескать, он на базе Б/У-радиомодулей собирают. Сам в это не верю, но всё же такая "капризность" в поведении наводит на мысль, что их собирают из отбракованных серий.
Длиннопост о энергопотреблении и режимах работы модулей 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 мА в спящем режиме - достойный результат. При питании от аккумулятора стоит применять.
Здравствуйте прошу подсказать как удалось победить проблему ? Только по питанию ?
У меня таже сети вокруг вилит а к мтс не подключаеться
at+cops=?
at+csq
Ну, похоже на то, что было у меня. Вопрос в следующем, если подключить к модулю только питание, к сети подключается?
Здравствуйте прошу подсказать как удалось победить проблему ? Только по питанию ?
У меня таже сети вокруг вилит а к мтс не подключаеться
at+cops=?
at+csq
у МТС насколько я помню, код 25001
у вс такого кода нет, соответственно и не подключается
возможно 2 проблемы: в данном месте нет в принципе МТС
или у МТС нет 2G базовых станций в этом месте - модуль их не видит
Друзья, спасибо за быструю реакцию
Сеть словило, помогла замена сим карты, хз почему, прежняя симка в телефоне нормально работает
И перепаял напрямую все провода без бред-борда к модулю по питанию
Уважаемые форумчане прошу Вашей помощи по работе с модулем
Использую Arduino nano (таже проблема в мониторе порта и на меге )
Решил повторить опыт Гарачика о GSM сигнализации от сюда (http://arduinoprom.ru/arduino/276-gsm-signalizacija-dlja-dachnogo-domika-na-sim800l.html)
Программа для ардуино создана через FLProg
Сама схема не запустилась, в поисках причины решил посмотреть в монитор порта, что там отображаеться но там старословянские маты одни квадратики и буквы кирилицы, и то только при запуске самой ардуины и все больше в порт ничего не приходит
Думал проблема в скорости порта но я перепробовал все и ни одна не помогла как отображались крючки так и продолжают
Есть подозрение что криво составляеться и заливаеться программа из ФЛ прог в ардуино
Прошу глянуть специалистов поверхностно в чем может быть проблемма что монитор порта не выводит нормальные символы
Заранее благодарен
Поверхностно на эту простыню не взглянешь, да и про flprog тут уже было мнение что добавление и исправление чего либо сильно сложно, вы бы сами попытались написать - гораздо полезнее.
спасибо, согласен, самому полезнее. Но тут всю простынь и аннализировать наверное нет смысла т.к. суть в том что ардуина даже без обвеса после прошивки в монитор порта выдает иероглифы, т.е. скорее проблема в написании именно строк связаных с сериалом
Я бы для начала скорость serial уменьшил до 9600
Строка 143
пробовал, не помогло
А если в МК тупой скетч вписать он вообще serial print нормально отображает?
да, другие тестовые примеры с sim800 в сериал нормально выводят инфо
Снова пришлось использовать эти модули. Проблему нашел - косяк модуля/несовместимость с местной сетью. Так же перезагружался после команды SMS Ready. Спасло:
AT+CBAND="DCS_MODE"
AT&W
После этого все заработало идеально
решил потренироваться обрабатывать длинные ответы от модема, используя короткий циклический буфер,
в итоге получился скетч чтения русских и / или длинных СМС. состоит из трех файлов.
1
2
3
Привет, где расписано мигание светодиода на sim-800l? У меня мигает -7-9-7-9- раз, питание нормальное.
не может словить сеть, я тоже так думал но он очень прихотлив к питанию. Попробуйте провода питания припаять на прямую не использовать разьемы
Привет, где расписано мигание светодиода на sim-800l? У меня мигает -7-9-7-9- раз, питание нормальное.
Не поверишь - в даташите.
у меня модуль был в бред борде и пока напрямую провода не припаял сеть не мог словить и еще в момент регистрации просадка напряжения была пока от бп и dc-dc step down не запитал
Не поверишь - в даташите.
не поверю, даташит на 70 листов перечитал, там мигание по соединению только, не по проблеммам
У меня часто мигает при установке gprs сессии
попался ликбез про GSM модули и в частности sim800L , особенности питания и подключения
будет познавательно для тех кто не в теме
https://youtu.be/6hi-wMx6T9A
попался ликбез про GSM модули и в частности sim800L , особенности питания и подключения
очередной Дима осипов :) Без майки незачет
Привет всем, делаю автозапуск в машину. SIM800L и NANO корректно работают, но релюшки срабатывают немного не так. Работать должно так - если я звоню на сим, то замыкается реле зажигания, через некоторое время замыкается реле стартера на 2,5 секунды и сразу размыкается. Далее через 10 секунд выключается реле зажигания (через 10 секунд после замыкания) Написал вот код, только работает так - после заливки скетча реле зажигания замыкается(или размыкается) после чего через несколько секунд снова делает это и все стоит. Когда звоню - реле зажигания замыкается, замыкается и отключается через 2с реле стартера, при отключении реле стартера сразу же отключается и реле зажигания. нужна помощь, думаю что то не так в скетче
Думаю, что закралась какая то ошибка в этой части
Просьба подсказать по аккумуляторному питанию SIM800.
Задумал железку для своих нужд, что бы не городить лишних стабилизаторов, планирую подключить по ниже приведенной схеме. Модем SIM800L подключить напрямую параллельно аккумулятору 18650, фактически на выходе модуля заряда TP4056.
Учитывая что буду использовать голый atmega328p - его бы аналогично параллельно и модему и аккумулятору запитал.
Насколько жизнеспособно это будет?
Moй опыт по использованию sim800l :
1. Модули очень капризные по питанию. Для sim800L минимум 3,7 Вольта, чтобы он вообще адекватно мог реагировать на простые AT-команды и нужно максимум 4,2 В для полноценной работы. Но(!), тут ещё 2 параметра вступают в игру: ток и делители по шине данных Rx и Тх.
2. Очень мнохо бахвальства на тему прямого подключения Rx и Tx -шины напрямую к Ардуино. Не скажу за все модели, но если подключить напрямую к Nano, то гарантированно летит к чертям шина управление gsm-модуля. Если не в течении минуты-часа, то через пару дней стабильно будет пробой, и модуль начинает жить своей жизнью.
3. Сложности начинаются, когда идёт приём звонка или дозвон. Тут сюрпризом великое множество. Можно сутками биться на решением проблемы внезапной перезагрузки модуля при поступлении на симку звонка. И напряжения ОК, и блок питания более 2А, и конденсатор параллельно цепи питания модуля - хоть тресни, если модуль взумал сбрасыватся при входящих - это приговор.
Это вы батенька их готовить не умеете.
Несколько десятков устройств ездит по стране вообще без проблем.
Завтра посторяюсь выложить схему соединения nano и sim800 какую я использую - все отлично работает в любых режимах.
1 стоит стабилизатор на 2 ампера 4 вольта
2 обычные резисторные делитель - это сложно?
3 фильтры на питание модуля - дроссель и 4 конденсатора согласно даташита
1. стабилизатор стоит в DC-DC понижающем , куда уж больше?
2. делитель давно стоит, и не в них дело.
3. вообше непонятно, куда ещё больше стабилизации, мало уже стабилизатора по току, так ещё и дополнительные фильтры? Это лишь подтверждает, что модули настолько капризны, что как не дунешь - сразу в перезагрузку.
Ну сравните работу с модулями a6, впрочем дело вкуса, у тысяч людей все работает, у вас нет, выводы делайте сами.
схема:
https://easyeda.com/andycat/MultiFuncSIM800L
БП вот такой использую
https://ru.aliexpress.com/store/product/12V1A-5V1A-fully-isolated-switch...
схема:
https://easyeda.com/andycat/MultiFuncSIM800L
БП вот такой использую
https://ru.aliexpress.com/store/product/12V1A-5V1A-fully-isolated-switch...
Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.
Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Установка нескольких параллельных конденсаторов обычно практикуется в цепях питания, при этом все причины, по которым это делается, обычно можно объединить в две большие группы:
- из-за неидеальности конденсаторов,
- из-за неидеальности проводников.
схема:
https://easyeda.com/andycat/MultiFuncSIM800L
БП вот такой использую
https://ru.aliexpress.com/store/product/12V1A-5V1A-fully-isolated-switching-power-supply-AC-DC-modules-220V-switch-12v-5v-dual-output/2413055_32810982837.html?spm=a2g0v.12010612.8148356.31.290a3c57f1XllT
Спасибо за схемку. Принципиально ясно, что после DC-DC, у которого на выходе уже есть конденсатор, установлены дополнительно несколько параллельно подключённых конденсаторов. Зачем это, когда можно один поставить высокого номинала?
Это, наверное, какое-то полупромышленное...У меня обычный зарядник для телефонов/планшетов с током 2,1 А на выходе стоит.
В даташите на модем нарисованы схемы подключения питания для модема и там же написано почему это сделано, в том числе и для фильтрации высокочастиотных помех.
Соберите схему как у меня и проведите эксперимент - позвоните на модем и послушайте фон - его не будет, потом уберите конденсаторы и дроссель и позвоните/сравните.
И что значит промышленное или нет, да, это можно сказать образец для нескольких десятков устройств которые уже собраны, но в любом случае вы как разработчик должны стремиться к идеально работающему устройству.
Поставить-то можно, только будет ли от этого лучше?
будет лучше, проверено на себе.
Поставить-то можно, только будет ли от этого лучше?
будет лучше, проверено на себе.
На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?
Поставить-то можно, только будет ли от этого лучше?
будет лучше, проверено на себе.
На всякий случай переспрошу: Вы действительно утверждаете, что если все конденсаторы, которые на принципиальной схеме выглядят как параллельные, заменить одним единственным большей емкости, то будет лучше?
Нет, я поставил конденсаторы согласно даташита и стало лучше, один большей ёмкости не пробовал, но интернет читал, в институте предметы изучал и сомневаюсь что один большой конденсатор защитит от всех видов помех.
ЗЫ. Никому ничего утверждать не собираюсь, прежде всего я практик а не теоретик.
Так а что именно Вы "проверяли на себе"?
После внимательного изучения номиналось конденсаторов стало понятно, почему параллельно стоят. Гасители высокочастотных помех. Раз такое ставят, тогда тем более очевидно, что модуль капризный и на любое малейшее колебание по U ,начинает бесноваться...
Там ещё важны материалы из чего конденсаторы сделаны, электролит керамика металлопреночный и ещё какой то, не помню, я в схеме маркировки старался привести, если нужно точнее - в понедельник конкретику напишу.
Очередной скетч без практического применения, из серии "дурная голова рукам покоя не дает", вдруг кому пригодиться для SIM800.
Чтение СМС, выполнение команд из СМС, получение температур с нескольких DS18B20, отправка http запроса каждые N минут, при использовании OLED 128*64 и нажатии на кнопку отправляет модем в спячку, на 20 секунд выводит инфу на дисплей и выводит модем в рабочий режим.
Скажу за SIM800C. Крайне глючная какашка, требующая исключительно хорошего питания и строгого соблюдения протокола обмена, что в реальных серьёзных проетах не всегда возможно.
Ток потребления ~30-40mA, с резкими короткими скачками до >1А при сетевой активности. Источник питания лучше импульсный с большой частотой ШИМ и быстрой реакцией, тот же mini360 не вывозит, частые глюки, даже при параллельном включении кондёра 3300uF и обвязки из керамики.
При несоблюдении прокола по UART последствия непредказуемые, вплоть до необходимости сброса в заводские установки. Послал команду, не дождавшись ответа послал вторую - жди сюрприз, т.е. неблокирующие алгоритмы малоприменимы. Пример:
Вот такой он китай-модем. Впрочем как "звонилка" с учётом копеечной стоимости вполне себе годный
требующая исключительно хорошего питания и строгого соблюдения протокола обмена, что в реальных серьёзных проетах не всегда возможно.
в серьезных проектах на питании не экономят
Хотел просто ничего не отвечать, дабы не разводить палемику, ну да ладно, по пунктам:
1. Здесь имелась ввиду блокирующая задержка а не питание. Про питание было сказано как про один из "капризов" SIM'a
2. LM2596S обладает ещё вдвое меньшим быстродействием чем mp23070 на которой собран mini360.
3. Про "4 кондёра" действительно поржал. Так вот оно что, дело в количестве? ))) На сколько я понимаю принципов байпаса по питанию Вы не представляете, просто скажу что для МОДУЛЯ (платки с обвязкой) эффективность 10pF и 33pF мягко говоря нулевая. Да и в случе с отдельным чипом это как бы перестраховка от влияния на "соседей" СВЧ трансивера.
4. При "соблюдении" протокола в однопоточном цикле опять же появляются зачастую недопустимые задержки. Ведь нам кроме как "держать вязь" с модемом нужно ещё что то обрабатывать, правда? А события в контролируемых цепях хотелось бы хоть как то держать в синхроне с управлением этими цепями.Идеальным вариантом было бы некое подобие DMA, но к сожалению его нет.
5. delay не использую без крайней необхдимости никогда.
дабы не разводить палемику
вот и не разводите срач, я только одно напишу:
У меня и тысяч других пользователей модуль работает просто отлично, а у вас и других теоретиков он капризный - вот и делайте выводы сами, у кого руки и/или голова кривые.
В шапке топика конктерный список вопросов по модулю, я по списку высказал свою точку зрения. А срач из этого как раз раздули Вы.
Без участия в мелкосрачке, добавлю - были бы модули не такими капризными, стоили бы тогда раза в 3-4 дороже. Ходит байка, дескать, он на базе Б/У-радиомодулей собирают. Сам в это не верю, но всё же такая "капризность" в поведении наводит на мысль, что их собирают из отбракованных серий.
Длиннопост о энергопотреблении и режимах работы модулей 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 мА в спящем режиме - достойный результат. При питании от аккумулятора стоит применять.
добрый день.
в ДШ упоминается PWRKEY пин. но на выводах сим800 такого нету. есть варианты как можно программно его выключать /включать ?
добрый день.
в ДШ упоминается PWRKEY пин. но на выводах сим800 такого нету
есть, ищите. Может называться PWR или похоже