Звонок модуля GSM SIM800C при срабатывании датчика

polok
Offline
Зарегистрирован: 18.09.2016

Приветствую. Нужна помощь в разделении операций входящих в void loop().

1. Опрос и реакция датчика (горит диод на ledPin нужное кол-во времени).

2. Звонок модулем GSM SIM800C на телефон, по реакции датчика (пока горит диод на ledPin).

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

Ситуация такая.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

polok
Offline
Зарегистрирован: 18.09.2016
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);

// Датчик удара 
const int keyPin = 3; // Нога датчика удара 
const int ledPin = 7; // Светодиод (исполнитель)
const int maxcount = 1000; // Циклы 500 миллисекунд =0,5 сек  

int keyState = 0; //текущее состояние сенсора.
int count = 0; //предыдущее состояние сенсор
int oldstat = 0; //в этой переменной будет хранится кол-во циклов без изменения состояния

// настройка СИМ800С
void initGSM(void) {  
  delay(2000);                            
  mySerial.begin(9600);        // Выставляем скорость общения с GSM-модулем 9600 Бод/сек.  
  mySerial.println("AT+CLIP=1");          
  delay(300);                             
  mySerial.println("AT+GSMBUSY=1");  
  delay(300);                             
  mySerial.println("AT+CSCB=1");
  delay(300);                             
  mySerial.println("AT+CMGD=1,4"); 
  delay(300); 
}

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  initGSM(); 
  pinMode(ledPin, OUTPUT);      
  pinMode(keyPin, INPUT); 
} 

void loop(){ //опрос датчика и загорание диода

  keyState = digitalRead(keyPin); //значение с сенсора

  if (keyState != oldstat) { //сравниваем его с предыдущим состоянием сенсора
    count=0;  //если состояния не равны, то есть оно изменилось, тогда
    oldstat = keyState; //устанавливаем новое значение
  }
  if (count < maxcount){
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW); 
  }
  if (count<=maxcount+1) {
    ++count;
  }
  delay(1);

  //звонок по сигналу датчика

  if(!digitalRead(keyPin)){ //звонит непрерывно по горящему диоду 
    //при ledPin звонит непрерывно без датчика
    delay(100);

    mySerial.println("ATD+790*******6;");
    delay(1000); 
  }
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Пока не уберете delay (тоесть не замените на millis()) программа правильно работать не будет!

polok
Offline
Зарегистрирован: 18.09.2016

Спасибо! Будем попробовать.

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

1. Для регистрации срабатывания датчика удара (серия очень коротких импульсов) настоятельно рекомендую использовать регистры аппаратных  прерываний, и соответствующие пины, дабы это событие не пропустить.

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/attachinterrupt#comment-437331

А Вы по факту один раз в секунду пытаетесь отловить импульс рандомной ничтожной длительности (зависит от резонансной частоты пьезоэлемента и силы оплеухи).

2. Строки с 56 по 61 будут долбить модем пока он.. не знаю что он в итоге сделает, но так не надо. Раз закинули ATD и отлавливайте ответ

..... 
if (mySerial.available())....
.....

в Вашем случае. Варианта ответа фактически четыре:

  вх исх
ответ   +COLP: "79xxxxxxxxxx"....
отбой до отв NO CARRIER BUSY
отбой в разг NO CARRIER NO CARRIER
не отвечает   NO ANSWER
занят   BUSY
недоступен   NO CARRIER

3. При первом входе в loop()  у Вас датчик уже "сработал", count инициирован нулём при объявлении. Если честно вообще не очень понял что он "считает".

4. Как правильно Вам уже подсказали выкидывайте все delay'и из скетча, они здесь не нужны.

polok
Offline
Зарегистрирован: 18.09.2016

 Датчик механический SW-420, проблема датчика в том что - в состоянии покоя на входе датчика уровень может быть любым (LOW или  HIGH, как бог пошлёт). Для этого сделана проверка состояния, и из любого входного состояния при колебаниях, на выходе датчика появляется высокий уровень (LedPin =HIGH). Отдельно обработка датчика работает как надо, безукаризненно.

Чертовщина начинается когда я начинаю считывать ledPin для подачи звонка. Скетч обработки датчика сходит с ума, ledPin горит постоянно, звонки идут непрерывно, зацикливается насмерть. Delay() все убрал. Скетч уменьшен до минимума для выяснения проблемы. Звонок вынес из loop(), и ничего не изменилось.


void loop(){ //опрос датчика и загорание диода

  keyState = digitalRead(keyPin); //значение с сенсора

  if (keyState != oldstat) { //сравниваем его с предыдущим состоянием сенсора
    count=0;  //если состояния не равны, то есть оно изменилось, тогда
    oldstat = keyState; //устанавливаем новое значение
  }
  if (count < maxcount){
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW); 
  }
  if (count<=maxcount+1) {
    ++count;
  }
  alarm();
}
  void alarm(){                   //звонок по сигналу датчика
  if(!digitalRead(ledPin)== LOW){ //звонит непрерывно по горящему диоду   
   mySerial.println("ATD+790*******6;");
                                   // Ждём 5 секунд
    mySerial.println("ATH0");      // Разрываем соединение    
  }
}

 

vlad072
Offline
Зарегистрирован: 01.08.2017
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);

const int keyPin = 3; // Нога датчика удара 
const int ledPin = 7;

bool     old    = false; // хранимое состояние датчика
uint32_t talarm = 0;     // момент сработки

void setup() {
  old = digitalRead(keyPin); // сохраняем первичное состояние датчика
}

void loop(){
  if (old != digitalRead(keyPin)) { // сработка - состояние датчика изменилось
    old = !old; talarm = millis();  // сохраняем его и время сработки
    digitalWrite(ledPin, HIGH);     // зажигаем диод
    mySerial.println("ATD>\"admin\";"); // звоним абоненту "admin" на сим-карте
  }
  if ((millis() - talarm) > 2000ul) digitalWrite(ledPin, LOW); // через 2 сек после сработки гасим диод
}

Но я Вам скажу это не датчик удара а максимум датчик "тряски", и то фиксирует эту тряску только в одной оси. В спирали катается шарик и всего то.

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

polok
Offline
Зарегистрирован: 18.09.2016

 Есть ещё гиро GY-521, решаем проблемы по порядку.

Ваш пример скетча ещё оптимальнее, но тоже не работает. LedPin работает, звонок не проходит. Хотя в мониторе порта проходит!

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

Нужно симку вставить в любой телефон и добавить в записную книжку сим-карты запись с соответствующим именем и нужным номером, в моём примере это "admin"

Или с терминала

AT+CPBW=1,"+790xxxxxxxx",145,"admin"

Ну и в setup между 10 и 11 строками конечно же добавьте открытие порта, забыл

  mySerial.begin(9600);

 

polok
Offline
Зарегистрирован: 18.09.2016

Открытие порта прописано, номер телефона в sim нужен в случае управления с этого номера. Это управление телефонной книгой SIM, исходящий звонок должен быть на любой номер, если не определён номер для звонка в скетче. Я не прав?

polok
Offline
Зарегистрирован: 18.09.2016

vlad072 ваш скетч работает, виноват я. Плата GSM запитана +5v от dc-dc преобразователя на 3А, но на модуль GSM подаётся 3,8v через линейный стабилизатор платы. На пиках потребления была просадка до 3,5v, что вызывало нестабильную работу GSM. Я знал про проблему с питанием GSM, но чужие грабли не бьют.

