Вопрос по модулю SIM900

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Имеется такой модуль SIM900

Подключил к Arduino UNO

При попытке отправки SMS или GPRS пакета идет перезагрузка контроллера. Питание подавал как по USB, так и по внешнему разъему Arduino 12V с блока ATX. 

Как подать к данной плате внешнее питание? 

На какие ноги Arduino заведены POWER и RESET ?

Что за странный разъем RI Jumper с ногами D14 RI D2 ?

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

вам на кофе погадать? или пасьянс разложим?

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Puhlyaviy пишет:

вам на кофе погадать? или пасьянс разложим?

Да хоть на столе спляшите. Мне все равно.

Может кто-то имел опыт работы с такими модулями?

Life23
Offline
Зарегистрирован: 10.08.2013

Имел.. отличный модуль!!! но есть косяки... по крайней мере там где я покупал... 

Life23
Offline
Зарегистрирован: 10.08.2013

вот ветка, где мне помогли с написанием кода к этому модулю! http://arduino.ru/forum/programmirovanie/pomogite-novichku-dopisat-kod#comment-40099

Life23
Offline
Зарегистрирован: 10.08.2013

откройте datasheet и внимательно изучите! там все есть! и попробуй только поспорить! 

Life23
Offline
Зарегистрирован: 10.08.2013

если все сложно - по логике, достаточно открыть datasheet на sim900, взять мультиметр и все выяснить! и не надо лениться! не стоит покупать такие модули и не ударить "палец об палец"!

 

Life23
Offline
Зарегистрирован: 10.08.2013

Puhlyaviy пишет:

вам на кофе погадать? или пасьянс разложим?

действительно!!! Хотя бы написали, каким образом вы пытались отправить "что-то там"...

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Life23 пишет:

откройте datasheet и внимательно изучите! там все есть! и попробуй только поспорить! 

Даташит там очень короткий

С мультиметром разобрался по своим вопросом, но проблема осталась:

Использую GSM Shield Library for Arduino. Плата работает на програмном COM. Все AT команды работают без проблем. Плата принимает звонки и SMS, но вот при попытки отправки SMS хоть функцией SendSMS, хочь через AT Arduino уходит в перезагрузку. Похоже, что данная проблема аппаратная, поэтому код и не приводил

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

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

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Ну вот по всем вопросам разобрался:

POWER сидит на 9-м пине 
RESET на 10-м пине

D14 RI D2 сигнализируют о получении SMS, входящих звноках и прочих событий с модуля

Питания на модуль подать можно с ноги шилда 5В

Перезагрузки контроллера к питанию не имеют отношения, а имеет глючная библиотека, которой пользовался первоначально. Плюнул на все эти библиотеки и через SoftwareSerial напрямую с AT командами разобрался. Остался один вопрос. Хочу отослать по GPRS информацию на народный мониторинг. Получаю следующее:

ATE1
OK
AT+CGATT=1
OK
AT+CIPSHUT
SHUT OK
AT+CIPCSGP=1,"internet.usi.ru","",""
OK
AT+CIPATS=0
OK
AT+CLPORT="TCP","7777"
OK
AT+CIPSTART="TCP","91.122.49.168","8283"
#XXXXXXXXXXXXX
XXXXXXXXXXXXX01#100
XXXXXXXXXXXXX01#100
##
STATE: PDP DEACT  
CONNECT FAIL

Через Ethernet спокойно отсылаю эти данные, через GPRS ошибка получается. Перепрошивка SIM900 поможет?

Life23
Offline
Зарегистрирован: 10.08.2013

Зачем вы "AT+CIPSHUT" в начале отсылаете?

Life23
Offline
Зарегистрирован: 10.08.2013

AT+CMEE=1

AT+CGATT=1

AT+CSTT="internet" // Ваша точка APN и логин с паролем

AT+CIICR

AT+CIFSR // в ответ - ваш IP покажет. без этой команды - дальше не будет работать.

AT+CIPSTART="TCP","narodmon.ru","8283" // Адрес и порт сервера. Почему у вас 7777 не понятно..

AT+CIPSEND // В ответ будет знак ">" после чего надо отсылать данные. не успеете за 10сек. вас отбросит сервер.

#XXXXXXXXXXXXX

XXXXXXXXXXXXX01#100

##

AT+CIPSHUT // Закрываем TCP.

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Life23 пишет:

Зачем вы "AT+CIPSHUT" в начале отсылаете?

После этой команды статус AT+CIPSTATUS становится STATE: IP INITIAL

Life23
Offline
Зарегистрирован: 10.08.2013

после CIPSHUT "падает" PDP! что вам и ответил модуль:  STATE: PDP DEACT!

Попробуйте, то что я написал выше. Я сам недавно только закончил проэкт для NARODMON под 8 датчиков DHT22 на Icomsat 1.1 (Sim900) шилде. 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013
ATE1

OK
AT+CMEE=1

OK
AT+CGATT=1

OK
AT+CSTT="internet.mts.ru","mts","mts"

OK
AT+CIICR

OK
AT+CIPSTART="TCP","nardomon.ru","8283"

+CME ERROR: 3
AT+CIPSEND

+CME ERROR: 3
#XXXXXXXXXXXX
#XXXXXXXXXXXX01#11
#XXXXXXXXXXXX02#55
##


AT+CIPSHUT

SHUT OK

Сокет не открывается с народным мониторингом

Life23
Offline
Зарегистрирован: 10.08.2013

читайте внимательней!!!

"AT+CIFSR // в ответ - ваш IP покажет. без этой команды - дальше не будет работать."

UPD: "AT+CIFSR" Возвращает IP-адрес модуля. Если в ответ нет IP адреса - оператор вашей сети не на делил вас IP! дальнейшая работа - бесполезна! 

Life23
Offline
Зарегистрирован: 10.08.2013

И еще, я не знаю как у вас там мтс работает, у нас на Украине (для MTS) достаточно только строчки "AT+CSTT="internet"", без логина и пароля. На даный момент, у них так заявлено на сайте mts.com.ua.

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Life23 пишет:

И еще, я не знаю как у вас там мтс работает, у нас на Украине (для MTS) достаточно только строчки "AT+CSTT="internet"", без логина и пароля. На даный момент, у них так заявлено на сайте mts.com.ua.

MTS у нас очень плохо работает. Поменял симку на Ростелеком, и все заработало с вашим кодом.

Спасибо. Вы мне очень помогли!

Life23
Offline
Зарегистрирован: 10.08.2013

Рад что помог! ;)

Советую еще этот ресурс: Module Tester | M2MSupport.net он мне очень помог разобраться с командами для модуля SIM900.

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Всем кто работает с GSM/GPRS модулями совет - храните AT команды в PROGMEM. Иначе они очень быстро съедают оперативную память и скетч начинает глючить (перезагружается, виснет, сбивает перемнные). Никаких аппаратных проблем по питанию, например с USB в связке UNO - SIM900 не выявлено.

Jek
Offline
Зарегистрирован: 05.01.2014

sav13

Выложите пожалуйста пример кода для отправки данных на narodmon.

Я уже совсем запутался... Через LAN один код, через WiFi другой, через SIM900 третий...

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013
// Через SIM900
void SendTCPMessage(int x)
{
  char b1[20];
  gsm.SimpleWriteln("AT+CGATT=1");
  delay(100);
  gsm.SimpleWriteln("AT+CDNSCFG=\"8.8.8.8\"");
  delay(100);
  gsm.SimpleWriteln("AT+CIPCSGP=1,\"mts.internet,ru\",\"\",\"\"");   
  delay(5000);
  gsm.SimpleWriteln("AT+CIPSTART=\"TCP\",\"narodmon.ru\",\"8283\"");
  delay(100);
  gsm.SimpleWriteln("#00-11-22-33-44-5");
  sprintf(b1,"#00112233445566#%d",x);
  gsm.SimpleWriteln(b1);
  gsm.SimpleWriteln("##");
  delay(100);
  gsm.SimpleWriteln((char)26);//the ASCII code of the ctrl+z is 26
  delay(100);
  gsm.SimpleWriteln("");
}

 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013
// Через Ethernet
boolean SendToNM()
{
       if (client.connect(nm_server, 8283)) 
       {
              Serial.println("connected for error");
              client.print("#00-11-22-33-44-55"); // Отправляем GET запрос
              client.print("\n");
               client.print("#00112233445566#");
              client.print(t2);
              client.print("\n");
              client.print("##");
              client.stop();              
        }//end if 
  }

 

ESV
Offline
Зарегистрирован: 16.12.2015

Код для narodmon.ru sim900 dht22 bmp180 по протоколу UDP

Правда для слегка другого шилда.

https://drive.google.com/file/d/0B8Yn3QheuZFGdHpfZFZjdUFWRFU/view?usp=sharing

* ВНИМАНИЕ  Для перепрограммирования требуется отключение arduino от шилда.
*  доработано для отправки данных датчиков на сайт narodmon.ru
*  Используемые датчики
*  DHT-22
* SIM900 arduino шидлов мне известно 2 типа
* у моего сигнал ON-OFF на пине D9
* у другого сигнал ON-OFF на пине D8
* следует поправить int onSIM900Pin= 9 или 8;
* В данной реализации использован апаратный RT-TX порт поэтому
* Перемычки RT-TX на плате следует установить в положение HW (HardWare)

*******************************************************************************************
____________________________________________________
здесь следует изменить MAC_ADDRESS и APN по своему разумению
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 В соответствии с протоколом http://narodmon.ru/#proto
например 11-22-33-AA-CC-FF  112233AACCFF  11:22:33:AA:CC:FF с точки зрения сервера тождественны.
тире и двоеточия не обязательны,поскольку проигнорируются сервером - проверено.
*******************************************************************************************/

// Mac устройства можно генерировать вот тут http://www.miniwebtool.com/mac-address-generator/
#define  MAC_ADDRESS "112233AACCFF" //этот незабудь поправить - поскольку уже занят
/*
Настроим модем SIM900 под своего оператора связи
http://www.gpshome.ru/gprs_apn
*/
//команда - конфигурации модема под оператора MTS
#define command_APN "AT+CSTT=\"internet.mts.ru\",\"mts\",\"mts\""
//команда - конфигурации модема под оператора beeline
//#define command_APN "AT+CSTT=\"\",\"beeline\",\"beeline\""
//команда - конфигурации модема под оператора МегаФон
//#define command_APN "AT+CSTT=\"internet\",\"gdata\",\"gdata\""
//команда - конфигурации модема под оператора Теле2
//#define command_APN "AT+CSTT=\"internet.tele2.ru\",\"\",\"\""

#define DEPTH_FILTRE 15//глубина фильтрации
#define PERIOD 58 //период опроса датчика 58 секунд.
// период отправки сообщений в 58 секунд умноженный на 15 (глубина фильтрации)итого ~ 15 минут +-чуток

