GSM A6 зависание.

panason2008@yan...
Offline
Зарегистрирован: 24.02.2017

Всем приве!  Собрал скетч для управление реле по смс.

Скетч на основе того что выкладывали в форуме. Текущая проблема:

Либо после отправки  смс или ussd кода модем перестает отвечать. Смс не доходит. Помогает включить выключить несколько раз.  Вообщем никакой стабильности. Битр рейт выставил низкий из-за того что иногда приходят кракозяблы

Сам скетч

 

#include <AltSoftSerial.h> //8,9 rx,tx
#include <SoftwareSerial.h>
#include <Arduino.h>
// First we include the libraries
#include <OneWire.h> 
#include <DallasTemperature.h>
/********************************************************************/
// Data wire is plugged into pin 2 on the Arduino 
#define ONE_WIRE_BUS 3
#define DEBUG

struct RelayCmd {
    int pin;
    String name;

};


const RelayCmd relay1 = {10, "relay1"};
const RelayCmd relay2 = {11, "relay2"};
const RelayCmd relay3 = {12, "relay3"};
const RelayCmd relay4 = {13, "relay4"};

const RelayCmd relayCmds[] = {
    relay1, relay2, relay3, relay4
};


const int count = 4;
#define ON "on"
#define OFF "off"
#define STATUS "status"
#define END_SMS "#"


/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices  
// (not just Maxim/Dallas temperature ICs) 
OneWire oneWire(ONE_WIRE_BUS);
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

char number[] = "+7XXXXXXXXX";
const char balanceRequest[] = "AT+CUSD=1,#102#,15";


String val = "";
String currStr = "";
String str = "";
String temp = "";
boolean ok = false;
unsigned int rate = 2400;
uint32_t msAT=0;
////////////////////////////
unsigned long delayPing = 0;
boolean boolPing = true;





AltSoftSerial altSerial;

void setup() {
    Serial.begin(9600);
    altSerial.begin(rate);
    Serial.print("Start load");
    Serial.print("Wait connect to GSM...");
  
    while( !waitConnect( 10000 ) )
  {
    Serial.println("timeout");
    Serial.print("Wait connect to GSM...");
  }
  
  Serial.println("ok");
  
  Serial.print("Wait registration in net...");
  while( !waitRegistration( 10000 ) )
  {
    Serial.println("timeout");
    Serial.print("Wait registration in net...");
  }
  Serial.println("ok");
    
    do {
        Serial.print(".");
        delay(2000);
        Serial.print(".");
        altSerial.println("ATZ+IPR=" + rate);
        delay(500);
        altSerial.begin(rate);
        delay(200);
        Serial.print(".");
        altSerial.println("ATE0"); //отключаем эхо
        delay(200);
        Serial.print(".");
        altSerial.println("AT");
        delay(200);
        str = "";
        while (altSerial.available()) {
            char ch = altSerial.read();
            Serial.print(ch);
            str += ch;
            delay(5);
        }

        if (str.indexOf("OK") > -1) {
            ok = true;
            Serial.print(".");
            delay(200);
            //altSerial.println("AT+CPIN=2113"); //Pin sim карты
            altSerial.println("AT+CNMI=2,2");
            Serial.print(".");
            delay(200);

            altSerial.println("AT+CMGF=1");
            Serial.print(".");
            delay(200);

            altSerial.println("AT+CSCS=GSM");
            Serial.print(".");
            delay(200);

            Serial.println("OK");
        } else {
            altSerial.end();
            delay(500);
            ok = false;
            Serial.print("-");
        }
    } while (ok == false);


    for (int i = 0; i < count; i++) {
        RelayCmd relay = relayCmds[i];
        pinMode(relay.pin, OUTPUT);
        digitalWrite(relay.pin, HIGH);
        Serial.print("Setup relay ");
        Serial.println(relay.name);
    }
    sensors.begin();
    delay(5000);

}