polok
Offline
Зарегистрирован: 18.09.2016

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

Подскажите, почему принимает ВСЕ входящие вызовы?

#define TELMODE "79043733615"
if(softSerial.find("RING")){       // если нашли RING
  softSerial.println("AT+CLIP=1"); // включаем АОН, 
  
 while(1){   // в цикле
if (softSerial.find(TELMODE)){  // ищим номер телефона, если нашли
  softSerial.println("ATA");            // поднимаем трубку
  break;                        // выходим из цикла
  } 
else{                        // иначе 
  softSerial.println("AT+CPAS"); // спрашиваем состояние модема 
  delay(100);
if (softSerial.find("+CPAS: 0")) // и если он в "готовности"
  break;                         //  выходим из цикла
  }
 }
}

 

vic163-163
Offline
Зарегистрирован: 06.03.2018

Посмотри этот код, все работает, отзванивается, но управление в коде кривое

#include <SoftwareSerial.h>
SoftwareSerial SIM800(7, 6);        // для новых плат начиная с версии RX,TX

#define ON           10            // иммитация команды на запуск от arduino, через диод c D10 на A1
#define STARTER      12            // на пуск/стоп автозапуска сигналки
#define Block        8             // на реле блокировки двигателя
#define Klaxon       9             // на реле дальнего света и клаксона // для програмного управления реле дальнего света и клаксона //позже убрать
#define BAT_Pin      A0            // на батарею, через делитель напряжения 39кОм / 11 кОм
//#define Feedback_Pin, A1            // на A1 от диода с D10, иммитация команды на запуск от arduino
#define STOP_Pin     A2            // на концевик педали тормоза для отключения (на нейтрали запрещения) режима прогрева
#define Ignition_Pin A3            // на провод от замка зажигания, анализ заведенного мотора
#define IN_1         3             // на кнопку обратного звонка, кнопка на массу
#define STOP_Head    2             // через диод с D2 на A2, для сброса прогрева ардуино
//#define Zvonok       4
//#define TX           6
//#define RX           7
/*  ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!---------------------------------------------------------   */
String call_phone  = "+79000000000"; // телефон входящего вызова и исходящего вызова
String call_phone2 = "+79000000001"; // телефон входящего вызова, если ненужен номер то замени все или последнюю цыфру на *
String call_phone3 = "+79000000002"; // телефон входящего вызова, если ненужен номер то замени все или последнюю цыфру на *
// String call_phoneХ = "+***********"; // дописываем любое количество телефонов входящего вызова, заменяем Х на порядковый номер телефона
float Vstart = 13.50;              // порог распознавания момента запуска по напряжению
String pin = "";                   // строковая переменная набираемого пинкода
float Vbat, VbatStart, V_min ;     // переменная хранящая напряжение бортовой сети
float m = 69.91;                   // делитель для перевода АЦП в вольты для резистров 39/11kOm
unsigned long Time1, StarterTimeON = 0;
unsigned long StopHeadBut = 0;               // Задаем переменную, для внутреррнего сброса счетчика arduino
unsigned long previousMillis = 0;           // Зададим начальное значение для счетчика millis
unsigned long Time2 = 5000;                // Время для сброса на STOP_Pin через диод с D2 на A2, 40 сек
unsigned long interval = 500;      // интервал мигания в миллисекундах
int value = LOW;                   // предыдущее состояние светодиода
int StopHeadPin = LOW;             // устанавливаем начальное состояние STOP_Head
int Timer = 0;                     // таймер времени прогрева двигателя по умолчанию = 0
int Timer2 = 0;                    // часовой таймер (60 sec. x 60 min. / 10 = 360 )
bool heating = false;              // переменная состояния режим прогрева двигателя
bool ring = false;                 // флаг момента снятия трубки

void(* resetFunc) (void) = 0;

void setup() {
  pinMode(ON,      OUTPUT);
  pinMode(STARTER, OUTPUT);
  pinMode(Block,   OUTPUT);
  pinMode(Klaxon,   OUTPUT);
//  pinMode(Feedback_Pin, INPUT);
  pinMode(STOP_Pin, INPUT);
  pinMode(Ignition_Pin, INPUT);
  pinMode(IN_1, OUTPUT);        // указываем пин на вход для с внутричипной подтяжкой к +V питания.
  pinMode(STOP_Head, OUTPUT);
//  pinMode(Zvonok, OUTPUT);             // выход для обратного звонка, диод анодом на IN_1
//  digitalWrite(Zvonok, HIGH);           // устанавливаем выход pin3 HIGH


  delay(100);
  Serial.begin(9600);              //скорость порта
  //  Serial.setTimeout(50);

  SIM800.begin(9600);              //скорость связи с модемом
  // SIM800.setTimeout(500);          // тайм аут ожидания ответа

  Serial.println("+call_phone+");
  Serial.println("+call_phone2+");
  Serial.println("+call_phone3+");
  //   Serial.println("+call_phoneХ+");   // дописываем любое количество телефонов входящего вызова, заменяем Х на порядковый номер телефона
  SIM800_reset();
 }
/*  --------------------------------------------------- Перезагрузка МОДЕМА SIM800L ------------------------------------------------ */
void SIM800_reset() {
  delay(2000); SIM800.println("AT+CMGDA=\"DEL ALL\"");  // Удаляем все СМС
}

void loop() {

  if (SIM800.available())  resp_modem();                            // если что-то пришло от SIM800 в Ардуино отправляем для разбора
  if (Serial.available())  resp_serial();                           // если что-то пришло от Ардуино отправляем в SIM800
  if (millis() > Time1 + 10000) Time1 = millis(), detection();      // выполняем функцию detection () каждые 10 сек
  if (heating == true && digitalRead(STOP_Pin) == 1)  heatingstop(1); // если нажали на педаль тормоза в режиме прогрева
  if (digitalRead(STOP_Pin) == 1) Timer2 = 0 ;                      // если нажали на педаль тормоза в режиме прогрева

  //моргаем реле дальнего света и клаксона
  if (digitalRead(Block) == HIGH)  {
    if (millis() - previousMillis > interval) {
      previousMillis = millis();   // запоминаем текущее время // если светодиод был выключен – включаем и наоборот
      if (value == LOW)
        value = HIGH;
      else
        value = LOW;
      digitalWrite(Klaxon, value);
    }
  }
  if (digitalRead(Block) == LOW) digitalWrite(Klaxon, LOW);

  //если (Ignition_Pin, зажигание) переключился с 1 на 0 (по какой то причине отключилось зажигание авто)
  // и (ON) == HIGH (или heating == true, есть прогрев в arduino). на время больше 40 сек. то нужен сброс прогрева в arduino
  //нужно сбросить ( "уже прогреваюсь" Voice(5)
  //------  блок добавлен для сброса прогрева ардуино через диод с D2 (STOP_Head) на A2 (STOP_Pin)--------
  if (digitalRead(Ignition_Pin) == LOW && digitalRead(ON) == HIGH)  // если отключилось зажигание авто
  {
    if (millis() - previousMillis  >=  10)           // начинаем считать время  было =1, если =10 используется как множитель для Time2
    {
      previousMillis = millis();
      StopHeadBut++;                              // с каждой миллисекундой увеличиваем значение StopHeadBut
    }
  }
  else                                                  // если кнопку отпустили, то StopHeadBut становится равным 0
  { // это необходимо для защиты от срабатывания при частых, многократных переключениях Ignition_Pin
    StopHeadBut = 0;                                      //
  }
  if (StopHeadBut >= Time2)                              // как толькозначение StopHeadPin становится равным Time2
  { //
    digitalWrite(STOP_Head, StopHeadPin = ! StopHeadPin);         // то инвертируем состояние STOP_Head
    StopHeadBut = 0;                                     //  и устанавливаем StopHeadBut = 0
  }

  //---------------- обратный звонок при замыкании на массу входа D3,------------------
  if (digitalRead(IN_1) == HIGH) {
    delay(100);
    SIM800.println("ATD" + call_phone + ";");
    delay(100);
    if (SIM800.find("OK"));
    while (1) {                    // ожидание ответа вызова
      SIM800.println("AT+CPAS");        // при каждой итерации опрашиваем модуль
      if (SIM800.find("4")) break;      // если 4, то выходим из цикла while
      delay(100);
    }
    delay(1000);
    SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.println("11.amr\",0,95");
    delay(3000);
    SIM800.println("ATH0");
   digitalWrite(IN_1, LOW);    
  }
}