/*
Скорость Апаратного последовательного  порта
Иногда SIM900 приходит без включенной опции автоопределения скорости порта
Следует включить автоопределение скорости 
Либо назначить принудительно.
Это делается так -
AT+IPR? говорит какая скорость
AT+IPR=0              авто
AT+IPR=19200          19200 
Если это не под силу , то можно влоб - Брутфорсом. 
То-есть подобрать скорость экспериментально из ряда - 
 1200, 2400, 4800, 9600, 19200, 38400, 57600 , 115200  
 На этой-же скорости во время работы устройства 
 в мониторе терминала будет выводиться лог хода работы.
 
 Factory baudrate setting is auto-bauding by default. 
 Baudrate can be fixed using the command AT+IPR=baudrate. 
 Allowed baudrates: 
 0 (Auto-bauding) , 1200 , 2400 , 4800 , 9600 , 19200 , 38400 , 57600 and 115200 ;  */
#define SPEED_RXTX 19200

/*
* команда - что, куда, и в какой порт слать будем
* Мне всегда нравился протокол UDP . Выстрелил - забыл.
* Пропадание десятка сообщений в сутки из сотни - погоды не сделает :) */
#define data_ip_protocol "AT+CIPSTART=\"UDP\",\"narodmon.ru\",\"8283\""

//Идентификаторы датчиков
#define  SOURCE_1 "#T1#" // Температура DHT
#define  SOURCE_2 "#H1#" // Влажность DHT
#define  SOURCE_3 "#T2#" // Температура BMP085
#define  SOURCE_4 "#P1#" // Давление BMP085
#define  SOURCE_5 "#Z1#" // Расчётная точка росы
#define  SOURCE_6 "#Z2#" // время работы прибора в часах
#define endCODE "##"

unsigned long tim;
//Подключаем требуемые библиотеки
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here
// Получение температуры с BMP085  bmp.readTemperature();
// Получение давления с BMP085 в паскалях  bmp.readPressure();
float tempeBMP085_f = 0, tempeBMP085TMP= 0, pressBMP085_f = 0, pressBMP085TMP =0, timems;

#include <DHT.h>
#define PIN_DHT 2    
// what pin we're connected to
// Uncomment whatever type you're using!
//#define TYPE_DHT DHT11   // DHT 11 
#define TYPE_DHT DHT22   // DHT 22  (AM2302)
//#define TYPE_DHT DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your PIN_DHT is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
// У меня DHT22 на столе , на 5 метровом кабеле работало и без резистора

float temperature_f = 0, humidity_f = 0, temperatureTMP= 0,humidity_fTMP =0;
DHT dht(PIN_DHT, TYPE_DHT);
int8_t answer;

//PIN включения GSM модуля после пропадания питания
int onSIM900Pin= 9; //у моего модуля сигнал ON-OFF SIM900 на пине D9 ARDUINO
//Выделение буфера для строковых переменных
char aux_str[20];
char buf_ip_data[150]; //Пока на 2 датчика хватит({Хотя сообщение не больше 70 байт)
int ledPin = 13; //сигнальное устройство - светодиод
 /*===========================================================================================================*/
void setup() 
{
    pinMode(ledPin,OUTPUT);
    pinMode(onSIM900Pin, OUTPUT);
   // pinMode(resetSIM900Pin, OUTPUT);
    Serial.begin(SPEED_RXTX); // delay(5000);
    
     //Первое измерение с периодом измерения в 1 секунду и сразу фильтрованное. 
     sensor_filtr_read(1, DEPTH_FILTRE);

}
 /*===========================================================================================================*/
void loop() 
{   //добавим общую регулярную  перезагрузку  - раз в неделю
   tim = millis();
    if (604800000-long(tim)  <=  0) 
     {
      delSMS(); 
      powerpulse();
      asm volatile ("jmp 0x0000");
     }
  //Если всё хорошо передаём данные на сервер
    if (sendATcommand2("AT+CIFSR", ".", "ERROR", 10000) == 1)
     //if (sendATcommand2(data_ip_protocol, "CONNECT OK", "CONNECT FAIL", 3000) == 1)
     {// ♪♪♪♪♪♪♪♪♪♫ ♫ ♫ Иллюминация правильного состояния модема SIM900 ♪♪♪♪♪♪♪♪
     for (int i=1; i <= 32; i++)
      {
       ledblink();
      }
     }
  else//иначе  SIM900 был выключен или чтото пошло не так
   {  //Если SIM900 не отзывается на самую простую команду он точно выключен или висит
    if  (sendATcommand2("AT", "OK", "OK", 2000) == 0) 
    {  
      Serial.println("SIM900 OFF..."); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
      power_on();
    }
    Serial.println("Connecting to the GSM network..."); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    while ( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000)== 0 );
    //настраиваем sim900 
    initialize_Gprs();  //организуем UDP соединение с narodmon.ru:8283
   }
    if (sendATcommand2("AT", "OK", "OK", 2000) != 0 ) 
    {
     //Передаём данные на сервер 
     send_data();
     //Продолжаем измерение
     sensor_filtr_read(PERIOD,DEPTH_FILTRE);
    }
}
 /*===========================================================================================================*/