void loop() {

    ///если что то пришло, читаем
    if (altSerial.available()) {
        delay(5);
        char ch = altSerial.read();
        Serial.print(ch);
        val += char(ch);
    }

    if (val.indexOf("+CUSD:")>-1 && val.indexOf(",15")>-1) {
        resendMasage();
        val = "";

    }

    if (val.indexOf(number) > -1 && val.indexOf(END_SMS)>-1) {
        if (val.indexOf(STATUS) > -1) {
            Serial.println("income status");
            val = "echo";
        }
        if (val.indexOf("balance") > -1) {
            Serial.println("income balance");
            altSerial.println("AT+CUSD=1,#102#,15");
            delay(300);

        } else {
            for (int i = 0; i < count; i++) {
                RelayCmd relay = relayCmds[i];
                if (val.indexOf(relay.name)>-1) {
                    if (val.indexOf(ON)>-1) {
                        Serial.print("Income on ");
                        Serial.println(relay.name);
                        digitalWrite(relay.pin, LOW);
                    }
                    if (val.indexOf(OFF)>-1) {
                        Serial.print("Income off ");
                        Serial.println(relay.name);
                        digitalWrite(relay.pin, HIGH);
                    }
                }


            }
        }
        checkAndSendEchoSms();
        val = "";
    }

    /////////////////////////////////////
    //затираем переменную после отправки смс////
    if (val.indexOf("CMGS:") > -1) {
        val = "";
    }
    //оживляем модуль, если он уснул
    ////////////////////////////////////////////////////////
    if (millis() - delayPing > 900000) {
        if (boolPing == true) {
            altSerial.println("AT");
            boolPing = false;
        }
        if (val.indexOf("OK") > -1) {
            boolPing = true;
            delayPing = millis();
            val = "";
        }
    }

    if (millis() - delayPing > 905000) {
        altSerial.end();
        altSerial.begin(rate);
        altSerial.println("AT");
        boolPing = true;
    }
}
///////////////////////////////////////////////////////////////////// 

void smsSend(char tel[12], String text) {
    altSerial.print("AT+CMGS=\"");
    delay(200);
    for (int i = 0; i < 12; i++)altSerial.write(tel[i]);
    delay(300);
    altSerial.print(char(34));
    delay(200);
    altSerial.write(0x0D);
    delay(500);

    altSerial.print(text + "\x1a");
    delay(600);
    //  altSerial.println(char(26));
    Serial.println("sms sended");
}

void checkAndSendEchoSms() {
    Serial.println(val);
    if (val.indexOf("echo") > -1) {
        sensors.requestTemperatures();
        temp = String(sensors.getTempCByIndex(0));

        String text = "ECHO: ";

        for (int i = 0; i < count; i++) {
            RelayCmd relay = relayCmds[i];
            text += relay.name  + (digitalRead(relay.pin) == LOW ? " ON " : " OFF ");

        }

        text += " T: " + String(temp);
        Serial.println(text);
        smsSend(number, text);
    }
    val = "";
}

void decode7bit(String &instr, String &outstr) {
    byte reminder = 0;
    int bitstate = 7;
    for (int i = 0; i < instr.length(); i++) {
        byte b = instr[i];
        byte bb = b << (7 - bitstate);
        char c = (bb + reminder) & 0x7F;
        outstr += c;
        reminder = b >> bitstate;
        bitstate--;
        if (bitstate == 0) {
            char c = reminder;
            outstr += c;
            reminder = 0;
            bitstate = 7;
        }
    }
}

void printResponse() {
    while (altSerial.available()) {
        char ch = altSerial.read();
        Serial.print(ch);
        delay(5);
    }

}

void resendMasage() {
    int p1 = val.indexOf(F("\"")); //начало строки
    int p2 = val.lastIndexOf(F("\"")); //конец строки
    val = val.substring(p1 + 1, p2);
    String decodestr;
    decode7bit(val, decodestr);
    
    Serial.println(decodestr);
    
    smsSend(number,decodestr);


}


bool waitConnect(long timeout) {
  int countok = 0;
  String str;
  uint32_t tstart = millis();
  while(countok<5) //ждём пять ОК
  {  
    uint32_t ms = millis();
    if( ( ms - tstart) > timeout )
      return false;
      
    // Событие срабатывающее каждые 500 мс   
    if( ( ms - msAT ) > 500|| ms < msAT )
    {
      msAT = ms;
      //посылаем команду
      altSerial.println("AT");
      str = "";
      delay(100); //Ждём ответа
      while(altSerial.available())
      {
        char ch=altSerial.read();
        Serial.print(ch);
        str+=ch;
      } 
      if(str.indexOf(F("OK"))>-1)
        countok++;
      else
        countok = 0;
    }
  }  
  return true;
}

bool waitRegistration( long timeout ) {
  bool ok = false;
  String str;
  uint32_t tstart = millis();
  while(!ok)
  {  
    uint32_t ms = millis();
    if( ( ms - tstart) > timeout )
      return false;

    // Событие срабатывающее каждые 500 мс   
    if( ( ms - msAT ) > 500|| ms < msAT )
    {
      msAT = ms;
      //посылаем команду
      altSerial.println("AT+CREG?");
      delay(100); //Ждём ответа
      str = "";
      while(altSerial.available())
      {
        char ch=altSerial.read();
        Serial.print(ch);
        str+=ch;
      } 
      int p = str.indexOf(F("+CREG: "));
      int a = 0;
      int b = 0;
      if( p > -1 )
      {
        p += 7;
        str = str.substring(p);
        a = str.toInt();
        p = str.indexOf(F(","));
        if( p > -1 )
        {
          p += 1;
          str = str.substring(p);
          b = str.toInt();
        }  
      }
      Serial.print(a);
      Serial.print(",");
      Serial.print(b);
      Serial.print(" ");
      if(a==1 and b==1)
        ok = true;
    }
  }  
  return true;
}

 