void detection() {                                                // условия проверяемые каждые 10 сек

  if (digitalRead(STOP_Head == HIGH)) {           // сброс выхода STOP_Head в LOW
    delay(50), digitalWrite(STOP_Head, LOW);
  }

  Vbat = VoltRead();                                            // замеряем напряжение на батарее
  Serial.println ("");
  if (heating == true && Vbat < 11.0 )   heatingstop(1);  // остановка прогрева если напряжение просело ниже 11 вольт
  //   { Voice(12),  delay (2000), SIM800.println("ATH0");}
  
  if (Timer2 == 1) {
    Timer2 = 0;
    {
      enginestart(3);
    }
  }
  if (Timer2 >  1)  Timer2--;
}

// ---------------- ТРАНСЛИРУЕМ КОМАНДЫ из ПОРТА В МОДЕМ ----------------------------------

void resp_serial () {
  String at = "";
  //    while (Serial.available()) at = Serial.readString();
  int k = 0;
  while (Serial.available()) k = Serial.read(), at += char(k), delay(1);
  SIM800.println(at), at = "";
}

//------------------ НАЛИЗИРУЕМ БУФЕР ВИРТУАЛЬНОГО ПОРТА МОДЕМА------------------------------
void resp_modem () {
  String at = "";           // набиваем в переменную at
  int k = 0;
  while (SIM800.available()) k = SIM800.read(), at += char(k), delay(1);
  Serial.println(at);

  if (at.indexOf("+CLIP: \"" + call_phone + "\",") > -1) {
    delay(200), SIM800.println("ATA"), ring = true;

  } else if (at.indexOf("+CLIP: \"" + call_phone2 + "\",") > -1) {
    delay(200), SIM800.println("ATA"), ring = true;

  } else if (at.indexOf("+CLIP: \"" + call_phone3 + "\",") > -1) {
    delay(200), SIM800.println("ATA"), ring = true;

// ------------------ дописываем нужные телефоны входящего вызова, заменяем Х на порядковый номер телефона
    // } else if (at.indexOf("+CLIP: \"" + call_phoneХ + "\",") > -1) {
    //   delay(200), SIM800.println("ATA"), ring = true;   
    
  } else if (at.indexOf("+DTMF: ")  > -1)        {
    String key = at.substring(at.indexOf("") + 9, at.indexOf("") + 10);
    pin = pin + key;
    if (pin.indexOf("*") > -1 ) pin = "";

  } else if (at.indexOf("NO CARRIER") > -1 ) {
    SIM800.println("AT+CLIP=1;+DDET=1"); // Активируем АОН и декодер DTMF
  }
  at = "";            // Возвращаем ответ можема в монитор порта , очищаем переменную

    if (pin.indexOf("151") > -1 ) {
    pin = "", Voice(11), delay (3000), SIM800.println("ATH0"), delay (100), digitalWrite(IN_1, HIGH);   //обратный звонок
  } else if (pin.indexOf("789") > -1 ) {
    pin = "", Voice(8), digitalWrite(Block, HIGH), delay (3000), heatingstop(1), SIM800.println("ATH0"); // блокировка двигателя
  } else if (pin.indexOf("987") > -1 ) {
    pin = "", Voice(9), digitalWrite(Block, LOW), delay (3000), SIM800.println("ATH0"); //снятие сблокировки двигателя
  } else if (pin.indexOf("123") > -1 ) {
    pin = "";
    if (digitalRead(ON) == HIGH)
    {
      false;
    }
    else {
      (digitalRead(ON) == LOW);
      {
        Voice(7), enginestart(3); // запуск на сигналку  // "все поняла завожу"
      }
    }
  } else if (pin.indexOf("321") > -1 ) {
    pin = "";  // стоп запуска на сигналку
    if (digitalRead(ON) == LOW)  //необходима что бы командой "стоп" не запустить дистанционно двигатель
    {
      false;
    }
    else {
      (digitalRead(ON) == HIGH);
      {
        Voice(6), digitalWrite(STARTER, HIGH), delay(3000), digitalWrite(STARTER, LOW), heatingstop(1); // (стоп прогрева)
      }
    }
    SIM800.println("ATH0");
  }

  /*------голосовые сообщения при входящем звонке-----------*/
  if (ring == true) {
    ring = false, delay (2000), pin = ""; // обнуляем пин

    //авто находится в режиме блокирови Voice(8)
    if (digitalRead(Block) == HIGH) {
      Voice(8);    // "двигатель блокирован"
    }
    //включено зажигание авто и нет прогрева от arduino, (  Voice(10)
    else if (digitalRead(ON) == LOW && digitalRead(Ignition_Pin) == HIGH) {
      Voice(10);  // "двигатель запущен"
    }
    // "привет жду команду"
    else if (digitalRead(ON) == LOW && digitalRead(Block) == LOW) {
      Voice(1);
    }
    // "уже прогреваюсь"
    else {
      Voice(5);
    }
  }
}
void enginestart(int Attempts ) {                                      // программа запуска двигателя
  /*  ----------------------------------------- ПРЕДНАСТРОЙКА ПЕРЕД ЗАПУСКОМ ---------------------------------------------------------*/
  //Serial.println("Предпусковая настройка");
  detachInterrupt(1);                                    // отключаем аппаратное прерывание, что бы не мешало запуску
  VbatStart = VoltRead();

  // ограничиваем время сигнала запуска на сигналку от 1 до 1 сек
  int  StTime  = constrain(StTime, 1000, 1000);
  V_min = 14;                                            // переменная хранящая минимальные напряжения в момент старта

  // если напряжение АКБ больше 10 вольт, зажигание выключено
  while (Vbat > 10.00 && digitalRead(ON) == LOW) {

    digitalWrite(ON,  HIGH),   delay (100);        // включаем виртуальное зажигание, с D10 на А1.

    if (digitalRead(STOP_Pin) == LOW) {         //  тормоз не нажат //или в нейтрали на минус
      StarterTimeON = millis();
      digitalWrite(STARTER, HIGH);  // на пуск автозапуска сигналки
    }  else  {
      Voice(4); // "я на передаче"
      heatingstop(1);
      break;
    }
    delay (100);
    while (millis() < (StarterTimeON + StTime) && digitalRead(Ignition_Pin) == LOW)   VoltRead(), delay (50);
    digitalWrite(STARTER, LOW), delay (1000);
    // Serial.println("пуск автозапуска сигналки выключил, ожидаем 4 сек.");
    delay (4000);       // запуск выключил, ожидаем 4 сек.

    if (digitalRead(Ignition_Pin)  == HIGH) {               // включилось зажигание от сигналки
      Serial.println ("Есть запуск!");
      Voice(2);      // "двигатель запущен"
      heating = true;
      break;
    }                   // считаем старт успешным, выходим из цикла запуска двигателя
    // "повторный запуск"
    Voice(3), heatingstop(1), SIM800.println("ATH0");

    // программный сброс если нет запуска(переход но 0 адрес)(нет + от замка зажигания(Ignition_Pin) 4 сек ), перезваниваем пробуем еще раз
    void(* resetFunc) (void) = 0;
    resetFunc();
  }

  Serial.println ("Выход из запуска");
  if (heating == false) {
    Timer = 0, Voice(6); // стоп прогрева
  }
  delay(3000), SIM800.println("ATH0");                            // вешаем трубку (для SIM800L)
  }