void  send_data()
{     digitalWrite(ledPin, HIGH);   // включаем LED
      //Отключаем эхо
      Serial.println("ATE0");
      //Вычисляем данные для передачи
      calculation();
      /*
      В результате в текстовом буфере- buf_ip_data с размером  strlen(buf_ip_data) байт оказалась подобное этому - 
      #112233AACCFF
      #T1#+25.00
      #H1#29.69
      #T2#+25.00
      #P1#754.21
      #Z1#+6.09
      ##
    Это и отправим на сервер narodmon.ru*/      
      sprintf(aux_str,"AT+CIPSEND=%d", strlen(buf_ip_data)); //Указываем модулю число  байт равное  длине данных в  буфера  buf_ip_data
       if (sendATcommand2(aux_str, ">", "ERROR", 10000) == 1)  //если получили приглашение ">"  передаём buf_ip_data в порт.  
        {
          sendATcommand2(buf_ip_data, "SEND OK", "ERROR", 10000); //Если всё прошло нормально, то в ответ получим "SEND OK" 
          delay(500); Serial.println("ATE1"); //Включаем эхо
         /*
          delay(1500);
          Serial.print("\n***********************\n"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print("SEND TO GPRS DATA\n");        //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print("in ");                        //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.println(data_ip_protocol);           //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print(strlen(buf_ip_data));              //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print(" - BYTE\n\n");                //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print(buf_ip_data);                      //Для удобства наладки дублируем на терминал(надо потом закоментировать)
          Serial.print("\n***********************\n\n\n"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         */ 
         }
        else  //Иначе ошибка - ERROR получен из порта или вообще ничего. Не судьба...
         {
           // Closes the socket
           sendATcommand2("AT+CIPCLOSE", "CLOSE OK", "ERROR", 10000);
           powerpulse();
           Serial.println("SEND TO GPRS FAILED"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         } 
      // Closes the socket
      // sendATcommand2("AT+CIPCLOSE", "CLOSE OK", "ERROR", 10000);
      digitalWrite(ledPin, LOW);    // выключаем LED
}
//=========================================================================================================== 
void initialize_Gprs()
{
    // Selects Single-connection mode
    if (sendATcommand2("AT+CIPMUX=0", "OK", "ERROR", 5000) == 1)
    {
        // Waits for status IP INITIAL
        while (sendATcommand2("AT+CIPSTATUS", "INITIAL", "", 5000)  == 0 );
        delay(5000);
        
        // Sets the APN, user name and password
        if (sendATcommand2(command_APN, "OK",  "ERROR", 30000) == 1)
        {            
            // Waits for status IP START
            while (sendATcommand2("AT+CIPSTATUS", "START", "", 5000)  == 0 );
                 
            // Brings Up Wireless Connection
            if (sendATcommand2("AT+CIICR", "OK", "ERROR", 30000) == 1)
            {
                // Waits for status IP GPRSACT
                while (sendATcommand2("AT+CIPSTATUS", "GPRSACT", "", 5000)  == 0 );
                
                // Gets Local IP Address
                if (sendATcommand2("AT+CIFSR", ".", "ERROR", 15000) == 1)
                {
                    // Waits for status IP STATUS
                    while (sendATcommand2("AT+CIPSTATUS", "IP STATUS", "", 5000)  == 0 );
                    //delay(5000);
                    Serial.println("Openning TCP/UDP"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
                    
                 if (sendATcommand2(data_ip_protocol, "CONNECT OK", "CONNECT FAIL", 30000) == 1)
                   //data_ip_protocol = "AT+CIPSTART=\"UDP\",\"IP_address\",\"port\""
                  {
                    return;
                    // Closes the socket
                    //sendATcommand2("AT+CIPCLOSE", "CLOSE OK", "ERROR", 10000);
                  }
                 else 
                  {
                    Serial.println("Error openning the connection"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
                  } // Opens a TCP socket
                }
                else
                {
                   Serial.println("Error getting the IP address"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
                }  
            }
            else
            {
                Serial.println("Error bring up wireless connection"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
            }
        }
        else
        {
            Serial.println("Error setting the APN"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        }
    }
    else
    {
       Serial.println("Error setting the single connection"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    }
    sendATcommand2("AT+CIPSHUT", "OK", "ERROR", 10000);
    powerpulse(); //Выключаем sim900
}

 /*===========================================================================================================*/
void power_on()
{   //Включаем sim900
    Serial.println("Starting  SIM900-ON..."); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    uint8_t answer=0;
    // checks if the module is started
 while (answer == 0)// waits for an answer from the module
 {    // power on pulse
      powerpulse(); 
      //если не понимает "AT" -  включаем правильную скорость модема
      if (sendATcommand2("AT", "OK", "OK", 2000) != 1) bruteforce_speed();
      answer = sendATcommand2("AT", "OK", "OK", 2000);
  } //переинициируем датчики на всякий случай.
    dht.begin(); bmp.begin(); 
    delSMS();
}
 /*===========================================================================================================*/
void  powerpulse() 
{      digitalWrite(onSIM900Pin,HIGH);
      delay(1500);
      digitalWrite(onSIM900Pin,LOW);
      delay(10000);
}
 /*===========================================================================================================*/      
void bruteforce_speed()
{ /* Было так, что пришел модуль с  запрограммированной скоростью 4800 пока допетрил много чая выпито было.
   * так вот, что-бы подобное  не повторялось - бъём хряка  в лоб кувалдой.
   * Иными словами перебираем все скорости и шлём в порт "парле ву франсэ" (команду включения  нужной SPEED_RXTX)
   * по албански , на корякском и других немецких.   */
  
    long int speedBF[] = {1200,2400,4800,9600,19200,38400,57600,115200,SPEED_RXTX};
    for (int i = 0; i < 9; i++) 
     {
      Serial.begin(speedBF[i]);
      Serial.print("AT+IPR="); Serial.println(SPEED_RXTX); 
      delay(500); 
      ledblink();
     }
}

/******************************************************************************************************* 
 * Этой Функйии передаётся 4 параметра 
 * 1- AT-команда для отсылкм в порт
 * 2- Два возможных ответа
 * 3- время ожидания ответа на команду
 * Возвращает 0 если не долждались того, что ждали  за время timeout или 1 или 2 в зависимости от ответа.
 * использует в памяти  100 байтовый буфер.
 *******************************************************************************************************/
int8_t sendATcommand2(char* commandAT, char* expected_answer1,
       char* expected_answer2, unsigned int timeout)
{
    uint8_t x=0,  answer=0; // возвращаемый параметр
    char response[100]; // размер приёмного буфера 
    unsigned long previous; //переменная для хранения времени начала операции
    memset(response, '\0', 100);    // Initialize the string
     
    delay(100);
    while ( Serial.available() > 0) Serial.read();    // Clean the input buffer
    Serial.println(commandAT);    // Send the AT command
    x = 0;
    previous = millis(); //синхронизируем часы
    // this loop waits for the answer
    do {
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if (Serial.available() != 0)
          { response[x] = Serial.read();
            x++;
            // check if the desired answer 1  is in the response of the module
            if (strstr(response, expected_answer1) != NULL)    
             {
                answer = 1;
             }
            // check if the desired answer 2 is in the response of the module
            else if (strstr(response, expected_answer2) != NULL)    
             {
                answer = 2;
             }
          }
        }
    // Waits for the asnwer with time out
    while ((answer == 0) && ((millis() - previous) < timeout) );    
    return answer;
}

 /*===========================================================================================================*/
/****************************************************
В цикле равном глубине фильтрации опрашивем датчик
находим среднее арифметическое за период измерений
*****************************************************/
void sensor_filtr_read(unsigned long timer, int ftr)
{ 
  Serial.print("Connecting to DHT22 period  =  "); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
  Serial.print(timer);                            //Для удобства наладки дублируем на терминал(надо потом закоментировать)
  Serial.println("s.");                           //Для удобства наладки дублируем на терминал(надо потом закоментировать)
  
  //Pressure_f     = 0;
  //Temperature_f = 0;
  temperature_f = 0;
  humidity_f     = 0;
  int Q  =  0;
  
  tempeBMP085_f = 0;
  pressBMP085_f = 0;
  int W  =  0;
  
  for (int i=1; i <= ftr; i++)
   { 
     delayLED(timer);
     // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    digitalWrite(ledPin, HIGH);   // включаем LED
    delay(448);
    float h = dht.readHumidity();
    delay(448);
    float t = dht.readTemperature();
    digitalWrite(ledPin, LOW);    // выключаем LED
       if (isnan(t) || isnan(h)) 
        { //Err++;
         Serial.println("  Failed to read from DHT "); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        
        } 
       else 
        { 
        //temperatureTMP = t; //ПОЛУЧАЕМ DHT22 ТЕМПЕРАТУРУ
        temperature_f = temperature_f + t;
        //humidity_fTMP = h; //ПОЛУЧАЕМ DHT22 ВЛАЖНОСТЬ
        humidity_f    = humidity_f + h;
        Q++;
        
        Serial.print("     DHT "); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.print(t);          //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.print(" C");       //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.print("  ---  ");  //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.print(h);          //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.print("%  ");      //Для удобства наладки дублируем на терминал(надо потом закоментировать)
        Serial.println(Q);        //Для удобства наладки дублируем на терминал(надо потом закоментировать)    
                          
        }
       if (!bmp.begin()) 
        {
	        Serial.println("Could not find a valid BMP085 sensor, check wiring!"); //Для удобства наладки дублируем на терминал(надо потом закоментировать)   
	      } 
       else
        { 
          W++;
          float t = bmp.readTemperature();
          tempeBMP085_f = tempeBMP085_f + t;
          float P = bmp.readPressure();
          pressBMP085_f = pressBMP085_f + P;
         
         Serial.print("     BMP "); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print(t);           //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print(" C");        //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print("  ---  ");   //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print(P);           //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print("Pa  ");      //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print(P/133.3);     //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.print(" MM ");      //Для удобства наладки дублируем на терминал(надо потом закоментировать)
         Serial.println(W);         //Для удобства наладки дублируем на терминал(надо потом закоментировать)         
         
        }
     }
  
   if (Q == 0)
   {
 /*Если датчик DHT вообще неопрашивается - отправляем "отфонарные" значения, 
   по которым определим что есть неисправность датчика*/
    temperatureTMP = -0.01;
   // Serial.println(temperatureTMP); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    humidity_fTMP = -1;
   // Serial.println(humidity_fTMP);    //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   }
   else
   { //среднее показание за период DHT
    temperatureTMP = temperature_f/Q;
    humidity_fTMP=humidity_f/Q;
  //  Serial.println(temperatureTMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   // Serial.println(humidity_fTMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   }
   if (W == 0)
   {
   /** если датчик BMP085 вообще неопрашивается - отправляем "отфонарные" значения, 
 по которым определим что есть неисправность датчика*/
    tempeBMP085TMP = -0.01;
   // Serial.println(tempeBMP085TMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    pressBMP085TMP = -1;
   // Serial.println(pressBMP085TMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   }
   else
   {
   //среднее показание за период BMP085
    tempeBMP085TMP = tempeBMP085_f/W;
    pressBMP085TMP = pressBMP085_f/W;
   // Serial.println(tempeBMP085TMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   // Serial.println(pressBMP085TMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
    pressBMP085_f = pressBMP085_f/W;
    pressBMP085TMP = pressBMP085TMP/133.3;
   // Serial.println(pressBMP085TMP,3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   // Serial.println(pressBMP085TMP/133.3); //Для удобства наладки дублируем на терминал(надо потом закоментировать)
   }
}
 /*===========================================================================================================*/
void calculation()
{   
  char z = '+';
  if ( 0 > temperatureTMP)  z = '-';
  char zBMP = '+';
  if ( 0 > tempeBMP085TMP)  zBMP = '-';
  
   //Форматируем  температуру с DHT22 на вывод 
   float tDHT = abs(temperatureTMP);
   int temptDHT = (tDHT - int(tDHT))*10; // выделяем дробную часть десятые
   int tempTtDHT = (tDHT - int(tDHT))*100-temptDHT*10 ; // выделяем дробную часть сотые
                      
   //Форматируем влажность с DHT22 на вывод                    
   float humidityDHT = float(humidity_fTMP);
   int temp_H_humidityDHT = (humidityDHT - int(humidityDHT))*10; // выделяем дробную часть десятые
   int temp_L_humidityDHT = (humidityDHT - int(humidityDHT))*100-temp_H_humidityDHT*10 ; // выделяем дробную часть сотые
   
   //Форматируем  температуру с BMP085 на вывод 
   float tBMP = abs(tempeBMP085TMP);
   int temptBMP = (tBMP - int(tBMP))*10; // выделяем дробную часть десятые
   int tempttBMP = (tBMP - int(tBMP))*100-temptBMP*10 ; // выделяем дробную часть сотые
  
   //Форматируем  Давление с BMP085 на вывод 
   float pBMP = pressBMP085TMP;
   int tempPBMP = (pBMP - int(pBMP))*10; // выделяем дробную часть десятые
   int tempPPBMP = (pBMP - int(pBMP))*100-tempPBMP*10 ; // выделяем дробную часть сотые
   
   
   
   //Форматируем точку росы на вывод                    
   float dpDHT = float(dewPoint(temperatureTMP, humidity_fTMP));
   char zR = '+';
   if ( 0 > temperatureTMP)  zR = '-';
   dpDHT = abs(dpDHT);
   int tempdpDHT = (dpDHT - int(dpDHT))*10; // выделяем дробную часть десятые
   int tempDPTDHT = (dpDHT - int(dpDHT))*100-tempdpDHT*10 ; // выделяем дробную часть сотые

   //Форматируем время работы на вывод
   tim = millis();
   float timems1 = float(tim)/1000/3600;
   int working1 = timems1;
   int working2 = timems1*10 - working1*10;
   int working3 = timems1*100 - working1*100 - working2*10;  
    
    //Трамбуем в символьный буфер "buf_ip_data" в установленном для отправки на narodmon.ru формате. 
    sprintf(buf_ip_data,"#" MAC_ADDRESS "\n" SOURCE_1  "%c%d.%d%d" "\n" SOURCE_2 "%d.%d%d" "\n" SOURCE_3  "%c%d.%d%d" "\n" SOURCE_4 "%d.%d%d" "\n" SOURCE_5  "%c%d.%d%d" "\n" SOURCE_6 "%d.%d%d" "\n" endCODE,
    z, abs(int(tDHT)), abs(temptDHT), abs(tempTtDHT), 
    int(humidityDHT), abs(temp_H_humidityDHT), abs(temp_L_humidityDHT),
    zBMP, abs(int(tBMP)),  abs(temptBMP), abs(tempttBMP), 
    int(pBMP), abs(tempPBMP), abs(tempPPBMP),
    zR, abs(int(dpDHT)), abs(tempdpDHT), abs(tempDPTDHT), 
    working1 , working2, working3 );
    
    
  // Serial.print(buf_ip_data); //Для удобства наладки дублируем на терминал(надо потом закоментировать) 
   
}

 /*===========================================================================================================*/
void delSMS() 
{    // Delete All messages
     //mySerial.println( "AT+CMGF=1" ); // Did not help
     //delay(1000);                      //Did not help
     //Serial.println( "Delete SMS from SIMCARD" );
     Serial.println("AT+CMGDA=\"DEL ALL\""); 
     //Serial.println("DEL ALL\"");
     delay(5000);
     Serial.println("AT+CMGD=4");
     delay(5000);
     Serial.println( "All Messages Deleted" );
}
 /*===========================================================================================================*/
void delayLED(unsigned long cicle)
{
  for (int i=1; i <= cicle; i++)
  {
   digitalWrite(ledPin,LOW);
   delay(450);
   Serial.print("*");
   digitalWrite(ledPin,HIGH);
   delay(100);
   digitalWrite(ledPin,LOW);
   delay(450);
  }
  Serial.print("\n");
}
 /*===========================================================================================================*/
// dewPoint function NOAA
//Эмпирическая формула получения точки росы длинная
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double dewPoint(double celsius, double humidity)
{
        double A0= 373.15/(273.15 + celsius);
        double SUM = -7.90298 * (A0-1);
        SUM += 5.02808 * log10(A0);
        SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
        SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
        SUM += log10(1013.246);
        double VP = pow(10, SUM-3) * humidity;
        double T = log(VP/0.61078);   // temp var
        return (241.88 * T) / (17.558-T);
}
/*===========================================================================================================*/
void ledblink()
{
  digitalWrite(ledPin, HIGH);   // включаем LED
  delay(80);
  digitalWrite(ledPin, LOW);    // выключаем LED
  delay(80);
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
 /*===========================================================================================================*/
/*
//Эмпирическая формула получения точки росы короткая
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
        double a = 17.271;
        double b = 237.7;
        double temp = (a * celsius) / (b + celsius) + log(humidity/100);
        double Td = (b * temp) / (a - temp);
        return Td;
}


void asmreset() 
  {
    asm volatile ("jmp 0x0000");
  }
  */

 

iStefan
Offline
Зарегистрирован: 19.03.2016

Доброго дня! Собрался повторить термометр с отправкой данных на narodmon.ru из предидущего сообщения, но при проверке высыпалось множество ошибок с которыми не смог справится (в програмировании новичок). Вопрос к автору как повторить ваш проект?

rapidshe
Offline
Зарегистрирован: 31.12.2015

sav13 пишет:

Всем кто работает с GSM/GPRS модулями совет - храните AT команды в PROGMEM. Иначе они очень быстро съедают оперативную память и скетч начинает глючить (перезагружается, виснет, сбивает перемнные). Никаких аппаратных проблем по питанию, например с USB в связке UNO - SIM900 не выявлено.

Добрый день! не могли бы дать пример скетча  с PROGMEM для SIM900

rapidshe
Offline
Зарегистрирован: 31.12.2015

sav13, Вроде бы сделал с PROGMEN, но глюки не ушли. но наблюдаю у себя вроде бы то же что и было у вас

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

мой изначальный вариант скетча:

#include <SoftwareSerial.h>
#include <OneWire.h>
#include <EEPROM.h>
#include <RCSwitch.h>
SoftwareSerial gsm(7, 8); 
OneWire  ds(10);
RCSwitch RC = RCSwitch();


unsigned long TimePrint; // из конечного устройства можно убрать


int che=1; //
//Сигнализация


unsigned long loopTime[4]; //указать количество беспроводных датчиков сигнализации
unsigned long currentTime;
unsigned long zaderjkaSignSMS = 10000;//интервал между сообщениями сигнализации 1000=1секунда

//Беспроводные датчики
byte numRC = 4; //количество беспроводных датчиков сигнализации
int RCvalue[4] = {12410657,12410658,12410660,12410664}; //добавить коды всех датчиков через запятую
String RCvalueName [4] = {"Kuhn9","Dver' vhod","Dver' garaj","Luk"}; //названия должны соответствовать кодам датчиков из предыдущей строки


//датчики температуры DS18B20
//____НЕОБХОДИМО ПРОПИСАТЬ АДРЕСА СВОИХ ДАТЧИКОВ______
byte flagDallRead;
byte addr[1][8]={{0x28,0xBC,0x74,0x03,0x00,0x00,0x80,0x12}}; //в первых скобках [] скобках необхлодимо указать сколько у вас DS18B20 и в фигурных скобках прописать их адреса {{},{}.....{},{}} 
byte numDS = 1; // количество DS18B20.
float Temp[1]; //в скобках указать количество ваших DS18B20
bool TkritFlag = true;
int TkritMax;
int TkritMin;
unsigned long loopTimeTemp;
unsigned long zaderjkaTempSMS = 30000;//000; //интервал между сообщениями о критической температуре 1000=1секунда



//ДЛЯ GSM и около него
boolean isStringMessage = false;  // Переменная принимает значение True, если текущая строка является сообщением
int ch;
String sms = "";
String val = ""; 
String val1 = ""; //переменная для хранения технической информации сообщения/звонка (номер, время)
String val2 = ""; //переменная для хравнения содержания полученной СМСки
String master1 = "7916ХХХххХХ"; /ваш номер
byte PIN_PWRKEY = 9; //пин включения sim900

//ДЛЯ РЕЛЕ
byte Pins[6] = {14, 15, 16, 17,18,19}; // Массив задействованных номеров Pins Arduino, для управления реле. 
byte PinStatus[6]; // Массив для фиксации изменений
byte numPins = 6; // количество реле
byte ON = HIGH; //для проверки работоспособности на светодиодах ON=HIGH, для реле ON=LOW
byte OFF = LOW; //для проверки работоспособности на светодиодах OFF=LOW, для реле OFF=HIGH


void setup() {
{// GSM 
 pinMode(9, OUTPUT);
  digitalWrite(9,LOW);
  delay(1000);
  digitalWrite(9,HIGH);
  delay(2000);
  digitalWrite(9,LOW);
  delay(15000);

    Serial.begin(9600);
    gsm.begin(19200);
    //gsm.write("A\r"); // отправляем А чтобы sim900 автоматически настроился на скорость
//    delay(1000);
//gsm.println("AT+IPR=19200\r");
    delay(100);
gsm.print("AT+CMGF=1\r");         //устанавливает текстовый режим смс-сообщения
    delay(300);
gsm.print("AT+IFC=1, 1\r");       //устанавливает программный контроль потоком передачи данных
    delay(300);
gsm.print("AT+CPBS=\"SM\"\r");    //открывает доступ к данным телефонной книги SIM-карты
    delay(300);
gsm.print("AT+GSMBUSY=1, 1\r");   //запрет всех входящих звонков
    delay(300);
gsm.print("AT+CMGDA=«DEL ALL»\r");  //Очищаем накопившиеся СМС
    delay(300);
gsm.print("AT+CNMI=1,2,2,1,0\r"); //включает оповещение о новых сообщениях
    delay(10000);}
che=EEPROM.read(10);
TkritMin=EEPROMReadInt(11);
TkritMax=EEPROMReadInt(13);
TkritFlag=EEPROM.read(15);

RC.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
for(int i = 0; i <= numPins -1; i++) { //восставновление состояния реле
   pinMode(Pins[i],OUTPUT);
   PinStatus[i]=EEPROM.read(i); //считываем состояние до перезагрузки ардуины
   digitalWrite(Pins[i],PinStatus[i]); //восстанавливаем состояние реле
   } 
for(int i = 0; i <= numRC -1; i++) { //для отправки смс
   loopTime[i] = 0;
   } 
   TimePrint = 0;
   loopTimeTemp = 0;
Serial.println("GOTOVO");
}

void loop() {
      currentTime = millis();       // считываем время, прошедшее с момента запуска программы
      dallRead(flagDallRead * 1000);
if (Serial.available()) {  //обработка Serial данных
    while (Serial.available()) 
         {  //сохраняем строку в переменную val
         ch = Serial.read();
         val2 += char(ch);
         delay(10);
         }
         Serial.println(val2);
   val1=master1; 
   razborkomand();
   val2="";
   val1="";  //очищаем
  }
if (gsm.available()) {//если модуль что то шлет
    while(gsm.available()) 
         {
          ch = gsm.read();
          if(ch == '\r') continue;
          if(ch == '\n') 
            {
            gsmRead(val); 
            val = ""; 
            }
          else val += char(ch);
         }
    }
if (RC.available()) { //Обработка беспроводных датчиков
  if (che == 1) {
   //обработа сигналов с беспроводных датчиков
     ch = RC.getReceivedValue(); 
     for(int i = 0; i <= numRC -1; i++) 
        {
        if (ch == RCvalue[i]) 
           {
           if (currentTime >= loopTime[i])
              {
              loopTime[i] = currentTime + zaderjkaSignSMS;
              Alarm(RCvalueName[i]);
              for(int n = 0; n <= numRC -1; n++)
                 {
                 if (n!=i)
                    {
                    loopTime[n] = 0;  
                    }
                 }
              
              }
           
           }
        }
     
   }
   RC.resetAvailable();
   }
if (TkritFlag) { //если TkritFlag=true, заходим в оповещения о крит температуре
   for(byte n = 0; n <= numDS-1; n++) //перебор всех темп. датчиков 
      {
      if (Temp[n]!=-0.06 && Temp[n]!=0.00)
         {
         if ((Temp[n] <= TkritMin) || (Temp[n] >= TkritMax))
            {
            if (currentTime >= loopTimeTemp)
               {
               TempStatus(master1);
               loopTimeTemp = currentTime + zaderjkaTempSMS; 
               }
            }
         }
      }
   }

  { //Печать данных в монитор. нужно только для отладки. из конечного устройства вырезать
  if (currentTime >= TimePrint) 
     {
     TimePrint = currentTime+15000;
     Serial.print("Temp1=");
     Serial.println(Temp[0]);
     Serial.println("- - - - - -");
     }  
  }
}



void Alarm(String zona) {
sms = "Trevoga!";
sms += zona;
smssend(master1);
Serial.println("Trevoga! " + zona);
}
void razborkomand () {
if (val1.indexOf(master1) > -1) //на команды в этом блоке придет ответ
   {
   if (val2.indexOf("Pozvoni") > -1) Proslushka(master1); //если в сообщении "позвони", ардуинка звонит нам на номер, с которого пришел запрос
   if (val2.indexOf("Temp?") > -1) TempStatus(master1); //если в сообщении "температура?", ардуинка высылает температуры на номер, с которого пришел запрос
   if (val2.indexOf("Tkriton") > -1) TkritONOFF(true, master1); // {TkritFlag = true; EEPROM.write(15,TkritFlag);Serial.println("Tkriton");}
   if (val2.indexOf("Tkritoff") > -1) TkritONOFF(false, master1); // {TkritFlag = false; EEPROM.write(15,TkritFlag);Serial.println("Tkritoff");}
   if (val2.indexOf("Off") > -1) AlarmSet(0, master1, String ("OFF")); //если в сообщении "OFF", ардуинка выключает режим сигнализации и отправляет смс с оповещением о сняьтт с сигнализации тому, кто прислал команду
   if (val2.indexOf("On") > -1) AlarmSet(1, master1, String ("ON")); //если в сообщении "ON", ардуинка включает режим сигнализации и отправляет смс с оповещением о постановке на сигнализацию тому, кто прислал команду
   if (val2.indexOf("Vkl") > -1) { //если в сообщении "вкл1234", включить реле №1 и №2 и №3 и №4
      sms = "Vklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, ON);
      if (val2.indexOf("2")> -1) RelaySet(2, ON);
      if (val2.indexOf("3")> -1) RelaySet(3, ON);
      if (val2.indexOf("4")> -1) RelaySet(4, ON);
      if (val2.indexOf("5")> -1) RelaySet(5, ON);
      if (val2.indexOf("6")> -1) RelaySet(6, ON);
      smssend(master1);
      } 
   if (val2.indexOf("Vikl") > -1) { //если в сообщении "выкл1234", выключить реле №1 и №2 и №3 и №4
      sms = "Viklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, OFF);
      if (val2.indexOf("2")> -1) RelaySet(2, OFF);
      if (val2.indexOf("3")> -1) RelaySet(3, OFF);
      if (val2.indexOf("4")> -1) RelaySet(4, OFF);
      if (val2.indexOf("5")> -1) RelaySet(5, OFF);
      if (val2.indexOf("6")> -1) RelaySet(6, OFF);
      smssend(master1);
      } 

   }
if (val2.indexOf("Tkritmin") > -1) {val1= val2.substring(9, 14); Serial.println(val1); TkritMin = val1.toInt(); Serial.println(TkritMin); EEPROMWriteInt(11,TkritMin);}
if (val2.indexOf("Tkritmax") > -1) {val1= val2.substring(9, 12); Serial.println(val1); TkritMax = val1.toInt(); Serial.println(TkritMax); EEPROMWriteInt(13,TkritMax);}
}
void TkritONOFF (boolean onoff, String phone) {
  TkritFlag = onoff;
  EEPROM.write(15,TkritFlag);
  Serial.println(TkritFlag);
  if (TkritFlag) 
     {
     sms = "TKrit VKL";
     sms += '\n';
     sms += "Tmin ";
     sms += TkritMin;
     sms += '\n';
     sms += "Tmax ";
     sms += TkritMax;
     }
  if (TkritFlag==false)
     {
     sms = "TKrit VIKL";
     }
  smssend(phone);
}
void gsmRead(const String val) { //разбираем данные от gsm
 if (!val.startsWith("+CMT") && isStringMessage == false ) {Serial.println(val);} //если НЕ смс и это не вторая строка(которая является непосредственно сообщением), значит это иная информация от модуля. выводим в сериал
 
 if (isStringMessage == true) // если флаг "ПРАВДА", значит дошли до строки с сообщением
    {
    isStringMessage = false;  // меняем флаг на "ЛОЖЬ", чтобы при обработке последующей информации, не относящейся к сообщению, в этот кусок не попасть снова
    if (val1.indexOf(master1) > -1) // Если в первой строке VAL1 есть мастер(или один из номеров) номер
       {
       Serial.println("master"); //в сериал шлется, что сообщение от мастера
       val2 = val; // сохраняем в переменную
       Serial.println("VAL2: " + val2); // выводим в сериал 
       razborkomand();  // разбираем что за команда пришла
       }
    else Serial.println("NE master");
    }
 else 
    { 
    if (val.startsWith("+CMT"))  // если текущая строка начинается с "+CMT", то следующая строка является сообщением;
       {
       val1=val; 
       isStringMessage = true; //флаг означающий, что следующая строка сообщение
       Serial.println("VAL1: " + val1); // выводим в сериал 
       } 
    }   
}  
void smssend(String phone) { //процедура отправки СМС
//   Serial.print(sms);   Serial.println(phone); 
  Serial.println("SMS send started");
  gsm.print("AT+CMGF=1\r");
  delay(100);
  gsm.println("AT + CMGS = \"+" + phone + "\"");
  delay(100);
  gsm.print(sms);
//  text = ""; 
  delay(100);
  gsm.print((char)26);
  delay(100);
  Serial.println("SMS send complete");
  sms="";
}
void Proslushka(String phone){ //Цикл дозвона абоненту (для аудиоконтроля)___________________
  gsm.println("AT+CMIC=0,10");    // Команда для установки чувствительности микрофона Поэкспериментировать с цифрой.
// 0,- это канал микрофона (1,2,3),15 это уровень см.инструкцию к СИМ900
delay(2000);
  gsm.println("ATD+"+ phone + ";");  // Набираем номер
//Serial2.println("ATH"); // Вешаем трубку
}
void RelaySet(byte rnum, byte state) { //управление реле
  PinStatus[(rnum-1)] = state; 
  digitalWrite(Pins[(rnum-1)],PinStatus[(rnum-1)]); 
  EEPROM.write((rnum-1),PinStatus[(rnum-1)]); //запись в энергонезависимую память состояния реле для вооставноления этого состояния после потери питания
  sms += rnum;
}
void AlarmSet(int vklvikl, String phone, String onoff) {
  che = vklvikl;
  EEPROM.write(10,che);
  sms=onoff;
  smssend(phone);

}
void TempStatus(String phone) {
  sms = "";
  for(byte n = 0; n <= numDS-1; n++) 
      {
      sms += "T";
      sms += (n+1);
      sms += " ";
      sms += Temp[n];
      sms += "C";
      sms += '\n';
      }
  smssend(phone);

  sms = "";
}
void EEPROMWriteInt(int address, int value) { //Запись двухбайтового числа в память
  EEPROM.write(address, lowByte(value));
  EEPROM.write(address + 1, highByte(value));
}
unsigned int EEPROMReadInt(int address) { //Чтение числа из памяти
  byte lowByte = EEPROM.read(address);
  byte highByte = EEPROM.read(address + 1);
  return (highByte << 8) | lowByte;
}
void dallRead(unsigned long interval){ //температура
  static unsigned long prevTime = 0;
  if (millis() - prevTime > interval) { //Проверка заданного интервала
  static boolean flagDall = 0; //Признак операции
  prevTime = millis();
  flagDall =! flagDall; //Инверсия признака
  if (flagDall) {
    ds.reset();
    ds.write(0xCC); //Обращение ко всем датчикам
    ds.write(0x44); //Команда на конвертацию
    flagDallRead = 1; //Время возврата в секундах
  }
  else {
    byte i;
     int temp;
    for (i = 0; i < 3; i++){ //Перебор количества датчиков
     ds.reset();
     ds.select(addr[i]);
     ds.write(0xBE); //Считывание значения с датчика
     temp = (ds.read() | ds.read()<<8); //Принимаем два байта температуры
     Temp[i] = (float)temp / 16.0; 
     flagDallRead = 2; //Время возврата в секундах
     }
   }
  }
}

попытка два, с (F(.....));

#include <SoftwareSerial.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <OneWire.h>
#include <EEPROM.h>
#include <RCSwitch.h>
SoftwareSerial gsm(7, 8); 
OneWire  ds(10);
RCSwitch RC = RCSwitch();


unsigned long TimePrint; // из конечного устройства можно убрать


int che=1; //
//Сигнализация


unsigned long loopTime[4]; //указать количество беспроводных датчиков сигнализации
unsigned long currentTime;
unsigned long zaderjkaSignSMS = 10000;//интервал между сообщениями сигнализации 1000=1секунда

//Беспроводные датчики
byte numRC = 4; //количество беспроводных датчиков сигнализации
int RCvalue[4] = {12410657,12410658,12410660,12410664}; //добавить коды всех датчиков через запятую
String RCvalueName [4] = {"Kuhn9","Dver' vhod","Dver' garaj","Luk"}; //названия должны соответствовать кодам датчиков из предыдущей строки


//датчики температуры DS18B20
//____НЕОБХОДИМО ПРОПИСАТЬ АДРЕСА СВОИХ ДАТЧИКОВ______
byte flagDallRead;
byte addr[1][8]={{0x28,0xBC,0x74,0x03,0x00,0x00,0x80,0x12}}; //в первых скобках [] скобках необхлодимо указать сколько у вас DS18B20 и в фигурных скобках прописать их адреса {{},{}.....{},{}} 
byte numDS = 1; // количество DS18B20.
float Temp[1]; //в скобках указать количество ваших DS18B20
bool TkritFlag = true;
int TkritMax;
int TkritMin;
unsigned long loopTimeTemp;
unsigned long zaderjkaTempSMS = 30000;//000; //интервал между сообщениями о критической температуре 1000=1секунда



//ДЛЯ GSM и около него
boolean isStringMessage = false;  // Переменная принимает значение True, если текущая строка является сообщением
int ch;
String sms = "";
String val = ""; 
String val1 = ""; //переменная для хранения технической информации сообщения/звонка (номер, время)
String val2 = ""; //переменная для хравнения содержания полученной СМСки
String master1 = "7916xxxxxxx"; //ваш номер
byte PIN_PWRKEY = 9; //пин включения sim900




//ДЛЯ РЕЛЕ
byte Pins[6] = {14, 15, 16, 17,18,19}; // Массив задействованных номеров Pins Arduino, для управления реле. 
byte PinStatus[6]; // Массив для фиксации изменений
byte numPins = 6; // количество реле
byte ON = HIGH; //для проверки работоспособности на светодиодах ON=HIGH, для реле ON=LOW
byte OFF = LOW; //для проверки работоспособности на светодиодах OFF=LOW, для реле OFF=HIGH

void reboot() {
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
}

void setup() {

  pinMode(12, INPUT); 
  Serial.begin(9600);
  Serial.println(F("START")); 
  pinMode(19, OUTPUT); 
  digitalWrite(19,LOW); 
  
  {// GSM 
 if (digitalRead(12)==LOW) //пин12 мониторит включенность ГСМ(напругу на светодиоде status). если ГСМ выключен, то после включения ардуина перезагружается и загружается при ключенном ГСМ
    {
    Serial.println(F("Budet RESET")); 
    pinMode(9, OUTPUT);
    digitalWrite(9,LOW);
    delay(1000);
    digitalWrite(9,HIGH);
    delay(2000);
    digitalWrite(9,LOW);
    delay(15000);
    reboot();
    delay(500);
    }
    
gsm.begin(19200);
    //gsm.write("A\r"); // отправляем А чтобы sim900 автоматически настроился на скорость
//    delay(1000);
//gsm.println("AT+IPR=19200\r");
    delay(100);
gsm.print(F("AT+CMGDA=\"DEL ALL\"\r"));  //Очищаем накопившиеся СМС
    delay(300);
    gsm.print(F("AT+CMGF=1\r"));         //устанавливает текстовый режим смс-сообщения
    delay(300);
gsm.print(F("AT+IFC=1, 1\r"));       //устанавливает программный контроль потоком передачи данных
    delay(300);
gsm.print(F("AT+CPBS=\"SM\"\r"));    //открывает доступ к данным телефонной книги SIM-карты
    delay(300);
//gsm.print(F("AT+GSMBUSY=1, 1\r"));   //запрет всех входящих звонков
//    delay(300);

gsm.print(F("AT+CNMI=1,2,2,1,0\r")); //включает оповещение о новых сообщениях
    delay(300);}
che=EEPROM.read(10);
TkritMin=EEPROMReadInt(11);
TkritMax=EEPROMReadInt(13);
TkritFlag=EEPROM.read(15);

RC.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
for(int i = 0; i <= numPins -1; i++) { //восставновление состояния реле
   pinMode(Pins[i],OUTPUT);
   PinStatus[i]=EEPROM.read(i); //считываем состояние до перезагрузки ардуины
   digitalWrite(Pins[i],PinStatus[i]); //восстанавливаем состояние реле
   } 
for(int i = 0; i <= numRC -1; i++) { //для отправки смс
   loopTime[i] = 0;
   } 
   TimePrint = 0;
   loopTimeTemp = 0;
Serial.println(F("GOTOVO"));
}

void loop() {
      currentTime = millis();       // считываем время, прошедшее с момента запуска программы
      dallRead(flagDallRead * 1000);
if (Serial.available()) {  //обработка Serial данных
    while (Serial.available()) 
         {  //сохраняем строку в переменную val
         ch = Serial.read();
         val2 += char(ch);
         delay(10);
         }
         Serial.println(val2);
   val1=master1; 
   razborkomand();
   val2="";
   val1="";  //очищаем
  }
if (gsm.available()) {//если модуль что то шлет
    while(gsm.available()) 
         {
          ch = gsm.read();
          if(ch == '\r') continue;
          if(ch == '\n') 
            {
            gsmRead(val); 
            val = ""; 
            }
          else val += char(ch);
         }
    }
if (RC.available()) { //Обработка беспроводных датчиков
  if (che == 1) {
   //обработа сигналов с беспроводных датчиков
     ch = RC.getReceivedValue(); 
     for(int i = 0; i <= numRC -1; i++) 
        {
        if (ch == RCvalue[i]) 
           {
           if (currentTime >= loopTime[i])
              {
              loopTime[i] = currentTime + zaderjkaSignSMS;
              Alarm(RCvalueName[i]);
              for(int n = 0; n <= numRC -1; n++)
                 {
                 if (n!=i)
                    {
                    loopTime[n] = 0;  
                    }
                 }
              
              }
           
           }
        }
     
   }
   RC.resetAvailable();
   }
if (TkritFlag) { //если TkritFlag=true, заходим в оповещения о крит температуре
   for(byte n = 0; n <= numDS-1; n++) //перебор всех темп. датчиков 
      {
      if (Temp[n]!=-0.06 && Temp[n]!=0.00)
         {
         if ((Temp[n] <= TkritMin) || (Temp[n] >= TkritMax))
            {
            if (currentTime >= loopTimeTemp)
               {
               TempStatus(master1);
               loopTimeTemp = currentTime + zaderjkaTempSMS; 
               }
            }
         }
      }
   }

  { //Печать данных в монитор. нужно только для отладки. из конечного устройства вырезать
  if (currentTime >= TimePrint) 
     {
     TimePrint = currentTime+15000;
     Serial.print(F("Temp1="));
     Serial.println(Temp[0]);
     Serial.println(F("- - - - - -"));
     }  
  }
}



void Alarm(String zona) {
sms = "Trevoga!";
sms += zona;
smssend(master1);
Serial.println(F("Trevoga! "));
Serial.println(zona);
}
void razborkomand () {
if (val1.indexOf(master1) > -1) //на команды в этом блоке придет ответ
   {
   if (val2.indexOf("Pozvoni") > -1) Proslushka(master1); //если в сообщении "позвони", ардуинка звонит нам на номер, с которого пришел запрос
   if (val2.indexOf("Temp?") > -1) TempStatus(master1); //если в сообщении "температура?", ардуинка высылает температуры на номер, с которого пришел запрос
   if (val2.indexOf("Tkriton") > -1) TkritONOFF(true, master1); // {TkritFlag = true; EEPROM.write(15,TkritFlag);Serial.println("Tkriton");}
   if (val2.indexOf("Tkritoff") > -1) TkritONOFF(false, master1); // {TkritFlag = false; EEPROM.write(15,TkritFlag);Serial.println("Tkritoff");}
   if (val2.indexOf("Off") > -1) AlarmSet(0, master1, String ("OFF")); //если в сообщении "OFF", ардуинка выключает режим сигнализации и отправляет смс с оповещением о сняьтт с сигнализации тому, кто прислал команду
   if (val2.indexOf("On") > -1) AlarmSet(1, master1, String ("ON")); //если в сообщении "ON", ардуинка включает режим сигнализации и отправляет смс с оповещением о постановке на сигнализацию тому, кто прислал команду
   if (val2.indexOf("Vkl") > -1) { //если в сообщении "вкл1234", включить реле №1 и №2 и №3 и №4
      sms = "Vklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, ON);
      if (val2.indexOf("2")> -1) RelaySet(2, ON);
      if (val2.indexOf("3")> -1) RelaySet(3, ON);
      if (val2.indexOf("4")> -1) RelaySet(4, ON);
      if (val2.indexOf("5")> -1) RelaySet(5, ON);
      if (val2.indexOf("6")> -1) RelaySet(6, ON);
      smssend(master1);
      } 
   if (val2.indexOf("Vikl") > -1) { //если в сообщении "выкл1234", выключить реле №1 и №2 и №3 и №4
      sms = "Viklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, OFF);
      if (val2.indexOf("2")> -1) RelaySet(2, OFF);
      if (val2.indexOf("3")> -1) RelaySet(3, OFF);
      if (val2.indexOf("4")> -1) RelaySet(4, OFF);
      if (val2.indexOf("5")> -1) RelaySet(5, OFF);
      if (val2.indexOf("6")> -1) RelaySet(6, OFF);
      smssend(master1);
      } 

   }
if (val2.indexOf("Tkritmin") > -1) {val1= val2.substring(9, 14); Serial.println(val1); TkritMin = val1.toInt(); Serial.println(TkritMin); EEPROMWriteInt(11,TkritMin);}
if (val2.indexOf("Tkritmax") > -1) {val1= val2.substring(9, 12); Serial.println(val1); TkritMax = val1.toInt(); Serial.println(TkritMax); EEPROMWriteInt(13,TkritMax);}
}
void TkritONOFF (boolean onoff, String phone) {
  TkritFlag = onoff;
  EEPROM.write(15,TkritFlag);
  Serial.println(TkritFlag);
  if (TkritFlag) 
     {
     sms = "TKrit VKL";
     sms += '\n';
     sms += "Tmin ";
     sms += TkritMin;
     sms += '\n';
     sms += "Tmax ";
     sms += TkritMax;
     }
  if (TkritFlag==false)
     {
     sms = "TKrit VIKL";
     }
  smssend(phone);
}
void gsmRead(const String val) { //разбираем данные от gsm
 if (!val.startsWith("+CMT") && isStringMessage == false ) {Serial.println(val);} //если НЕ смс и это не вторая строка(которая является непосредственно сообщением), значит это иная информация от модуля. выводим в сериал
 
 if (isStringMessage == true) // если флаг "ПРАВДА", значит дошли до строки с сообщением
    {
    isStringMessage = false;  // меняем флаг на "ЛОЖЬ", чтобы при обработке последующей информации, не относящейся к сообщению, в этот кусок не попасть снова
    if (val1.indexOf(master1) > -1) // Если в первой строке VAL1 есть мастер(или один из номеров) номер
       {
       Serial.println(F("master")); //в сериал шлется, что сообщение от мастера
       val2 = val; // сохраняем в переменную
       Serial.print(F("VAL2: ")); // выводим в сериал 
       Serial.println(val2);
       razborkomand();  // разбираем что за команда пришла
       }
    else Serial.println(F("NE master"));
    }
 else 
    { 
    if (val.startsWith("+CMT"))  // если текущая строка начинается с "+CMT", то следующая строка является сообщением;
       {
       val1=val; 
       isStringMessage = true; //флаг означающий, что следующая строка сообщение
       Serial.println(F("VAL1: ")); // выводим в сериал 
       Serial.println(val1);
       } 
    }   
}  
void smssend(String phone) { //процедура отправки СМС
//   Serial.print(sms);   Serial.println(F(phone); 
  Serial.println(F("SMS send started"));
  gsm.print(F("AT+CMGF=1\r"));
  delay(100);
  gsm.print(F("AT + CMGS = \"+"));
  gsm.print(phone);
  gsm.println(F("\""));
  delay(100);
  gsm.print(sms);
//  text = ""; 
  delay(100);
  gsm.print((char)26);
  delay(100);
  Serial.println(F("SMS send complete"));
  sms="";
}
void Proslushka(String phone){ //Цикл дозвона абоненту (для аудиоконтроля)___________________
  gsm.println(F("AT+CMIC=0,10"));    // Команда для установки чувствительности микрофона Поэкспериментировать с цифрой.
// 0,- это канал микрофона (1,2,3),15 это уровень см.инструкцию к СИМ900
delay(2000);
  gsm.print(F("ATD+"));  // Набираем номер
  gsm.print(phone);
  gsm.println(F(";"));
//Serial2.println("ATH"); // Вешаем трубку
}
void RelaySet(byte rnum, byte state) { //управление реле
  PinStatus[(rnum-1)] = state; 
  digitalWrite(Pins[(rnum-1)],PinStatus[(rnum-1)]); 
  EEPROM.write((rnum-1),PinStatus[(rnum-1)]); //запись в энергонезависимую память состояния реле для вооставноления этого состояния после потери питания
  sms += rnum;
}
void AlarmSet(int vklvikl, String phone, String onoff) {
  che = vklvikl;
  EEPROM.write(10,che);
  sms=onoff;
  smssend(phone);

}
void TempStatus(String phone) {
  sms = "";
  for(byte n = 0; n <= numDS-1; n++) 
      {
      sms += "T";
      sms += (n+1);
      sms += " ";
      sms += Temp[n];
      sms += "C";
      sms += '\n';
      }
  smssend(phone);

  sms = "";
}
void EEPROMWriteInt(int address, int value) { //Запись двухбайтового числа в память
  EEPROM.write(address, lowByte(value));
  EEPROM.write(address + 1, highByte(value));
}
unsigned int EEPROMReadInt(int address) { //Чтение числа из памяти
  byte lowByte = EEPROM.read(address);
  byte highByte = EEPROM.read(address + 1);
  return (highByte << 8) | lowByte;
}
void dallRead(unsigned long interval){ //температура
  static unsigned long prevTime = 0;
  if (millis() - prevTime > interval) { //Проверка заданного интервала
  static boolean flagDall = 0; //Признак операции
  prevTime = millis();
  flagDall =! flagDall; //Инверсия признака
  if (flagDall) {
    ds.reset();
    ds.write(0xCC); //Обращение ко всем датчикам
    ds.write(0x44); //Команда на конвертацию
    flagDallRead = 1; //Время возврата в секундах
  }
  else {
    byte i;
     int temp;
    for (i = 0; i < 3; i++){ //Перебор количества датчиков
     ds.reset();
     ds.select(addr[i]);
     ds.write(0xBE); //Считывание значения с датчика
     temp = (ds.read() | ds.read()<<8); //Принимаем два байта температуры
     Temp[i] = (float)temp / 16.0; 
     flagDallRead = 2; //Время возврата в секундах
     }
   }
  }
}

попытка с прогмен:

#include <SoftwareSerial.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <OneWire.h>
#include <EEPROM.h>
#include <RCSwitch.h>
SoftwareSerial gsm(7, 8); 
OneWire  ds(10);
RCSwitch RC = RCSwitch();


unsigned long TimePrint; // из конечного устройства можно убрать


int che=1; //
//Сигнализация


unsigned long loopTime[4]; //указать количество беспроводных датчиков сигнализации
unsigned long currentTime;
unsigned long zaderjkaSignSMS = 10000;//интервал между сообщениями сигнализации 1000=1секунда

//Беспроводные датчики
byte numRC = 4; //количество беспроводных датчиков сигнализации
int RCvalue[4] = {12410657,12410658,12410660,12410664}; //добавить коды всех датчиков через запятую
String RCvalueName [4] = {"Kuhn9","Dver' vhod","Dver' garaj","Luk"}; //названия должны соответствовать кодам датчиков из предыдущей строки


//датчики температуры DS18B20
//____НЕОБХОДИМО ПРОПИСАТЬ АДРЕСА СВОИХ ДАТЧИКОВ______
byte flagDallRead;
byte addr[1][8]={{0x28,0xBC,0x74,0x03,0x00,0x00,0x80,0x12}}; //в первых скобках [] скобках необхлодимо указать сколько у вас DS18B20 и в фигурных скобках прописать их адреса {{},{}.....{},{}} 
byte numDS = 1; // количество DS18B20.
float Temp[1]; //в скобках указать количество ваших DS18B20
bool TkritFlag = true;
int TkritMax;
int TkritMin;
unsigned long loopTimeTemp;
unsigned long zaderjkaTempSMS = 30000;//000; //интервал между сообщениями о критической температуре 1000=1секунда



//ДЛЯ GSM и около него
boolean isStringMessage = false;  // Переменная принимает значение True, если текущая строка является сообщением
int ch;
String sms = "";
String val = ""; 
String val1 = ""; //переменная для хранения технической информации сообщения/звонка (номер, время)
String val2 = ""; //переменная для хравнения содержания полученной СМСки
String master1 = "7916xxxxxxx"; //ваш номер
byte PIN_PWRKEY = 9; //пин включения sim900


const char string_0[] PROGMEM = "AT+CMGF=1\r"; 
const char string_1[] PROGMEM = "AT+IFC=1, 1\r";
const char string_2[] PROGMEM = "AT+CPBS=\"SM\"\r";
const char string_3[] PROGMEM = "AT+CMGDA=\"DEL ALL\"\r";
const char string_4[] PROGMEM = "AT+CNMI=1,2,2,1,0\r";
const char string_5[] PROGMEM = "AT + CMGS = \"+";
const char string_6[] PROGMEM = "AT+CMIC=0,10";
const char string_7[] PROGMEM = "ATD+";
const char string_8[] PROGMEM = "AT+CMGD=1,4\r";
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8};
char buffer[30];

//ДЛЯ РЕЛЕ
byte Pins[6] = {14, 15, 16, 17,18,19}; // Массив задействованных номеров Pins Arduino, для управления реле. 
byte PinStatus[6]; // Массив для фиксации изменений
byte numPins = 6; // количество реле
byte ON = HIGH; //для проверки работоспособности на светодиодах ON=HIGH, для реле ON=LOW
byte OFF = LOW; //для проверки работоспособности на светодиодах OFF=LOW, для реле OFF=HIGH



void reboot() {
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
}

void setup() {

  pinMode(12, INPUT); 
  Serial.begin(9600);
  Serial.println(F("START")); 
  pinMode(19, OUTPUT); 
  digitalWrite(19,LOW); 
  
  {// GSM 
 if (digitalRead(12)==LOW) //пин12 мониторит включенность ГСМ(напругу на светодиоде status). если ГСМ выключен, то после включения ардуина перезагружается и загружается при ключенном ГСМ
    {
    Serial.println(F("Budet RESET")); 
    pinMode(9, OUTPUT);
    digitalWrite(9,LOW);
    delay(1000);
    digitalWrite(9,HIGH);
    delay(2000);
    digitalWrite(9,LOW);
    delay(15000);
    reboot();
    delay(500);
    }
    
gsm.begin(19200);

//gsm.println("AT+IPR=19200\r");
    delay(100);
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); //gsm.print(F("AT+CMGF=1\r"));
gsm.print(buffer);         //устанавливает текстовый режим смс-сообщения
    delay(300);
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[1])));  //gsm.print(F("AT+IFC=1,1\r")); 
gsm.print(buffer);       //устанавливает программный контроль потоком передачи данных
    delay(300);
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[2]))); //gsm.print(F("AT+CPBS=\"SM\"\r"));  
gsm.print(buffer);    //открывает доступ к данным телефонной книги SIM-карты
    delay(300);
//gsm.print(F("AT+GSMBUSY=1, 1\r"));   //запрет всех входящих звонков
//    delay(300);
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); //gsm.print(F("AT+CMGDA=\"DEL ALL\"\r")); 
gsm.print(buffer);  //Очищаем накопившиеся СМС
    delay(300);
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[8]))); //gsm.print(F("AT+CMGD=1,4\r"));
gsm.print(buffer); //включает оповещение о новых сообщениях
    delay(300);}
