GSM A6 зависание.
- Войдите на сайт для отправки комментариев
Пнд, 15/05/2017 - 11:43
Всем приве! Собрал скетч для управление реле по смс.
Скетч на основе того что выкладывали в форуме. Текущая проблема:
Либо после отправки смс или 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;
}
panason2008@y удалось побороть зависания?
4 к 1, что не хватает питания.
должно хватать. на уно приходит 9 вольт, 3.5 А.
хотя может вы и правы. сейчас подтянул ногу 5 вольт к gpio1. прочитал в соседней ветке. буду смотреть.
должно хватать. на уно приходит 9 вольт, 3.5 А.
Мне кажется. я это (именно этими словами) уже читал.
Очевидно, что вы питаете модем А6 через Уно. В этом случае не имеет ни малейшего значения, какие там амперы на входе - хоть 3.5А, хоть 333А. Все равно модем получит ровно столько. сколько может выдать регулятор напряжения Уно - а он на лригинальной плате дает 0.8А (которые расходуются на все. что подключено к Уно, а не только на модем). Если же Уно китайская. то скорее всего и 800 мА там не будет.
Вообще. почему-то почти все новички питают свои поделки высоким напряжением - 9В, 12В и тд. Зачем вам это? У вас есть в системе компоненты, которым нужно 9в? Номинальное напряжение Уно - 5в, модема А6 - либо 4-4.2в, либо 5в. Берите БП 5в 2А и от него питайте и ардуину и модем параллельно
уно не китайская. описаный мною блок питания шел в комплекте. мысль я вашу понял. спасибо.
уно не китайская. описаный мною блок питания шел в комплекте. мысль я вашу понял. спасибо.
А можно уточнить как зависает модем? И точно ли дело в модеме?
Я тоже долго искал проблемы и думал что проблема в A6, оказалось нет:
1 скорость порта
2 переход на аппаратный uart
3 следить за переполнению памяти, особенно при использовании soft serial
В итоге уже неделя полет нормальный
Ещё у себя добавил перезагрузку модема при неответе в течении 30 секунд и watchdog на 8 секунд для самого контроллера.
следить за переполнению памяти, особенно при использовании soft serial
а можно уточнить, как именно следите? В смысле - при написании программы или прямо в рантайме как-то отслеживаете свободную память?
Нет конечно, такие тонкие материи мне не по силам)
Долго вылавливал пару странных поведений программы, в итоге нашёл ошибки в скетч - выход за выделенный кусок памяти, из-за чего было вообще не понятно что виновато, то ли модем то ли МК - не адекватное поведение.
ок, понял
Кстати даже сейчас какие то странности)
Все работает, все хорошо, устройство команды обрабатывает и отвечает корректно, а LCD 1602 выдаёт какую то хрень - иероглифы, ну и фиг с ним - на работу не влияет. Иногда просто гаснет.
Я так думаю моя китайская совсем УНО плата глючит.
в моем случае А6 обеспечивает связь с mqtt брокером. я удаленно получаю данные с датчика температуры и управляю реле. во время работы происходит обрыв связи. причем это происходило рандомно. иногда менее часа, а иногда сутки. выручал резет уно. чтобы разобраться в причине, подключил все к компу и открыл монитор порта, дополнительно при подключении к брокеру загорается светодиод. при разрыве связи с брокером светодиод гаснет. предусмотрена возможность переподключения к брокеру. так вот, через некоторое время я увидел погасший диод, а в монитор порта циклическую попытку подключится к брокеру. из чего я сделал вывод о зависании (засыпании или еще чего) модема.
как то так. пинайте.
Ключевая фраза - помогает сброс уно - т е вы не уверены что дело в модеме.
Ну и советую что уже писал - аппаратный serial, сброс модема при не ответе, WDT на сам МК.
И да, я например не вижу смысла в готовом устройстве оставлять код, выдающий какую-то информацию отладочную в консоль - лишняя задержка и нагрузка на МК.
Как вариант например светодиоды, сигналищирующие об ошибках, lcd самый дешёвый, тут где то я выкладывал приемник отдельный uart на attiny85 и т д, вариантов масса сигнализировать о проблемах.
Хотя бы несколько суток пройдёт тогда можно считать что все гуд
это точно. буду ждать.
t19.31u8d18h
Температура и аптайм реального устройства, правда на другом модеме.