float VoltRead()    {                               // замеряем напряжение на батарее и переводим значения в вольты
  float ADCC = analogRead(BAT_Pin);
  ADCC = ADCC / m ;
  Serial.print(ADCC);
  if (ADCC < V_min) V_min = ADCC;
  return (ADCC);
}                  // переводим попугаи в вольты

void heatingstop(bool reset_timer) {                                 // программа остановки прогрева двигателя
  digitalWrite(ON, LOW), delay (100);
  heating = false, delay(2000);
  Serial.println ("Выключить все");
  if (reset_timer == true) Timer = 0;
}

void Voice(int Track) {
  SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.print(Track), SIM800.println(".amr\",0,95");
}

 

vic163-163
Offline
Зарегистрирован: 06.03.2018

Этоп код, с дозвоном с номера SIM карты, полностью рабочий, доработанный. Описание http://arduino.ru/forum/proekty/arduino-pro-minisim800-dopolnenie-k-avto-signalizatsii-s-avtozapuskom

//  1 КОМАНДА НА ЗАПУСК, 1 КОМАНДА НА СТОП, ПО ОДНОМУ ПРОВОДУ

// "45"  обратный звонок
// "03"  старт
// "30"  стоп
// "56"  отключение контроля дверей
// "65"  включение контроля дверей
// "89"  блокировка двигателя
// "98"  снятие блокировки двигателя
// "22"  Voice(1)
// "1"   Voice(20),память переполнена, сброс звонка

#include <avr/wdt.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM800(7, 6);       // для новых плат начиная с версии RX,TX

#define ON             9             // вывод для отработки иммитации команды на запуска arduino
#define Start          12            // на пуск/стоп автозапуска сигналки
#define Block          10            // на реле блокировки двигателя
#define Klaxon         8             // на реле дальнего света и клаксона 
#define BAT_Pin        A6            // на батарею, через делитель напряжения 39кОм(47kom) / 10 кОм
#define Parking        A1            // на датчик паркинга или нейтрали, (Parking) == HIGH на паркинге
#define StopPin        A2            // на концевик педали тормоза для отключения (на нейтрали запрещение) режима прогрева
#define Ignition       A3            // на провод от замка зажигания, анализ заведенного мотора
#define StopHead       4             // через диод с D4 на A2, для сброса прогрева ардуино, при долгом отсутствии Ignition (зажигание)
#define ObrabotkaCall  11            // вывод для отработки обратного звонка
#define Alarm          2             // вход для звонка при срабатывания сигналки
#define Door           3             // вход для звонка при срабатывании дверей
#define ObrabotkaDveri A4            // выход для обработки открытой двери
#define ZapretDoor     A5            // выход для обработки, отключения контроля открытия двери
#define ResetSim       5             // зарезервирован для сброса SIM модуля или вкл/откл
//#define                A0
//#define                A7

/*  ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!---------------------------------------------------------   */
String pin = "";                   // строковая переменная набираемого пинкода
float Vbat, VbatStart, V_min ;     // переменная хранящая напряжение бортовой сети
float m = 69.50;                   // делитель для перевода АЦП в вольты для резистров 39/20kOm, подбор напряжения индикации АЦП.
unsigned long Time1, StartTimeON = 0;
unsigned long StopHeadBut = 0;               // Задаем переменную, для внутреннего сброса счетчика arduino
unsigned long previousMillis = 0;           // Зададим начальное значение для счетчика millis
unsigned long Time2 = 4000;                // Время для сброса на StopPin через диод с D2 на A2, 40 сек
unsigned long interval = 500;      // интервал мигания (срабатывания клаксона/света) в миллисекундах
int value = LOW;                   // предыдущее состояние светодиода (срабатывания клаксона/света)
int StopHeadPin = LOW;             // устанавливаем начальное состояние StopHead (сброс прогрева) 
int Timer1 = 0;                     // таймер времени прогрева двигателя по умолчанию = 0
bool heating = false;              // переменная состояния режим прогрева двигателя
bool ring = false;                 // флаг момента снятия трубки

unsigned long PsoTime3 = 0;                // для таймера в цикле отработки обратного звонка
bool timer3 = 0;                           // флаг включен ли таймер, 0 - выключен, 1 - включен
uint16_t TimePush3 = 1000;                 // Время срабатывания вывод для отработки обратного звонка
bool call_is_made3 = false;                // флаг "звонок выполнен" (в цикле отработки обратного звонка)

unsigned long PsoTime4 = 0;                // для таймера в цикле срабатывания сигналки
bool timer4 = 0;                           // флаг включен ли таймер, 0 - выключен, 1 - включен
uint16_t TimePush4 = 1500;                 // Время срабатывания сигналки
bool call_is_made4 = false;                // флаг "звонок выполнен" (в цикле срабатывания сигналки)

unsigned long PsoTime5 = 0;                // для таймера в цикле срабатывания двери
bool timer5 = 0;                           // флаг включен ли таймер, 0 - выключен, 1 - включен
uint16_t TimePush5 = 500;                  // Время срабатывания двери
bool call_is_made5 = false;                // флаг "выполнения" (в цикле срабатывания двери)

unsigned long PsoTime6 = 0;                // для таймера в цикле включения опции обработки для срабатывания двери
bool timer6 = 0;                           // флаг включен ли таймер, 0 - выключен, 1 - включен
uint16_t TimePush6 = 10;                  // Время включения опции обработки для срабатывания двери
bool call_is_made6 = false;                // флаг "выполнения" (в цикле включения опции обработки для срабатывания двери)




void(* resetFunc) (void) = 0;

