"пропадают" данные в диаграмме
- Войдите на сайт для отправки комментариев
Пт, 10/05/2019 - 13:47
Здравствуйте
Прошу подсказки в следующей ситуации. Набросал скетч, котрый по содержимому входящей смс активирует соотв. реле и при этом отвечает смской со статусом реле и дополнительными данными - температурой, влажностью и напряжением.
Проблема в том, что при различной комбинации команд, ответная смс от ардуино не всегда содержит весь набор данных. На каком-то этапе из строки просто "выпадают" значения. Иногда ответное смс вообще пустое.
Если продолжать слать команды в хаотичной последовательности - в какой-то момент снова появляется полное смс в ответ на ту же команду, на которую отвечало с потерей данных.
В терминале это выглядит так:
ROP (команда)
AT+CMGS="+380957314297"
> Yes, Capitan!!! Humi: 45.00 Temp: 22.00 Voltage: 0.00 Cool OFF Vent OFF Light OFF (ответ полный, как надо)
>
COOL ON (команда)
AT+CMGS="+380957314297"
> Yes, Capitan! Humi: 45.00 Temp: 22.00 Voltage: 0.00 Cool ON Vent OFF Light OFF (ответ полный, как надо)
>
COOL OFF (команда)
AT+CMGS="+380957314297"
> (ответ пустой, никаких данных)
>
COOL ON (команда)
AT+CMGS="+380957314297"
> Yes, Capitan! Humi: 45.00 Temp: 22.00 Voltage: 0.00 Cool ON Vent OFF Light OFF (ответ полный, как надо)
>
ROP (команда)
AT+CMGS="+380957314297"
> Vent OFF Light OFF (ответ неполный, потеряны данные о температуре, влажности, напряжению, статусе)
>
COOL OFF
AT+CMGS="+380957314297"
> (пустой ответ вообще)
>
COOL ON
AT+CMGS="+380957314297"
> Yes, Capitan! Humi: 46.00 Temp: 22.00 Voltage: 0.00 Cool ON Vent OFF Light OFF (снова все ок)
>
ROP
AT+CMGS="+380957314297"
> Vent OFF Light OFF
>
VENT OFF
AT+CMGS="+380957314297"
> 45.00 Temp: 22.00
>
LIGHT OFF
AT+CMGS="+380957314297"
> Yes! Capitan! voltage: 0.00 Cool ON Vent OFF Light OFF Humi: 45.00 Temp: 22.00
>
LIGHT ON
AT+CMGS="+380957314297"
> Temp: 22.00
>
ROP
AT+CMGS="+380957314297"
> Vent OFF Light ON
Ну и дальше в том же духе.
Это мои первые шаги в освоении, прошу отнестись с пониманием.
Буду очень благодарен за подсказки - что не так? Куда и почему пропадают данные?
Вот сам текст скетча:
void setup()
{
analogReference(INTERNAL); // выбираем внутреннее опорное напряжение 1.1
pinMode(6, OUTPUT);
pinMode(8, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, INPUT); // вход массы
pinMode(4, INPUT); // вход датчика движения
statusCool = "Cool OFF";
statusVent = "Vent OFF";
statusLight = "Light OFF";
Serial.begin(9600);
Serial.println("ROP Progect");
dht.begin(); // DHT11
mySerial.begin(9600); //подключаем порт модема на скорости по умолчанию (можно менять AT-командой)
mySerial.println("ATI"); //вывести в терминал иноформацию о модеме
delay(100);
mySerial.println("AT+CSQ"); //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(100);
mySerial.println("AT+CLIP=1"); //включаем АОН
delay(100);
mySerial.println("AT+CMGF=1"); //режим кодировки СМС - обычный (для англ.)
delay(100);
mySerial.println("AT+CSCS=\"GSM\""); //режим кодировки текста
delay(100);
mySerial.println("AT+CNMI=2,2"); //отображение смс в терминале сразу после приема (без этого сообщения молча падают в память)
delay (5000);
}
void sms(String text, String phone){ //процедура отправки СМС
if (Smsoff==false)
{
Serial.println("SMS send started");
mySerial.println("AT+CMGS=\"" + phone + "\"");
delay(500);
mySerial.print(text);
delay(500);
mySerial.print((char)26);
delay(500);
Serial.println("SMS send complete");
delay(2000);
}
}
void loop() {
float humi = dht.readHumidity();
float temp = dht.readTemperature();
int analogValue = analogRead(analogPin); // читаем значение на аналоговом входе 3
float volt = (analogValue * 12.40) / 1023; // пересчет измерения в вольты
if (mySerial.available()) { //если есть данные от GSM модуля
delay(400); //выждем, чтобы строка успела попасть в порт целиком раньше чем будет считана
while (mySerial.available()) { //сохраняем входную строку в переменную val
ch = mySerial.read();
val += char(ch);
delay(10);
}
Serial.println(val); // дублируем сообщение в терминал
if (val.indexOf("SMS OFF") > -1) { // если обнаружено кодовое слово SMS OFF
smsoffStr = "Yes, Capitan! SMS OFF";
Serial.println("sms disabled"); // сообщаем об этом в терминал
sms(smsoffStr, MASTER); // отвечаем смской смс отключены
Smsoff = true; // отключаем смс
}
//else
if (val.indexOf("ROP") > -1) { // если обнаружено кодовое слово ROP
ropStr = "Yes, Capitan!!! Humi: "+ String (humi)+" " + "Temp: "+" " +String (temp)+ " "+ "Voltage: " +String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight); // ответ на запрос смс РОП
Smsoff = false;
Serial.println("ROP request"); // сообщаем об этом в терминал
sms(ropStr, MASTER); // отвечаем смской температура, влажность, напряжение, статусы
}
//else
if (val.indexOf("COOL ON") > -1) { // если обнаружено кодовое слово Cool On
statusCool = "Cool ON";
coolStr = "Yes, Capitan! Humi: "+ String (humi)+" " + "Temp: "+String (temp)+" "+ "Voltage: "+ String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight);
Serial.println("Cool ON"); // сообщаем об этом в терминал
sms(coolStr, MASTER); // отвечаем смской
digitalWrite(LED12Pin, HIGH); //включаем 12 пин плюс
}
//else
if (val.indexOf("COOL OFF") > -1) { // если обнаружено кодовое слово Cool off
statusCool = "Cool OFF" ;
cooloffStr = "Yes, Capitan! Humi: "+ String (humi)+" " + "Temp: "+String (temp)+" "+ "Voltage: "+ String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight);
Serial.println("COOL OFF"); // сообщаем об этом в терминал (если нужно)
sms(cooloffStr, MASTER); // отвечаем смской
digitalWrite(LED12Pin, LOW);
}
//else
if (val.indexOf("VENT ON") > -1) { // если обнаружено кодовое слово Vent On
statusVent = "Vent ON" ;
ventStr = String (statusCool)+" "+String (statusVent)+" " +String (statusLight)+" " + "Humi: "+ String (humi)+" " + "Temp: "+String (temp)+" "+ "Voltage: " +String (volt);
Serial.println("VENT ON"); // сообщаем об этом в терминал
sms(ventStr, MASTER); // отвечаем смской
digitalWrite(LED11Pin, HIGH); //включаем 11 пин плюс
}
// else
if (val.indexOf("VENT OFF") > -1) { // если обнаружено кодовое слово vent off
statusVent = "Vent OFF" ;
ventoffStr = "VENT OFF Voltage: " +String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight)+" Humi: "+ String (humi)+" " + "Temp: "+String (temp);
Serial.println("Vent OFF"); // сообщаем об этом в терминал
sms(ventoffStr, MASTER); // отвечаем смской
digitalWrite(LED11Pin, LOW);
}
//else
if (val.indexOf("LIGHT ON") > -1) { // если обнаружено кодовое слово Light On
statusLight = "Light ON" ;
lightStr = "Yes! Capitan! voltage: " +String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight)+" " +"Humi: "+ String (humi)+" " + "Temp: "+String (temp);
Serial.println("Light ON"); // сообщаем об этом в терминал
sms(lightStr, MASTER); // отвечаем смской
digitalWrite(LED10Pin, HIGH);
}
//else
if (val.indexOf("LIGHT OFF") > -1) { // если обнаружено кодовое слово light off
statusLight = "Light OFF";
lightoffStr = "Yes! Capitan! voltage: " +String (volt)+" "+String (statusCool)+" "+String (statusVent)+" " +String (statusLight)+" " +"Humi: "+ String (humi)+" " + "Temp: "+String (temp);
Serial.println("Light OFF"); // сообщаем об этом в терминал
sms(lightoffStr, MASTER); // отвечаем смской
digitalWrite(LED10Pin, LOW);
}
val = "";
}
}
Всем спасибо!!!
Прочитайте вот эту тему, а потом попробуйте зайти на второй заход.
ROP (команда)
AT+CMGS="+380957314297"
Благодарю за участие.
думаю, что проблема с памятью, но это надо проверить.
Попробуйте сделать такую вещь:
1. откройте файл <место, ге установлено IDE>\hardware\arduino\avr\cores\arduino\WString.cpp
2. В этом файле найдите строку содержащую слово realloc. Выглядит она примерно вот так
3. В строке 6 после } добавьте elsle Serial.println("BEDA!!!");
Попробуйте скомпилировать. Если будет ругаться нв Serial, то добавьте в начале файла #include <arduino.h>
В общем, скомпилируйте.
Запустите и смотрите. Если сообщение о "беде" будет вылетать перед проблемами, то виноваты проблемы с памятью.
Если нет, будем дальше думать.
Компиляция не проходит. Ругаться начинает так:
Сообщение #3 читайте внимательнее.
Если я правильно понял намек - речь идет о подключении arduino.h библиотеки?
Просто дописать строку не дало результата. Символы слова "arduino" не выделяются цветом, это значит, что библиотека не найдена?
В списке библиотек такой нет. Гуглом тоже не нашел, чтобы скачать.
Поиском нашел файл arduino.h но нет нигде arduino.cpp. Если я верно понял инструкции из сети по библиотекам - эти файлы должны быть в паре. Просто подложив в список библиотек один файл arduino.h в папке - тоже результата не добился.
Мне продолжать решать вопрос с библиотекой или я опять не туда ?
Благодарю за подсказки
Не туда. Сообщение #3, п.3.
Туплю :(
Ругается почему-то на первую строчку (124:37)unsigned char String :: changeBuffer(unsigned int maxStrLen)
Туплю :(
Тупите.
НИЧЕГО не добавляёте в свой файл. Просто поменяйте ОДНУ строку в системном файле (потом вернёте как было).
Все получилось. Благодарю вас.
"беда" в мониторе появляется регулярно, иногда по паре сообщений подряд :(
Мой скетч слишком кривой? Или "нано" надо заменить на что-то мощнее?
При этом всем команда по активизации реле выполняется четко и всегда. Вопрос пока только с содержимым ответных смс.
Спасибо.
"беда" в мониторе появляется регулярно, иногда по паре сообщений подряд :(
Каждое появление этого сообщения означает, что система попыталась запросить память, а ей не дали - кончилась. Вот Вам и пустые или полупустые сообщения.
Т.е. причина установлена.
теперь про то как быть. Взять что-то помощнее нано, конечно, можно, но это порочный путь. У Вас ужасно написана программа ( с точки зрения работы с памятью). Не плохо, а именно ужасно. Если её переписать по-человечески, то и наны хватит за глаза. А если оставить как есть и не научиться нормально работать с памятью, то завтра Вы ещё пару сообщений добавите и может случиться, что Вам и Меги не хватит.
В разделе "программирование" вверху есть три мои статьи о работе с памятью Прочитайте все три (они там пронумерованы, соблюдайте порядок) и после этого попробуйте переписать то, что у Вас написано. Например, сделайте свои многочисленные String локальными.
Нахрена Вы их все выперли глобально? Вам все сообщения одновременно нужны в памяти? Они ведь, будучи созданы, никогда не удаляются пока новое такого типа делать не прдётся. В принципе, уже одна эта минутная оптимизация снимет Вашу текущую проблему как рукой.
Спасибо большое за объяснение.
Я новичок в этих вопросах, поэтому был рад что вообще хоть как-то заработало. Буду изучать, причесывать.
Еще раз спасибо
Ну, просто перенесите описания своих переменных в те блоки, где они нужны и заработает.
Вопрос к Гуру. Часто вижу обявление пинов и др. через переменные:
Ведь это все можно сделать препроцессором
И данное действо так же осовободит память? И не будет держать эти переменные у себя в памяти НАВЕКА?
Препроцессор не оперирует типом переменной, что может привести к труднопонимаемым проблемам. Я предпочитаю через переменные типа const задавать такие значения.
Еще один вопрос возник.
Как-то можно создать индикатор "загруженности" памяти? Какую-то величину контролировать через терминал, чтобы понимать насколько легче (тяжелее) становится после моих поправок кода?
Спасибо
Теоретически, через это: http://robocraft.ru/blog/arduino/531.html
переменные типа const
Они ещё константами называются :)
Как-то можно создать индикатор "загруженности" памяти? Какую-то величину контролировать через терминал, чтобы понимать насколько легче (тяжелее) становится после моих поправок кода?
Здесь, на этом форуме, лежит библиотека MemoryExplorer с кучей примеров использования!! И чего вас всех в поиске-то забанили? Небось много видео со срамными девками искали? :)
Благодарю. Ушел в чтение. Как говорится - чем дальше в лес....
Так я ж вроде сегодня же Вам давал эти ссылки (ну, их описание) и Вы тогда ещё почитать собирались :)
Бытовая рутина выходного дня отняла время. "Между строк" читать - себе во вред, а вдумчиво получится уже только с понедельника.
Зато уже точно знаю где проблема и в какую сторону копать. А благодаря вашим ссылкам - где копать тоже знаю.
Спасибо за участие
переменные типа const
Они ещё константами называются :)
Написал, как для себя - чтобы на визуальном уровне запомнился квалификатор.
Признаюсь честно - собрался с духом, читать начал (и статьи и обсуждения ниже). Сказать, что понял хотя бы 10% написанного - нагло соврать :(
Тем не менее, какие-то горизонты обозначились.
Спасибо за подсказки.
Снова здравствуйте. Благодаря вашим подсказкам, предыдущая задумка воплотилась таки в рабочую версию. Спасибо еще раз.
Эксперементы продолжаются, снова вопрос связанный с ресурсами ардуино и использованием памяти.
Задача банальная - с помощью GPS модуля NEO6 получить и передать в смс координаты и время.
Нашел в сети массу примеров, запустил скетч - работает. Но, судя по сообщению при компиляции
(Скетч использует 11398 байт (37%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 805 байт (39%) динамической памяти, оставляя 1243 байт для локальных переменных. Максимум: 2048 байт.)
- скетч слишком "тяжелый" для моей нано 328. Если я пробую добавить его к части скетча с смс и остальным - получаю предупреждение о нехватке памяти и возможной нестабильности работы программы.
Все, что мне надо - lat, lng, date, time. На это "уходит" почти половина всей мощности контроллера.
Как можно, если можно в принципе, оптимизировать это?
Я почитал (и перепроверил) что подключении соотв. библиотек сразу занимает место в памяти. #include <TinyGPS++.h> - может быть как-то "урезана" (находил такой текст в сети, но по неопытности не могу судить о достоверности), чтобы она "обслуживала" только мои четыре переменные и не занимала столько ресурсов?
Или выход только в поиске более производетельного контроллера? Если да - посоветуйте какого.
Я уже даже начал рассматривать вторую нано+neo, которая будет на первую нано+GSM слать данные. Но даже на этапе шальных мыслей это очень тупо выглядит...
Спасибо всем.
"В принципе" оптимизировать можно, но если Вы сами понимаете, что неопытны, то проще поменять МК. Следующий по "моще" и популярности из линейки Ардуино - Mega2560.
Благодарю вас.
Я могу как-то предварительно оценить хватит ли мне 2560? Сейчас мой "полный" скетч до 80% нано328 "кушает". Если я возьму мегу2560 - то сколько от ее ресурса это будет в процентах?
Что следующее после 2560 по производительности? Задумок масса, пока буду "шифовать" навычки создания скетчей, хотелось бы под рукой иметь аппаратную возможность запустить хоть в каком-то виде.
Спасибо!
Mega 2560 PRO MINI
следущий шаг
https://ark.intel.com/content/www/us/en/ark/products/83137/intel-galileo-gen-2-board.html
Благодарю, джентельмены.
Пока попробую во время ожидания 2560 "попричесывать" скетч.
Имеет ли право на жизнь такой путь - открыть файл библиотеки, пробовать удалять оттуда "ненужные" мне строки, и проверять работает ли еще мой скетч после этого?
Спасибо
канпилятор сам выкинет "ненужные тебе строчки"
Благодарю. Походу я неверно представил себе это.
Стало быть надо искать готовую библиотеку с похожим функционалом но с меньшим "аппетитом" или увеличивать аппаратные ресурсы.
мне почему-то кажется. что библиотека тут непричем. Вы бы скетч свой показали для начала. Почти всегда, когда в ардуино не хватает памяти - виноват кривой код пользователя, а не библиотеки.
особенно это относится к случаю, когда новичек работает со строками - а это, похоже, именно ваш случай....
Вы абсолютно правы. Скетч достаточно кривой, его даже не сразу удалось заставить работать. Но пока я не пробую туда добавить ЖПС - он свое выполняет.
Вот первая, отдельно работающая часть.
ну я так и думал. Почитайте про оператор F() для константных строк - одно это, думаю, даст вам экономию оперативной памяти раза в три, не меньше
ссылка - https://www.arduino.cc/reference/en/language/variables/utilities/progmem/ - то, о чем я говорю - это самый последний абзац "The F() macro". Но вообще полезно прочитать все.
Спасибо. Прочитал.
Вот из этого:
The
F()
macroWhen an instruction like :Serial.print("Write something on the Serial Monitor");
is used, the string to be printed is normally saved in RAM. If your sketch prints a lot of stuff on the Serial Monitor, you can easily fill the RAM. If you have free FLASH memory space, you can easily indicate that the string must be saved in FLASH using the syntax:
Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));
Я понял, что:
1. Я могу из скетча удалить все ненужные мне (кроме как на этапе отладки) выводы в порт сообщений строками Serial.print. Во время работы устройства, они реально не нужны больше.
2. Дополнительно воспользовавшись Serial.print (F (...) ); и "запихнув" туда свои string с переменными - я еще более "разгружу" скетч.
Поправьте, плиз, если ошибся.
Спасибо!
по п 1 только вам решать. какие строки нужны. какие нет
по п 2 - похоже, вы поняли неправильно. Макрос F() работает с константами. поэтому "строки с переменными" в него запихнуть не выйдет
По пункту 1 - Serial.print и mySerial.print - это разные функции. Первая выводит данные в монитор порта (и поэтому может быть полностью исключена из финальной версии скетча), вторая - выводит данные на модем. Так?
По пункту 2 - я еще очень путаюсь в этих вещах. Насколько я себе представлял - мой скетч использует много памяти из-за наличия строк, которые в монитор и в модем выводят набор данных.
Я сейчас глупость спрошу, но если у меня значения, из которых формируется смс ( val) это постоянно обновляемый набор данных (напряжение, температура, баланс и т.д) - то разве это константа?
Спасибо. Голова кругом уже, но я стараюсь понять и разобраться
UPD:
Please note that variables must be either globally defined, OR defined with the static keyword, in order to work with PROGMEM.
The following code will NOT work when inside a function:
const char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n";
The following code WILL work, even if locally defined within a function:
const static char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n"
Читаю дальше чуть внимательнее - получается, что я могу только фиксированные строки таким образом "перебросить" в флеш. Получается, чтобы отправить смс по-новому мне надо сформировать строку из "постоянной части", которая теперь будет "жить" во флеши, и переменных из скетча.
Правильно? Или опять мимо?
Спасибо!
Читаю дальше чуть внимательнее - получается, что я могу только фиксированные строки таким образом "перебросить" в флеш. Получается, чтобы отправить смс по-новому мне надо сформировать строку из "постоянной части", которая теперь будет "жить" во флеши, и переменных из скетча.
Правильно? Или опять мимо?
правильно.
Кроме того, у вас в программе масса просто фиксированных строк - например команды модема.
Правильно? Или опять мимо?
А по мне так опять мимо.
Если Вы собираетесь "формировать", то никакой экономии не получите. Вам надо формировать только переменную часть. Постоянную часть выводить прямо из прогмем, и туту же переменную часть ей в догонку.
Снова здравствуйте
Начал пробовать "переселять" во флеш строки.
Сейчас, увы, проверить в работе нет возможности, пока на уровне компилятора.
Добавил такие библиотеки (но есть подозрение, что это одно и то же, подскажите плиз).
Переделал запросы модему так:
Компиляция прошла успешно. Вместо 73% показало 70%. Должно работать? Я на верном пути?
Спасибо!
Должно работать? Я на верном пути?
что касается строк - да :)
Вам надо формировать только переменную часть. Постоянную часть выводить прямо из прогмем, и туту же переменную часть ей в догонку.
Вот так? Постоянная часть сообщения (строка) из флеши, переменная из скетча.
Компилятор "скушал" вроде, не ругнулся.
Вот так? Постоянная часть сообщения (строка) из флеши, переменная из скетча.
а в 8-й строке почему так же не сделали?
не так. что плюс забыл в строке 4. Какаа Вы вообще её понимаете?
Вот так? Постоянная часть сообщения (строка) из флеши, переменная из скетча.
а в 8-й строке почему так же не сделали?
Пропустил. Вот так?
Вряд ли. В кавычках получится просто набор символов, а не вызов из памяти.
А если так делаю - ругается компилятор. Не могу допереть как правильно синтаксис тут выполнить. Подскажете?
не так. что плюс забыл в строке 4. Какаа Вы вообще её понимаете?
Ход мыслей был таков - вывести в монитор порта (serial.print) сообщение из двух составляющих. Первая часть - из области флеши (для экономии памяти) набор букв "substring bal Sms " и из скетча значение переменной "val". По итогу ожидал увидеть в мониторе после строки "substring bal Sms" результат выполнения функции substring (обрезок из входящей смс) .
Ход мыслей был таков - вывести в монитор порта (serial.print) сообщение из двух составляющих. Первая часть - из области флеши (для экономии памяти) набор букв "substring bal Sms " и из скетча значение переменной "val". По итогу ожидал увидеть в мониторе после строки "substring bal Sms" результат выполнения функции substring (обрезок из входящей смс) .
А что, просто посмотреть что выводится не судьба? Вы же складываете там ужа с ежом.
Если хотите "вывести в монитор порта (serial.print) сообщение из двух составляющих", то и выводите двумя вызовами Serial.print. Одним константу, вторым переменную. Чего Вы там с плюсами мудрите.
Ход мыслей был таков - вывести в монитор порта (serial.print) сообщение из двух составляющих. Первая часть - из области флеши (для экономии памяти) набор букв "substring bal Sms " и из скетча значение переменной "val". По итогу ожидал увидеть в мониторе после строки "substring bal Sms" результат выполнения функции substring (обрезок из входящей смс) .
А что, просто посмотреть что выводится не судьба? Вы же складываете там ужа с ежом.
Если хотите "вывести в монитор порта (serial.print) сообщение из двух составляющих", то и выводите двумя вызовами Serial.print. Одним константу, вторым переменную. Чего Вы там с плюсами мудрите.
Благодарю, попробую.
Не могу понять почему фокус с выносом во флеш не получается при формировании строки смс
Как правильно оформить синтаксис в таком случае, чтобы "подтягивались" значения из скетча к фразам из флеши? По аналогии с serial.Print не получается, компилятор ругаться начинает.
Спасибо!
Только всё равно это сравнимо с ударом сковородкой по голове. Гораздо "дешевле" по ресурсам сразу в Serial.print() передавать указатель на PGM-строку.