SIM800l vs SIM800l v2.

xellow
Offline
Зарегистрирован: 12.03.2016

Вечер добрый! Помогите кто чем может)

Есть, вернее было вполне работоспособное устройство - блок автозапуска автомобиля. Управлялось по СМС, контролировало напряжение и температуру. 3-года трудилось, но заболело и умерло( здох вначале SIM800 v2(я помог, случайно), потом и ардуинка шиться перестала. Есть в загашнике новая Ардуино нано и SIM800l, первой версии. 

Так вот проблема в том, что новая парочка работает как попало: то принимает СМС, то нет. То отправляет их в ответ, то нет. Питание в порядке - 4В на Sim, 5В на Ардуино. 

Может кто подскажет в чём может быть засада? Скетч один и тот же. 

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


//Замер температуры, напряжения, старт-стоп по СМС, с отчётами.  С реле закрытия двери.
//подключаем библиотеки
#include <OneWire.h> // Подключаем библиотеку для работы с шиной OneWire
OneWire oneWire(4); // Термометр будет подключен на Pin4
#include <DallasTemperature.h> //Подключаем библиотеку для работы с термометром
DallasTemperature sensors(&oneWire);//Создаем объект sensors, подключенный по OneWire
//Создаем переменные для работы с термометром
DeviceAddress tempDeviceAddress;  //переменная для хранения адреса датчика

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;

//Переменные Вольтметра
int analogInput = 0; //Вход измерения U
float vout = 0.0;
float vin = 0.0;
//float R1 = 100000.0; // сопротивление R1 (100K)
//float R2 = 10000.0; // сопротивление R2 (10K)
int value = 0;
 
//назначаем переменные
//Объявим переменные для задания задержки
long previousMillis1 = 0;
long interval1 = 10000; // интервал опроса датчиков температуры и U

//стандартный набор из примера 
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
//новые переменные
String input_string = "";
String smsContent = "";
char pos; //номер последней смс
char sendsms[160];//содержание СМС
//флаги, для однократности действия команд
int flag=0;
int flagT=1; 
int flagV=0;
int flagV1=0;
int Start=0;
int Stop=0;
int flag_Start=0;
int flag_Stop=0;

char n1[] = "+79206601085"; //разрешённый номер для СМС
//переменные измерения температуры
float temp; //переменная для текущего значения температуры
int LowTmp= -10; // переменная для низкой температуры
int HiTmp= 110; // переменная для высокой температуры
int ErrorTmp= -127; // переменная для высокой температуры

//Настройки 
unsigned long ENGINE_WARM_TIME = 900000; //В миллисекундах время работы мотора после запуска 1200000 миллисекунд = 20 минут
int ENGINE_START_MAX_TIME = 5; //В секундах масимальное время работы стартера типично 3 -10 сек

// select pins for input
const int hand_brake_in  = 11;  //d11 adruino Контакт стояночного тормоза "-", МКПП.
const int sharging_in  = 5;  //d5 adruino - лампа заряд
 
const int sharging_on = 1; // 0 когда во время работы генератора или от датчика давления масла на этом входе низкое состояние , 1 когда на лампе генератора при работе генератора высокое состояние
const int hand_brake_on = 0; //  0 поднятый датчик ручника замыкает на массу тормоз активен (жигули), 1 датчик ручника в поднятом состоянии выдает высокий уровень напряжения 
 
// select pins for output
const int starter_out  = 6;  //d6 adruino реле стартера
const int engine_out  = 8;  //d7 adruino зажигание
const int secpower_out  = 7;  //d8 цепи вторичного питания печка, фары итд
const int status_out  = 9;  //d9 светодиод статуса системы  моргает равномерно = система готова к работе(включена, ручник стоит). одно мигание запущен с первой попытки 2 со второй 3 с третьей 
                            //светодиод подключать с этого пина на массу
const int door_out  = 10; //имитация открытия вод. двери, для выключения головного света
const int door_lock  = 12; //закрытие дверей после остановки двигателя
// variable for actual mode
int actual_mode = 0; //  2 engine started  
int left_start_try = 0;  // переменная для хранения остатка числа попыток запуска 
unsigned long last_start_time = 0; //время в тысячных секунды когда был запущен движок 
int ledState = LOW; // этой переменной устанавливаем состояние светодиода
long previousMillis_led = 0;        // храним время последнего переключения светодиода 
long interval_led = 1000;

void setup() {
//Инициализируем термодатчик 
  sensors.begin();
 
 // init input  
  pinMode(analogInput, INPUT); 
  
  pinMode(hand_brake_in, INPUT); // enable input 
  pinMode(sharging_in, INPUT); // enable input 
 
// init outputs
  pinMode(starter_out, OUTPUT); // enable output
  digitalWrite(starter_out, LOW); //set digital 0
 
  pinMode(engine_out, OUTPUT); // enable output
  digitalWrite(engine_out, LOW); //set digital 0
 
  pinMode(secpower_out, OUTPUT); // enable output
  digitalWrite(secpower_out, LOW); //set digital 0 

  pinMode(status_out, OUTPUT); // enable output
  digitalWrite(status_out, LOW); //set digital 0 

  pinMode(door_out, OUTPUT); // enable output
  digitalWrite(door_out, LOW); //set digital 0
  
  pinMode(door_lock, OUTPUT); // enable output
  digitalWrite(door_lock, LOW); //set digital 0

//Скорости портов и текст сообщение в сериал порт
Serial.begin(9600);
if (gsm.begin(2400)) 
{
Serial.println("\nstatus=READY");
started=true;
 } 
 else 
 Serial.println("\nstatus=IDLE");
 
for (int i=0; i <= 20; i++)
{
sms.DeleteSMS(i);
} 
}

void loop() 
{  
//Модуль опроса датчиков и получения сведений о температуре и напряжении
//Вызывается 1 раз в 10 секунд
  unsigned long currentMillis1 = millis();
if(currentMillis1 - previousMillis1 > interval1)
{
 previousMillis1 = currentMillis1;  

 gettemperature();
 voltage();

// Вывод текущего значения температуры в порт

Serial.println("temp: "+String(temp));
Serial.println("Voltage: "+String(vin)); 
}
pos = sms.IsSMSPresent(SMS_UNREAD); // смотрим непрочитанные СМС
delay(1000);
if (pos)
{                    
// Если непрочитанные СМС есть, то...        
getsms(); // получаем непрочитанную СМС                    
}
delay(1000);
//Начальные условия автозапуска
if (actual_mode < 2 )  //если двигатель не запущен
check_start();  //Управляем режимом запуска
//код условия обязательно включать в фигурные скобки если должно быть выполнено несколько инструкций, в данном случае одна, поэтому скобки опущены        
      
else   // иначе
 {
 check_for_shutdown(); //Управляем режимом ожидания окончания прогрева
 } //но хорошая привычка фигурные скобки ставить всегда
 
 set_status_led(); //независимо от режима Управляем светодиодом статуса     
 

  //------------------конец основного кода -----------------

}

void getsms()
{
 sms.GetSMS(pos,n,20,smsbuffer,160);
 Serial.println(n);
 Serial.println(smsbuffer);
 input_string =String(smsbuffer);
 //Если номер входящей СМС соответствует заданному (char n1[] = "+79XXXXXXXXX";) 
 if(strstr(n, n1) != NULL)
{
 if (input_string=="1")//запуск авто
{
Start=1;
check_start();
memset(n,0,20);
}
else if (input_string=="2")//останов
{
 Stop=1;
memset(n,0,20);
}
else if (input_string=="3")//Temp_Start OFF
{
 flagT=1;
 sms.SendSMS(n1, "Temp_Start OFF");
memset(n,0,20);
}
else if (input_string=="4")//запрос температуры
{
flagT=0; 
sms.SendSMS(n1, "Temp_Start ON");
memset(n,0,20);
}
else if (input_string=="5")//Запрос напряжения и температуры
{
  //отправляем СМС при входящей СМС "5"
  smsContent=("Voltage: "+String(vin)+"Temp: "+String(temp));
  smsContent.toCharArray(sendsms,160);
  sms.SendSMS(n1, sendsms);
  memset(n,0,20);
}
}
  EndSMS();
}

  void EndSMS() //__________________Чистим СМС_______________________
{
  for (int i=0; i <= 21; i++)
{
  sms.DeleteSMS(i);
}
}

//Считывание значения температуры
void gettemperature() 
{
{
  //Запуск процедуры измерения температуры
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  sensors.setWaitForConversion(true);
  delay(750);// задержка для обработки информации внутри термометра, 
//в данном случае можно не задавать
  sensors.getAddress(tempDeviceAddress, 4);
  temp = sensors.getTempC(tempDeviceAddress); 
}
  if (temp>ErrorTmp&&temp<=LowTmp && flag==0)
{
  sms.SendSMS(n1, "t < -25C, Nizkaya temperatura");//оповещение о низкой температуре двигателя
  delay(1000); 
  flag = 1 ;
  if (temp>ErrorTmp && temp<LowTmp && flagT==0 && Start==0)
  {
    Start = 1 ;
    flagT = 1 ;//запуск двигателя по СМС "Temp_Start ON "
  }
}
  
if (temp>HiTmp && flag==0)
{
  sms.SendSMS(n1, "t > 110C, Peregrev");//оповещение о высокой температуре двигателя 
  delay(1000); 
  flag = 1 ;
}
 if (temp<=100&&temp>=0)
{
  flag = 0 ;
} 
}

// считывание напряжения
void voltage()
{
// считывание аналогового значения
   value = analogRead(analogInput);
   vout = (value * 0.005078125); //vout = (value * 5.20) / 1024.0;                                                                             
   vin = (vout / 0.090744266); //vin = vout / (R2/(R1+R2)); 
   //if (vin<0.09)
   //{
   //vin=0.0;// обнуляем нежелательное значение
   //}
   if (vin<11.5 && flagV==1 && flagV1==1) //Второе измерение - отправляем СМС 
{
sms.SendSMS(n1, "Voltage < 11.5V");flagV=0;//оповещение о разряде АКБ и  сбрасываем один флаг
}
if (vin<11.5 && flagV==0 && flagV1==0) //Первое измерение напряжения - поднимаем флаги
{
flagV=1;flagV1=1;//оповещение о разряде АКБ
}
if (vin>12.5)
{
flagV=0;flagV1=0; //Напряжение поднялось выше порога - сброс флагов
}
}

void check_start()
{
if (Start != 0 && left_start_try == 0) // 1 is command for start  - 1  значит импульс старта пришел с дистанционного управления <--- тут определяется полярность импульса запуска
{ 
left_start_try = 3;// указываем что нужно попытаться трижды запустить движок
delay(1000); 
Start = 0 ;
}   
 
 if ( left_start_try > 0 )   
 {
 digitalWrite(engine_out, HIGH);   //включаем зажигание 
 delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление, все датчики включились
    
 if (digitalRead(hand_brake_in) != hand_brake_on) //без ручника не делаем запуск
 {
 actual_mode = 2; // заканчиваем попытки запустить движок
 left_start_try = 0; //без ручника другие попытки бесполезны
 //Start = 0 ;
 return;  
 } 
 if (digitalRead(sharging_in) != sharging_on  )    // проверяем что генератор не работает
 {
 do_start(); // пытаемся запустить движок
 left_start_try = left_start_try - 1 ; //уменьшаем число попыток

 if (left_start_try == 0 ) 
 actual_mode = 2; // заканчиваем попытки запустить движок
 } // конец проверки что ручник стоит а генератор не работает
}         
} // конец процедуры старта

void do_start()
{
 //тут будет запуск движка    
//----------------------------------------------------------------------------------- цикл стартера 
 digitalWrite(starter_out, HIGH); //включаем стартер 
 for (int secs=0; secs <= ENGINE_START_MAX_TIME ; secs++) // 
 {
 delay(1000); // и продолжаем его держать включенным 1 секунду
 if (digitalRead(sharging_in) == sharging_on) //если зарядка пошла то 
 break;  // прерываем цикл
 }
//----------------------------------------------------------------------------------- 
 digitalWrite(starter_out, LOW); //отключаем стартер 

 if (digitalRead(sharging_in) == sharging_on) //еще раз смотрим что  зарядка пошла  
 {
 actual_mode = 2; //Запоминаем что движок запущен
 last_start_time = millis(); // запоминаем время запуска движка
 //sms.SendSMS(n1, "Start OK");
 }
 else
 {
 digitalWrite(engine_out, LOW);   //выключаем зажигание что бы разблокировать реле стартера
 delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление
 }    
}

void check_for_shutdown() 
{
//сюда мы попадаем когда контроллер считает что движок работает

   
   
    if (digitalRead(sharging_in) != sharging_on  ) //проверяем что движок случайно не заглох
    {
    do_shutdown();
    }
    else 
    {
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд
    if (flag_Start==0) //однократность СМС
    {    
    sms.SendSMS(n1, "Start OK");
    }
    flag_Start=1;//однократность СМС
    flag_Stop=0;
    }
    
    if (digitalRead(hand_brake_in) != hand_brake_on ) //проверяем что если злодеи сняли с ручника то глушим мотор
    {
    do_shutdown();
    left_start_try =0; // и больше не заводим
    if ((digitalRead(hand_brake_in) != hand_brake_on ) &&  (digitalRead(sharging_in) != sharging_on ))//если мотор заглох - отправляем СМС
    {
    sms.SendSMS(n1, "Alarm STOP");
    }
    }
    if (Stop != 0 ) // СМС на выключение
    {  
    do_shutdown();
    left_start_try =0; // и больше не заводим
    }
    
//тут будем контролировать чтоб если забыли машинку заведенной она не молотила до скончания бензобака а выключалась через какоето время
 
 
    if (actual_mode != 0  ) //значит не выключили заглохший двигатель только что 
    {
      
      // милисекунды в ардуино обнуляются каждые 49 суток
      // для того чтобы в случае если запуск произошел в течении последних 20 минут до обнуления мотор не молотил еще 49 суток
      //  нужно обнулить и время старта, при этом мотор максимум будет прогреваться вдвое больше обычного 
      if (millis() < last_start_time)
      {
      last_start_time = 0;
      }   
      
      
      if (millis() > last_start_time+ENGINE_WARM_TIME)  // если текущее время больше чем время старта + время прогрева
         {
         do_shutdown();
         left_start_try =0; // и больше не заводим
         }
    }
}
 void do_shutdown()
{
 
        digitalWrite(secpower_out, LOW); //выключаем печку фары итд         
        digitalWrite(engine_out, LOW); //вырубаем зажигание
        actual_mode = 0;  // движок выключили запомним это
        last_start_time = 0; // ну и забудем о том что он был включен
        Stop = 0; //Разблокируем следующий запуск
        flag_Start=0;//и отправку СМС
        delay(1000); 
        digitalWrite(door_out, HIGH);   //хлопнули дверью - свет погас
        delay(1000); 
        digitalWrite(door_out, LOW);
        if ((digitalRead(sharging_in) != sharging_on ) && (flag_Stop==0))//проверяем что двигатель заглох и отправляем СМС
    {
    sms.SendSMS(n1, "Stop OK");
    flag_Stop=1;
    } 
    digitalWrite(door_lock, HIGH);   //закрыли двери
    delay(1000); 
    digitalWrite(door_lock, LOW);      
 }


void set_status_led()
{
if (digitalRead(hand_brake_in) != hand_brake_on  ) //Если ручник не стоит то выкл светодиод нечего ему в пути мигать попусту
  {
  digitalWrite(status_out, LOW);
  return; //прерываем выполнение функции
  }
  
if (actual_mode ==  2) //Движок запущен
     status_led_flash(); // показываем с какой попытки был прошлый запуск
else
     status_led_flash1(); // показываем с какой попытки был прошлый запуск // постоянное свечение - показываем что готов к следующему запуску

}



void status_led_flash()
{
static unsigned long big_interval = 0;
static unsigned long flash_interval = 0;
unsigned long flash_count = 0;
flash_count = 3 - left_start_try;  //сколько раз мигать


//1 секндный интервал
if (millis() > flash_interval + 1000L)
      flash_interval = millis() ; //задаем счетчие от 0 до 1 секунды

//задаем 6 секунд 
if (millis() > big_interval + 6000L)
     {
      big_interval = millis() ;  //задаем счетчие от 0 до 10секунд
      flash_interval = big_interval;
     }  



if (millis() <  big_interval +  flash_count * 1000L) // делим 6 секндный интервал на два периода, в первый мигаем количество раз соответствующее числу израсходованных попыток
  { //мигает 
    if (millis() > flash_interval + 500L) 
      digitalWrite(status_out, HIGH);
    else
      digitalWrite(status_out, LOW);

  } 
else 
  { // негорит
    digitalWrite(status_out, LOW); //set digital 0 
  }
}

 void status_led_flash1()
{

//const int status_out =  13;      // номер выхода, подключенного к светодиоду
// Variables will change:
//int ledState = LOW;             // этой переменной устанавливаем состояние светодиода
//long previousMillis = 0;        // храним время последнего переключения светодиода
 
//long interval = 1000;           // интервал между включение/выключением светодиода (1 секунда)
 
 

  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями свето
  unsigned long currentMillis_led = millis();
  
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis_led - previousMillis_led > interval_led) {
    // сохраняем время последнего переключения
    previousMillis_led = currentMillis_led; 
 
    // если светодиод не горит, то зажигаем, и наоборот
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
 
    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(status_out, ledState);
  }
}




 

 

xellow
Offline
Зарегистрирован: 12.03.2016

Ну что ж, всем спасибо за внимание)))

В коде обнаружил существенные ошибки, влияющие на удаление прочитанных СМС. Скорее всего в этом и была проблема.