che=EEPROM.read(10);
TkritMin=EEPROMReadInt(11);
TkritMax=EEPROMReadInt(13);
TkritFlag=EEPROM.read(15);

RC.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
for(int i = 0; i <= numPins -1; i++) { //восставновление состояния реле
   pinMode(Pins[i],OUTPUT);
   PinStatus[i]=EEPROM.read(i); //считываем состояние до перезагрузки ардуины
   digitalWrite(Pins[i],PinStatus[i]); //восстанавливаем состояние реле
   } 
for(int i = 0; i <= numRC -1; i++) { //для отправки смс
   loopTime[i] = 0;
   } 
   TimePrint = 0;
   loopTimeTemp = 0;
Serial.println(F("GOTOVO"));
}

void loop() {
      currentTime = millis();       // считываем время, прошедшее с момента запуска программы
      dallRead(flagDallRead * 1000);
if (Serial.available()) {  //обработка Serial данных
    while (Serial.available()) 
         {  //сохраняем строку в переменную val
         ch = Serial.read();
         val2 += char(ch);
         delay(10);
         }
         Serial.println(val2);
   val1=master1; 
   razborkomand();
   val2="";
   val1="";  //очищаем
  }
if (gsm.available()) {//если модуль что то шлет
    while(gsm.available()) 
         {
          ch = gsm.read();
          if(ch == '\r') continue;
          if(ch == '\n') 
            {
            gsmRead(val); 
            val = ""; 
            }
          else val += char(ch);
         }
    }
if (RC.available()) { //Обработка беспроводных датчиков
  if (che == 1) {
   //обработа сигналов с беспроводных датчиков
     ch = RC.getReceivedValue(); 
     for(int i = 0; i <= numRC -1; i++) 
        {
        if (ch == RCvalue[i]) 
           {
           if (currentTime >= loopTime[i])
              {
              loopTime[i] = currentTime + zaderjkaSignSMS;
              Alarm(RCvalueName[i]);
              for(int n = 0; n <= numRC -1; n++)
                 {
                 if (n!=i)
                    {
                    loopTime[n] = 0;  
                    }
                 }
              
              }
           
           }
        }
     
   }
   RC.resetAvailable();
   }
if (TkritFlag) { //если TkritFlag=true, заходим в оповещения о крит температуре
   for(byte n = 0; n <= numDS-1; n++) //перебор всех темп. датчиков 
      {
      if (Temp[n]!=-0.06 && Temp[n]!=0.00)
         {
         if ((Temp[n] <= TkritMin) || (Temp[n] >= TkritMax))
            {
            if (currentTime >= loopTimeTemp)
               {
               TempStatus(master1);
               loopTimeTemp = currentTime + zaderjkaTempSMS; 
               }
            }
         }
      }
   }

  { //Печать данных в монитор. нужно только для отладки. из конечного устройства вырезать
  if (currentTime >= TimePrint) 
     {
     TimePrint = currentTime+15000;
     Serial.print(F("Temp1="));
     Serial.println(Temp[0]);
     Serial.println(F("- - - - - -"));
     }  
  }
}



