Прочёл, проникся, исправил. Вот новый код и ответ на него.
#include <SoftwareSerial.h>
// 8 - RX Arduino (TX GSM_A6), 9 - TX Arduino (RX GSM_A6)
SoftwareSerial GSM_A6(8, 9);// 8 - RX Arduino (TX GSM_A6), 9 - TX Arduino (RX GSM_A6)
unsigned long current_millis=millis();
int ch = 0;
int LedG = 4; // Пин для зелёного светодиода
int LedR = 7; // Пин для красного светодиода
String val = "";
byte Flag=false;
void setup()
{
pinMode(LedG, OUTPUT);
digitalWrite(LedG, LOW); // Зелёный светодиод ВЫКЛ
pinMode(LedR, OUTPUT);
digitalWrite(LedR, LOW); // Красный светодиод ВЫКЛ
Serial.begin(9600); // Скорость обмена данными с компьютером
Serial.println("Start!");
GSM_A6.println("AT+IPR=9600");
GSM_A6.begin(9600); // Скорость обмена данными с модемом 9600
initModem();
}
void loop() {
if (GSM_A6.available()) // Ожидаем прихода данных (ответа) от модема...
{
Serial.write(GSM_A6.read()); // ...и выводим их в Serial
}
if (Serial.available()) // Ожидаем команды по Serial...
{
GSM_A6.write(Serial.read()); // ...и отправляем полученную команду модему
}
}
void initModem()
{
while ((millis() - current_millis) <= 5000UL)
{
GSM_A6.println("AT"); // Посылаем команду АТ
delay(1000);
// Контроль ответа ОК
val="";
while (GSM_A6.available())
{
ch = GSM_A6.read();
val += char(ch); // Сохраняем входную строку в переменную val
delay(10);
if (val.indexOf("OK"))
{
Serial.println("LedG");
digitalWrite(LedG, HIGH); // Зелёный светодиод ВКЛ
Flag=true;
break;
}
}
if (Flag) break;
}
GSM_A6.println("AT+IPR?"); // Посылаем запрос о скорости соединения
// Контроль скорости 9600
val="";
while (GSM_A6.available())
{
ch = GSM_A6.read();
val += char(ch); // Сохраняем входную строку в переменную val
delay(10);
if (val.indexOf("9600"))
{
Serial.println("LedR");
digitalWrite(LedR, HIGH); // Красный светодиод ВКЛ
break;
}
}
delay(1000);
GSM_A6.println("ATI"); // Посылаем запрос о версии модуля
}
А вот ответ.
Start!
LedG
LedR
OK
AT+IPR?
+IPR: 9600
OK
ATI
Ai Thinker Co.LTD
A6
V03.03.20161229019H03
OK
Чего я не могу понять, так это почему мои сообщения "LedG" и "LedR" (и соответсвенно включаются светодиоды) выводятся раньше ответа модема? И почему на мой запрос "АТ" всё также приходит ответ в виде набора чисел? Ведь эту часть я срисовал с http://codius.ru/articles/GSM_модуль_SIM800L_часть_1.
Честно говоря я что-то не понял. После очередного запуска модем стал отвечать эхом, то есть что я посылаю, то и получаю в ответ. Но только на команды введённые через монитор порта.
Примерно так.
Start!
LedG
LedR
OK
AT+IPR?
+IPR: 9600
OK
ATI
Ai Thinker Co.LTD
A6
V03.03.20161229019H03
OK
AT
AT+IPR?
ATI
Дал команды сответственно "AT", "AT+IPR?" и "ATI" и получил из же в ответ. На Arduino явственно перемигиваются светодиоды TX и RX в момент передачи команды иполучения ответа. Что бы это значило?
Мой чайник скоро закипит, но не от удачной работы, а от непонимания...
Про автоответ это банально - есть команда модема которая отключает автоответ - нагуглите легко.
По поводу остального - у вас логика программы страдает, вы выводите сообщения до того как вывод ответа, да и вообще все криво.
У вас как вообще с программированием?
Т е вам надо взять в толк что работает все последовательно, необходимо в loop разделять режимы работы программы и в зависимости от это этого выводить сообщения. Куча примеров на форуме....
"АТЕ0" пробовал - не помогло, просто никакого ответа. Программированием занимаюсь профессионально, около 30 лет. На логику никто не жаловался. С языком СОСИ++ связался впервые. Настолько идиотские конструкции, что поневоле принимаешь за правду то, что он был придуман как пример языка с невозможными конструкциями, в качестве первоапрельской шутки студентами МТИ. Почему-то очень понравился профессору. С этого момента и началось шествие С по умам программистов.
По поводу последовательности команд. Если я подав команду "АТ" дожидаюсь ответа модема "ОК" и ТОЛЬКО ПОСЛЕ ЭТОГО вывожу "LedG" и включаю зелёный светодиод, затем подаю команду "AT+IPR?", дожидаюсь ответа "+IPR: 9600" и ТОЛЬКО ПОСЛЕ ЭТОГО вывожу "LedR" и включаю красный светодиод. В чём отсутствие логики?
Кину ещё один камень в огород С. Хреново работать со строками. Нет элементарных функций наподобие LEFT(), RIGHT() для выделения определённого количества символов из строки. Пытался подключить "STRING.H", "CSTRING.H", меняне поняли ;). Получилответ,что библиотеки не подходят. Можете что-либо посоветовать?
................................ Программированием занимаюсь профессионально, около 30 лет. На логику никто не жаловался. .......................................................
Кину ещё один камень в огород С. ..........................................
че то не вяжеться, тут частенько приходят супер программисты, а примитивного сделать не могут :(
ЗЫ. Извините, но я уйду с этой темы. Еслиб у Вас было желание разобраться - давно бы уже кучу примеров разобрали.
P.P.S. Не хвалюсь - просто констатация факта, ни капли не программист, работаю поверхностностно с: Ассемблер,C,Pascal,PHP,C++ ну ни разу не было желания поругаться на язык, это всего лишь инструмент, который надо учить.
Вот скетч, там много всяких, возможно ненужных наворотов, но, по-моему, важен принцип - работает устойчиво.
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу
SoftwareSerial GSM_A6(8, 9); // 8 - RX, 9 - TX
int Pins[4] = {2, 4, 7, 12}; // Пины с подключенными светодиодами
int Zvuk=3; // Пин зуммера
bool CorrFlg; // Флаг корректного завершения
bool CorrTlf; // Признака вхождения номера телефона в БЕЛЫЙ СПИСОК
String Mdm_Rsp = ""; // Переменная для хранения ответа модуля
long Upd_Lst = millis(); // Время последнего обновления
long Upd_Prd = 60000; // Проверять каждую минуту
int Cnt=0; // Счётчик на все случаи жизни
int LED_Ctrl=0; // Контроль включения светодиодов
// БЕЛЫЙ СПИСОК телефонов в виде массива строк, с ОБЯЗАТЕЛЬНЫМ(!) "End" в конце списка
char* Ph_Nums[] = {"+7922*******", "+7919*******", "+7919*******", "+7982*******", "End"};
void setup()
{
delay(10000); // Задержка 10 секунд перед запуском программы
for (Cnt = 0; Cnt < 4; Cnt++)
{
pinMode(Pins[Cnt], OUTPUT); // Настраиваем пины в OUTPUT
}
GSM_A6.begin(9600); // Скорость обмена данными с модемом
Send_AT_Cmd("AT", true); // Отправка AT для настройки скорости обмена данными
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
Send_AT_Cmd("AT+CLIP=1", true); // Включаем АОН
Send_AT_Cmd("ATE0;&W", true); // Выключаем эхо-режим и сразу сохраняем значение (AT&W)!
Send_AT_Cmd("AT+CMGF=1;&W", true); // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
String M_R=Send_AT_Cmd("AT+IPR?", true); // Запрос скорости обмена с модемом
if (M_R.indexOf("9600")) // Контроль скорости обмена с модемом
{
digitalWrite(12, HIGH); // Индикация нормальной связи с модемом
}
Send_AT_Cmd("AT+CPMS=\"SM\",\"SM\",\"SM\"", true); // Команда распределения памяти (хранить SMS сообщения в памяти SIM-карты)
Upd_Lst = millis(); // Обнуляем таймер
}
// Основная программа
void loop()
{
if (GSM_A6.available()) // Если у модема есть что сказать
{
Mdm_Rsp = Wait_Rsp(); // Получаем ответ от модема для анализа
Mdm_Rsp.trim(); // Убираем лишние пробелы в начале и конце
if (Mdm_Rsp.startsWith("+CIEV:")) // Пришло сообщение о получении SMS
{
RazborSMS(Mdm_Rsp); // Разобрать SMS на элементы
}
}
}
// Подпрограмма разбора полученной SMS с определением номера телефона и команды
void RazborSMS(String SMS_Msg)
{
String SMS_Msgheader = ""; // Объявление строковой переменной заголовка
String SMS_Cmd = ""; // Объявление строковой переменной команды
int index = SMS_Msg.indexOf("+7"); // Находим первое вхождение "+7", получаем индекс
String Ph_Num = SMS_Msg.substring(index, index+12); // Получаем номер телефона
String SMS_MsgToSend = ""; // Объявление строковой переменной SMS
Ph_Num.trim(); // Убираем пробелы в начале/конце
// Проверка номера телефона на вхождение в БЕЛЫЙ СПИСОК
CorrTlf=false; // Сброс признака вхождения номера телефона в БЕЛЫЙ СПИСОК
Cnt=0; // Обнуление счётчика
while (Ph_Nums[Cnt]!="End") // Перебор номеров телефонов с целью определения вхождения в БЕЛЫЙ СПИСОК
{
if (Ph_Num.compareTo(Ph_Nums[Cnt])==0) // Номер телефона совпал с имеющимся в БЕЛОМ СПИСКЕ
{
CorrTlf=true; // Установка признака вхождения номера телефона в БЕЛЫЙ СПИСОК
break; // Выход из цикла при нахождении номера
}
Cnt++; // Приращение счётчика
}
if (CorrTlf)
{
// Номер телефона входит в БЕЛЫЙ СПИСОК
SMS_Msg = SMS_Msg.substring(SMS_Msg.indexOf("+CMT: ")); // Определяем начало строки заголовка
SMS_Msgheader = SMS_Msg.substring(0, SMS_Msg.indexOf("\r")); // Получаем заголовок
SMS_Cmd = SMS_Msg.substring(SMS_Msgheader.length() + 2); // Выделяем строку сообщения, включая "ОК"
SMS_Cmd.toUpperCase(); // Переводим сообщение в верхний регистр
SMS_Cmd = SMS_Cmd.substring(0, SMS_Cmd.lastIndexOf("OK")); // Выделяем собственно команду
SMS_Cmd.trim(); // Убираем лишние пробелы в начале и конце
if (SMS_Cmd.length() == 2) // Длина команды = 2 символам (корректно)
{
int LED_Ind = ((String)SMS_Cmd[0]).toInt(); // Получаем первую цифру команды - адрес устройства (1-3)
int LED_St = ((String)SMS_Cmd[1]).toInt(); // Получаем вторую цифру команды - состояние (0 - выкл, 1 - вкл)
if (LED_Ind >= 1 && LED_Ind <= 3 && (LED_St == 0 or LED_St == 1))
// Если адрес и состояние входят в допустимые границы
{
if (digitalRead(Pins[LED_Ind - 1])!=LED_St) // Состояние светодиода должно изменится
{
// Если все нормально, исполняем команду
digitalWrite(Pins[LED_Ind - 1], LED_St); // Исполнение команды
tone(Zvuk, 500*LED_Ind, 500);
if (digitalRead(Pins[LED_Ind - 1])==LED_St) // Контроль корректности исполнения команды
{
// Формирование сообщения об ИСПОЛНЕНИИ(!) команды
SMS_MsgToSend = "LED:" + (String)LED_Ind + " set to " + (LED_St == 0 ? "OFF" : "ON")+". Uspeshno :-)";
}
else
{
// Формирование сообщения о НЕИСПОЛНЕНИИ(!) команды
SMS_MsgToSend = "LED:" + (String)LED_Ind + ". set to " + (LED_St == 0 ? "OFF" : "ON")+". Ne vypolneno :-(";
}
}
else // Состояние светодиода НЕ должно изменится
{
// Формирование сообщения о НЕИЗМЕНЕНИИ состояния светодиода
SMS_MsgToSend = "LED:" + (String)LED_Ind + ". Sostoyanie ne izmenilos :-|";
}
}
else
{
// Формирование сообщения о НЕВОЗМОЖНОСТИ выполнить команду
SMS_MsgToSend = "Mission: Impossible :-(";
}
}
else
{
// Формирование сообщения о НЕКОРРЕКТНОСТИ команды
SMS_MsgToSend = "Nekorrektnaya komanda :-(";
}
}
else
// Номер телефона не входит в БЕЛЫЙ СПИСОК
{
// Формирование сообщения о невхождении телефона в БЕЛЫЙ СПИСОК
SMS_MsgToSend = "Izvinite, telefon ne opoznan! :-(";
}
Send_SMS(Ph_Num, SMS_MsgToSend); // SMS об РЕЗУЛЬТАТЕ команды
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
}
// Подпрограмма отправки SMS
void Send_SMS(String SMS_Num, String Ansver)
{
Send_AT_Cmd("AT+CMGS=\"" + SMS_Num + "\"", true); // Передаём модему номер телефона и...
Send_AT_Cmd(Ansver + "\r\n" + (String)((char)26), true); // ...текст сообщения, после текста отправляем перенос строки и Ctrl+Z
}
// Подпрограмма отправки команд АТ модулю
String Send_AT_Cmd(String Cmd, bool Waiting)
{
String M_Rsp = ""; // Переменная для хранения результата
GSM_A6.println(Cmd); // Отправляем команду модулю
if (Waiting) // Если флаг ожидания TRUE
{
M_Rsp = Wait_Rsp(); // При необходимости ждем ответ
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
// Функция ожидания ответа и возврата полученного результата
String Wait_Rsp()
{
String M_Rsp = ""; // Переменная для хранения результата
long TimeOut = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд)
while (!GSM_A6.available() && millis() < TimeOut) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
if (GSM_A6.available()) // Если у модема есть что сказать
{
M_Rsp = GSM_A6.readString(); // Считываем и запоминаем данные модема
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
Номера телефонов скрыл, SIM карта в модеме от MOTIV. Для нормального запуска модема на 9600 НЕ ТРЕБУЕТСЯ многократной передачи AT+IPR=9600, один раз указал скорость обмена и он понял. Были некоторые сложности в начале пути, но в итоге всё заработало нормально. Скетч разработан ТОЛЬКО для проверки возможностей модема по приёму-передаче SMS.
Вот схема подключения. Расчита на работу под управлением скетча, но каждый волен переделать её и скетч под свои нужды. Плата модема показана условно, только выводы, из них,как видите, используется только 4.
Если у кого-то возникнут вопросы - милости прошу, отвечу по мере сил и умения.
Спасибо всем принявшим участие.
PS. А Си, действительно, трёхнутый на всю голову язык.
PPS. Гораздо лучший справочник по языку Си для Arduino находится тут: https://doc.arduino.ua/ru/prog/
На заре своей трудовой деятельности, в году этак 1986-87, обслуживал СМ-4 и СМ-1420. После месячных курсов влёт писал тестовые программки для блоков... Сейчас уже, конечно, всё забылось.
А Си всё равно ипанутый язык, даже Fortran-77. смотрится логичнее...
Нет, они использовались локально, но сложность СМ-ки и Arduin-ки, сравнивать невозможно, ибо это слишком разные устройства. Программировал, естественно, не с лёту, нопрограммы в 150-200 строк писалисьза пару дней, так как за простой натягивали крепко. Зато в результате определась неисправная плата, а то и элемент на ней. Учился в Киеве, при заводе выпускавшем эти машины, учили добротно, коллектив преподователей (они же работники завода) знал своё дело туго. В то время, на каждую плату имелись принципиальные схемы, с контрольными точками, с эпюрами (осциллограммами), то есть искать неисправности приходилось не по наитию, а по приборам. А программы на Макроассемблере помогали быстрее найти неисправность и заменить мёртвый элемент. Если, конечно, это был не процессор. Тогда Цэшку и осциллограф в зубы и вперёд, на мины... Такое правда было всего один раз, тогда обошлось малой кровью, нашли непропай заводской... А вот с периферией таки да, раз в 2-3 месяца что-нибудь да помирало. Был курьёзный случай: утром включили машину, чере пару секунд из одного шкафа раздался грохот. Быстро выключили, открыли шкаф и охренели: из блока вентиляиторов сорвались лопасти, упали вовнутрь и частично перерубили плоский кабель межблочной связи (интерфейс). Заменили вентилятор и кабель за 20 минут и всё заработало.
Вы уж извините, ударился в воспоминания...
Спасибо помогло, только еще пришлось питание дополнительное подать от повер банка. Я что то так и подумал, что вы с 80-х годов. Я позже начал в 1990-м.
И снова приветствую гуру Arduino и модуля gsm/gprs А6.
Нарисовал программку под свои нужды, дошло дело до подключения и внедрения А6, и тут "такое началось" ;)
В общем ситуация такая: воззвал к старой (которую накатал с вашей помощью) программке получения и отправки SMS, кое что изменил, добавил-убрал, в общем, получил результат, который меня полностью удовлетворяет.
Вот текстовка:
#include <Wire.h> // Бибилиотека для I2C (SDA - A4, SCL - A5)
#include <Time.h> // Библиотека времени
#include <DS1307RTC.h> // Библиотека для модуля часов
#include <I2C_LCD_RUS_NoCyrB.h> // Библиотека для lcd без кириллицы (только БОЛЬШИЕ буквы)
#include <EEPROM.h> // Библиотека для работы с памятью EEPROM
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу
I2C_LCD_RUS_NoCyrB lcd(0x27, 16, 2); // Подключаем lcd (адрес, 16 столбцов, 2 строки)
SoftwareSerial GSM_A6(8, 9); // 8 - RX, 9 - TX
String Mdm_Rsp = ""; // Строковая переменная для хранения ответа модуля
String S_Tlf="+7904*******"; // Свой телефон TELE2
// БЕЛЫЙ СПИСОК телефонов в виде массива строк, с ОБЯЗАТЕЛЬНЫМ(!) "End" в конце списка
char* Ph_Nums[]= {"+7922*******", "+7919*******", "+7982*******", "End"};
void setup()
{
Serial.begin(9600); // Скорость обмена данными с компьютером
GSM_A6.begin(9600); // Скорость обмена данными с модемом
lcd.begin(); // Инициализация ЖК дисплея
lcd.clear();
lcd.print("GSM MOДУЛЬ");
lcd.setCursor(0,1);
lcd.print("ПOДГOTOBKA ");
Serial.println("Start!");
Send_AT_Cmd("AT", true); // Отправка AT для настройки скорости обмена данными
lcd.print(4);
delay(500);
Send_AT_Cmd("ATE0", true); // Отправка AT для настройки скорости обмена данными
lcd.print(3);
delay(500);
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
lcd.print(2);
delay(500);
// Команды настройки модема при каждом запуске
Mdm_Rsp = Send_AT_Cmd("AT+CLIP=1", true); // Включаем АОН
lcd.print(1);
delay(500);
Mdm_Rsp = Send_AT_Cmd("AT+CMGF=1;&W", true); // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
lcd.print(0);
delay(500);
Mdm_Rsp = Send_AT_Cmd("AT+IPR?", true); // Запрос скорости соединения
lcd.setCursor(0,1);
lcd.print("ГOTOB ES = "+Mdm_Rsp.substring(7, 12)); //*Сообщение о завершении инициалиции GSM модуля
}
void loop()
{
if (GSM_A6.available()) // Если у модема есть что сказать
{
Mdm_Rsp =GSM_A6.readString(); // Получаем ответ от модема для анализа
Mdm_Rsp.trim(); // Убираем лишние пробелы в начале и конце
Serial.println(Mdm_Rsp+"\n");
if (Mdm_Rsp.startsWith("+CIEV:")) // Пришло сообщение о получении SMS
{
RazborSMS(Mdm_Rsp); // Разобрать SMS на элементы
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
}
}
}
}
// Подпрограмма отправки команд АТ модулю
String Send_AT_Cmd(String Cmd, bool Waiting)
{
String M_Rsp = ""; // Переменная для хранения результата
GSM_A6.println(Cmd); // Отправляем команду модулю
if (Waiting) // Если флаг ожидания TRUE
{
M_Rsp = Wait_Rsp(); // При необходимости ждем ответ
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
// Функция ожидания ответа и возврата полученного результата
String Wait_Rsp()
{
String M_Rsp = ""; // Переменная для хранения результата
long TimeOut = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд)
while (!GSM_A6.available() and millis() < TimeOut) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
if (GSM_A6.available()) // Если у модема есть что сказать
{
M_Rsp = GSM_A6.readString(); // Считываем и запоминаем данные модуля
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
// Подпрограмма разбора полученной SMS с определением номера телефона и команды
void RazborSMS(String SMS_Msg)
{
Serial.println("Разбор SMS \n");
// Локальные переменные
byte Cnt=0; // Обнуление счётчика
String SMS_Msgheader = ""; // Объявление строковой переменной заголовка
String SMS_Cmd = ""; // Объявление строковой переменной команды
int index = SMS_Msg.indexOf("+7"); // Находим первое вхождение "+7", получаем индекс
String Ph_Num = SMS_Msg.substring(index, index+12); // Получаем номер телефона
String S_Date = SMS_Msg.substring(index+16, index+26);
String S_Time = SMS_Msg.substring(index+27, index+35);
String S_Sdvg = SMS_Msg.substring(index+35, index+38);
Serial.println(SMS_Msg);
Serial.println(Ph_Num);
Serial.println(S_Date);
Serial.println(S_Time);
Serial.println(S_Sdvg);
String SMS_MsgToSend = ""; // Объявление строковой переменной SMS
bool CorrTlf=false; // Сброс признака вхождения номера телефона в БЕЛЫЙ СПИСОК
Ph_Num.trim(); // Убираем пробелы в начале/конце
// Проверка номера телефона на вхождение в БЕЛЫЙ СПИСОК
while (Ph_Nums[Cnt]!="End") // Перебор номеров телефонов с целью определения вхождения в БЕЛЫЙ СПИСОК
{
if (Ph_Num.compareTo(Ph_Nums[Cnt])==0) // Номер телефона совпал с имеющимся в БЕЛОМ СПИСКЕ
{
CorrTlf=true; // Установка признака вхождения номера телефона в БЕЛЫЙ СПИСОК
break; // Выход из цикла при нахождении номера
}
Cnt++; // Приращение счётчика
}
if (CorrTlf)
{
lcd.clear(); // Очистка дисплея и установка курсора на 1-ю позицию 1-й строки
lcd.print("SMS "+Ph_Num); // Вывод сообщения о номере телефона
lcd.setCursor(0, 1); // Установка курсора на 1-ю позицию 2-й строки
// Номер телефона входит в БЕЛЫЙ СПИСОК
SMS_Msg = SMS_Msg.substring(SMS_Msg.indexOf("+CMT: ")); // Определяем начало строки заголовка
SMS_Msgheader = SMS_Msg.substring(0, SMS_Msg.indexOf("\r")); // Получаем заголовок
SMS_Cmd = SMS_Msg.substring(SMS_Msgheader.length() + 2); // Выделяем строку сообщения, включая "ОК"
SMS_Cmd.toUpperCase(); // Переводим сообщение в верхний регистр
SMS_Cmd = SMS_Cmd.substring(0, SMS_Cmd.lastIndexOf("OK")); // Выделяем собственно команду
SMS_Cmd.trim(); // Убираем лишние пробелы в начале и конце
if (SMS_Cmd.length() >= 2 && SMS_Cmd.length() <= 8) // Длина команды не менее 2 и не более 8 символов
{
lcd.print("KOMAHДA "+SMS_Cmd); // Вывод сообщения о команде
// Формирование сообщения о получении команды
SMS_MsgToSend = "Komanda "+SMS_Cmd+" prinyata k ispolneniyu";
}
else
{
SMS_MsgToSend = "Nekorrektnaya komanda :-("; // Формирование сообщения о НЕКОРРЕКТНОСТИ команды
}
}
else
// Номер телефона не входит в БЕЛЫЙ СПИСОК
{
lcd.clear();
lcd.print("ЧУЖOЙ HOMEP"); // Вывод сообщения о чужом номере
// Формирование SMS сообщения о невхождении телефона в БЕЛЫЙ СПИСОК
SMS_MsgToSend = "Izvinite, telefon ne opoznan! :-(";
}
Send_SMS(Ph_Num, SMS_MsgToSend); // SMS об РЕЗУЛЬТАТЕ команды
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
}
// Подпрограмма отправки SMS
void Send_SMS(String SMS_Num, String Ansver)
{
Send_AT_Cmd("AT+CMGS=\"" + SMS_Num + "\"", true); // Передаём модему номер телефона и...
Send_AT_Cmd(Ansver + "\r\n" + (String)((char)26), true); // ...текст сообщения, после текста отправляем перенос строки и Ctrl+Z
}
И получаю SMS:
+CIEV: "MESSAGE",1
+CMT: "+7922*******",,"2020/04/27,18:12:48+05"
Qwerty
После того, как я попытался интегрировать этот код в свою программу (привожу не весь код, а только ту часть, что имеет значение):
#include <Wire.h> // Бибилиотека для I2C (SDA - A4, SCL - A5)
#include <Time.h> // Библиотека времени
#include <DS1307RTC.h> // Библиотека для модуля часов
#include <I2C_LCD_RUS_NoCyrB.h> // Библиотека для lcd без кириллицы (только БОЛЬШИЕ буквы)
#include <EEPROM.h> // Библиотека для работы с памятью EEPROM
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу
I2C_LCD_RUS_NoCyrB lcd(0x27, 16, 2); // Подключаем lcd (адрес, 16 столбцов, 2 строки)
SoftwareSerial GSM_A6(8, 9); // 8 - ТX (U_TXD), 9 - RX (U_RXD), в скобках обозначения на модуле А6
//...
String Mdm_Rsp=""; // Строковая переменная для хранения ответа модуля
String S_Tlf="+7904*******"; // Свой телефон TELE2
// БЕЛЫЙ СПИСОК телефонов в виде массива строк, с ОБЯЗАТЕЛЬНЫМ(!) "End" в конце списка
char* Ph_Nums[]= {"+7922*******", "+7919*******", "+7982*******", "End"};
void setup()
{
Serial.begin(9600);
lcd.begin();
//...
// Работаем с GSM модулем А6
GSM_A6.begin(9600); // Скорость обмена данными с модемом
lcd.begin(); // Инициализация ЖК дисплея
lcd.clear(); // Очистка ЖК дисплея
lcd.print("GSM MOДУЛЬ"); // Выводим 1-ю строку служебного сообщения об инициализации GSM модуля
lcd.setCursor(0,1); // Ставим курсор в 1-ю позицию 2-й строки
lcd.print("ПOДГOTOBKA "); // Выводим 2-ю строку служебного сообщения об инициализации GSM модуля
while (millis()<Old_Mil) {}; // Задержка до 15 сек до начала инициализации GSM модуля
// Начинаем инициализацию GSM модуля путём посылки АТ команд
Send_AT_Cmd("AT", true); // Отправка AT для настройки скорости обмена данными
lcd.print(4); // Выводим текущий этап инициализации (в обратном порядке)
delay(500); // Задержка 0,5 сек
Send_AT_Cmd("ATE0", true); // Отключить ЭХО-режим
lcd.print(3); // Выводим текущий этап инициализации (в обратном порядке)
delay(500); // Задержка 0,5 сек
Send_AT_Cmd("AT+CMGD=1,4", true); // Удалить все сообщения, чтобы не забивали SIM-карту
lcd.print(2); // Выводим текущий этап инициализации (в обратном порядке)
delay(500); // Задержка 0,5 сек
Mdm_Rsp = Send_AT_Cmd("AT+CLIP=1", true); // Включить АОН
lcd.print(1); // Выводим текущий этап инициализации (в обратном порядке)
delay(500); // Задержка 0,5 сек
Mdm_Rsp = Send_AT_Cmd("AT+CMGF=1;&W", true); // Включить текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
lcd.print(0); // Выводим текущий этап инициализации (в обратном порядке)
delay(500); // Задержка 0,5 сек
Mdm_Rsp = Send_AT_Cmd("AT+IPR?", true); // Запрос скорости соединения
lcd.setCursor(0,1); // Ставим курсор в 1-ю позицию 2-й строки
lcd.print("ГOTOB ES = "+Mdm_Rsp.substring(7, 12)); //*Сообщение о завершении инициалиции GSM модуля
delay(3000);
}
void loop()
{
//...
if (GSM_A6.available()) // Если у модема есть что сказать
{
Mdm_Rsp =GSM_A6.readString(); // Получаем ответ от модема для анализа
Mdm_Rsp.trim(); // Убираем лишние пробелы в начале и конце
Serial.println(Mdm_Rsp+"\n");
if (Mdm_Rsp.startsWith("+CIEV:")) // Пришло сообщение о получении SMS
{
RazborSMS(Mdm_Rsp); // Разобрать SMS на элементы
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
D_T=true; // Взводим флаг вывода информации на дисплей (для обновления даты и времени, на всякий случай)
}
}
//...
}
//==========================================================================================
// Подпрограмма отправки команд АТ модулю
//==========================================================================================
String Send_AT_Cmd(String Cmd, bool Waiting)
{
String M_Rsp = ""; // Переменная для хранения результата
GSM_A6.println(Cmd); // Отправляем команду модулю
if (Waiting) // Если флаг ожидания TRUE
{
M_Rsp = Wait_Rsp(); // При необходимости ждем ответ
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
//==========================================================================================
// Функция ожидания ответа и возврата полученного результата
//==========================================================================================
String Wait_Rsp()
{
// Локальные переменные
String M_Rsp; // Переменная для хранения результата
long TimeOut = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд)
while (!GSM_A6.available() and millis() < TimeOut) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
if (GSM_A6.available()) // Если у модема есть что сказать
{
M_Rsp = GSM_A6.readString(); // Считываем и запоминаем данные модуля
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
//==========================================================================================
// Подпрограмма разбора полученной SMS с определением номера телефона и команды
//==========================================================================================
void RazborSMS(String SMS_Msg)
{
Serial.println("Разбор SMS \n");
// Локальные переменные
byte Cnt=0; // Обнуление счётчика
String SMS_Msgheader = ""; // Объявление строковой переменной заголовка
String SMS_Cmd = ""; // Объявление строковой переменной команды
byte Index = SMS_Msg.indexOf("+7"); // Находим первое вхождение "+7", получаем индекс
String Ph_Num = SMS_Msg.substring(Index, Index+12); // Получаем номер телефона
String S_Date = SMS_Msg.substring(Index+16, Index+26);
String S_Time = SMS_Msg.substring(Index+27, Index+35);
String S_Sdvg = SMS_Msg.substring(Index+35, Index+38);
//Serial.println(SMS_Msg);
//Serial.println(Index);
//Serial.println(Ph_Num);
//Serial.println(S_Date);
//Serial.println(S_Time);
//Serial.println(S_Sdvg);
String SMS_MsgToSend = ""; // Объявление строковой переменной SMS
bool CorrTlf=false; // Сброс признака вхождения номера телефона в БЕЛЫЙ СПИСОК
Ph_Num.trim(); // Убираем пробелы в начале/конце
// Проверка номера телефона на вхождение в БЕЛЫЙ СПИСОК
while (Ph_Nums[Cnt]!="End") // Перебор номеров телефонов с целью определения вхождения в БЕЛЫЙ СПИСОК
{
if (Ph_Num.compareTo(Ph_Nums[Cnt])==0) // Номер телефона совпал с имеющимся в БЕЛОМ СПИСКЕ
{
CorrTlf=true; // Установка признака вхождения номера телефона в БЕЛЫЙ СПИСОК
break; // Выход из цикла при нахождении номера
}
Cnt++; // Приращение счётчика
}
if (CorrTlf)
{
// Номер телефона входит в БЕЛЫЙ СПИСОК
lcd.clear(); // Очистка дисплея и установка курсора на 1-ю позицию 1-й строки
lcd.print("SMS "+Ph_Num); // Вывод сообщения о номере телефона
lcd.setCursor(0, 1); // Установка курсора на 1-ю позицию 2-й строки
SMS_Msg = SMS_Msg.substring(SMS_Msg.indexOf("+CMT: ")); // Определяем начало строки заголовка
Serial.println("1 "+SMS_Msg);
// Получаем заголовок
SMS_Msgheader = SMS_Msg.substring(0, SMS_Msg.indexOf("\r"));
Serial.println("2 "+SMS_Msgheader);
SMS_Cmd = SMS_Msg.substring(SMS_Msgheader.length() + 2); // Выделяем строку сообщения, включая "ОК"
Serial.println("3 "+SMS_Cmd);
SMS_Cmd.toUpperCase(); // Переводим сообщение в верхний регистр
SMS_Cmd = SMS_Cmd.substring(0, SMS_Cmd.lastIndexOf("OK")); // Выделяем собственно команду
Serial.println("4 "+SMS_Cmd);
SMS_Cmd.trim(); // Убираем лишние пробелы в начале и конце
if (SMS_Cmd.length() >= 2 && SMS_Cmd.length() <= 8) // Длина команды не менее 2 и не более 8 символов
{
lcd.print("KOMAHДА "+SMS_Cmd); //*Вывод сообщения о команде
// Формирование сообщения о получении команды
SMS_MsgToSend = "Komanda "+SMS_Cmd+" prinyata k ispolneniyu";
}
else
{
SMS_MsgToSend = "Nekorrektnaya komanda :-("; // Формирование сообщения о НЕКОРРЕКТНОСТИ команды
}
}
else
// Номер телефона не входит в БЕЛЫЙ СПИСОК
{
lcd.clear();
lcd.print("ЧУЖOЙ HOMEP"); // Вывод сообщения о чужом номере
// Формирование SMS сообщения о невхождении телефона в БЕЛЫЙ СПИСОК
SMS_MsgToSend = "Izvinite, telefon ne opoznan! :-(";
}
Send_SMS(Ph_Num, SMS_MsgToSend); // SMS об РЕЗУЛЬТАТЕ команды
Send_AT_Cmd("AT+CMGD=1,4", true); // Удаляем все сообщения, чтобы не забивали SIM-карту
}
//==========================================================================================
// Подпрограмма отправки SMS
//==========================================================================================
void Send_SMS(String SMS_Num, String Ansver)
{
Send_AT_Cmd("AT+CMGS=\"" + SMS_Num + "\"", true); // Передаём модему номер телефона и...
Send_AT_Cmd(Ansver + "\r\n" + (String)((char)26), true); // ...текст сообщения, после текста отправляем перенос строки и Ctrl+Z
}
Получаю уже вот такую SMS:
+CIEV: "MESSAGE",1
+CMT: "+7922*******",,"2020/04/27,18:24
Вот для наглядности, какую SMS получил в первом варианте:
+CIEV: "MESSAGE",1
+CMT: "+7922*******",,"2020/04/27,18:12:48+05"
Qwerty
То есть обрезается самая, для меня,важная часть SMS.
Так вот, у с=меня возникает вопрос, каким образом обрезается SMS?
Так, спасибо всем, проблему решил. Возможно через задний проход и автогеном...
Опрашиваю модем на каждом цикле void Loop(), записываю SMS-ку в переменную, а уже обрабатываю её примерно через секунду, после опроса датчиков (если ни одного сработавшего), иначе только после обработки срабатывания.
Если кому интересно - пишите, постараюсь ответить.
Опрашиваю модем на каждом цикле void Loop(), записываю SMS-ку в переменную
судя по коду - именно в этом у вас и проблема. Вы считываете СМС в переменную. не проверяя - а пришло ли сообщение целиком? -вместо этого вы просто ждете 10 секунд :
// Функция ожидания ответа и возврата полученного результата
String Wait_Rsp()
{
String M_Rsp = ""; // Переменная для хранения результата
long TimeOut = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд)
while (!GSM_A6.available() and millis() < TimeOut) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
if (GSM_A6.available()) // Если у модема есть что сказать
{
M_Rsp = GSM_A6.readString(); // Считываем и запоминаем данные модуля
}
return M_Rsp; // Возвращаем данные, если таковые имеются
}
Код - просто сборище разных ляпов и глупостей. Тайм аут (строка 5) отмеряете неправильно. Блокирующий цикл ожидания (строка 6) - это просто жесть, все это время программа висит, датчики не проверяет, на сигналы не реагирует.
Ну и самый апофеоз - несмотря на тупое ожидание 10 секунд - все это не дает никакой гарантии, что вы правильно обработаете СМС. Представьте, например, что за эти 10 секунд придет еще одно сообщение или служебная инфа от оператора связи? - и все. вся ваша конструкция заткнется...
Ну, обидеть художника может каждый, а вот подсказать правильное решение не у всех получается.
Вряд ли мне удастся отправить 2 SMS за 10 секунд, а служебная инфа отсекается ещё на этапе проверки SMS (в доработанной версии) путём проверки наличия "CMT". А вот подсказать про таймер не судьба???
Когда я попытался отправить по запросу отчёт, примерно из 80 символов, то получил пустую SMS. Никто не сталкивался с каким либо ограничением на количество символов передаваемых в SMS. Примерно до 70 символов передаётся и получается нормально, а потом - просто пустота... Хотя, по идее, можно посылать до 160 символов...
Все символы в отчёте - латиница и цифры, кириллицы нет.
Похоже я доэкспериментировался с А6. На выходе U_TXD теперь напряжение в 1.6 v (вместо 3,39 v), слегка подсвечивает синий светодиод, соединённый с этим выходом, обмен с Arduino на нуле. надежды, как я понимаю практически никакой. Некоторую надежду внушают пины H_TXD и H_TXD это HST_TXD и HST_RXD, если верить верить ;) руководству от Ai ThinkerTechnology. Пока не нашёл расшифровки, что это такое, HST, но надежды не теряю. Может кто сталкивался?
Вот кусочек таблицы из руководства:
30 UART_TXD UART_TXD,Pin level 2.8V
31 UART_RXD UART_RXD,Pin level 2.8V
32 HST_RXD Download serial port RXD Pin,pin level 2.8V
33 HST_TXD Download serial port TXD pin,pin level 2.8V
Внушает надежду, что у них указано одинаковое напряжение: 2.8V.
Если интересны подробности, то был момент, когда я по ошибке посадил на U_RXD землю, а U_TXD соединил с выходным пином Arduino. Возможно, что это повлияло на работоспособность...
PS. Заказал новый модуль А6, буду насиловать дальше, когда придёт от китаяйцев.
Когда на Ali выбирал, мне этот больше понравился, если честно чисто внешне. А когда выяснил, что делитель по входу не нужен, было оч-чень приятно. Да и то, что на моих глазах, можно сказать, 2 800-х накрылись медным тазиком, один просто в процессе работы на же рабочем проекте, тоже сыграло свою роль...
Наконец-то восстановил схему, допилил программу, всё вроде работает.
Смущает только одно: от оператора (Tele2) постоянно идут служебные сообщения, я их игнорирую, но немного напрягает эта ситуация. Если SIM карту ставишь в телефон, то такого не наблюдается.
Вот примеры сообщений, для удобства я отделил посылки пустыми строками.
10:41:08.608 -> SMS > +CIEV: service, 0
10:41:08.643 -> +CIEV: roam, 0
10:41:08.677 ->
10:41:08.677 -> +CREG: 2
10:41:14.560 -> SMS > +CIEV: service, 1
10:41:14.594 -> +CIEV: roam, 0
10:41:14.628 ->
10:41:14.628 -> +CREG: 1
10:43:35.525 -> SMS > +CIEV: service, 0
10:43:35.525 -> +CIEV: roam, 0
10:43:35.558 ->
10:43:35.558 -> +CREG: 2
10:43:59.529 -> SMS > +CIEV: service, 0
10:43:59.565 -> +CIEV: roam, 0
10:43:59.599 ->
10:43:59.599 -> +CREG: 3
10:45:40.356 -> SMS > +CIEV: service, 0
10:45:40.356 -> +CIEV: roam, 0
10:45:40.394 ->
10:45:40.394 -> +CREG: 2
10:45:45.720 -> SMS > +CIEV: service, 1
10:45:45.760 -> +CIEV: roam, 0
10:45:45.803 ->
10:45:45.803 -> +CREG: 1
10:51:14.371 -> SMS > +CIEV: service, 0
10:51:14.405 -> +CIEV: roam, 0
10:51:14.405 ->
10:51:14.405 -> +CREG: 2
10:51:38.994 -> SMS > +CIEV: service, 0
10:51:39.031 -> +CIEV: roam, 0
10:51:39.067 ->
10:51:39.067 -> +CREG: 3
10:53:19.700 -> SMS > +CIEV: service, 0
10:53:19.734 -> +CIEV: roam, 0
10:53:19.734 ->
10:53:19.734 -> +CREG: 2
10:53:25.195 -> SMS > +CIEV: service, 1
10:53:25.229 -> +CIEV: roam, 0
10:53:25.229 ->
10:53:25.229 -> +CREG: 1
Как видно за 12 минут 10 сообщений. "SMS >" - это моё.
Что можете посоветовать, уважаемые знатоки? Или плюнуть и забить?
Смущает только одно: от оператора (Tele2) постоянно идут служебные сообщения, я их игнорирую, но немного напрягает эта ситуация. Если SIM карту ставишь в телефон, то такого не наблюдается.
я не спец в сотовой связи. но насколько знаю. эти сообщения и в телефоне идут, просто юзеру не показываются.
Почитайте вот тут https://www.developershome.com/sms/cpmsCommand.asp- получение и хранениее cлужебных сообщений настраивается параметрами BM ("broadcast messages") и SR ("status report") команды AT+CPMS. Правда тут в тексте оговорка, что к сожалению, далеко не все модемы поддерживают управление служебными сообщениями
где я опять накосячил?
практически везде.
write и read команды оперируют одним байтом, зачем в init 52 и 55 строка вообще не понятно
зачем ставить скорость 115200 а потом 9600, что за извращение
какими командами и как инициализироват модем А6 уже писалось
светодиод загорается но не видно где он должен гаснуть
почитайте цикл статей вдумчиво с разбором каждого примера, а потом уж пытайтесь написать реальный пример
http://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_1
Прочёл, проникся, исправил. Вот новый код и ответ на него.
А вот ответ.
Честно говоря я что-то не понял. После очередного запуска модем стал отвечать эхом, то есть что я посылаю, то и получаю в ответ. Но только на команды введённые через монитор порта.
Примерно так.
Про автоответ это банально - есть команда модема которая отключает автоответ - нагуглите легко.
По поводу остального - у вас логика программы страдает, вы выводите сообщения до того как вывод ответа, да и вообще все криво.
У вас как вообще с программированием?
Т е вам надо взять в толк что работает все последовательно, необходимо в loop разделять режимы работы программы и в зависимости от это этого выводить сообщения. Куча примеров на форуме....
"АТЕ0" пробовал - не помогло, просто никакого ответа. Программированием занимаюсь профессионально, около 30 лет. На логику никто не жаловался. С языком СОСИ++ связался впервые. Настолько идиотские конструкции, что поневоле принимаешь за правду то, что он был придуман как пример языка с невозможными конструкциями, в качестве первоапрельской шутки студентами МТИ. Почему-то очень понравился профессору. С этого момента и началось шествие С по умам программистов.
По поводу последовательности команд. Если я подав команду "АТ" дожидаюсь ответа модема "ОК" и ТОЛЬКО ПОСЛЕ ЭТОГО вывожу "LedG" и включаю зелёный светодиод, затем подаю команду "AT+IPR?", дожидаюсь ответа "+IPR: 9600" и ТОЛЬКО ПОСЛЕ ЭТОГО вывожу "LedR" и включаю красный светодиод. В чём отсутствие логики?
Кину ещё один камень в огород С. Хреново работать со строками. Нет элементарных функций наподобие LEFT(), RIGHT() для выделения определённого количества символов из строки. Пытался подключить "STRING.H", "CSTRING.H", меняне поняли ;). Получилответ,что библиотеки не подходят. Можете что-либо посоветовать?
................................ Программированием занимаюсь профессионально, около 30 лет. На логику никто не жаловался. .......................................................
Кину ещё один камень в огород С. ..........................................
че то не вяжеться, тут частенько приходят супер программисты, а примитивного сделать не могут :(
ЗЫ. Извините, но я уйду с этой темы. Еслиб у Вас было желание разобраться - давно бы уже кучу примеров разобрали.
P.P.S. Не хвалюсь - просто констатация факта, ни капли не программист, работаю поверхностностно с: Ассемблер,C,Pascal,PHP,C++ ну ни разу не было желания поругаться на язык, это всего лишь инструмент, который надо учить.
И всё-таки я его добил. И он подчинился...
Вот скетч, там много всяких, возможно ненужных наворотов, но, по-моему, важен принцип - работает устойчиво.
Номера телефонов скрыл, SIM карта в модеме от MOTIV. Для нормального запуска модема на 9600 НЕ ТРЕБУЕТСЯ многократной передачи AT+IPR=9600, один раз указал скорость обмена и он понял. Были некоторые сложности в начале пути, но в итоге всё заработало нормально. Скетч разработан ТОЛЬКО для проверки возможностей модема по приёму-передаче SMS.
Вот схема подключения. Расчита на работу под управлением скетча, но каждый волен переделать её и скетч под свои нужды. Плата модема показана условно, только выводы, из них,как видите, используется только 4.
Если у кого-то возникнут вопросы - милости прошу, отвечу по мере сил и умения.
Спасибо всем принявшим участие.
PS. А Си, действительно, трёхнутый на всю голову язык.
PPS. Гораздо лучший справочник по языку Си для Arduino находится тут: https://doc.arduino.ua/ru/prog/
Долбаните то же самое на ассемблере. После этого будете храмы ставить Cи на каждом перекрестке.
На заре своей трудовой деятельности, в году этак 1986-87, обслуживал СМ-4 и СМ-1420. После месячных курсов влёт писал тестовые программки для блоков... Сейчас уже, конечно, всё забылось.
А Си всё равно ипанутый язык, даже Fortran-77. смотрится логичнее...
Ну и что, эти ваши СМ-ки с модемами работали, Вы в асинхронном режиме перифирию программировали с лёту?
(просто интересно)
Нет, они использовались локально, но сложность СМ-ки и Arduin-ки, сравнивать невозможно, ибо это слишком разные устройства. Программировал, естественно, не с лёту, нопрограммы в 150-200 строк писалисьза пару дней, так как за простой натягивали крепко. Зато в результате определась неисправная плата, а то и элемент на ней. Учился в Киеве, при заводе выпускавшем эти машины, учили добротно, коллектив преподователей (они же работники завода) знал своё дело туго. В то время, на каждую плату имелись принципиальные схемы, с контрольными точками, с эпюрами (осциллограммами), то есть искать неисправности приходилось не по наитию, а по приборам. А программы на Макроассемблере помогали быстрее найти неисправность и заменить мёртвый элемент. Если, конечно, это был не процессор. Тогда Цэшку и осциллограф в зубы и вперёд, на мины... Такое правда было всего один раз, тогда обошлось малой кровью, нашли непропай заводской... А вот с периферией таки да, раз в 2-3 месяца что-нибудь да помирало. Был курьёзный случай: утром включили машину, чере пару секунд из одного шкафа раздался грохот. Быстро выключили, открыли шкаф и охренели: из блока вентиляиторов сорвались лопасти, упали вовнутрь и частично перерубили плоский кабель межблочной связи (интерфейс). Заменили вентилятор и кабель за 20 минут и всё заработало.
Вы уж извините, ударился в воспоминания...
Спасибо помогло, только еще пришлось питание дополнительное подать от повер банка. Я что то так и подумал, что вы с 80-х годов. Я позже начал в 1990-м.
И снова приветствую гуру Arduino и модуля gsm/gprs А6.
Нарисовал программку под свои нужды, дошло дело до подключения и внедрения А6, и тут "такое началось" ;)
В общем ситуация такая: воззвал к старой (которую накатал с вашей помощью) программке получения и отправки SMS, кое что изменил, добавил-убрал, в общем, получил результат, который меня полностью удовлетворяет.
Вот текстовка:
И получаю SMS:
Получаю уже вот такую SMS:
Так вот, у с=меня возникает вопрос, каким образом обрезается SMS?
Так, спасибо всем, проблему решил. Возможно через задний проход и автогеном...
Опрашиваю модем на каждом цикле void Loop(), записываю SMS-ку в переменную, а уже обрабатываю её примерно через секунду, после опроса датчиков (если ни одного сработавшего), иначе только после обработки срабатывания.
Если кому интересно - пишите, постараюсь ответить.
Опрашиваю модем на каждом цикле void Loop(), записываю SMS-ку в переменную
судя по коду - именно в этом у вас и проблема. Вы считываете СМС в переменную. не проверяя - а пришло ли сообщение целиком? -вместо этого вы просто ждете 10 секунд :
Код - просто сборище разных ляпов и глупостей. Тайм аут (строка 5) отмеряете неправильно. Блокирующий цикл ожидания (строка 6) - это просто жесть, все это время программа висит, датчики не проверяет, на сигналы не реагирует.
Ну и самый апофеоз - несмотря на тупое ожидание 10 секунд - все это не дает никакой гарантии, что вы правильно обработаете СМС. Представьте, например, что за эти 10 секунд придет еще одно сообщение или служебная инфа от оператора связи? - и все. вся ваша конструкция заткнется...
Ну, обидеть художника может каждый, а вот подсказать правильное решение не у всех получается.
Вряд ли мне удастся отправить 2 SMS за 10 секунд, а служебная инфа отсекается ещё на этапе проверки SMS (в доработанной версии) путём проверки наличия "CMT". А вот подсказать про таймер не судьба???
А вот подсказать про таймер не судьба???
какой таймер? зачем он тут?
Тайм аут имел в виду...
И снова я,со своими наивными вопросами.
Когда я попытался отправить по запросу отчёт, примерно из 80 символов, то получил пустую SMS. Никто не сталкивался с каким либо ограничением на количество символов передаваемых в SMS. Примерно до 70 символов передаётся и получается нормально, а потом - просто пустота... Хотя, по идее, можно посылать до 160 символов...
Все символы в отчёте - латиница и цифры, кириллицы нет.
Есть два ограничения :
1 стандарт GSM
2 кривизна скетча / библиотеки
Похоже я доэкспериментировался с А6. На выходе U_TXD теперь напряжение в 1.6 v (вместо 3,39 v), слегка подсвечивает синий светодиод, соединённый с этим выходом, обмен с Arduino на нуле. надежды, как я понимаю практически никакой. Некоторую надежду внушают пины H_TXD и H_TXD это HST_TXD и HST_RXD, если верить верить ;) руководству от Ai ThinkerTechnology. Пока не нашёл расшифровки, что это такое, HST, но надежды не теряю. Может кто сталкивался?
Вот кусочек таблицы из руководства:
30 UART_TXD UART_TXD,Pin level 2.8V
31 UART_RXD UART_RXD,Pin level 2.8V
32 HST_RXD Download serial port RXD Pin,pin level 2.8V
33 HST_TXD Download serial port TXD pin,pin level 2.8V
Внушает надежду, что у них указано одинаковое напряжение: 2.8V.
Если интересны подробности, то был момент, когда я по ошибке посадил на U_RXD землю, а U_TXD соединил с выходным пином Arduino. Возможно, что это повлияло на работоспособность...
PS. Заказал новый модуль А6, буду насиловать дальше, когда придёт от китаяйцев.
Homo Faber , мне конечно все равно, а почему не Sim800L модем? у него и прошивки постабильнее и документации больше и работают практически всегда....
Когда на Ali выбирал, мне этот больше понравился, если честно чисто внешне. А когда выяснил, что делитель по входу не нужен, было оч-чень приятно. Да и то, что на моих глазах, можно сказать, 2 800-х накрылись медным тазиком, один просто в процессе работы на же рабочем проекте, тоже сыграло свою роль...
Наконец-то восстановил схему, допилил программу, всё вроде работает.
Смущает только одно: от оператора (Tele2) постоянно идут служебные сообщения, я их игнорирую, но немного напрягает эта ситуация. Если SIM карту ставишь в телефон, то такого не наблюдается.
Вот примеры сообщений, для удобства я отделил посылки пустыми строками.
Смущает только одно: от оператора (Tele2) постоянно идут служебные сообщения, я их игнорирую, но немного напрягает эта ситуация. Если SIM карту ставишь в телефон, то такого не наблюдается.
я не спец в сотовой связи. но насколько знаю. эти сообщения и в телефоне идут, просто юзеру не показываются.
Почитайте вот тут https://www.developershome.com/sms/cpmsCommand.asp- получение и хранениее cлужебных сообщений настраивается параметрами BM ("broadcast messages") и SR ("status report") команды AT+CPMS. Правда тут в тексте оговорка, что к сожалению, далеко не все модемы поддерживают управление служебными сообщениями