void setup() {
  pinMode(ON,      OUTPUT);
  pinMode(Start, OUTPUT);
  pinMode(Block,   OUTPUT);
  pinMode(Klaxon,   OUTPUT);
  pinMode(Parking, INPUT);
  pinMode(StopPin, INPUT);
  pinMode(Ignition, INPUT);
  pinMode(StopHead, OUTPUT);
  pinMode(ObrabotkaCall, OUTPUT);
  pinMode(Alarm, INPUT_PULLUP);   // указываем пин на вход для с внутричипной подтяжкой к +V, для звонка при срабатывания сигналки
  pinMode(Door, INPUT_PULLUP);    // указываем пин на вход для с внутричипной подтяжкой к +V, для звонка при срабатывании двери
  pinMode(ObrabotkaDveri, OUTPUT);
  pinMode(ZapretDoor, OUTPUT);
  pinMode(ResetSim, OUTPUT);

  delay(100);
  Serial.begin(9600);              //скорость порта
  SIM800.begin(9600);              //скорость связи с модемом

  SIM800_reset();
  detachInterrupt(0);                                    // отключаем обработку внешнего прерывания
  detachInterrupt(1);                                    // отключаем обработку внешнего прерывания
}

/*  --------------------------------------------------- Перезагрузка МОДЕМА SIM800L ------------------------------------------------ */
void SIM800_reset() {
  delay(10000); SIM800.println("AT+CMGDA=\"DEL ALL\"");  // Удаляем все СМС чекрез 10 сек, после старта SIM модуля
}


void loop() {

  if (SIM800.available())  resp_modem();                            // если что-то пришло от SIM800 в Ардуино отправляем для разбора
  if (Serial.available())  resp_serial();                           // если что-то пришло от Ардуино отправляем в SIM800
  if (millis() > Time1 + 10000) Time1 = millis(), detection();      // выполняем функцию detection () каждые 10 сек
  if (heating == true && digitalRead(StopPin) == 1)  heatingstop(1); // если нажали на педаль тормоза в режиме прогрева

  //---------моргаем реле дальнего света и клаксона-------------
  if (digitalRead(Block) == HIGH)  {
    if (millis() - previousMillis > interval) {
      previousMillis = millis();   // запоминаем текущее время // если светодиод был выключен – включаем и наоборот
      if (value == LOW)
        value = HIGH;
      else
        value = LOW;
      digitalWrite(Klaxon, value);
    }
  }
  if (digitalRead(Block) == LOW) digitalWrite(Klaxon, LOW);

  //если (Ignition, зажигание) переключился с 1 на 0 (по какой то причине отключилось зажигание авто)
  // и (ON) == HIGH (или heating == true, есть прогрев в arduino). на время больше 40 сек. то нужен сброс прогрева в arduino
  //нужно сбросить ( "уже прогреваюсь" Voice(5)
  //блок добавлен для сброса прогрева ардуино через диод с D2 (StopHead) на A2 (StopPin)--------
  if (digitalRead(Ignition) == LOW && digitalRead(ON) == HIGH)  // если отключилось зажигание авто
  {
    if (millis() - previousMillis  >=  10)       // начинаем считать время, =10 используется как множитель для Time2
    {
      previousMillis = millis();
      StopHeadBut++;                             // с каждой миллисекундой увеличиваем значение StopHeadBut
    }
  }
  else                                   // если Ignition (зажигание) включилось, то StopHeadBut становится равным 0
  {
    StopHeadBut = 0;                    // это необходимо для защиты от срабатывания при частых многократных переключениях
  }
  if (StopHeadBut >= Time2)                              // как только значение StopHeadPin становится равным Time2
  { digitalWrite(StopHead, StopHeadPin = ! StopHeadPin);  // то инвертируем состояние StopHead (сброс на A2 через диод от D2)
    StopHeadBut = 0;                                     //  и устанавливаем StopHeadBut = 0
  }

  //----------------обработка обратного звонка ------------------
   if (!timer3 && digitalRead(ObrabotkaCall) == HIGH) {
    timer3 = 1;  // если таймер выключен и ObrabotkaCall == HIGH запускаем таймер 
    PsoTime3 = millis();
  }
  if (digitalRead(ObrabotkaCall) == LOW) {
    timer3 = 0;  // если ObrabotkaCall == LOW молчит выключаем таймер, сбрасываем флаг "звонок выполнен"
    call_is_made3 = 0;
  }
  if (timer3 && millis() - PsoTime3 > TimePush3)                  // если таймер был включен и кончился,
  {
    timer3 = 0;                                                  // выключаем таймер и
    if (call_is_made3 == 0) call1();                             // если флаг "звонок выполнен" в фальсе то звоним хозяину
  }

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

  if (!timer6 && digitalRead(Alarm) == LOW && digitalRead(ZapretDoor) == LOW) {
    timer6 = 1;  // если таймер выключен и пикнул колокол запускаем таймер
    PsoTime6 = millis();
  }
  if (digitalRead(Alarm) == HIGH) {
    timer6 = 0;                // если колокол молчит выключаем таймер, сбрасываем флаг
    call_is_made6 = 0;
  }
  if (timer6 && millis() - PsoTime6 > TimePush6)                  // если таймер был включен и кончился,
  {
    timer6 = 0;                                                  // выключаем таймер и
    if (call_is_made6 == 0)  digitalWrite(ObrabotkaDveri, HIGH); // если флаг выполнен в фальсе то включаем ObrabotkaDveri
  }

  //----------------срабатывание сигналки-----------------
  if (!timer4 && digitalRead(Alarm) == LOW) {
    timer4 = 1;  // если таймер выключен и работает колокол запускаем таймер
    PsoTime4 = millis();
  }
  if (digitalRead(Alarm) == HIGH) {
    timer4 = 0;  // если колокол молчит выключаем таймер, сбрасываем флаг "звонок выполнен"
    call_is_made4 = 0;
  }
  if (timer4 && millis() - PsoTime4 > TimePush4)                  // если таймер был включен и кончился,
  {
    timer4 = 0;                                                  // выключаем таймер и
    if (call_is_made4 == 0) call2();                             // если флаг "звонок выполнен" в фальсе то звоним хозяину
  }

  //----------------срабатывание дверей-----------------
  if (!timer5 && digitalRead(Door) == LOW && digitalRead(ObrabotkaDveri) == HIGH) {
    timer5 = 1;  // если таймер выключен и открыты двери запускаем таймер
    PsoTime5 = millis();
  }
  if (digitalRead(Door) == HIGH && digitalRead(ObrabotkaDveri) == HIGH) {
    timer5 = 0;  // если дверь закрыли выключаем таймер, сбрасываем флаг
    call_is_made5 = 0;
  }
  if (timer5 && millis() - PsoTime5 > TimePush5)                  // если таймер был включен и кончился,
  {
    timer5 = 0;                                                  // выключаем таймер и
    if (call_is_made5 == 0) call3();                             // если флаг "звонок выполнен" в фальсе то звоним хозяину
  }
}

//----------------звонок обработки двери------------------
void call1() {
  delay(100);
  SIM800.println("AT+CPBR=1"); // считывает запись с индексом 1 телефонной книги SIM-карты
  delay(200);
  SIM800.println("ATD>1");   // позвонить на 1 номер  телефонной книги SIM-карты, читает номер с sim карты но не набирает, поэтому->
  delay(200);
  SIM800.println("ATDL");    // позвонить на последний номер
  delay(100);
  if (SIM800.find("OK"));
  while (1) {                    // ожидание ответа вызова
    SIM800.println("AT+CPAS");        // при каждой итерации опрашиваем модуль
    if (SIM800.find(":")) break;      // если :, то выходим из цикла while
    delay(100);
  }
  delay(1000);
  SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.println("11.amr\",0,95");    //голосовое сообщение "контроль связи"
  delay(4000);
  SIM800.println("ATH0");
  call_is_made3 = 1;                // флаг "звонок выполнен" в труе
  digitalWrite(ObrabotkaCall, LOW);
}