void Alarm(String zona) {
sms = "Trevoga!";
sms += zona;
smssend(master1);
Serial.println(F("Trevoga! "));
Serial.println(zona);
}
void razborkomand () {
if (val1.indexOf(master1) > -1) //на команды в этом блоке придет ответ
   {
   if (val2.indexOf("Pozvoni") > -1) Proslushka(master1); //если в сообщении "позвони", ардуинка звонит нам на номер, с которого пришел запрос
   if (val2.indexOf("Temp?") > -1) TempStatus(master1); //если в сообщении "температура?", ардуинка высылает температуры на номер, с которого пришел запрос
   if (val2.indexOf("Tkriton") > -1) TkritONOFF(true, master1); // {TkritFlag = true; EEPROM.write(15,TkritFlag);Serial.println("Tkriton");}
   if (val2.indexOf("Tkritoff") > -1) TkritONOFF(false, master1); // {TkritFlag = false; EEPROM.write(15,TkritFlag);Serial.println("Tkritoff");}
   if (val2.indexOf("Off") > -1) AlarmSet(0, master1, String ("OFF")); //если в сообщении "OFF", ардуинка выключает режим сигнализации и отправляет смс с оповещением о сняьтт с сигнализации тому, кто прислал команду
   if (val2.indexOf("On") > -1) AlarmSet(1, master1, String ("ON")); //если в сообщении "ON", ардуинка включает режим сигнализации и отправляет смс с оповещением о постановке на сигнализацию тому, кто прислал команду
   if (val2.indexOf("Vkl") > -1) { //если в сообщении "вкл1234", включить реле №1 и №2 и №3 и №4
      sms = "Vklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, ON);
      if (val2.indexOf("2")> -1) RelaySet(2, ON);
      if (val2.indexOf("3")> -1) RelaySet(3, ON);
      if (val2.indexOf("4")> -1) RelaySet(4, ON);
      if (val2.indexOf("5")> -1) RelaySet(5, ON);
      if (val2.indexOf("6")> -1) RelaySet(6, ON);
      smssend(master1);
      } 
   if (val2.indexOf("Vikl") > -1) { //если в сообщении "выкл1234", выключить реле №1 и №2 и №3 и №4
      sms = "Viklucheno ";
      if (val2.indexOf("1")> -1) RelaySet(1, OFF);
      if (val2.indexOf("2")> -1) RelaySet(2, OFF);
      if (val2.indexOf("3")> -1) RelaySet(3, OFF);
      if (val2.indexOf("4")> -1) RelaySet(4, OFF);
      if (val2.indexOf("5")> -1) RelaySet(5, OFF);
      if (val2.indexOf("6")> -1) RelaySet(6, OFF);
      smssend(master1);
      } 

   }
if (val2.indexOf("Tkritmin") > -1) {val1= val2.substring(9, 14); Serial.println(val1); TkritMin = val1.toInt(); Serial.println(TkritMin); EEPROMWriteInt(11,TkritMin);}
if (val2.indexOf("Tkritmax") > -1) {val1= val2.substring(9, 12); Serial.println(val1); TkritMax = val1.toInt(); Serial.println(TkritMax); EEPROMWriteInt(13,TkritMax);}
}
void TkritONOFF (boolean onoff, String phone) {
  TkritFlag = onoff;
  EEPROM.write(15,TkritFlag);
  Serial.println(TkritFlag);
  if (TkritFlag) 
     {
     sms = "TKrit VKL";
     sms += '\n';
     sms += "Tmin ";
     sms += TkritMin;
     sms += '\n';
     sms += "Tmax ";
     sms += TkritMax;
     }
  if (TkritFlag==false)
     {
     sms = "TKrit VIKL";
     }
  smssend(phone);
}
void gsmRead(const String val) { //разбираем данные от gsm
 if (!val.startsWith("+CMT") && isStringMessage == false ) {Serial.println(val);} //если НЕ смс и это не вторая строка(которая является непосредственно сообщением), значит это иная информация от модуля. выводим в сериал
 
 if (isStringMessage == true) // если флаг "ПРАВДА", значит дошли до строки с сообщением
    {
    isStringMessage = false;  // меняем флаг на "ЛОЖЬ", чтобы при обработке последующей информации, не относящейся к сообщению, в этот кусок не попасть снова
    if (val1.indexOf(master1) > -1) // Если в первой строке VAL1 есть мастер(или один из номеров) номер
       {
       Serial.println(F("master")); //в сериал шлется, что сообщение от мастера
       val2 = val; // сохраняем в переменную
       Serial.print(F("VAL2: ")); // выводим в сериал 
       Serial.println(val2);
       razborkomand();  // разбираем что за команда пришла
       }
    else Serial.println(F("NE master"));
    }
 else 
    { 
    if (val.startsWith("+CMT"))  // если текущая строка начинается с "+CMT", то следующая строка является сообщением;
       {
       val1=val; 
       isStringMessage = true; //флаг означающий, что следующая строка сообщение
       Serial.println(F("VAL1: ")); // выводим в сериал 
       Serial.println(val1);
       } 
    }   
}  
void smssend(String phone) { //процедура отправки СМС
//   Serial.print(sms);   Serial.println(F(phone); 
  Serial.println(F("SMS send started"));
  strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); //"AT+CMGF=1\r"
  gsm.print(buffer);
  delay(100);
  strcpy_P(buffer, (char*)pgm_read_word(&(string_table[5]))); //"AT + CMGS = \"+"
  gsm.print(buffer);
  gsm.print(phone);
  gsm.println(F("\""));
  delay(100);
  gsm.print(sms);
