Но... с точки зрения "феншуя разработки" решение "Еще чуть-чуть помучать этот" - это не правильный выбор.
И все таки я думаю, что "не реагировать" на регистр, проверять номер отправителя и "защита" от переполнения входящих смс это не феншуй, а обязательная необходимость. О которой я вообще забыл..(( особенно о проверке номера отправителя и переполнения вх.смс.
Но... с точки зрения "феншуя разработки" решение "Еще чуть-чуть помучать этот" - это не правильный выбор.
И все таки я думаю, что "не реагировать" на регистр, проверять номер отправителя и "защита" от переполнения входящих смс это не феншуй, а обязательная необходимость. О которой я вообще забыл..(( особенно о проверке номера отправителя и переполнения вх.смс.
Вы не поняли. "Феншуй" не говорит "делать или не делать". Феншуй говорит "в каком порядке" делать. Если бы мы собирали самодельный автомобиль, то.... двери, лобовое стекло, капот и проч. - это тоже "необходимость". При этом, мы бы уже на этапе "рама с колесами и движком" уже попытались бы слелать кружок по двору. А еще раньше, даже когда еще колеса не прикрутили - просто завести двигатель, убедится что он рабочий и подключили мы его правильно.
В нашем случае, ну вот представте себе что вы впихнули все эти "необходимости". Потратите еще пару дней на них. А потом "оно блин не работает". И нужно искать почему не работает. Где легче найти проблему в 20-ти строках кода или в 100?
Так что лучше "убедится что работает 20-ть строк". Потом добавили ОДНУ за раз фишку (Скажем "проверку номера телефона")- убедились что "продолжает работать". Потом добавили "удалять sms" - опять проверили и т.д.
В таком случае если "хомутнули", то вы сразу знаете "где искать собаку". Вам нужно просмотреть всего 3-5ть строк кода которые вы добавили во время последней итерации. И у вас есть два варианта "заведомо рабочий" и "не рабочий". Имея эту комбинацию гораздо легче заставить работать чем имея "простыню которая фиг пойми чего не пашет".
Так что "по феншую", нужно даже не объединением заниматся, а.... пора проверить этот скетч на реальном железе. Переключиться на настоящий gprs и убедится что наше "абстрактное мышление" еще не полностью оторвалось от реальности :). Убедится что наша "эмуляция руками через Serial" действительно идентична поведению реального шилда.
Кстати, в перед этим нам Setup нужно что поправить не забыть.
DBG.begin(9600);
GPRS.begin(9600);
Инициализировать оба "Serial-a". Не страшно что в "тестовом" варианте, когда DBG и GPRS одно и тоже мы фактически сделаем begin два раза одному и тому же Serial. Зато когда DBG будет не равно GPRS мы не забудем выставить скорость каждому.
Так я не лепил все сразу. каждую, как вы говорите "фичу" я испытывал в сериал :) конечно если бы все сразу - то я не нашел бы ошибки. Или искал бы 3 дня. Сейчас еще проверю с шилдом.
Загрузил код тот что в #250 посте(только закоментил DBG ) - все работает. Хоть load on, хоть LoAd oN. - реагирует правильно (вкл и Выкл.светик на 6-м пине.) выполняет команды только с указанного мною номера тел. Проверил потом количество входящих смс на шилде - 0. т.е. все удаляет после выполнения команды. Можно сказать "по двору проехались" )) хоть еще и "без дверей" и "сидя на табуретке" ))
Ну как раз DBG - можно и оставить было. Его же для того и вводили, что-бы даже переключившись на реальный шилд - сохранить возможность видеть в логе "что происходит". Нам нужно было заменить объявление #define GRPS Serial, на #define GPRS gprsSerial
Можно вообще сделать что-то такое, что-бы переключать "реальный/не реальный" одной буквой.
#define GPRS_TO_DBG // закоментируйте эту строчку если нужно использовать настоящий gprs
#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(3, 2);
#ifdef GPRS_TO_DBG
#define GPRS Serial // gprs руками в Serial мониторе эмулируем
#else
#define GPRS gprsSerial // используем настоящий шилд
#endif
Тогда "переключение" между настоящим и псевдо будет сводится в добавлении или уборке // перед первой строкой
Только "табуретка" стоит вверх ногами. Любое "неосторожное движение" и.... :(
Вот я читаю код. Вижу вызов actionLoadOn(), в принципе я предполагаю что эта функция вызывает включение нагрузки.... и вдруг... у меня полезли какие AT-команды в Serial. Откуда? С чего вдруг функция выполняющая команду, вдруг занялась еще чем-то другим? У юристов это называется "превышение служебных полномочий".
Вот скажем в #232 я расписывал "смотрите как класно, executeCommand больше ни от чего не зависит. можно ее взять и тестировать отдельно вот таким кодом". Теперь этого нельзя сделать :(
Теперь нельзя сделать что-бы команды могли приходить еще откуда-то кроме gprs шилда. Скажем из Serial, Ethernet-шилда и проч. Теперь executeCommand и все что внутри ее - имеет зависимость от того что команда пришла именно в виде sms. Скажем сделать что-бы этот же gprs шилд получал команды не sms-сками, а через интернет - уже не выйдет.
Или захочу я что-бы нагрузка включалась еще и физической кнопкой, а не только SMS-ской. Так бы сделал digitalRead() и вызвал actionLoadOn(). А теперь - нельзя. Теперь она еще попробует удалить SMS-ску которой небыло.
Да банально. Сам факт того что вам пришлось два раза писать одинаковый код
GPRS.println("AT+CMGD=1,4"); //Удаление всех входящих сообщений.
уже должен был насторожить что "что-то не то". А если бы нужно было 5-ть команд для этого? Типа "получить количество SMS-ско в памяти и удалять их по одной? Весь кусок бы копировали? Да в любом случае "дублирование кода" - это повод "притормозить и подумать можно ли как то обойтитьс без этого".
Вообщем удаление SMS-сок гораздо более логично было видеть в waitAndExecuteCommand(). Возможно даже переименовать ее, в этом случае в waitAndExecuteSMSCommand (раз она перестала быть "независиомй"). Кусок кода
Читался бы гораздо легче. При этом в явном виде видно "что тут делается". Никаких "скрытых эффектов". Четко видно "получили команду, выполнили ее, удалили SMS-ску"
#include <SoftwareSerial.h>
SoftwareSerial GPRS(2, 3); //Пины SoftwareSerial
#define DBG Serial
#define LOAD_PIN 6
#define INPUT_BUF_SIZE 20 // размер входного буфера
char input_buff[INPUT_BUF_SIZE+1]; // место под хранение входящих из GPRS данных
//************* Входящие SMS - команды ************************
char* cmd_prefix="+cmt";
char* cmd_numTel="+380********9"; //Номер телефона на который реагируем
char* cmd_on="load on";
char* cmd_off="load off";
//************* /Входящие SMS - команда ***********************
void setup(){
pinMode(LOAD_PIN,OUTPUT);
GPRS.begin(9600);
DBG.begin(9600);
}
void loop() {
waitAndExecuteCommand();
}
void waitAndExecuteCommand(){
static bool nextLineWillCommand = false;
if(isLineReady()){
DBG.println(input_buff);
strlwr(input_buff); //Когда есть готовая строка, переводим символы в нижний регистр.
if(!nextLineWillCommand && startsWith(input_buff,cmd_prefix) && strstr(input_buff,cmd_numTel)){ //добавил strstr(input_buff,cmd_numTel) для проверки номера.
nextLineWillCommand = true;
return; // сразу выходим
}
if(nextLineWillCommand){
executeCommand(input_buff);
deleteAllSms();
nextLineWillCommand = false;
}
}
}
bool isLineReady(){
static byte inputBuffIndex=0;
if (GPRS.available()){
byte t = GPRS.read();
switch(t){
case '\n':
input_buff[inputBuffIndex] = 0;
inputBuffIndex=0;
return true;
break;
case '\r':
break;
default:
if (inputBuffIndex < INPUT_BUF_SIZE){
input_buff[inputBuffIndex] = t;
inputBuffIndex++;
}
}
}
return false;
}
bool startsWith (char* inputString, char* prefix) {
return (strstr(inputString, prefix) - inputString) == 0;
}
void executeCommand(char* command){
// ******** Debag Logo ***********************
DBG.print("Yo--ho!!! Command '");
DBG.print(command);
DBG.println("' received");
// ******** /Debag Logo **********************
if(strstr(command, cmd_on)){
actionLoadOn();
}
else if(strstr(command, cmd_off)){
actionLoadOff();
}
}
void actionLoadOn(){
DBG.println("Load On");
digitalWrite(LOAD_PIN,HIGH);
}
void actionLoadOff(){
DBG.println("Load Off");
digitalWrite(LOAD_PIN,LOW);
}
void deleteAllSms(){
GPRS.println("AT+CMGD=1,4"); //Удаление всех входящих сообщений.
DBG.println("Udalenie SMS");
}
До этого я не совсем правильно понимал DBG. Теперь понял, что "лог" (DBG.print) отсылает сообщения на пины 0,1. а GPRS.print работает с Шилдом на пинах 2,3.
объект обозван большими буквами? Мы же вроде говорили что есть принятое в C/C++ соглашение об именах говорит о том что переменные и функции должны называся с маленькой буквы. А все большими буквами - так обычно макросы (#define) обзывают. Вводите в заблуждение.
P.S. назвать с маленькой и потом менять везде в коде - тоже не выход.
объект обозван большими буквами? Мы же вроде говорили что есть принятое в C/C++ соглашение об именах говорит о том что переменные и функции должны называся с маленькой буквы. А все большими буквами - так обычно макросы (#define) обзывают. Вводите в заблуждение.
P.S. назвать с маленькой и потом менять везде в коде - тоже не выход.
Совсем нет. Просто показал к чему привела попытка.... а непонятно зачем вообще это было сделано. Если мы еще,не помню сколько страниц назад решили "давайте сделаем псевдоним и будем потом менять только его объявление". Почему вы вдруг решили отказатся от псевдонима?. Не один раз написал "а потом просто заменим '#define GPRS Serial' на '#define gprsSerial' "
Полность сохранится "единообразие". И в работе с gprs и в работе с логом. Почему не
Котлеты отдельно, мухи - отдельно. Пины объявления в одном месте, управление "куда какие потоки данных отправляем" - в другом. Все однотипно.
В #255 - показал пример как можно пользоватся условной компиляцией. Что-бы в коде было сразу два вариант и не приходилось их "каждый раз набирать" при переключении. Там вообще можно было просто "комментить/декоментить" первую строку. Мне вообще не понятно почему вы не взяли кусок кода из #255 - он же готовый.
код получился полезный,самое главное у leshak получилось подробно все объяснить и с огромным терпением все расписать,за что ему огромное спасибо.для себя сделал много полезных заметок(хотя все эти 250 сообщений получились как одна большая инструкция:). я тоже только учусь, с огромным интересом вчитывался в каждое слово в теме,и есть вопрос к ув. leshak,в данном примере мы научились принимать,разбирать и читать пришедшие данные из сериала. при входящем сообщении данные идут в две строки
+CMT:"066......
СООБЩЕНИЕ
Т.Е. после первой "\n" мы ждем команду. а хочется узнать как быть если команда прийдет после 3 или 4 строк данных сериала (как при звонке,с использованием dtmf).в данном примере авто поднятие после 2 гудка,и приходит строчка данных с нажатой клавишей телефона
RING
+CLIP:"066.....
RING
+DTMF:8
где "8" нажатая кнопка,и может менятся 1-9,#,* . как я вижу алгоритм,нужно дождатся во входящих данных третьего "\n" и дальше уже записать в буфер,и оттуда уже прочесть команду "после +DTMF".подскажите пожалуйста
но смс отправляеться только кагда нажать кнопку. а мне надо что бы отправлялось смс и когда отпустить кнопку. т.е. обратная связь для LED. Точнее вместо светодиода будет реле с дублирующими контактами. Надо знать с помощью смс включилось ли реле на самом деле. и оповещать если разомкнулись контакты. Даже если с Ардуины LED (реле) включено.
Код включения LED:
#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(3, 2);
int greenPin = 4;
void setup()
{
gprsSerial.begin(9600);
pinMode(greenPin, OUTPUT);
// Настраиваем приём сообщений с других устройств
// Между командами даём время на их обработку
gprsSerial.print("AT+CMGF=1\r");
delay(300);
gprsSerial.print("AT+IFC=1, 1\r");
delay(300);
gprsSerial.print("AT+CPBS=\"SM\"\r");
delay(300);
gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
delay(500);
}
String currStr = "";
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;
void loop()
{
if (!gprsSerial.available())
return;
char currSymb = gprsSerial.read();
if ('\r' == currSymb) {
if (isStringMessage) {
//если текущая строка - SMS-сообщение,
//отреагируем на него соответствующим образом
if (!currStr.compareTo("Green on")) {
digitalWrite(greenPin, HIGH);
} else if (!currStr.compareTo("Green off")) {
digitalWrite(greenPin, LOW);
}
isStringMessage = false;
} else {
if (currStr.startsWith("+CMT")) {
//если текущая строка начинается с "+CMT",
//то следующая строка является сообщением
isStringMessage = true;
}
}
currStr = "";
} else if ('\n' != currSymb) {
currStr += String(currSymb);
}
}
Код отправки смс по нажатию кнопки.
#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);
int btnPin = 12;
boolean prevBtn = LOW;
void setup()
{
gprsSerial.begin(9600);
delay(500);
}
void loop()
{
boolean currBtn = digitalRead(btnPin);
if (prevBtn != currBtn && currBtn == HIGH) {
//сразу после нажатия кнопки отправляем "тревожное" сообщение по заданному номеру
sendTextMessage();
}
prevBtn = currBtn;
}
/*
* Функция отправки SMS-сообщения
*/
void sendTextMessage() {
// Устанавливает текстовый режим для SMS-сообщений
gprsSerial.print("AT+CMGF=1\r");
delay(100); // даём время на усваивание команды
// Устанавливаем адресата: телефонный номер в международном формате
gprsSerial.println("AT + CMGS = \"+79************\"");
delay(100);
// Пишем текст сообщения
gprsSerial.println("ALARM!");
delay(100);
// Отправляем Ctrl+Z, обозначая, что сообщение готово
gprsSerial.println((char)26);
}
P.S. Прозьба сильно не пинать.. Новичек в этом деле..
Добрый день, у меня это не работает , поменял для удобства пин светодиода на 13 , грех не применить раз уж есть. ПОслал СМС и ноль. Пример тот что все кругом показывают приема СМС тоже не работает нормально. СМС отправляет, но сам их принимает но передачей в порт как в примере ничего не показывает , иногда постоит подумает и потом только выдает , номер отправителя и время и дату . Попытка подключить шилд к гипертерминалу успеха тоже не дала, не отвечает на команды, до этого пользовался модемами от Овен там все отлично. Удалось настроить шилд с ардуино на то чтобы он звонил применив команду :
мда leshak грамотный дядя все доступно понятно и правильно, а то начитаемся горе авторов книг потом косячим. а у такого как вы я бы с удовольствием поучился
Огромное СПАСИБО топикстартеру и leshak-у за эту тему.
У меня стояла похожая задача, но мне нужно было еще получать в дополнении к смс (точнее в самом смс) время события. Я пробовал пользоваться часами DS1307 но их точность была никакой. Тогда решил брать время от часов самого GSM шилда. Мы примерно все тут пользуемся одинаковыми шилдами и в них есть часы, которые можно корректировать от самой GSM сети - т.е. они всегда будут точны. В дополнении к этому стоит необходимость проверки статуса, для чего нужно посылать смску с запросом.
Никаких проблем с запросом статуса нет, а вот с узнаванием времени шилда есть.
Для того чтоб синхронизировать шилд с GSM сетью нужно в настройке шилда подать команду AT+CLTS=1
После этого, при включении шилда его часы будут всегда синхронизированы с GSM сетью.
Для того чтоб узнать время нужно послать шилду команду AT+CCLK? Он ответит так -
+CCLK: "15/05/13,15:33:21+12"
НО! возникает проблема чтения этого времени (для последующей вставки в смс), которую мне не удается решить - дело в том, что на запрос времени шилд отвечает строкой, что я указал, а потом шлет OK.
И вот что тут я читаю - мне непонятно. Если есть возможность - давайте разберем этот момент.
Уважаемые коллеги нужна подсказка, хочу написать функцию которая будет читать все ответы от модуля SIM800 и возвращать то что прочитано но немного застрял.
Первая идея была считать все в переменную типа String. все получилось но полазив по форуму почитал и решил его не использовать
вот написал такую функцию
char readSIM (){
char buffer[100];
int i = 0;
if (Serial.available()) {
delay(100);
//загоняем прочитанное в буфер
while ( Serial.available() && i < 99) {
buffer[i++] = Serial.read();
}
//закрываем массив
buffer[i++] = '\0';
return buffer;
}
}// end readSIM
IDE выдает ошибку (In function 'char readSIM()': ... error: invalid conversion from 'char*' to 'char' [-fpermissive]) конечно можно вывести переменную как глобальную но снова не очень хороший тон программирования а хочется красиво , для себя ведь.
в чем я ошибаюсь? (или же функция должна вернуть ссылку на char которая в свою очередь может разрушиться?) или это снова бред ?
Ошибок две: функция должна возвращать char, а ты делаешь return buffer, а это указатель на char. И да, нельзя возращать указатель на объект, который умрет при выходе из функции.
if('\0' == buffer[0])
С локальным статическим буфером нужно быть готовым огрести грабли при повторном вызове функции, старый буфер испортится. Как вариант, передавать в функцию указатель и длину буфера и использовать внешний буфер.
написал во такой скетч чтобы разобрать ответ от модуля SIM800 (помоему страшноватый и возможно не правильный весь подход)
что хочу сделать... если чтото получаю от модуля то считываю строку и делю ее на 2 части с разделителем : (все что до символа : это команда на которую нужно както отреагировать, а все что после будет зависить от первой части)
void setup() {
Serial.begin(9600);
}
void loop() {
int i = 0;
int y = 0;
char* str;
char strComand[10];
char strText[200];
char st;
if (Serial.available()) {
str = readSIM();
//Serial.println(str );
memset(strComand, 0, strlen(strComand)); // очистим массив
memset(strText, 0, strlen(strText)); // очистим массив
for (i = 0; i < strlen(str); i++)
{
st = str[i];
//Serial.println(st);
if ((i < 10) && (st != '\0') ) {
strComand[i] = st ;
}// enf if
else if (st != '\0') {
strText[y] = st ;
y ++;
} else {
break;
}
}//end for
strComand[i] = '\0' ;
Serial.println(strComand);
Serial.println("strComand");
strText[i - y] = '\0' ;
Serial.println(strText);
Serial.println("strText");
i = 0;
y = 0;
}//end if
}// end loop
char* readSIM() {
static char buffer[256];
int i = 0;
memset(buffer, 0, 256); // очистим массив
if (Serial.available()) {
delay(100);
//загоняем прочитанное в буфер
while ( Serial.available() && i < 99) {
buffer[i++] = Serial.read();
}
//закрываем массив
buffer[i++] = '\0';
return buffer;
}
else
{
//буфер пустой ничего не пришло
}
}// end readSIM
жду критики или подсказок,вроди работает, также выдает вот такие 2 строки в монитор потра и в первой строке какойто символ затесался (тут его не видно квадратик) , не пойму откуда он взялся отправляю строку 12345678901234567890 . подскажите где ошибка или как можно сделать по другому и правильно :)
В строке 10 объявлена переменная и она не проинициализирована, поскольку она локальная, то в ней мусор. Запомнили этот момент.
В строке 16 мы пытаемся очистить не проинициализированную переменную, для которой функция streln выдаст любое значение, вплоть до больше длины объявленного в 10 строке массив.
"Очищать" строки можно по разному, здесь достаточно записать первый символ strCommand[0] = '\0'; Впрочем и во всех остальных случаях (другие два массива) тоже.
Цикл 18-31 строки проходит по исходной строке. Поскольку цикл ограничен длиной строки (в него НЕ ВХОДИТ символ завершения строки '\0'). Поэтому в строках 22 и 25 сравнение st с '\0' бессмысленно.
strCommand может получить строку не длиннее 10 символов (строка 22), а после цикла (18-31) i будет равно длине ВХОДНОЙ строки, потому в строке 32 мы записываем 0 совсем не в конец строки strCommand, а дальше, потому возможен мусор от 10 сивола и до значения i.
В строке 35 нужно записать 0 в y-ый элемент, а не в i-y.
Строка 39 бессмысленна, потому что в начале цикла (строка 18) этот индекс ВСЕГДА будет проинициализирован значением 0, более того, это локальная переменная, потому в конце loop она вообще перестанет существовать.
Это навскидку, что первое в глаза лезет красной тряпкой.
господа прошу подсказать такой момент, сравниваю 2 строки типа String, сравниваю через ==, но не в этом дело..
строка 1 приходит из модуля сим800 и выводится в IDE
RING
+CLIP:
строка 2 вписываю в скетч "RING+CLIP:"
вот никак не могу понять что там за переход на новую строку, пробовал пробелы и '\r' и '\n' и '\0' удалить, все равно переход остается, как привисти одну из строк к одинаковому виду?
Но... с точки зрения "феншуя разработки" решение "Еще чуть-чуть помучать этот" - это не правильный выбор.
И все таки я думаю, что "не реагировать" на регистр, проверять номер отправителя и "защита" от переполнения входящих смс это не феншуй, а обязательная необходимость. О которой я вообще забыл..(( особенно о проверке номера отправителя и переполнения вх.смс.
Но... с точки зрения "феншуя разработки" решение "Еще чуть-чуть помучать этот" - это не правильный выбор.
И все таки я думаю, что "не реагировать" на регистр, проверять номер отправителя и "защита" от переполнения входящих смс это не феншуй, а обязательная необходимость. О которой я вообще забыл..(( особенно о проверке номера отправителя и переполнения вх.смс.
Вы не поняли. "Феншуй" не говорит "делать или не делать". Феншуй говорит "в каком порядке" делать. Если бы мы собирали самодельный автомобиль, то.... двери, лобовое стекло, капот и проч. - это тоже "необходимость". При этом, мы бы уже на этапе "рама с колесами и движком" уже попытались бы слелать кружок по двору. А еще раньше, даже когда еще колеса не прикрутили - просто завести двигатель, убедится что он рабочий и подключили мы его правильно.
В нашем случае, ну вот представте себе что вы впихнули все эти "необходимости". Потратите еще пару дней на них. А потом "оно блин не работает". И нужно искать почему не работает. Где легче найти проблему в 20-ти строках кода или в 100?
Так что лучше "убедится что работает 20-ть строк". Потом добавили ОДНУ за раз фишку (Скажем "проверку номера телефона")- убедились что "продолжает работать". Потом добавили "удалять sms" - опять проверили и т.д.
В таком случае если "хомутнули", то вы сразу знаете "где искать собаку". Вам нужно просмотреть всего 3-5ть строк кода которые вы добавили во время последней итерации. И у вас есть два варианта "заведомо рабочий" и "не рабочий". Имея эту комбинацию гораздо легче заставить работать чем имея "простыню которая фиг пойми чего не пашет".
Так что "по феншую", нужно даже не объединением заниматся, а.... пора проверить этот скетч на реальном железе. Переключиться на настоящий gprs и убедится что наше "абстрактное мышление" еще не полностью оторвалось от реальности :). Убедится что наша "эмуляция руками через Serial" действительно идентична поведению реального шилда.
Кстати, в перед этим нам Setup нужно что поправить не забыть.
Инициализировать оба "Serial-a". Не страшно что в "тестовом" варианте, когда DBG и GPRS одно и тоже мы фактически сделаем begin два раза одному и тому же Serial. Зато когда DBG будет не равно GPRS мы не забудем выставить скорость каждому.
Так я не лепил все сразу. каждую, как вы говорите "фичу" я испытывал в сериал :) конечно если бы все сразу - то я не нашел бы ошибки. Или искал бы 3 дня. Сейчас еще проверю с шилдом.
Загрузил код тот что в #250 посте(только закоментил DBG ) - все работает. Хоть load on, хоть LoAd oN. - реагирует правильно (вкл и Выкл.светик на 6-м пине.) выполняет команды только с указанного мною номера тел. Проверил потом количество входящих смс на шилде - 0. т.е. все удаляет после выполнения команды. Можно сказать "по двору проехались" )) хоть еще и "без дверей" и "сидя на табуретке" ))
Ну как раз DBG - можно и оставить было. Его же для того и вводили, что-бы даже переключившись на реальный шилд - сохранить возможность видеть в логе "что происходит". Нам нужно было заменить объявление #define GRPS Serial, на #define GPRS gprsSerial
Можно вообще сделать что-то такое, что-бы переключать "реальный/не реальный" одной буквой.
Тогда "переключение" между настоящим и псевдо будет сводится в добавлении или уборке // перед первой строкой
> "сидя на табуретке"
Только "табуретка" стоит вверх ногами. Любое "неосторожное движение" и.... :(
Вот я читаю код. Вижу вызов actionLoadOn(), в принципе я предполагаю что эта функция вызывает включение нагрузки.... и вдруг... у меня полезли какие AT-команды в Serial. Откуда? С чего вдруг функция выполняющая команду, вдруг занялась еще чем-то другим? У юристов это называется "превышение служебных полномочий".
Вот скажем в #232 я расписывал "смотрите как класно, executeCommand больше ни от чего не зависит. можно ее взять и тестировать отдельно вот таким кодом". Теперь этого нельзя сделать :(
Теперь нельзя сделать что-бы команды могли приходить еще откуда-то кроме gprs шилда. Скажем из Serial, Ethernet-шилда и проч. Теперь executeCommand и все что внутри ее - имеет зависимость от того что команда пришла именно в виде sms. Скажем сделать что-бы этот же gprs шилд получал команды не sms-сками, а через интернет - уже не выйдет.
Или захочу я что-бы нагрузка включалась еще и физической кнопкой, а не только SMS-ской. Так бы сделал digitalRead() и вызвал actionLoadOn(). А теперь - нельзя. Теперь она еще попробует удалить SMS-ску которой небыло.
Да банально. Сам факт того что вам пришлось два раза писать одинаковый код
уже должен был насторожить что "что-то не то". А если бы нужно было 5-ть команд для этого? Типа "получить количество SMS-ско в памяти и удалять их по одной? Весь кусок бы копировали? Да в любом случае "дублирование кода" - это повод "притормозить и подумать можно ли как то обойтитьс без этого".
Вообщем удаление SMS-сок гораздо более логично было видеть в waitAndExecuteCommand(). Возможно даже переименовать ее, в этом случае в waitAndExecuteSMSCommand (раз она перестала быть "независиомй"). Кусок кода
Читался бы гораздо легче. При этом в явном виде видно "что тут делается". Никаких "скрытых эффектов". Четко видно "получили команду, выполнили ее, удалили SMS-ску"
Исправился..
До этого я не совсем правильно понимал DBG. Теперь понял, что "лог" (DBG.print) отсылает сообщения на пины 0,1. а GPRS.print работает с Шилдом на пинах 2,3.
Работать конечно будет, но... почему у вас тут
объект обозван большими буквами? Мы же вроде говорили что есть принятое в C/C++ соглашение об именах говорит о том что переменные и функции должны называся с маленькой буквы. А все большими буквами - так обычно макросы (#define) обзывают. Вводите в заблуждение.
P.S. назвать с маленькой и потом менять везде в коде - тоже не выход.
Работать конечно будет, но... почему у вас тут
объект обозван большими буквами? Мы же вроде говорили что есть принятое в C/C++ соглашение об именах говорит о том что переменные и функции должны называся с маленькой буквы. А все большими буквами - так обычно макросы (#define) обзывают. Вводите в заблуждение.
P.S. назвать с маленькой и потом менять везде в коде - тоже не выход.
Ну Вы уже издеваетесь.. (
Ну Вы уже издеваетесь.. (
Совсем нет. Просто показал к чему привела попытка.... а непонятно зачем вообще это было сделано. Если мы еще,не помню сколько страниц назад решили "давайте сделаем псевдоним и будем потом менять только его объявление". Почему вы вдруг решили отказатся от псевдонима?. Не один раз написал "а потом просто заменим '#define GPRS Serial' на '#define gprsSerial' "
Полность сохранится "единообразие". И в работе с gprs и в работе с логом. Почему не
Котлеты отдельно, мухи - отдельно. Пины объявления в одном месте, управление "куда какие потоки данных отправляем" - в другом. Все однотипно.
В #255 - показал пример как можно пользоватся условной компиляцией. Что-бы в коде было сразу два вариант и не приходилось их "каждый раз набирать" при переключении. Там вообще можно было просто "комментить/декоментить" первую строку. Мне вообще не понятно почему вы не взяли кусок кода из #255 - он же готовый.
Мне вообще не понятно почему вы не взяли кусок кода из #255 - он же готовый.
Наверно потому, что не совсем понимал работу с DBG логом.
Теперь понял, что SoftwareSerial работает с шилдом(пинами 2,3). а DBG отправляет на комп.
Фактически два сериала: с шилдом и ПК. просто в начале до меня это не дошло )
Да и строчка SoftwareSerial GPRS(2, 3); была для меня понятней. А о "универсальности" кода постоянно забываю.. (
вот что получилось:
Второй день издеваюсь с "девайса" - полет нормальный.
код получился полезный,самое главное у leshak получилось подробно все объяснить и с огромным терпением все расписать,за что ему огромное спасибо.для себя сделал много полезных заметок(хотя все эти 250 сообщений получились как одна большая инструкция:). я тоже только учусь, с огромным интересом вчитывался в каждое слово в теме,и есть вопрос к ув. leshak,в данном примере мы научились принимать,разбирать и читать пришедшие данные из сериала. при входящем сообщении данные идут в две строки
Т.Е. после первой "\n" мы ждем команду. а хочется узнать как быть если команда прийдет после 3 или 4 строк данных сериала (как при звонке,с использованием dtmf).в данном примере авто поднятие после 2 гудка,и приходит строчка данных с нажатой клавишей телефона
где "8" нажатая кнопка,и может менятся 1-9,#,* . как я вижу алгоритм,нужно дождатся во входящих данных третьего "\n" и дальше уже записать в буфер,и оттуда уже прочесть команду "после +DTMF".подскажите пожалуйста
все получилось управлять с помощью DTMF, вопрос закрыт.
Помогите объеденить и дописать код.
Есть код для включения LED с помощью смс.
и отправка смс с кнопки.
но смс отправляеться только кагда нажать кнопку. а мне надо что бы отправлялось смс и когда отпустить кнопку. т.е. обратная связь для LED. Точнее вместо светодиода будет реле с дублирующими контактами. Надо знать с помощью смс включилось ли реле на самом деле. и оповещать если разомкнулись контакты. Даже если с Ардуины LED (реле) включено.
Код включения LED:
Код отправки смс по нажатию кнопки.
P.S. Прозьба сильно не пинать.. Новичек в этом деле..
Добрый день, у меня это не работает , поменял для удобства пин светодиода на 13 , грех не применить раз уж есть. ПОслал СМС и ноль. Пример тот что все кругом показывают приема СМС тоже не работает нормально. СМС отправляет, но сам их принимает но передачей в порт как в примере ничего не показывает , иногда постоит подумает и потом только выдает , номер отправителя и время и дату . Попытка подключить шилд к гипертерминалу успеха тоже не дала, не отвечает на команды, до этого пользовался модемами от Овен там все отлично. Удалось настроить шилд с ардуино на то чтобы он звонил применив команду :
gsm.SimpleWriteln("ATD89123456789;");
gsm.SimpleWriteln("ATH");
таким образом дозвон пошел. Как заставить его стабильно принимать смс , и выполнять команды AT?
мда leshak грамотный дядя все доступно понятно и правильно, а то начитаемся горе авторов книг потом косячим. а у такого как вы я бы с удовольствием поучился
Огромное СПАСИБО топикстартеру и leshak-у за эту тему.
У меня стояла похожая задача, но мне нужно было еще получать в дополнении к смс (точнее в самом смс) время события. Я пробовал пользоваться часами DS1307 но их точность была никакой. Тогда решил брать время от часов самого GSM шилда. Мы примерно все тут пользуемся одинаковыми шилдами и в них есть часы, которые можно корректировать от самой GSM сети - т.е. они всегда будут точны. В дополнении к этому стоит необходимость проверки статуса, для чего нужно посылать смску с запросом.
Никаких проблем с запросом статуса нет, а вот с узнаванием времени шилда есть.
Для того чтоб синхронизировать шилд с GSM сетью нужно в настройке шилда подать команду AT+CLTS=1
После этого, при включении шилда его часы будут всегда синхронизированы с GSM сетью.
Для того чтоб узнать время нужно послать шилду команду AT+CCLK? Он ответит так -
+CCLK: "15/05/13,15:33:21+12"
НО! возникает проблема чтения этого времени (для последующей вставки в смс), которую мне не удается решить - дело в том, что на запрос времени шилд отвечает строкой, что я указал, а потом шлет OK.
И вот что тут я читаю - мне непонятно. Если есть возможность - давайте разберем этот момент.
Уважаемые коллеги нужна подсказка, хочу написать функцию которая будет читать все ответы от модуля SIM800 и возвращать то что прочитано но немного застрял.
Первая идея была считать все в переменную типа String. все получилось но полазив по форуму почитал и решил его не использовать
вот написал такую функцию
IDE выдает ошибку (In function 'char readSIM()': ... error: invalid conversion from 'char*' to 'char' [-fpermissive]) конечно можно вывести переменную как глобальную но снова не очень хороший тон программирования а хочется красиво , для себя ведь.
в чем я ошибаюсь? (или же функция должна вернуть ссылку на char которая в свою очередь может разрушиться?) или это снова бред ?
Ошибок две: функция должна возвращать char, а ты делаешь return buffer, а это указатель на char. И да, нельзя возращать указатель на объект, который умрет при выходе из функции.
понял что нужно глобально обьявлять строку, есть еще варианты правильного решения?
можно объявить как static внутри функции, тогда и возвращать указатель на неё.
очень интересный вариант, благодарю за подсказку.
у меня еще один вопрос в функцие поставлю условие и если в нее ничего не пришло то использую memset(buffer,0,100);// очистим
так вот вопрос как быстро провести проверку, есть ли чтото есть по указателю или он пустой?
if('\0' == buffer[0])
С локальным статическим буфером нужно быть готовым огрести грабли при повторном вызове функции, старый буфер испортится. Как вариант, передавать в функцию указатель и длину буфера и использовать внешний буфер.
написал во такой скетч чтобы разобрать ответ от модуля SIM800 (помоему страшноватый и возможно не правильный весь подход)
что хочу сделать... если чтото получаю от модуля то считываю строку и делю ее на 2 части с разделителем : (все что до символа : это команда на которую нужно както отреагировать, а все что после будет зависить от первой части)
жду критики или подсказок,вроди работает, также выдает вот такие 2 строки в монитор потра и в первой строке какойто символ затесался (тут его не видно квадратик) , не пойму откуда он взялся отправляю строку 12345678901234567890 . подскажите где ошибка или как можно сделать по другому и правильно :)
В строке 10 объявлена переменная и она не проинициализирована, поскольку она локальная, то в ней мусор. Запомнили этот момент.
В строке 16 мы пытаемся очистить не проинициализированную переменную, для которой функция streln выдаст любое значение, вплоть до больше длины объявленного в 10 строке массив.
"Очищать" строки можно по разному, здесь достаточно записать первый символ strCommand[0] = '\0'; Впрочем и во всех остальных случаях (другие два массива) тоже.
Цикл 18-31 строки проходит по исходной строке. Поскольку цикл ограничен длиной строки (в него НЕ ВХОДИТ символ завершения строки '\0'). Поэтому в строках 22 и 25 сравнение st с '\0' бессмысленно.
strCommand может получить строку не длиннее 10 символов (строка 22), а после цикла (18-31) i будет равно длине ВХОДНОЙ строки, потому в строке 32 мы записываем 0 совсем не в конец строки strCommand, а дальше, потому возможен мусор от 10 сивола и до значения i.
В строке 35 нужно записать 0 в y-ый элемент, а не в i-y.
Строка 39 бессмысленна, потому что в начале цикла (строка 18) этот индекс ВСЕГДА будет проинициализирован значением 0, более того, это локальная переменная, потому в конце loop она вообще перестанет существовать.
Это навскидку, что первое в глаза лезет красной тряпкой.
господа прошу подсказать такой момент, сравниваю 2 строки типа String, сравниваю через ==, но не в этом дело..
строка 1 приходит из модуля сим800 и выводится в IDE
строка 2 вписываю в скетч "RING+CLIP:"
вот никак не могу понять что там за переход на новую строку, пробовал пробелы и '\r' и '\n' и '\0' удалить, все равно переход остается, как привисти одну из строк к одинаковому виду?