Olegator607
Offline
Зарегистрирован: 26.09.2017

panason2008@y  удалось побороть зависания?

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

4 к 1, что не хватает питания.

Olegator607
Offline
Зарегистрирован: 26.09.2017

должно хватать. на уно приходит 9 вольт, 3.5 А.

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

 

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

Olegator607 пишет:

должно хватать. на уно приходит 9 вольт, 3.5 А.

Мне кажется. я это (именно этими словами) уже читал.

Очевидно, что вы питаете модем А6 через Уно. В этом случае не имеет ни малейшего значения, какие там амперы на входе - хоть 3.5А, хоть 333А. Все равно модем получит ровно столько. сколько может выдать регулятор напряжения Уно - а он на лригинальной плате дает 0.8А (которые расходуются на все. что подключено к Уно, а не только на модем). Если же Уно китайская. то скорее всего и 800 мА там не будет.

Вообще. почему-то почти все новички питают свои поделки высоким напряжением - 9В, 12В и тд. Зачем вам это? У вас есть в системе компоненты, которым нужно 9в? Номинальное напряжение Уно - 5в, модема А6 - либо 4-4.2в, либо 5в. Берите БП 5в 2А и от него питайте и ардуину и модем параллельно

Olegator607
Offline
Зарегистрирован: 26.09.2017

уно не китайская. описаный мною блок питания шел в комплекте. мысль я вашу понял. спасибо.

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

Olegator607 пишет:

уно не китайская. описаный мною блок питания шел в комплекте. мысль я вашу понял. спасибо.

А можно уточнить как зависает модем? И точно ли дело в модеме?
Я тоже долго искал проблемы и думал что проблема в A6, оказалось нет:
1 скорость порта
2 переход на аппаратный uart
3 следить за переполнению памяти, особенно при использовании soft serial

В итоге уже неделя полет нормальный

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

Ещё у себя добавил перезагрузку модема при неответе в течении 30 секунд и watchdog на 8 секунд для самого контроллера.

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

andycat пишет:

следить за переполнению памяти, особенно при использовании soft serial

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

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

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

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

andycat пишет:
Долго вылавливал пару странных поведений программы, в итоге нашёл ошибки в скетч - выход за выделенный кусок памяти, из-за чего было вообще не понятно что виновато, то ли модем то ли МК - не адекватное поведение.

ок, понял

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

Кстати даже сейчас какие то странности)
Все работает, все хорошо, устройство команды обрабатывает и отвечает корректно, а LCD 1602 выдаёт какую то хрень - иероглифы, ну и фиг с ним - на работу не влияет. Иногда просто гаснет.
Я так думаю моя китайская совсем УНО плата глючит.

Olegator607
Offline
Зарегистрирован: 26.09.2017

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

как то так. пинайте.

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

Ключевая фраза - помогает сброс уно - т е вы не уверены что дело в модеме.
Ну и советую что уже писал - аппаратный serial, сброс модема при не ответе, WDT на сам МК.

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

И да, я например не вижу смысла в готовом устройстве оставлять код, выдающий какую-то информацию отладочную в консоль - лишняя задержка и нагрузка на МК.
Как вариант например светодиоды, сигналищирующие об ошибках, lcd самый дешёвый, тут где то я выкладывал приемник отдельный uart на attiny85 и т д, вариантов масса сигнализировать о проблемах.

Olegator607
Offline
Зарегистрирован: 26.09.2017
 
теперь уверен. вот тут http://arduino.ru/forum/programmirovanie/problema-s-softwareserial-i-gsm... описывали похожую беду. сейчас добавил питания и уже почти 3 часа все гуд. нащелкался реле. раньше такого не было. максимум 5-6 переключений и привет. тест продолжается.
 
 
 
 
 
 
 
 
 
 
 
 
 
     

 

 

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

Хотя бы несколько суток пройдёт тогда можно считать что все гуд

Olegator607
Offline
Зарегистрирован: 26.09.2017

это точно. буду ждать.

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

t19.31u8d18h

Температура и аптайм реального устройства, правда на другом модеме.