//  text = ""; 
  delay(100);
  gsm.print((char)26);
  delay(100);
  Serial.println(F("SMS send complete"));
  sms="";
}
void Proslushka(String phone){ //Цикл дозвона абоненту (для аудиоконтроля)___________________
 strcpy_P(buffer, (char*)pgm_read_word(&(string_table[6]))); //"AT+CMIC=0,10"
 gsm.println(buffer);    // Команда для установки чувствительности микрофона Поэкспериментировать с цифрой.
// 0,- это канал микрофона (1,2,3),15 это уровень см.инструкцию к СИМ900
delay(1000);
  strcpy_P(buffer, (char*)pgm_read_word(&(string_table[7]))); //"ATD+"
  gsm.print(buffer);  // Набираем номер
  gsm.print(phone);
  gsm.println(F(";"));
//Serial2.println("ATH"); // Вешаем трубку
}
void RelaySet(byte rnum, byte state) { //управление реле
  PinStatus[(rnum-1)] = state; 
  digitalWrite(Pins[(rnum-1)],PinStatus[(rnum-1)]); 
  EEPROM.write((rnum-1),PinStatus[(rnum-1)]); //запись в энергонезависимую память состояния реле для вооставноления этого состояния после потери питания
  sms += rnum;
}
void AlarmSet(int vklvikl, String phone, String onoff) {
  che = vklvikl;
  EEPROM.write(10,che);
  sms=onoff;
  smssend(phone);

}
void TempStatus(String phone) {
  sms = "";
  for(byte n = 0; n <= numDS-1; n++) 
      {
      sms += "T";
      sms += (n+1);
      sms += " ";
      sms += Temp[n];
      sms += "C";
      sms += '\n';
      }
  smssend(phone);

  sms = "";
}
void EEPROMWriteInt(int address, int value) { //Запись двухбайтового числа в память
  EEPROM.write(address, lowByte(value));
  EEPROM.write(address + 1, highByte(value));
}
unsigned int EEPROMReadInt(int address) { //Чтение числа из памяти
  byte lowByte = EEPROM.read(address);
  byte highByte = EEPROM.read(address + 1);
  return (highByte << 8) | lowByte;
}
void dallRead(unsigned long interval){ //температура
  static unsigned long prevTime = 0;
  if (millis() - prevTime > interval) { //Проверка заданного интервала
  static boolean flagDall = 0; //Признак операции
  prevTime = millis();
  flagDall =! flagDall; //Инверсия признака
  if (flagDall) {
    ds.reset();
    ds.write(0xCC); //Обращение ко всем датчикам
    ds.write(0x44); //Команда на конвертацию
    flagDallRead = 1; //Время возврата в секундах
  }
  else {
    byte i;
     int temp;
    for (i = 0; i < 3; i++){ //Перебор количества датчиков
     ds.reset();
     ds.select(addr[i]);
     ds.write(0xBE); //Считывание значения с датчика
     temp = (ds.read() | ds.read()<<8); //Принимаем два байта температуры
     Temp[i] = (float)temp / 16.0; 
     flagDallRead = 2; //Время возврата в секундах
     }
   }
  }
}