//----------------звонок при срабатывании сигналки------------------
void call2() {
  delay(100);
  SIM800.println("AT+CPBR=1"); // считывает запись с индексом 1 телефонной книги SIM-карты
  delay(200);
  SIM800.println("ATD>1");   // позвонить на 1 номер  телефонной книги SIM-карты, читает номер с sim карты но не набирает, поэтому->
  delay(200);
  SIM800.println("ATDL");    // позвонить на последний номер
  delay(100);
  if (SIM800.find("OK"));
  while (1) {                    // ожидание ответа вызова
    SIM800.println("AT+CPAS");        // при каждой итерации опрашиваем модуль
    if (SIM800.find(":")) break;      // если :, то выходим из цикла while
    delay(100);
  }
  delay(1000);
  SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.println("14.amr\",0,95");    //голосовое сообщение "нарушение охраны"
  delay(4000);
  SIM800.println("ATH0");
  call_is_made4 = 1;                // флаг "звонок выполнен" в труе
}

//----------------звонок при срабатывании двери------------------
void call3() {
  delay(100);
  SIM800.println("AT+CPBR=1"); // считывает запись с индексом 1 телефонной книги SIM-карты
  delay(200);
  SIM800.println("ATD>1");   // позвонить на 1 номер  телефонной книги SIM-карты, читает номер с sim карты но не набирает, поэтому->
  delay(200);
  SIM800.println("ATDL");    // позвонить на последний номер
  delay(100);
  if (SIM800.find("OK"));
  while (1) {                    // ожидание ответа вызова
    SIM800.println("AT+CPAS");        // при каждой итерации опрашиваем модуль
    if (SIM800.find(":")) break;      // если :, то выходим из цикла while
    delay(100);
  }
  delay(1000);
  SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.println("15.amr\",0,95");    //голосовое сообщение "открыта дверь авто"
  delay(4000);
  SIM800.println("ATH0");
  call_is_made5 = 1;                // флаг "звонок выполнен" в труе
  if (digitalRead(Alarm) == HIGH) digitalWrite(ObrabotkaDveri, LOW); //сброс ObrabotkaDveri, до следующего импульса с сигналки
}

void detection() {                                                // условия проверяемые каждые 10 сек
  if (digitalRead(StopHead == HIGH)) {           // перевод выхода StopHead в LOW
    delay(50), digitalWrite(StopHead, LOW);
  }

  Vbat = VoltRead();                                            // замеряем напряжение на батарее
  Serial.println("");   // ОТКЛЮЧИТЬ ПОСЛЕ НАСТРОЙКИ АЦП
//  if (heating == true && Vbat < 11.0 )   heatingstop(1);  // остановка прогрева если напряжение просело ниже 11 вольт
}

// ---------------- ТРАНСЛИРУЕМ КОМАНДЫ из ПОРТА В МОДЕМ ----------------------------------
void resp_serial () {
  String at = "";
  int k = 0;
  while (Serial.available()) k = Serial.read(), at += char(k), delay(1);
  SIM800.println(at), at = "";
}

//------------------ НАЛИЗИРУЕМ БУФЕР ВИРТУАЛЬНОГО ПОРТА МОДЕМА------------------------------
void resp_modem () {
  String at = "";           // набиваем в переменную at
  int k = 0;
  while (SIM800.available()) k = SIM800.read(), at += char(k), delay(1);
  Serial.println(at);

  if (at.indexOf("RING")  > -1) {      // входящий звонок
    delay(200), SIM800.println("ATA"), ring = true;
  } else if (at.indexOf("+DTMF: ")  > -1)        {
    String key = at.substring(at.indexOf("") + 9, at.indexOf("") + 10);
    pin = pin + key;
    if (pin.indexOf("*") > -1 ) pin = "";

  } else if (at.indexOf("NO CARRIER") > -1 ) {
    SIM800.println("AT+CLIP=1;+DDET=1"); // Активируем АОН и декодер DTMF
  }
  at = "";            // Возвращаем ответ можема в монитор порта , очищаем переменную

  if (pin.indexOf("45") > -1 ) {
    pin = "", Voice(11), delay (3000), SIM800.println("ATH0"), delay (100), digitalWrite(ObrabotkaCall, HIGH);   //обратный звонок
  } else if (pin.indexOf("1") > -1 ) {
    pin = "", Voice(20), delay (3000), SIM800.println("ATH0"); // сброс при нажатии на 1
  } else if (pin.indexOf("89") > -1 ) {
    pin = "", Voice(8), digitalWrite(Block, HIGH), delay (3000), heatingstop(1), SIM800.println("ATH0"); // блокировка двигателя
  } else if (pin.indexOf("98") > -1 ) {
    pin = "", Voice(9), digitalWrite(Block, LOW), delay (3000), SIM800.println("ATH0"); //снятие сблокировки двигателя
  }
  else if (pin.indexOf("03") > -1 ) {           // пуск запуска на сигналку
    pin = "";
    if (digitalRead(ON) == HIGH)           //необходима что бы командой "старт" не остановить двигатель, при прогреве от arduino
    {
      false;
    }
    else if (digitalRead(Ignition) == HIGH)     //необходима что бы командой "старт"  не подать команду
    { // сигналке на запуск, при включенном зажигании
      false;
    }
    else if (digitalRead(StopPin) == HIGH)     //если нажат тормоз
    {
      Voice(16);
    }
    else {
      (digitalRead(ON) == LOW && digitalRead(Ignition) == LOW && digitalRead(StopPin) == LOW);
      {
        Voice(7), enginestart(3); // запуск на сигналку  // "все поняла завожу"
      }
    }
  }
  else if (pin.indexOf("30") > -1 ) {
    pin = "";  // стоп запуска на сигналку
    if (digitalRead(ON) == LOW)  //необходима что бы командой "стоп" не запустить дистанционно двигатель
    {
      false;
    }
    else if (digitalRead(Ignition) == HIGH && digitalRead(Parking) == LOW)     //необходима что бы командой "стоп" при включенном зажигании
    {                                                                          // и включенной скорости не подавать команду на старт запуска
      false;
    }
    else {
      (digitalRead(ON) == HIGH);
      {
        Voice(6), digitalWrite(Start, HIGH), delay(2000), digitalWrite(Start, LOW), heatingstop(1); // (стоп прогрева)
      }
    }
    SIM800.println("ATH0");
  }
  else if (pin.indexOf("56") > -1 ) {
    pin = "", Voice(17), digitalWrite(ZapretDoor, HIGH), delay (3000), SIM800.println("ATH0"); // "отключено! срабатывание! двери!"
  }
  else if (pin.indexOf("65") > -1 ) {
    pin = "", Voice(18), digitalWrite(ZapretDoor, LOW), delay (3000), SIM800.println("ATH0"); // "включено! срабатывание! двери!"
  }
  else if (pin.indexOf("22") > -1 ) {
    pin = "", Voice(1); // "привет жду команды"
  }

  //------голосовые сообщения при входящем звонке-----------
  if (ring == true) {
    ring = false, delay (2000), pin = ""; // обнуляем пин

    if (digitalRead(Alarm) == LOW && digitalRead(Block) == LOW) {    //сработала сигнализация на авто
      Voice(14);    // "нарушение охраны"
    }
    else if (digitalRead(Block) == HIGH) {    //авто находится в режиме блокирови Voice(8)
      Voice(8);    // "двигатель блокирован"
    }
    else if (digitalRead(ON) == LOW && digitalRead(Ignition) == HIGH && digitalRead(Block) == LOW) {  //включено зажигание авто и нет прогрева от arduino
      Voice(10);                          //   Voice(10) "двигатель уже запущен"
    }
    else if (Vbat < 10.5) {                   // "низкое напряжение"
      Voice(12);
    }
 /*   else if (digitalRead(StopPin) == HIGH) {
      Voice(16);                 // "нажат тормоз!"
    }  */
    else if (digitalRead(ON) == LOW && digitalRead(Ignition) == LOW && digitalRead(Parking) == LOW && digitalRead(Block) == LOW) {
      Voice(22);       //при входящем звонке, "короткие гудки" 13, "привет жду команды" 1, для записи сообщения нажамите один 19, тональный гудок 22
    }  else {
      Voice(5);          // "уже прогреваюсь"
    }
  }
}

