при такой загруженности памяти, у вас адекватно работает?!
у меня когда SRAM к 70% подходил, перестовал модем присылать сообщения, то пустое, по пару слов
Как видите, за последний месяц жалоб на нестабильную работу двух последних версий прошивок, они отличаются по функционалу, не поступало. У меня "боевая" сигналка в течение последнего месяца не накосячила ни разу.
Работает потому что от модема ещё не "прилетело" данных больше чем сам буфер, как только это произойдёт вы без труда сможете понять для чего увеличивается этот буфер. На 590 модеме "мусора" от модема прилетет меньше чем на SIM800L или A6_Mini, поэтому вам буфера хватает.
пример ровно ничего не доказывает, там нет никакий данных, были ли проблемы от маленького буфера и исправились ли они после его увеличения.
У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко. Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.
kvolk пишет:
b707 пишет:
Этим вы просто выкидываете 128 байт оперативки, а ее и так немного.
Вы ошибаетесь.
И в чем же я ошибаюсь? Увеличение буфера на 128 байт не уменьшает оперативку?
Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают? Интересно, как вы читаете СМС, что у вас буфер переполняется...
Доказывает, проблема решилась после увеличнения буфера, но вы это не хотите видеть.
b707 пишет:
У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко.
А у меня 590, сим800 и а6_мини и все они поддерживаются в одной прошивке. Сим800 в отличие от других модемов по умолчанию сильно спамит в порт. В моей реализации для отладки используется "тестовый режим" при включении которого в консоль валится вся инфа от модема.
b707 пишет:
Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.
Да делайте как хотите, это ваше право :) Причём тут смс?
b707 пишет:
И в чем же я ошибаюсь?...
В этом:
b707 пишет:
Этим вы просто выкидываете 128 байт оперативки.
Не просто и не выкидываю.
b707 пишет:
Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают?
Для того чтобы сырой код во время разработки, отладки, допила не растаскивали на куски и не лепили из него подобных "франкенштейнов". В конце концов не хочу, нет желания. Что касается кривого кода и ссаных тряпок - кода вы не видели, значит и утверждать о том, что он кривой не можете. А вот к тому коду из 206 поста, которым вы тут дружно пользуетесь, который я видел - ссаных тряпок могу подкинуть, поверьте, вам хватит :)
b707 пишет:
Интересно, как вы читаете СМС, что у вас буфер переполняется...
Кто вам вобще сказал что дело в чтении СМС? Дальше носа своего не видите? :)
kvolk, много слов и ничего по делу. Грозите раскритиковать код из поста 206 - да ради бога. с удовольствием послушаю. Люблю учиться. Тем более что свой код вы не показывайте - так хотя бы по замечаниям о чужом коде можно будет оценить ваш уровень...
как мне при приеме переменной, разбить ее на несколько переменных
допустим отправляем смс с кодом: 123456
присвоить A1 = 12, A2=34, A3=56
А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)
Общепринято посылать переменные, например, в виде пар "параметр=значение", разделяя из запятыми : "A1=12,A2=34,A3=56". Такой формат легко запомнить, и он гибче - порядок и число переменных можно менять.
Если А1-А3 положительное число не превышающее 255, то как-то так:
большое вам человеческое спасибо
b707 пишет:
А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)
для корректирование времени через смс запрос 073030 т.е. 07:30:30
Да, копипастят налево и направо. Это же очевидно :) Посмотрите первый пост этого топика :)
Вот оно что...банальная жадность! Ещё раз: Ардуина - свободная платформа.
Не надо, не выкладывайте свой код. Кто не хочет делать своими руками, пусть просто заливают код и пользуются незная как это устроено.
Лицензия LGPL не требует открывать свой код, разработанный для Ардуино, и позволяет создавать коммерческий продукт.
Русский язык тоже свободная платформа и говорить на нём можно бесплатно. Но, те, кто, например, написали на нём роман или песню, иногда хотят, чтобы их произведение приносило им доход.
Я это не к тому, что я разделяю позицию копирастов, нет, у меня к этому сложное отношение, но я понимаю эту позицию и признаю за людьми право так считать, и так себя вести.
Вы действительно считаете что если ардуина свободная платформа, то все программы для этой платформы обязаны предоставляться в виде исходных текстов? :)
А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Это как?
В моём понимании двузначное число состоит из двух цифр, минимальное значение которого равно 10 максимальное 99. Во втором классе меня учили так. 512 - трёхзначное число.
Вы не только невнимательный копираст, а еще свои ошибки признавать не любите...
Вот это чей код?
a1 = data.substring(0, 2).toInt();
скольку тут знаков в числе?
Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t было акцентировано внимаение на том что число должно быть положительное и не превышающее 255, потому что многие начинающие не знают этих нюансов. А на этой платформе памятью "разбрасываться" нельзя.
Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t
Вы опять с умным видом пытаетесь поучать других, хотя получается не очень. Я в форме шутки пытался указать вам, что ваш код перестанет работать задолго до числа 255 - именно потому, что вы извлекаете из строки только два знака, а вовсе не из-за выбранного типа int8_t для числовой переменной.
kvolk пишет:
А на этой платформе памятью "разбрасываться" нельзя.
как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.
как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.
Должен поправится, не вполне прав. на 328й ардуине 8bit data alignment, так что компилятор действительно пытается упаковать два первых типа в 8 бит. Правда это не всегда работает.
Код будет работать, так как числа больше 99 там быть не может, минимум 01 - максимум 99. Объясню ещё раз: 255 было упомянуто только из-за ограничения накладываемого на тип данных int8_t.
b707 пишет:
..типы byte, int8_t и int. Вас ждет удивительное открытие.
для корректирование времени через смс запрос 073030 т.е. 07:30:30
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные, но ручная корректировка тоже нужна или хотябы корректировка часового пояса.
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.
тогда уже NTP сервер использовать
сделал как kvolk порекомендовал, при любой смс корректируем время от оператора
if (val.indexOf(F("+cmt")) > -1) { // при любом обращении к GSM модулю корректирует часы от оператора
delay(500);
time.Hours = val.substring(34, 36).toInt();
time.minutes = val.substring(37, 39).toInt();
time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
}
kvolk - Я прочитал ваш блог. Уважение. Хорошая и интересная сигнализация. Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.
Я проверил вашу сигнализацию. Arduino NANO v.3 и модем M590E. Вы написали, что на D10 - красный светодиод, D11 - синий, D12 - зеленый.
После очередного включения сигнализации загорается зеленый светодиод (правильно).
После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?
..мне показалось проще и надежнее делать GPRS запрос типа HEAD ...
Довольно интересный способ, получения практически точного времени.
b707 пишет:
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.
Из всех вышеперечисленным методов я бы пожалуй сразу отказался от NTP - очень ресурсоёмкий процесс, и при наличии интернета можно менее затратно парсить заголовки сайтов.
Если бы позволяла память и было бы соединение с инетом - однозначно использовал бы заголовки http для получения практически точного времени.
В случае ограниченного ресурса памяти, использовал бы корректировку из смс. Но тут нужно ещё раз проверить, если выключить модем и отправить на него смс, а потом через пол часа включить - какое время прилетит на модем, время отправки смс или получения модемом смс?
smesharik пишет:
...при любой смс корректируем время от оператора
Проверьте что за время будет прилетать при получении смс с задержкой. Только что нашел свой пост в котором +CMT: "+380958xxxxxx",,«16/02/16,32:05:42+18» время и дата не являются правильными о_О.
UPD. Всё оказалось проще, на тот момент модема на работе не было, пришлось эмулировать его работу через USB-TTL конвертор, естественно все данные кроме номера взяты "от фонаря" :)
Gienekb пишет:
Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.
При наличии контроля температуры "запилить" простой контроль внешнего питания - простая задача, никаких библиотек подключать не надо, всего лишь достаточно мониторить состояние пина.
В моём случае контроль температуры был непозолительной роскошью.
Gienekb пишет:
После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?
Мигает синий светодиод - включен тестовый режим.
Светится зелёный светодиод - снято с охраны. Команда LedOff отключает этот светодиод - чтобы ночью несветил :)
Мигает красный светодиод - поставлено на охрану, основной и/или дополнительный датчики в режиме геркона, цепь одного или обоих герконов разомкнута.
Горит красный светодиод - поставлено на охрану, датчики в режиме геркона замкнуты.
Мигает синий светодиод в течение 2 секунд при замыкании геркона всегда, вне зависимоти от состояния сигнализации (проверка при снятой с охраны сигналке).
smesharik пишет:
Вот как это реализовано у меня со Скатом
Огромный плюс в том, что можно сразу и сирену подключить. Какая автономность? :)
if (val.indexOf(F("+cmt")) > -1) { // при любом обращении к GSM модулю корректирует часы от оператора
delay(500);
time.Hours = val.substring(34, 36).toInt();
time.minutes = val.substring(37, 39).toInt();
time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
}
Вы на 100% можете быть уверены том что на месте этих символов всегда будут часы, минуты, секунды?
substring(34, 36).toInt();
А если отправить смс с ru номера или ua, правильно ли установится время, длина номера то разная. Конечно же если вы делаете это устройство только для себя, то на эти мелочи можно просто забить, но всё же попробуйте не привязываться жестко к позиции символа в строке.
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.
Я предпочитаю проектировать программы так, чтобы они требовали как можно меньше внимания. Сигналка должна "управляться" самостоятельно, разве что пару тройку СМС послал при запуске, что подобрать параметры - а дальше СМС должны идти только от сигналки к вам - а не обратно.
Я думал о извлечении времени из СМС - этот метод очевиден - но отказался от него. Ситуация, что после каждого перезапуска программы для установки времени мне будет нужно отправить СМС - для меня не подходит.
сделал как kvolk порекомендовал, при любой смс корректируем время от оператора
на модеме А6, к сожалению, нет поддержки UDP стека - а то бы попробовал NTP.
Коррекцию времени вы написали плохо, согласен с замечанием kvolk. Ваш код парсинга времени из СМС крайне ненадежен, рекомендую его переписать. Ищите в строке характерные подстроки, например для времени - три группы цифр, разделенные двумя двоеточиями. Найти соответсвующие символы в строке совсем несложно, примеров кода в сети полно. То что написано у вас - это никуда не годится, никогда не полагайтесь на положение символа.
if (val.indexOf(F("+cmt")) > -1) { // при любом обращении к GSM модулю корректирует часы от оператора
delay(500);
time.Hours = val.substring(34, 36).toInt();
time.minutes = val.substring(37, 39).toInt();
time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
}
Посмотрите это сообщение, 21-ая строка кода. Там определяется позиция последовательности символов в строке, добавляется +1. Потом опять позиция поледовательности + длина строки которую необходимо получить. Профит!
Обратите внимание, в коде не все строки хранятся во флэш памяти F ("bla-bla-bla") - это важно при оптимизации памяти.
Последние 5 месяцев проекта была жесть просто жесть, необходимо было править баги и добавлять функционал практически на одном проценте памяти, в ченджлоге это видно. Иногда было проавильнее пожертвовать оперативной памятью для высвобождения флэш-памяти. Посмотрите на скрины компиляции:
Идентичные константы (строки) в оперативной памяти могут быть использованы в разных местах программы и не будут храниться дважы в ОЗУ. На примере это видно. Например, если используется символ "/" в тексте программы раз 50 или 100, то логичнее пожертвовать одним байтом ОЗУ чем 100 байтами флэш памяти.
kvolk, спасибо за поднятую тему. С интересом потестировал разные варианты. Действительно, макрос F() очень расточителен по отношению к флеш-памяти. Честно говоря, никогда не задумывался об этом. Правда, я обычно не использую F() для повторяющихся строк - не потому. что экономлю флеш, а просто лениво многократно набирать (или копировать) одно и то же :)
Вместо использования F() можно проделать все то же самое "вручную" - повторяющиеся строки разместить в PROGMEM, а в процедуру print() передавать ссылку. Этот вариант абсолютно идентичен F() для единичной строки, но при многократном использовании не так прожорлив по отношению к флеш - сравните со своим первым и вторым вариантом.
Пример:
const char aa[] PROGMEM = "Bla-bla-bla";
void setup() {
// put your setup code here, to run once:
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
}
void loop() {
// put your main code here, to run repeatedly:
}
//Скетч использует 1 462 байт (4%) памяти устройства.
//Глобальные переменные используют 188 байт (9%) динамической памяти
чтобы не загромождать скетч постоянным приведением типов, можно определить для него макрос
немного подправил скетч, команды и функционал не урезал. объединил команды смс и консоли (если команда введена в консоли то смс не оправляется), тем самым немного освободил места. мастер-номера и баланс теперь приходят в одном смс. теперь команды вкл/выкл понимает: так dooron и так door on.
на данный момент
Скетч использует 21538 байт (70%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 941 байт (45%) динамической памяти, оставляя 1107 байт для локальных переменных. Максимум: 2048 байт.
вот скетч:
#include <EEPROM.h>
#include <OneWire.h>
#include <RCSwitch.h>
#include<SoftwareSerial.h>
OneWire ds(6); // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial mySerial(7, 8); // модем подключен к 7 и 8 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.
#define DOOR 4 // пин 4. концевик двери.
#define PIR 5 // пин 5. датчик движения.
#define GAS 14 // пин A0. датчик дыма.
#define LED 13 // пин 13. состояние системы.
#define BUZ 16 // пин A2. сирена.
// DOOR - если сработал, на входе "+" HIGH.
// DOOR2 - если сработал, на пин 2 сигнал.
// PIR - если сработал, на входе "+" HIGH.
// GAS - если сработал, на входе "+" HIGH.
// BUZ - если "-" LOW, то горит.
// LED - если "-" LOW, то горит.
int8_t Guard = 0; // 1. охрана: 1 - вкл, 0 - выкл.
int8_t AlarmRING = 1; // 2. вызов при сработке: 1 - вкл, 0 - выкл.
int8_t SendSMS = 1; // 3. отправка смс при сработке: 1 - вкл, 0 - выкл.
int8_t DOORon = 1; // 4. контроль концевика двери: 1 - вкл, 0 - выкл.
int8_t DOOR2on = 1; // 4. контроль концевика двери 2: 1 - вкл, 0 - выкл.
int8_t PIRon = 1; // 5. контроль датчика движения: 1 - вкл, 0 - выкл.
int8_t GASon = 1; // 6. контроль датчика дыма: 1 - вкл, 0 - выкл.
int8_t Sirena = 1; // 7. сирена: 1 - вкл, 0 - выкл.
int8_t DOORFlag = 0; // флаг состояние датчика двери.
int8_t DOOR2Flag = 0; // флаг состояние датчика двери 2.
int8_t PIRFlag = 0; // флаг состояние датчика движения.
int8_t GASFlag = 0; // флаг состояние датчика газа.
int8_t DOORState = LOW; // Состояние концевика двери.
int8_t PIRState = LOW; // Состояние датчика движения.
int8_t LEDState = HIGH; // Состояние светодиода.
int8_t Smoky = LOW; // Состояние датчика газа.
int8_t Firststart = 1; // первый старт.
int8_t sendsmscaller = 1; // отправка смс.
uint32_t msAT = 0;
unsigned long door2 = 3258553; // адрес 433 передатчика геркона двери
char Bal[4] = ""; // для временного хранения номера баланса.
char Phone[12]; // для временного хранения номера телефона.
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.
String val; // переменная для хранения пришедших данных.
String temp; // температура.
String csq; // уровень сигнала.
String LastEvent; // полное состояние системы.
String EEPhone; // все номера из EEPROM.
String RingPhone; // номер звонившего.
String AlarmPhone[5]; // номера для постановки/снятии с охраны и отправки смс.
int p = 0;
int GASThres = 400; // предельная концентрация газа
int interval_alarm = 20; // Секунд до отключения "тревожного" пина.
int previousMillis_alarm = 0;
int interval_led = 1000; // для мигания LED, 1 сек.
int previousMillis_led = 0;
int interval_door = 10; // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
int interval_door2 = 20; // секунд не смотрим на датчик двери 2.
int previousMillis_door2 = 0;
int interval_pir = 20; // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
int interval_gas = 60; // секунд не смотрим на датчик газа.
int previousMillis_gas = 0;
/* EEPROM Data:
№ ячейки - значение:
0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
1 - Guard = 0; // охрана: 0 - выкл.
2 - AlarmRING = 1; // звонок: 1 - вкл.
3 - SendSMS = 1; // отправка смс: 1 - вкл.
4 - DOORon = 1; // концевик двери: 1 - вкл.
5 - DOOR2on = 1; // концевик двери 2: 1 - вкл.
6 - PIRon = 1; // датчик движения: 1 - вкл.
7 - GASon = 1; // датчик дыма: 1 - вкл.
8 - Sirena = 1; // сирена: 1 - вкл.
10 - Firststars = 1; // первый запуск 1.
20 - ячейка памяти баланса,
25, 40, 55, 70, 85 - ячейки памяти телефонов.
100 - ячейка памяти номера последнего звонившего RingPhone.
*/
void setup() { /// === настройка программы === ///
Serial.begin(9600);
Serial.println(F("Alarm v4.1"));
pinMode(DOOR, INPUT_PULLUP); // вход датчика двери с подтяжкой на +.
pinMode(PIR, INPUT);
pinMode(GAS, INPUT);
pinMode(BUZ, OUTPUT);
pinMode(LED, OUTPUT); // светодиод горит во время запуска.
digitalWrite(BUZ, HIGH); // сирена выкл.
digitalWrite(PIR, HIGH); // игнорируем при включении.
InitModem(); // запускаем инициализация модема.
eepromconfig();
eepromtext();
eepromphone();
mySwitch.enableReceive(0); // 433 приемник на 2 пине
digitalWrite(LED, HIGH); // гасим светодиод состояния сигнализации.
}
void loop() { /// === основной цикл программы === ///
AlarmPinOff(); // выключаем сирену, если прошло время.
if (Guard == 1) { // если на охране
Detect(); // проверяем датчики.
Led(); // моргаем светодиодом.
}
if (mySerial.available()) { // если GSM модем что-то послал.
while (mySerial.available()) { // сохраняем входную строку в переменную val.
char ch = mySerial.read();
val += char(ch); // собираем принятые символы в строку
delay(3);
}
if (val.indexOf("+PBREADY") > -1) InitModem();
if (val.indexOf(F("+CLIP")) > -1) { // если обнаружен вызов.
Serial.println(F("Process RING"));
delay(2000); // дадим гудок
mySerial.println(F("ATH")); // сбрасываем вызов.
if (CheckPhone() == 1) { // проверяем номер, если наш.
Serial.println(F("Master Ring OK!"));
MasterRing(); // меняем состояние охраны
} else Serial.println(F("No Master Ring!"));
} else if (val.indexOf(F("+CMT")) > -1) { // если обнаруженa СМС
Serial.println(F("Process CMT"));
Serial.println(String(F("SMS->")) + val); // что пришло в смс
if (CheckPhone() == 1) { // если СМС от хозяина
Serial.println(F("Master SMS OK!"));
Komand();
} else Serial.println(F("No Master SMS!"));
} else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс
// команда проверки баланса AT+CUSD=1,#105#,15
// анализируем строку
int p1 = val.indexOf(F("\"")); // начало строки
int p2 = val.lastIndexOf(F("\"")); // конец строки
val = val.substring(p1+1,p2);
Serial.println("");
Serial.println(F("Input string:")); // пишем в порт пришедшую строку
Serial.println(val);
String decodestr;
Decode7bit(val, decodestr);
Serial.println("");
Serial.println(F("Decode string:")); // пишем в порт конвертированную строку
Serial.println(decodestr);
sms(String("SIM " + decodestr), RingPhone); // смс на последний звонивший
mySerial.println("AT+CUSD=0");
} else if (val.indexOf(F("+CSQ:")) > -1) { // пришел уровень сигнала сети
int x = val.indexOf("+CSQ:");
csq = val.substring(x+6, x+8);
} val = "";
} if (Serial.available()) { // если в мониторе порта что-то ввели
while (Serial.available()) { // сохраняем входную строку в переменную val.
char ch = Serial.read();
val += char(ch); // собираем принятые символы в строку
delay(3);
}
sendsmscaller = 0;
Komand(); // запускаем консольную программу
val = "";
sendsmscaller = 1;
}
}
int CheckPhone() { /// === проверка телефона === ///
if (Firststart == 0) { // если не первый старт
for (int i = 0; i < 5; i++) {
if (val.indexOf(AlarmPhone[i]) > -1) { // && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
RingPhone = AlarmPhone[i]; // запоминаем его.
RingPhone.toCharArray(Phone, 12);
EEPROM.put(100, Phone); // записываем RingPhone в память.
Serial.println(String(F("RingPhone ")) + RingPhone);
return 1; // возвращаем 1 - номер наш!
}
} return 0; // возвращаем 0 - номер не наш!
} else if (Firststart == 1) { // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
if (val.indexOf("+CLIP: \"7") > -1) {
int ind = val.indexOf("+CLIP:"); // обрезаем номер
String num = val.substring(ind + 8, ind + 19);
num.toCharArray(Phone, 12);
EEPROM.put(25, Phone); // пишем номер в EEPROM
EEPROM.put(100, Phone); // записываем RingPhone в память.
AlarmPhone[0] = Phone; // запишем
RingPhone = Phone; // запоминаем его.
EEPROM.update(10, 0); // обновляем Firststart
Firststart = 0; // пишем 0
Serial.println(String(F("Master0:")) + AlarmPhone[0]);
Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), num); // смс на звонивший
// приходит смс в виде: " Master0:79111234567 Ok "
}
} return 1;
}
void eepromconfig() { /// === конфигурирование сигнализации === ///
if (EEPROM.read(0) != 1) { // если записана не 1
for (int i = 0 ; i < 512 ; i++) { // переписываем все ячейки
EEPROM.write(i, 0);
} // и записываем:
EEPROM.update(1, 0); // Guard охрана выкл.
EEPROM.update(2, 1); // AlarmRING вызов вкл.
EEPROM.update(3, 1); // SendSMS смс вкл.
EEPROM.update(4, 1); // DOORon датчики дверей вкл.
EEPROM.update(5, 1); // DOOR2on датчики дверей вкл.
EEPROM.update(6, 1); // PIRon датчик движения вкл.
EEPROM.update(7, 1); // GASon датчик газа вкл.
EEPROM.update(8, 1); // Sirena сирена вкл.
EEPROM.update(10, 1); // Firststart первый старт!.
EEPROM.update(20, 0); // баланс, записываем массив в EEPROM
EEPROM.update(0, 1); //
Serial.println(F("EEPROM != 1/ RESET!"));
}
if (EEPROM.read(0) == 1) {
Guard = EEPROM.read(1); // Охрана
AlarmRING = EEPROM.read(2); // Вызов
SendSMS = EEPROM.read(3); // Отправка смс
DOORon = EEPROM.read(4); // Датчик двери
DOOR2on = EEPROM.read(5); // Датчик двери
PIRon = EEPROM.read(6); // Датчик движения
GASon = EEPROM.read(7); // Датчик газа/дыма
Sirena = EEPROM.read(8); // сирена
Firststart = EEPROM.read(10); //
}
}
void eepromtext() { /// === состояние системы === ///
mySerial.println("AT+CSQ");
TempC();
String SIGN = ""; // текущее состояние системы.
String SIRENA = ""; // аварийная сирена.
String RING = ""; // текущее состояние вызов.
String SMS = ""; // текущее состояние смс.
String Door = ""; // текущее состояние датчика двери.
String Door2 = ""; // текущее состояние датчика двери.
String Pir = ""; // текущее состояние датчика движения.
String Gas = ""; // текущее состояние датчика газа.
if (Guard == 1) SIGN = String(F("System on\n")); else (SIGN = String(F("System off\n")));
if (Sirena == 1) SIRENA = String(F("Sirena on\n")); else (SIRENA = String(F("Sirena off\n")));
if (AlarmRING == 1) RING = String(F("Ring on\n")); else (RING = String(F("Ring off\n")));
if (SendSMS == 1) SMS = String(F("SMS on\n")); else (SMS = String(F("SMS off\n")));
if (DOORon == 1) Door = String(F("Door on\n")); else (Door = String(F("Door off\n")));
if (DOOR2on == 1) Door2 = String(F("Door2 on\n")); else (Door2 = String(F("Door2 off\n")));
if (PIRon == 1) Pir = String(F("Pir on\n")); else (Pir = String(F("Pir off\n")));
if (GASon == 1) Gas = String(F("Gas on\n")); else (Gas = String(F("Gas off\n")));
String System = SIGN + SIRENA + RING + SMS; // состояние (вкл/выкл) системы.
String Sensors = Pir + Door + Door2 + Gas + temp; // состояние (вкл/выкл) датчиков.
String CSQ = String(F("Signal ")) + csq + "%";
LastEvent = System + Sensors + CSQ; // полное состояние системы и датчиков.
Serial.println(LastEvent);
}
void eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
for (int i = 0; i < 5 ; i++) {
EEPROM.get(Adress[i], Phone); // считываем мастер-номера
AlarmPhone[i] = Phone;
}
String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
EEPROM.get(100, Phone); // считываем номер последнего звонившего
RingPhone = Phone;
String ring = String(F("Ring ")) + RingPhone + "\n";
EEPROM.get(20, Bal); // считываем номер баланса
String bal = String(F("Balance *")) + Bal + String(F("#\n"));
Firststart = EEPROM.read(10); // cчитаем первый старт
String FST;
if (Firststart == 1) FST = String(F("Firststart Yes")); else FST = String(F("Firststart No"));
EEPhone = numbers + ring + bal + FST;
Serial.println(EEPhone); // полный список номеров
}
void Detect() { /// === чтение датчиков === ///
DOORState = digitalRead(DOOR);
PIRState = digitalRead(PIR);
Smoky = analogRead(GAS);
if (DOORon == 1) {
if (DOORState == HIGH && DOORFlag == 0) {
previousMillis_door = millis();
DOORFlag = 1;
Serial.println(F("Dver' otkrita!"));
Alarm(); //
}
if (DOORState == LOW && DOORFlag == 1) {
int currentMillis_door = millis();
if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
DOORFlag = 0;
}
}
}
if (DOOR2on == 1) {
if (mySwitch.available()) {
unsigned long value = mySwitch.getReceivedValue();
if (value == door2 && DOOR2Flag == 0) {
previousMillis_door2 = millis();
DOOR2Flag = 1;
Serial.println(F("Dver' 2 otkrita!"));
Alarm(); //
}
mySwitch.resetAvailable();
}
int currentMillis_door2 = millis();
if (((currentMillis_door2 - previousMillis_door2) / 1000 > interval_door2)) {
DOOR2Flag = 0;
}
}
if (PIRon == 1) {
if (PIRState == HIGH && PIRFlag == 0) {
previousMillis_pir = millis();
PIRFlag = 1;
Serial.println(F("Dvizhenie u dveri!"));
Alarm(); //
}
if (PIRState == LOW && PIRFlag == 1) {
int currentMillis_pir = millis();
if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_door)) {
PIRFlag = 0;
}
}
}
if (GASon == 1) {
if ((Smoky > GASThres) && GASFlag == 0) {
previousMillis_gas = millis();
GASFlag = 1;
delay(100);
Serial.println(F("Gas v dome!"));
Alarm(); //
}
if ((Smoky < GASThres) && GASFlag == 1) {
int currentMillis_gas = millis();
if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_door)) {
GASFlag = 0;
}
}
}
}
void Alarm() { /// === запускаем сирену и отправку смс === ///
if (Guard == 1) {
previousMillis_alarm = millis();
if (Sirena == 1) digitalWrite(BUZ, LOW);
Serial.println(F("Alarm!!!"));
if (SendSMS == 1) {
for (int i = 0; i < 5; i++) { // if (AlarmPhone[i] != 0) {
if (DOORFlag == 1) {
sms(String(F("Dver' otkrita!")), AlarmPhone[i]); // смс на все номера
}
if (DOOR2Flag == 1) {
sms(String(F("Dver' 2 otkrita!")), AlarmPhone[i]); // смс на все номера
}
if (PIRFlag == 1) {
sms(String(F("Dvizhenie y dveri!")), AlarmPhone[i]); // смс на все номера
}
if (GASFlag == 1) {
sms(String(F("Gas v dome!")), AlarmPhone[i]); // смс на все номера
}
}
}
if (AlarmRING == 1) {
mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
}
}
}
void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///
int currentMillis_alarm = millis();
if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
digitalWrite(BUZ, HIGH);
}
}
void MasterRing() { /// === мастер звонков === //
if (Guard == 1) GuardOff(); // меняем состояние
else if (Guard == 0) GuardOn(); // меняем состояние
}
void GuardOff() { /// === выключение сигнализации === ///
Guard = 0;
EEPROM.update(1, Guard);
Serial.println(String(F("System->off. Ring:")) + RingPhone);
for (int i = 0; i < 5; i++) { // if (AlarmPhone[i] != 0) {
sms(String(F("System->off ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
}
}
void GuardOn() { /// === включение сигнализации === ///
Guard = 1;
EEPROM.update(1, Guard);
Serial.println(String(F("System->on. Ring:")) + RingPhone);
for (int i = 0; i < 5; i++) { // if (AlarmPhone[i] != 0) {
sms(String(F("System->on ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
}
}
void Led() { /// === состояние светодиода === ///
if (Guard == 1) { // если на охране
int currentMillis_led = millis(); // светодиод моргает
//проверяем не прошел ли нужный интервал, если прошел то
if (currentMillis_led - previousMillis_led > interval_led) {
// сохраняем время последнего переключения
previousMillis_led = currentMillis_led;
// если светодиод не горит, то зажигаем, и наоборот
if (LEDState == HIGH) LEDState = LOW;
else LEDState = HIGH;
digitalWrite(LED, LEDState);
}
} else digitalWrite(LED, HIGH); // иначе гасим его
}
void Komand() { /// === мастер смс === ///
val.toLowerCase();
if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) { // команды выполняются только с 0 мастер номера
if (val.indexOf(F("reset")) > -1) { // полный сброс ЕЕПРОМ
sms(String("All System Reset!!!"), RingPhone); // смс на последний номер
Serial.println(F("Reset System!!!"));
EEPROM.write(0, 0);
eepromconfig();
eepromtext();
eepromphone();
}
if ((p = val.indexOf(F("master"))) > -1) { // добавление мастер-номера
master(val.substring(p + 6, p + 7).toInt(), val.substring(p + 8, p + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
}
if ((p = val.indexOf(F("balance:"))) > -1) { // добавление номера баланса
balnum(val.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
}
if ((p = val.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки
dellphone(val.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
}
if (val.indexOf(F("phone")) > -1) { // инфо о номерах системы
eepromphone();
sms(String(EEPhone), RingPhone); // смс на последний номер
}
}
if (val.indexOf(F("status")) > -1) { // инфо о состоянии системы
eepromconfig();
eepromtext();
sms(String(LastEvent), RingPhone); // смс на последний номер
}
if (val.indexOf(F("money")) > -1) { // запрос баланса
balance();
}
if (val.indexOf(F("sirena")) > -1) { // вкл/выкл сирены
if (val.indexOf(F("on")) > -1) { // вкл
Sirena = 1;
EEPROM.update(8, Sirena);
Serial.println(F("Sirena->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("Sirena->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
Sirena = 0;
EEPROM.update(8, Sirena);
Serial.println(F("Sirena->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("sirena->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("system")) > -1) { // вкл/выкл сигнализацию
if (val.indexOf(F("on")) > -1) { // вкл
GuardOn();
}
if (val.indexOf(F("off")) > -1) { // вкл
GuardOff();
}
}
if (val.indexOf(F("ring")) > -1) { // вкл/выкл вызов при сработке
if (val.indexOf(F("on")) > -1) { // вкл
AlarmRING = 1;
EEPROM.update(2, AlarmRING);
Serial.println(F("AlarmRing->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("Ring->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
AlarmRING = 0;
EEPROM.update(2, AlarmRING);
Serial.println(F("AlarmRing->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("Ring->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("sms")) > -1) { // вкл/выкл смс при сработке
if (val.indexOf(F("on")) > -1) { // вкл
SendSMS = 1;
EEPROM.update(3, SendSMS);
Serial.println(F("SendSMS->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("SMS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
SendSMS = 0;
EEPROM.update(3, SendSMS);
Serial.println(F("SendSMS->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("SMS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("door")) > -1) { // вкл/выкл контроль датчика двери
if (val.indexOf(F("on")) > -1) { // выкл
DOORon = 1;
EEPROM.update(4, DOORon);
Serial.println(F("DOOR->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл контроль датчика двери
DOORon = 0;
EEPROM.update(4, DOORon);
Serial.println(F("DOOR->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("DOOR->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("door2")) > -1) { // вкл/выкл контроль датчика двери 2
if (val.indexOf(F("on")) > -1) { // вкл
DOOR2on = 1;
EEPROM.update(5, DOOR2on);
Serial.println(F("DOOR2->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("DOOR2->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
DOOR2on = 0;
EEPROM.update(5, DOOR2on);
Serial.println(F("DOOR2->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("DOOR2->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("pir")) > -1) { // вкл/выкл контрол датчика движения
if (val.indexOf(F("on")) > -1) { // вкл
PIRon = 1;
EEPROM.update(6, PIRon);
Serial.println(F("PIR->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("PIR->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
PIRon = 0;
EEPROM.update(6, PIRon);
Serial.println(F("PIR->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("PIR->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
if (val.indexOf(F("gas")) > -1) { // вкл/выкл контроль датчика газа
if (val.indexOf(F("on")) > -1) { // вкл
GASon = 1;
EEPROM.update(7, GASon);
Serial.println(F("GAS->on"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("GAS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
if (val.indexOf(F("off")) > -1) { // выкл
GASon = 0;
EEPROM.update(7, GASon);
Serial.println(F("GAS->off"));
for (int i = 0; i < 5 ; i++) { // смс на все номера
sms(String("GAS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
}
}
}
}
void balance() { /// === проверка баланса сим-карты === ///
EEPROM.get(20, Bal); // считываем массив символов
delay(1000);
mySerial.println(String(F("AT+CUSD=1,#")) + Bal + String(F("#,15")));
Serial.println(String("Balance#") + Bal + "#");
}
int master (int i, String num) { /// === добавление мастер-номеров === ///
if (i < 5 && i != 0) {
num.toCharArray(Phone, 12); // конвертируем
AlarmPhone[i] = num; // пишем номер
Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
EEPROM.put(Adress[i], Phone); // записываем массив в EEPROM
sms(String(String("Master") + i + ":" + num + " add"), RingPhone); // смс на 0 номер.
sms(String("Master: " + AlarmPhone[i]), AlarmPhone[i]); // смс на добавленный номер.
} else Serial.println(F("MAX number 4!")); // 4 номера максимум!
// 0 номер можно удалить только через RESET!!!
return 1;
}
int dellphone (int i) { /// === удаление мастар-номеров === ///
if (i < 5 && i != 0) {
Serial.println(String(F("Master")) + i + String(F(" dell")));
sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), RingPhone); // смс на 0 номер
sms(String("Dell: " + AlarmPhone[i]), AlarmPhone[i]); // смс на удаленный номер.
EEPROM.put(Adress[i], 0);
AlarmPhone[i] = ""; // обнулим номер
} return 1;
}
int balnum (String num) { /// === добавляем номер баланса === ///
num.toCharArray(Bal, 4); // конвертируем
Serial.println(String(F("Balance *")) + Bal + "#");
EEPROM.put(20, Bal); // записываем массив в EEPROM
sms(String("Balance:*" + num + "# Ok"), RingPhone); // смс на 0 номер
return 1;
}
void TempC() { /// === измеряем температуру === ///
byte data[2];
ds.reset();
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read();
data[1] = ds.read();
int Temp = (data[1] << 8) + data[0];
Temp = Temp >> 4;
temp = String(F("Temp ")) + Temp + String(F("*C\n"));
}
void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
byte reminder = 0;
int bitstate = 7;
for (unsigned int i = 0; i < instr.length(); i++) {
byte b = instr[i];
byte bb = b << (7 - bitstate);
char c = (bb + reminder) & 0x7F;
outstr += c;
reminder = b >> bitstate;
bitstate--;
if (bitstate == 0) {
char c = reminder;
outstr += c;
reminder = 0;
bitstate = 7;
}
}
}
void InitModem() { /// === инициализация модема === ///
Serial.println(F("Start GSM"));
mySerial.begin(9600); //Скорость порта для связи Arduino с GSM модулем
waitConnect();
Serial.println(F("GSM connected"));
waitRegistration();
delay(1000);
}
void waitConnect() { /// === запуск модема === ///
int countok = 0;
String str;
while(countok < 5) { //ждём пять ОК
uint32_t ms = millis();
if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс
msAT = ms;
// Serial.println(">>AT");
mySerial.println(F("AT")); // посылаем команду
str = "";
delay(100); // ждём ответа
while(mySerial.available()) {
char ch = mySerial.read();
str += ch;
}
// Serial.println("C>");
// Serial.println(str);
if(str.indexOf(F("OK")) > -1)
countok++;
else
countok = 0;
}
}
Serial.println(F("Turn on AOH:"));
mySerial.println(F("AT+CLIP=1")); // включить АОН
delay(200);
Serial.println(F("GSM registration"));
mySerial.println(F("AT+CMGF=1"));
delay(200);
Serial.println(F("Mode GSM:"));
mySerial.println(F("AT+CSCS=\"GSM\"")); // кодировка текста - GSM
delay(300);
mySerial.println(F("AT+CNMI=2,2,0,0,0"));
delay(300);
}
void waitRegistration() { /// === регистрация модема в сети === ///
bool ok = 0;
String str;
while(!ok) {
uint32_t ms = millis();
if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
msAT = ms;
Serial.println(F(">>AT+CREG?"));
mySerial.println(F("AT+CREG?")); //посылаем команду
delay(100); //Ждём ответа
str = "";
while(mySerial.available()) {
char ch = mySerial.read();
str += ch;
}
Serial.println(F("R>"));
Serial.println(str);
if(str.indexOf(F("+CREG:"))>-1)
ok = 1;
}
}
}
void sms(String text, String phone) { /// === отправка СМС === ///
if (phone != 0 && sendsmscaller == 1) {
phone = "+" + phone;
Serial.println(F("Start SMS send"));
mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
delay(300);
mySerial.print(text);
delay(300);
mySerial.print((char)26);
delay(300);
Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
delay(5000);
}
}
при такой загруженности памяти, у вас адекватно работает?!
у меня когда SRAM к 70% подходил, перестовал модем присылать сообщения, то пустое, по пару слов
Как видите, за последний месяц жалоб на нестабильную работу двух последних версий прошивок, они отличаются по функционалу, не поступало. У меня "боевая" сигналка в течение последнего месяца не накосячила ни разу.
Kvolk, а нафига? все и так работает.
Работает потому что от модема ещё не "прилетело" данных больше чем сам буфер, как только это произойдёт вы без труда сможете понять для чего увеличивается этот буфер. На 590 модеме "мусора" от модема прилетет меньше чем на SIM800L или A6_Mini, поэтому вам буфера хватает.
Пример тут: https://mysku.ru/blog/ebay/43282.html#comment2174532
пример ровно ничего не доказывает, там нет никакий данных, были ли проблемы от маленького буфера и исправились ли они после его увеличения.
У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко. Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.
Этим вы просто выкидываете 128 байт оперативки, а ее и так немного.
Вы ошибаетесь.
И в чем же я ошибаюсь? Увеличение буфера на 128 байт не уменьшает оперативку?
Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают? Интересно, как вы читаете СМС, что у вас буфер переполняется...
пример ровно ничего не доказывает...
Доказывает, проблема решилась после увеличнения буфера, но вы это не хотите видеть.
У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко.
А у меня 590, сим800 и а6_мини и все они поддерживаются в одной прошивке. Сим800 в отличие от других модемов по умолчанию сильно спамит в порт. В моей реализации для отладки используется "тестовый режим" при включении которого в консоль валится вся инфа от модема.
Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.
Да делайте как хотите, это ваше право :) Причём тут смс?
И в чем же я ошибаюсь?...
В этом:
Этим вы просто выкидываете 128 байт оперативки.
Не просто и не выкидываю.
Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают?
Для того чтобы сырой код во время разработки, отладки, допила не растаскивали на куски и не лепили из него подобных "франкенштейнов". В конце концов не хочу, нет желания. Что касается кривого кода и ссаных тряпок - кода вы не видели, значит и утверждать о том, что он кривой не можете. А вот к тому коду из 206 поста, которым вы тут дружно пользуетесь, который я видел - ссаных тряпок могу подкинуть, поверьте, вам хватит :)
Интересно, как вы читаете СМС, что у вас буфер переполняется...
Кто вам вобще сказал что дело в чтении СМС? Дальше носа своего не видите? :)
kvolk, много слов и ничего по делу. Грозите раскритиковать код из поста 206 - да ради бога. с удовольствием послушаю. Люблю учиться. Тем более что свой код вы не показывайте - так хотя бы по замечаниям о чужом коде можно будет оценить ваш уровень...
может кто то подсказать?!
как мне при приеме переменной, разбить ее на несколько переменных
допустим отправляем смс с кодом: 123456
присвоить A1 = 12, A2=34, A3=56
А в каком виде Вы её получаете? Какого она типа?
может кто то подсказать?!
как мне при приеме переменной, разбить ее на несколько переменных
допустим отправляем смс с кодом: 123456
присвоить A1 = 12, A2=34, A3=56
А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)
Общепринято посылать переменные, например, в виде пар "параметр=значение", разделяя из запятыми : "A1=12,A2=34,A3=56". Такой формат легко запомнить, и он гибче - порядок и число переменных можно менять.
может кто то подсказать?!
как мне при приеме переменной, разбить ее на несколько переменных
допустим отправляем смс с кодом: 123456
присвоить A1 = 12, A2=34, A3=56
Если А1-А3 положительное число не превышающее 255, то как-то так:
...можно будет оценить ваш уровень...
Я на экзамене или просто обязан вам что-либо доказазывать? :)
kvolk, доказывать ничего уже и не надо! вы показали себя самым умным, что у вас супер код, который работает без глюков, а показать нечего.
Возможно выложу, но не скоро :(
А чё так? Копираст?
А чё так? Копираст?
Да, копипастят налево и направо. Это же очевидно :) Посмотрите первый пост этого топика :)
Если А1-А3 положительное число не превышающее 255, то как-то так:
большое вам человеческое спасибо
А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)
для корректирование времени через смс запрос 073030 т.е. 07:30:30
А чё так? Копираст?
Да, копипастят налево и направо. Это же очевидно :) Посмотрите первый пост этого топика :)
Вот оно что...банальная жадность! Ещё раз: Ардуина - свободная платформа.
Не надо, не выкладывайте свой код. Кто не хочет делать своими руками, пусть просто заливают код и пользуются незная как это устроено.
Если А1-А3 положительное число не превышающее 255, то как-то так:
Почему именно 255? А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Лицензия LGPL не требует открывать свой код, разработанный для Ардуино, и позволяет создавать коммерческий продукт.
Русский язык тоже свободная платформа и говорить на нём можно бесплатно. Но, те, кто, например, написали на нём роман или песню, иногда хотят, чтобы их произведение приносило им доход.
Я это не к тому, что я разделяю позицию копирастов, нет, у меня к этому сложное отношение, но я понимаю эту позицию и признаю за людьми право так считать, и так себя вести.
Ещё раз: Ардуина - свободная платформа.
Вы действительно считаете что если ардуина свободная платформа, то все программы для этой платформы обязаны предоставляться в виде исходных текстов? :)
Почему именно 255?
Потому что int8_t.
А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Это как?
В моём понимании двузначное число состоит из двух цифр, минимальное значение которого равно 10 максимальное 99. Во втором классе меня учили так. 512 - трёхзначное число.
Я чего-то не знаю?
А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Это как?
Это я у вас хотел спросить - как это. Это же вы написали. что двузначное десятичное число не должно превышать 255 :)
А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Это как?
Это я у вас хотел спросить - как это. Это же вы написали. что двузначное десятичное число не должно превышать 255 :)
Я написал? Где написано про двузначное число?
Если А1-А3 положительное число не превышающее 255, то как-то так:
Ваша цитата :
Если А1-А3 положительное число не превышающее 255, то как-то так:
Почему именно 255? А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)
Вы наверное прикалываетесь? :) Да вы просто фантазёр :)
Я написал? Где написано про двузначное число?
Вы не только невнимательный копираст, а еще свои ошибки признавать не любите...
Вот это чей код?
a1 = data.substring(0, 2).toInt();
скольку тут знаков в числе?
Я написал? Где написано про двузначное число?
Вы не только невнимательный копираст, а еще свои ошибки признавать не любите...
Вот это чей код?
a1 = data.substring(0, 2).toInt();
скольку тут знаков в числе?
Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t было акцентировано внимаение на том что число должно быть положительное и не превышающее 255, потому что многие начинающие не знают этих нюансов. А на этой платформе памятью "разбрасываться" нельзя.
Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t
Вы опять с умным видом пытаетесь поучать других, хотя получается не очень. Я в форме шутки пытался указать вам, что ваш код перестанет работать задолго до числа 255 - именно потому, что вы извлекаете из строки только два знака, а вовсе не из-за выбранного типа int8_t для числовой переменной.
А на этой платформе памятью "разбрасываться" нельзя.
как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.
как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.
Должен поправится, не вполне прав. на 328й ардуине 8bit data alignment, так что компилятор действительно пытается упаковать два первых типа в 8 бит. Правда это не всегда работает.
ваш код перестанет работать задолго до числа 255
Код будет работать, так как числа больше 99 там быть не может, минимум 01 - максимум 99. Объясню ещё раз: 255 было упомянуто только из-за ограничения накладываемого на тип данных int8_t.
..типы byte, int8_t и int. Вас ждет удивительное открытие.
byte, int8_t - 8 бит. int - 16 бит. Разве не так?
для корректирование времени через смс запрос 073030 т.е. 07:30:30
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные, но ручная корректировка тоже нужна или хотябы корректировка часового пояса.
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.
Не пробовали корректировать время при получении смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,
Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.
мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.
тогда уже NTP сервер использовать
сделал как kvolk порекомендовал, при любой смс корректируем время от оператора
kvolk - Я прочитал ваш блог. Уважение. Хорошая и интересная сигнализация. Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.
Я проверил вашу сигнализацию. Arduino NANO v.3 и модем M590E. Вы написали, что на D10 - красный светодиод, D11 - синий, D12 - зеленый.
После очередного включения сигнализации загорается зеленый светодиод (правильно).
После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?
Вот как это реализовано у меня со Скатом
..мне показалось проще и надежнее делать GPRS запрос типа HEAD ...
Довольно интересный способ, получения практически точного времени.
Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.
Из всех вышеперечисленным методов я бы пожалуй сразу отказался от NTP - очень ресурсоёмкий процесс, и при наличии интернета можно менее затратно парсить заголовки сайтов.
Если бы позволяла память и было бы соединение с инетом - однозначно использовал бы заголовки http для получения практически точного времени.
В случае ограниченного ресурса памяти, использовал бы корректировку из смс. Но тут нужно ещё раз проверить, если выключить модем и отправить на него смс, а потом через пол часа включить - какое время прилетит на модем, время отправки смс или получения модемом смс?
...при любой смс корректируем время от оператора
Проверьте что за время будет прилетать при получении смс с задержкой. Только что нашел свой пост в котором +CMT: "+380958xxxxxx",,«16/02/16,32:05:42+18» время и дата не являются правильными о_О.
UPD. Всё оказалось проще, на тот момент модема на работе не было, пришлось эмулировать его работу через USB-TTL конвертор, естественно все данные кроме номера взяты "от фонаря" :)
Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.
При наличии контроля температуры "запилить" простой контроль внешнего питания - простая задача, никаких библиотек подключать не надо, всего лишь достаточно мониторить состояние пина.
В моём случае контроль температуры был непозолительной роскошью.
После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?
Мигает синий светодиод - включен тестовый режим.
Светится зелёный светодиод - снято с охраны. Команда LedOff отключает этот светодиод - чтобы ночью несветил :)
Мигает красный светодиод - поставлено на охрану, основной и/или дополнительный датчики в режиме геркона, цепь одного или обоих герконов разомкнута.
Горит красный светодиод - поставлено на охрану, датчики в режиме геркона замкнуты.
Мигает синий светодиод в течение 2 секунд при замыкании геркона всегда, вне зависимоти от состояния сигнализации (проверка при снятой с охраны сигналке).
Вот как это реализовано у меня со Скатом
Огромный плюс в том, что можно сразу и сирену подключить. Какая автономность? :)
...при любой смс корректируем время от оператора
Вы на 100% можете быть уверены том что на месте этих символов всегда будут часы, минуты, секунды?
А если отправить смс с ru номера или ua, правильно ли установится время, длина номера то разная. Конечно же если вы делаете это устройство только для себя, то на эти мелочи можно просто забить, но всё же попробуйте не привязываться жестко к позиции символа в строке.
Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.
Я предпочитаю проектировать программы так, чтобы они требовали как можно меньше внимания. Сигналка должна "управляться" самостоятельно, разве что пару тройку СМС послал при запуске, что подобрать параметры - а дальше СМС должны идти только от сигналки к вам - а не обратно.
Я думал о извлечении времени из СМС - этот метод очевиден - но отказался от него. Ситуация, что после каждого перезапуска программы для установки времени мне будет нужно отправить СМС - для меня не подходит.
тогда уже NTP сервер использовать
сделал как kvolk порекомендовал, при любой смс корректируем время от оператора
на модеме А6, к сожалению, нет поддержки UDP стека - а то бы попробовал NTP.
Коррекцию времени вы написали плохо, согласен с замечанием kvolk. Ваш код парсинга времени из СМС крайне ненадежен, рекомендую его переписать. Ищите в строке характерные подстроки, например для времени - три группы цифр, разделенные двумя двоеточиями. Найти соответсвующие символы в строке совсем несложно, примеров кода в сети полно. То что написано у вас - это никуда не годится, никогда не полагайтесь на положение символа.
Посмотрите это сообщение, 21-ая строка кода. Там определяется позиция последовательности символов в строке, добавляется +1. Потом опять позиция поледовательности + длина строки которую необходимо получить. Профит!
Обратите внимание, в коде не все строки хранятся во флэш памяти F ("bla-bla-bla") - это важно при оптимизации памяти.
Обратите внимание, в коде не все строки хранятся во флэш памяти F ("bla-bla-bla") - это важно при оптимизации памяти.
kvolk. обьясните пожалуйста, почему важно, что не все строки во флеше? (спрашиваю серьезно, без подкола)
..почему важно...
Последние 5 месяцев проекта была жесть просто жесть, необходимо было править баги и добавлять функционал практически на одном проценте памяти, в ченджлоге это видно. Иногда было проавильнее пожертвовать оперативной памятью для высвобождения флэш-памяти. Посмотрите на скрины компиляции:
Идентичные константы (строки) в оперативной памяти могут быть использованы в разных местах программы и не будут храниться дважы в ОЗУ. На примере это видно. Например, если используется символ "/" в тексте программы раз 50 или 100, то логичнее пожертвовать одним байтом ОЗУ чем 100 байтами флэш памяти.
kvolk, спасибо за поднятую тему. С интересом потестировал разные варианты. Действительно, макрос F() очень расточителен по отношению к флеш-памяти. Честно говоря, никогда не задумывался об этом. Правда, я обычно не использую F() для повторяющихся строк - не потому. что экономлю флеш, а просто лениво многократно набирать (или копировать) одно и то же :)
Вместо использования F() можно проделать все то же самое "вручную" - повторяющиеся строки разместить в PROGMEM, а в процедуру print() передавать ссылку. Этот вариант абсолютно идентичен F() для единичной строки, но при многократном использовании не так прожорлив по отношению к флеш - сравните со своим первым и вторым вариантом.
Пример:
чтобы не загромождать скетч постоянным приведением типов, можно определить для него макрос
Да, так эффективнее, хотя и сложнее для новичков.
Да, так эффективнее, хотя и сложнее для новичков.
Да ну ладно, ничуть не сложнее F() - вместо одного макроса добавляем другой.
Еще раз спасибо за тему, сделал для себя вывод, что для коротких строк любые способы помещения во флеш неээфективны. Учту в своих проектах.
Вы не будете против. если я на эту тему напишу обзорное сообщение для новичков?
что для коротких строк любые способы помещения во флеш неээфективны.
Полностью согласен.
Вы не будете против. если я на эту тему напишу обзорное сообщение для новичков?
Естественно не буду против, это будет очень полезная инфа, особенно для тех кто упирается в ресурс памяти :)
немного подправил скетч, команды и функционал не урезал. объединил команды смс и консоли (если команда введена в консоли то смс не оправляется), тем самым немного освободил места. мастер-номера и баланс теперь приходят в одном смс. теперь команды вкл/выкл понимает: так dooron и так door on.
на данный момент
вот скетч:
сделал небольшую менюшку на LCD1602 shield
можно вкл/выкл режимы + просмотр, пока особо не проверял - некогда.
скетч:
Это по коду из 443 поста?
У меня с последних постов норм компиллируется
Компилится в 1.6.5 без проблем. Либа отсюда https://github.com/sui77/rc-switch
Да, это по коду из 443 поста. Из 442 поста тоже. У меня arduino 1.8.4, проверю на 1.6.5 (сейчас не владею)
У меня последняя версия, скорее всего дело в библиотеке
у меня тоже 2.6.2
Незнаю, странно это