а в монитор вот такое лезет:

START
Budet RESET
START
GOTOVO
AT+CMGF=1
OK
AT+IFC=1, 1
OK
AT+CPBS="SM"
OK

AT+CMGDA="
VAL1: 
+CMT: "+79161112219","","16/10/29,18:38:59+12"
master
VAL2: Pozvoni
AT+CMIC=0,10

OK
ATD+79161112219;

OK

NO CARRIER

VAL1: 
+CMT: "+79161112219","","16/10/29,18:39:44+12"
master
VAL2: Pozvoni
AT+CMIC=0,10

OK
Temp1=24.69
- - - - - -
ATD+79161112219;

OK



START
Budet RESET
START
GOTOVO
AT+CMGF=1
OK
AT+IFC=1, 1
OK
AT+CPBS="SM"
OK

AT+CMGDA="
VALяL'j
+CэЉҐZєКЉІЉЉЉ’’ЉКbbЉІzЉ‚z’КbЉВТўКТЄІZЉ’j

Vkl1к
юU1Е: 
+CM

 

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Здравствуйте!

Прошу новичка сильно не пинать. Хочу организовать передачу данных по MODBUS TCP через SIM900 на сервер.

Сервер выступает как Slave. 

В SIM900 стоит симка МТС, на тарифе Коннкект-4 с опцией "МТС планшет мини", где 17 Мб бесплатно.