void enginestart(int Attempts ) {                                      // программа запуска двигателя
  //  ----------------------------------------- ПРЕДНАСТРОЙКА ПЕРЕД ЗАПУСКОМ ---------------------------------------------------------
  //Serial.println("Предпусковая настройка");
//  detachInterrupt(1);                                    // отключаем аппаратное прерывание, что бы не мешало запуску
  VbatStart = VoltRead();

  // ограничиваем время сигнала запуска на сигналку от 1 до 1 сек
  int  StTime  = constrain(StTime, 1000, 1000);
//  V_min = 14;                                            // переменная хранящая минимальные напряжения в момент старта

  // если напряжение АКБ больше 10 вольт, зажигание выключено
  while (Vbat > 10.00 && digitalRead(ON) == LOW) {

    digitalWrite(ON,  HIGH);           // включаем виртуальное зажигание на D9
    delay (100);

    if (digitalRead(StopPin) == LOW) {         //  тормоз не нажат (или в нейтрали на минус)
      StartTimeON = millis();
      digitalWrite(Start, HIGH);  // на пуск автозапуска сигналки
    }
    else {
      //      Voice(16);                 // "нажат тормоз! -- здесь не работает
      heatingstop(1);
      break;
    }
    delay (100);
    while (millis() < (StartTimeON + StTime) && digitalRead(Ignition) == LOW)   VoltRead(), delay (50);
    digitalWrite(Start, LOW);
    delay (4000);        // пуск автозапуска сигналки включил, ожидаем 4 сек.

    if (digitalRead(Ignition)  == HIGH && digitalRead(Parking) == HIGH) {    // включилось зажигание от сигналки и на паркинге
      Voice(2);      // "двигатель запущен"
      heating = true;
      break;
    }                   // считаем старт успешным, выходим из цикла запуска двигателя

    if (digitalRead(Ignition)  == HIGH && digitalRead(Parking) == LOW) {               // включилось зажигание от сигналки не паркинге
      Voice(4);      // "я на передаче"
      heating = false;
      break;
    }                   // отказ если на передаче

    Voice(3), heatingstop(1), SIM800.println("ATH0");  // "повторный запуск" если авто не запустилось

    // переход но 0 адрес если нет запуска, нет + от замка зажигания(Ignition) 4 сек, перезваниваем пробуем еще раз
    void(* resetFunc) (void) = 0;
    resetFunc();
  }

  if (heating == false) {
    Timer1 = 0, Voice(6);     // стоп прогрева
  }
  delay(3000), SIM800.println("ATH0");                            // вешаем трубку (для SIM800L)
}

float VoltRead()    {                           // замеряем напряжение на батарее и переводим значения в вольты
  float ADCC = analogRead(BAT_Pin);
  ADCC = ADCC / m ;
  Serial.print(ADCC);                // ОТКЛЮЧИТЬ ПОСЛЕ НАСТРОЙКИ АЦП
  if (ADCC < V_min) V_min = ADCC;               // переводим данные ацп в вольты
  return (ADCC);
}

void heatingstop(bool reset_timer1) {                                 // программа остановки прогрева двигателя
  digitalWrite(ON, LOW), delay (100);
  heating = false, delay(2000);
  if (reset_timer1 == true) Timer1 = 0;
}

void Voice(int Track) {
  SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.print(Track), SIM800.println(".amr\",0,95");
}

 

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

Ответить что не так в вашем коде сложно, потому что не понятно что там "так". Вот в общих чертах как это реализовано у меня:


#include <SoftwareSerial.h>
SoftwareSerial modem(SIM800TX_PIN, SIM800RX_PIN);
char at[128] = "";

void athandling() {
  byte _atlen = 0;
  for (uint32_t _trecv = millis(); (millis() - _trecv) < 10ul;) {
    if (!modem.available()) continue;
    char _ch = modem.read(); _trecv = millis();
    if ((_atlen+1) < sizeof(at)) at[_atlen++] = _ch;
  } at[_atlen] = '\0';
  if (strstr(at, "RING")) modem.println(F("AT+CLIP=1"));
  if (strstr(at, "+CLIP:")) if (strstr(at, "\"admin")) {       
   modem.println(F("AT+DDET=1,500,0;A"));             
   modem.find("\r\nOK\r\n\r\nOK\r\n");                        
   play("hello");
  } else modem.println(F("ATH"));
 if (strstr(at, "+COLP:")) {
  modem.println(F("AT+DDET=1,500,0"));
  modem.find("\r\nOK\r\n");
  play("hello");
 }
 //...........
}
void setup() {
 // ...........
  modem.begin(UART_BPS);
 //...........
}
void loop() {
  if (modem.available()) athandling();
 //.........
}
polok
Offline
Зарегистрирован: 18.09.2016

vlad072 пишет:

... как это реализовано у меня:

Какой у вас модуль GSM?

У меня SIM800C.

После месяца мытарств, этот скетч работает, но только с монитором порта!

   if(softSerial.available()) {  //если GSM модуль что-то послал нам, то
    char ch = ' ';
    String val = "";   
    while(softSerial.available()){ // //сохраняем входную строку в переменную val
       ch = softSerial.read();
       val += char(ch);          //собираем принятые символы в строку
       delay(10);       
     }
    Serial.print("Sim800 send");
    Serial.println(val);

    if(val.indexOf("RING") > -1) {         //если есть входящий вызов, то проверяем номер
      if(val.indexOf("7908944xxxx") > -1) { //если номер звонящего наш. 
         Serial.println("Call MY PHONE");
         softSerial.println("ATA");       //поднимаем трубку
         Serial.println("Connect");
       }
        else {
          softSerial.println("ATH");      //разрываем связь
          Serial.println("Disconnect"); 
        } 
       }
     } 

Пробовал пример из https://codius.ru/articles/GSM_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_SIM800L_%D1%87%D0%B0%D1%81%D1%82%D1%8C_2

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

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

У меня тоже sim800c. Зачем 7 строка? Номер абонента передаётся в уведомлении "+CLIP:" а не "RING" (12 строка). У вас вообще АОН включен? Выше рабочий пример, не городитевы огород со String, зачем? Если будете в дальнейшем работать с пакетными данными, получите нерабочий код, поскольку там львиная доля байтов сообщения - нули, и постоянную неопределённость с памятью в придачу.

polok
Offline
Зарегистрирован: 18.09.2016

Приветствую вас vlad072.  АОН включен в setup.

Я пробовал ваш пример, изменив пины и скорость порта и закоментил строки относящиеся к DTFM (я использую аппаратный dtfm).

Не хочет у меня работать, может вы пропустили что-то важное.

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

Пример притянут из довольно объёмного проекта, поэтому немного неотёсаный. Если не используете адресную книгу симки и тоновый набор, вот, упростил для пробы.

#include <SoftwareSerial.h>
SoftwareSerial modem(8, 9);

void athandling() {
  char at[64] = ""; byte _atlen = 0;
  for (uint32_t _trecv = millis(); (millis() - _trecv) < 10ul;) {
    if (!modem.available()) continue;
    char _ch = modem.read(); _trecv = millis();
    if ((_atlen+1) < sizeof(at)) at[_atlen++] = _ch;
  } at[_atlen] = '\0';
  if (strstr(at, "RING"  )) modem.println(F("AT+CLIP=1"));
  if (strstr(at, "+CLIP:")) modem.println(strstr(at, "+7XXXXXXXXXX") ?  F("ATA") : F("ATH"));
 //...........
}
void setup() {
  modem.begin(57600);
 //...........
}
void loop() {
  if (modem.available()) athandling();
 //.........
}

Соответственно ставите свою скорость, пины rx/tx и номер телефона.

Да, и старайтесь в сетапе оставлять настройки только по крайней необходимости,, остальные настройки делайте "по месту", т.е. например АОН включайте каждый раз непосредственно при входящем звонке, усиление микрофона перезаливайте при каждом ответе и т.п. Эти модемы очень непредсказуемо себя иногда ведут, и то что вы когда то там ранее настроили при включении не факт что осталось в прежнем виде. Я в своё время об это много копий сломал.

polok
Offline
Зарегистрирован: 18.09.2016

Наверное не по феншую сижу - не работает! Идут вызовы и никакой реакции на данные передаваемые gsm в порт, а может их там и вовсе нет. Как проверить, только монитором?

С монитором порта искажается работа, как у меня с предыдущим скетчем.

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

vlad072 пишет:
Эти модемы очень непредсказуемо себя иногда ведут, и то что вы когда то там ранее настроили при включении не факт что осталось в прежнем виде. Я в своё время об это много копий сломал.

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

polok
Offline
Зарегистрирован: 18.09.2016

Не все же гениальные как вы. Беспроблемный вы наш.

Тыкать носом в каки не велика помощь.

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

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

Я и не утверждаю что они обязательно У ВСЕХ будут. На моих двух они есть, заказаны в разное время у разных продавцов. Для тех у кого плохая память, повторю: аналогичные проблемы не только у меня. И никого я не пугаю, а советую как уйти от возможных проблем в перспективе.

andycat пишет:
  Руки выпрямите и будет все хорошо.

Опять мои руки виноваты в том что в модемах рандомо слетают профили, они виснут и ребутятся? Мои руки к прошивкам модемов никогда не прикасались, хорош умничать. Повторюсь в который раз: нет что сказать по делу - проходим мимо, не знаем о чём говорим, не сталкивались - проходим мимо. Если интересно, могу привести пример, как завесить модем sim800c парой безобидных АТ - команд из офф. мануала.

polok
Offline
Зарегистрирован: 18.09.2016

Добрый день!

vlad072 вы используете команду AT+IFC=1,1 (контроль пнредачи данных)?

У меня похоже тишина в softSerial, если я провоцирую появление каких то данных, скетч начинает работать (ваш пример сбрасывает все входящие).

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

polok пишет:

вы используете команду AT+IFC=1,1 (контроль пнредачи данных)?

У меня похоже тишина в softSerial, если я провоцирую появление каких то данных, скетч начинает работать (ваш пример сбрасывает все входящие).

Нет

polok пишет:

У меня похоже тишина в softSerial, если я провоцирую появление каких то данных, скетч начинает работать (ваш пример сбрасывает все входящие).

Так для начала посмотрите что у вас вообще творится в сериале

#define RX XX
#define TX YY
#define BPS ZZZZZ
#include <SoftwareSerial.h>
SoftwareSerial modem(RX, TX);

void setup() {
  Serial.begin(BPS);
  modem.begin(BPS);
}
void loop() {
 while (Serial.available()) modem.write(Serial.read());
 while (modem.available()) Serial.write(modem.read());
}

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

polok
Offline
Зарегистрирован: 18.09.2016

Спасибо!

Попробую. Давно брожу, уже дорогу протоптал.

polok
Offline
Зарегистрирован: 18.09.2016

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

Приехал новый модуль, всё работает.

Большое спасибо vlad072, за участие и помощь. Дай бог тебе здоровья!

Тему можно закрыть.

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

Да уж, судя по всему косоглазые эти модемы на помойке паяют с помошью гвоздя и и зажигалки. Уже третий sim800c пришёл в некондиционном сосянии. Специально заказываю у разных торговцев в нидежде что придёт нормальный. Первый безвременно покончил в себя, начал греться и не отвечал на АТ, у второго тотально холодная пайка, пришлось пропаивать чип трансивера, третий вот:Даже включать не стал, сфотал, открыл спор и кинул в мусор.

sotyi
Offline
Зарегистрирован: 05.01.2017

vlad072 пишет:

Ответить что не так в вашем коде сложно, потому что не понятно что там "так". Вот в общих чертах как это реализовано у меня:


#include <SoftwareSerial.h>
SoftwareSerial modem(SIM800TX_PIN, SIM800RX_PIN);
char at[128] = "";

void athandling() {
  byte _atlen = 0;
  for (uint32_t _trecv = millis(); (millis() - _trecv) < 10ul;) {
    if (!modem.available()) continue;
    char _ch = modem.read(); _trecv = millis();
    if ((_atlen+1) < sizeof(at)) at[_atlen++] = _ch;
  } at[_atlen] = '\0';
  if (strstr(at, "RING")) modem.println(F("AT+CLIP=1"));
  if (strstr(at, "+CLIP:")) if (strstr(at, "\"admin")) {       
   modem.println(F("AT+DDET=1,500,0;A"));             
   modem.find("\r\nOK\r\n\r\nOK\r\n");                        
   play("hello");
  } else modem.println(F("ATH"));
 if (strstr(at, "+COLP:")) {
  modem.println(F("AT+DDET=1,500,0"));
  modem.find("\r\nOK\r\n");
  play("hello");
 }
 //...........
}
void setup() {
 // ...........
  modem.begin(UART_BPS);
 //...........
}
void loop() {
  if (modem.available()) athandling();
 //.........
}

Поясните пожалуйста смысл 15-й и 20-й строки. Зачем нужно true в этих find?

А так спасибо за код. С этим алгоритмом лучше работает скетч.

P.S. Понял, это подтверждение предыдущих DDET.

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

А как Вы себе представляете проверку, что ответил модем?

Андрей01
Offline
Зарегистрирован: 04.11.2013

Жаль тема заглохла, а косяк был всего то в очень маленьком времени остановки!!!.  строка 52, остановка на 1 мили секунду!!! Я поменял на 10 и работает исправно. Спасибо автору!!

У меня работает, видео выложу на свои соцсети.