IMEI SIM900 прошил от планшета, теперь связь до 17 Мб в сутки бесплатно.

Написал соединение с сервером по IP и порту 502, в результате в терминале вижу, что подключение происходит.

Есть также программа, которая передает-принимает данные на сервер по MODBUS TCP через Ethernet модуль.

Хочу соединение через Ethernet модуль заменить соединением через SIM900.

Заменил в программе всю передачу-прием данных с Ethernet модуля на SIM900, соединение поднимается, данные идут, но скорее некорректные, т.к. сервер никак не реагирует. Так как данные мы уже передаем по порту(который уже соединен по TCP), надо наверно вместо MODBUS TCP поднимать просто Modbus по порту? Или проще использовать для приема-передачи библиотеку? У кого был подобный опыт, прошу помощи.

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Приветствую!

Пришел к такому вопросу, что SIM900 не отправляет данные на сервер.

Порядок действий:

 mySerial.println("AT");
   delay(1000);
   ShowSerialData();
   mySerial.println("AT+CREG?");         // Проверка регистрации в сети 
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CGATT?");        // Проверка регистрации в GPRS сети
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CIPSTATUS");     // Инициализируем IP стек.
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CSTT=\"internet.mts.ru\",\"mts\",\"mts\"");  // Устанавливаем установки соединения с нитернетом.
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CIICR");        // Открываем GPRS соединение.
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CIFSR");        // Получаем локальный IP адрес.
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CIPSTART=\"TCP\",\"XX.XX.XX.XX\",\"502\"");   // Подключаемся к серверу.
   delay(2000);
   ShowSerialData();
   mySerial.println("AT+CIPSEND");      // Запрос на посылку сообщения серверу
   delay(1000);
   ShowSerialData();
byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x01, 0x00, 0xE0 };  // Массив передачи в 16-ричном виде.
   mySerial.write(data, 12);            // Передаем в модуль.
   delay(100);
   mySerial.write((char)26);          // Команда на передачу данных на сервер.
   delay(1000);
   ShowSerialData();
....................................

void ShowSerialData()
{
  while(mySerial.available()!=0)
  Serial.write(mySerial.read());
}

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

На входящий звонок он выдает сообщение "ERROR" и далее информацию о звонке. Сбросив звонок, модуль снова начинает реагировать на команды, пока опять не дашь команду AT+CIPSEND, появляется > и снова данные, далее команда 26, и тишина.

Что я делаю не так?

Питание модуля отличное, симка рабочая, а данные не идут. Через модуль Ethernet эти же данные на сервер идут на ура.

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Разобрался. Оказывается GPRS пакеты на отправляются с СИМ-картой оператора МТС, несмотря на то, что соединение устанавливается. Сейчас все работает с Мегафоном. Для бесплатного пользования GPRS подключайте тариф "Интернет планшет ХС" (600 Мб интернета в месяц бесплатно), программируйте IMEI модуля командой AT+SIMEI="xxxxxxxxxxxxxxx", где xxx.... должен быть IMEI планшета, например 860944020813422. Перед прошивкой обязательно проверьте IMEI на сайте http://imeidata.net  IMEI ищите на прострах интернета, есть базы с корректными номерами, а также возможность правильного составления IMEI.

Всем Удачи!

 

 

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Обнаружился один недостаток SIM900.

Если отправлять данные в формате Modbus TCP, пример данных (0,1,0,0,0,6,1,6,0,0,0,0x1A), где 0x1A(0x1B) - данные, (в десятичном виде 26 или 27), то модуль обрежет пакет, приняв данные за команду отправки данных на сервер (26), или команду отмены отправки данных на сервер (27).

Получается, через SIM900 можно отправить любоые значения кроме 0x1A (26) и 0x1B (27).

Для того, чтобы обойти это ограничение, необходимо присвоить конкретную длину пакета данных. В данном случае  AT+CIPSEND=12. И пакет отправится автоматически при достижении данной длины оправляемых данных. Команд конца строки 0x1A посылать не надо.

 

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

При работе в сети Биллайн GPRS по протоколу TCP/IP, соединяясь с сервером, пакеты также невозможно отправить, как и в сети МТС. При этом входящие пакеты будут приходить.  К сожалению, Мегафон возможность подключения к тарифу Планшет без забот, закрыл, оставив возможность подключения к данному тарифу только при покупке планшета.

rodger-1
Offline
Зарегистрирован: 14.06.2017

Люди помогите!!!!! Не видит СИМ карту, уже чего только не пробывал! И пропоял sim holder, и протел все спиртом, и пробывал перепрошивать, На AT выдает Ok, на все команды реагирует, за исключением рабочих с картой, но симку ни как. Что можно сделать подскажите пожааааааааалуйста!!!

rodger-1
Offline
Зарегистрирован: 14.06.2017

Шилд китайский

  

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Привет, rodger.

Работал с данным шилдом. Был первый по части экспериментов. Не так требователен к питанию, как например sim800l с одним конденсатором на борту, но в достаточной мере, поэтому проверь, у Тебя питание медными проводами идет пайкой на плату, или хрень-перемычкой? Я подавал со стабилизарованного испочника питания 1А 4,1В плюс аккумуляторная батарея на 4,1В плюс электролит на 1500 мкФ и в параллели 100мкФ керамики, все это 0,5 проводом длиной 5см сразу пайкой на плату.

Недостаточное питание - 100% невозможность регистрации в сети, отсюда признаки нерабочей симки, а также постоянная перезагрузка модуля.

Недостаточное питание у меня было с лабораторного стабиллизированного блока питания на 5А 4,1В, 0,75 проводом, но подцепил его через хрень-перемычку 10см длиной, что обычно используются в макетках.

Как только выкинул перемычку - все заработало.

Если это не поможет - тогда плата, но этой модификации неисправных плат не встречал, брака не было.

rodger-1
Offline
Зарегистрирован: 14.06.2017

1 Припаял все на плату проводом 0,5 - не помогло! Но я, если честно, сомневаюсь что дело в питании, потому что: при включении модуля просадки по питанию нет, В COM порт выдает сразу что симка не установлена:

Только включил и сразу:

RDY
 
+CPIN: NOT INSERTED
 
+CFUN: 1
Так что наверно всетаки плата, везет мне на брак! :( 
SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

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

Прозвонил контакты сим-карты на ножки самого напаянного модуля Sim900 ?

В режиме регистрации в сети потребление примерно 40-85 мА.

В режиме соединения с сервером и постоянной пересылки пакетов, модуль потребляет примерно 110-120мА на напряжении 4,1В.

 

rodger-1
Offline
Зарегистрирован: 14.06.2017

1) Да!

2) Да!

3) При включении ток 65-85 мА. 

4) До этого дело не доходит.

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Данная модификация в России стоит около 1800-2000 руб.

Модификация голой sim800L с керамическим конденсатором на борту или версии 2.0 с согласованием уровней Tx Rx, стоит 200-450 руб на Aliexpress. Обе модификации рабочие, но предпочтительней версии 2.0. Заказывайте, и будет Вам счастье.

 

rodger-1
Offline
Зарегистрирован: 14.06.2017

Спасибо, я  эту штуку на алике за 800 р. взял. Буду теперь расматривать Ваш вариант. Спасибо огромное за поомощь, успехов во всем!!!