Управление нагрузкой по звонку Arduino Nano + M590
- Войдите на сайт для отправки комментариев
Вс, 11/12/2016 - 20:34
Не могу понять почему не опознаётся номер телефона.
byte gsmOk = 13; //сеть поймана byte bootPin = 4; //пин включение радиомодуля byte zvonok = 5; //индикатор входящего звонка byte PinPower = 6; //пин управления нагрузкой byte NumT = 0; //номер ячейки массива byte KolMas = 10; //количество ячеек массива char* Tel[10] = {"79999999999", "79999999999", "79999999999", "79999999999", "79999999999", //массив номеров "79999999999", "79999999999", "79999999999", "79999999999", "79999999999"}; //массив номеров void setup() { Serial.begin(9600); pinMode(gsmOk, OUTPUT); pinMode(bootPin, OUTPUT); pinMode(zvonok, OUTPUT); pinMode(PinPower, OUTPUT); digitalWrite(bootPin, HIGH); digitalWrite(gsmOk, LOW); digitalWrite(zvonok, LOW); digitalWrite(PinPower, LOW); delay(2000); Serial.println("AT"); //пингуем включен ли модем Serial.flush(); //ждем ответа if (!Serial.find("OK")) { //если нет ответа digitalWrite(bootPin, LOW); //включаем модем } while(1){ //ждем подключение модема к сети Serial.println("AT+CREG?"); //пингуем наличие сети Serial.flush(); //ждем ответа if (Serial.find("+CREG: 0,1")) { //если сеть зарегестрирована Serial.flush(); //ждем ответа digitalWrite(gsmOk, HIGH); //говорим что сеть есть digitalWrite(bootPin, HIGH); break; } } } void loop() { if(Serial.find("RING")){ //если нашли RING digitalWrite(zvonok, HIGH); //говорим что есть входящий Serial.println("AT+CLIP=1"); //включаем АОН while(1){ //в цикле if (Serial.find(Tel[NumT])) { //ищем номер digitalWrite(PinPower, HIGH); //если нашли включаем нагрузку Serial.println("ATH0"); //сбрасываем вызов Serial.flush(); //ждем ответа digitalWrite(zvonok, LOW); //говорим что входящего нет Serial.println("AT+CLIP=0"); //отключаем АОН Serial.flush(); //ждем ответа break; //выходим из цикла } else { Serial.println("AT+CPAS"); //спрашиваем состояние модема Serial.flush(); //ждем ответа if (Serial.find("+CPAS: 0")) { //если звонок в процессе, возвращает +CPAS: 3,если он в "готовности" Serial.println("AT+CLIP=0"); //отключаем АОН Serial.flush(); //ждем ответа digitalWrite(zvonok, LOW); //говорим что входящего нет break; //выходим из цикла } } ++NumT; //ищем в следующей ячейке массива if (NumT=KolMas) NumT=0; //проверяем, чтоб не выйти за пределы массива } } //продолжение кода }
А должен? По-моему, так нет. И причин тому много. Начнём с мелочей, к крупным потом перейдём.
Как Вы понимаете строку 66?
На самом деле она полностью эквивалентна такой:
NumT=0;
Вы этого хотели? Если нет, то поставьте нормальное сравнение.
Но это не самое интересное.
Что Вы делаете в строке 46?
Вы ищете там нулевой номер из Вашего списка. Для это Вы вчитаываете из потока всё, пока либо не встретите нужный номер, либо не наступит таймаут.
Предположим Вам пришёл звонок от первого номера. А Вы в процесс поиска нулевого этот первый благополучно из потока вычитали и выбросили. Даже если Вы почините строку 66 и потом начнёте исакть первый номер - Вы его уже прочитали и выбросили - его уже нет.
При таком подходе Вы в лучшем случае найдёте номер только в том случае, если это нулевой номер из Вашего массива. Никакого другого номера Вы не найдёте никогда. найдёте ли первый - не знаю, я дальше в подробности кода не лез.
Вот собственно и всё.
Как Вы понимаете строку 66?
На самом деле она полностью эквивалентна такой:
NumT=0;
Вы этого хотели? Если нет, то поставьте нормальное сравнение.
Млин, это уже после полдня мучений такие косяки.
Так что же получается, функция Serial.find() после прочтения очищает приёмник сериал?
Так что же получается, функция Serial.find() после прочтения очищает приёмник сериал?
Сериал - это поток. Вот представьте себе, что данные сериала идут к Вам на ленте типа телеграфной. Функция find тянет ленту и читает данные в поисках того, что она ищет. Прочитанные куски ленты она при этом выбрасывает. find не отматывает поток назад, если ничего не нашла. Прочитанный кусок потока пропадает.
Т.е. если Вы потом захотите искать следующий номер, Вы будете искать его уже в новых данных, т.к. старые Вы уже выбросили и если там был этот новый номер - Вы его уже потеряли.
Понятно, надо менять подход, надо будет считать кусок до номера, а сам номер записать в переменную, а потом уже с этой переменной сравнивать.
Я думал, что поток данных записывается во временную память, а эта функция ищет там.
УРЯ!!!!! ПОЛУЧИЛОСЬ!!! РАБОТАЕТ!!! Теперь буду разбираться с СМС, и можно ли будет добавлять и убирать номера по СМС, если не получится, подумываю сделать мастер-номер, после звонка которого можно будет убирать/добавлять номер.
Значит приходит что-то не так, как ожидаете (не так как Вы с консоли подсовываете). Мега есть? Чтобы второй сериал бы? Или может через софт-сериал это включить, а хард для монитора порта использовать?
Тогда бы можно было по ходу выполнения программы всё подряд печатать и смотреть что приходит - стало бы сразу понятно в чём затык.
Проблема была в том, что команду strstr(), я взял из "кривого" источника, а там было сказано, что сначала указывается искомое, а потом уже строка в которой ищет. Сейчас нашел на этом форуме похожую проблему. После замены их местами все заработало.
В сериал, когда отлаживал с ПК, отсылалось что он принял, какую строку сохранил и с чем сравнивал а так-же номер ячейки массива, все сходилось. И все всегда работало.
Это мой второй проект, если не считать мигание лампочками и дерганьем реле. Поэтому приходится тыкаться как слепому котёнку и тратить день на поиск решения и адаптацию под задачу. Изначально это было https://www.youtube.com/watch?v=2ENbWDzX4IQ
ЕвгенийП, спасибо за потраченое на меня время.
Не за что, с Победой!
Кстати если не хватает сириалов на уне можно прикрутить lcd 16×02 ну или 20×04 экран и выводить на него то что получает унка, тогда будет видно все как в сириал. Я так делал когда моделировал передачу по сириал между двумя унами (до физического устройства дело пока не дошло...)
Можно, но с экранами у меня туго, то одно придуривается, то другое.
Мк это холст, как на нем нарисуешь так он и будет работать)
Я не спорю, только не у всех есть призвание писать код, некоторым приходится проходить сквозь дебри и шишки на голове.
Сейчас опять голова квадратная, с этим ЕЕПРОМ, как я понял туда можно писать только адресно и только по одной ячейке. Вот думаю как мой массив туда писать и считывать без нагромождений, а то память контроллера не резиновая. Думаю через недельку будет подобие кода.
А что сложного, у вас переменные заданной длинны length 11 символов, сделайте функцию eepromWriteNumber () которой будете передавать ячейку cell и ссылку на массив array, в функции перебирайте i от length*cell до length*(cell+1) и пишете туда ваши чары. Читаем наоборот
Вот думаю как мой массив туда писать и считывать без нагромождений
Да, так и писать
Это не работает только в самых древних версиях IDE (там старая библиотека EEPROM). В мало-мальски современных - нет проблем.
Завтра попробую на чистой ардуинке.
Я правильно понял, что для записи скажем второй ячейки массива надо будет просто отправить её на (11*2=22) 23 ячейку и функция просто запишет её в следующие 23-33 ячейки?
И считать её можно будет так же?
Или функция тупо запишет весь массив в строку, а потом из этой строки нужно будет вычленять нужную информацию?
PS: у меня только нано и промини для уже отлаженных проектов, еще парочка на тини85, забыл как они называются.
PPS: сегодня приехал олед экран на I2C, с ними, вроде, попроще. Да и пинов мало используют.
put пишет с указанного адреса то, что Вы её дадите. Весь массив, так весь, один элемент, так один элемент. Главное, чтобы на втором аргументе нормально sizeof отрабатывал, чтобы она знала сколько байтов писать.
Если писать по одному байту, то можно ещё проще - в нотации массива:
При этом, если склероз мне не изменяет, и put, и массив сделаны аккуратно. Они сначала читают, сравнивают и пишут только если новое значение отличается от того, что там итак есть - чтобы лишний раз не изнашивать EEPROM
Износ ЕЕПРОМ моей игрушке не грозит, ну забью я туда телефона три-четыре, и все, пусть работает, может когда телефон сменю - поменяю один. А от чтения память не помрет. А может наиграюсь и разберу. Стачала задачу решить хочу.
Сегодня пробовал с смс и мастер-номером, смс так и не понял как отправлять и принимать, фигня какая-то, дурацкий радиомодуль хочет какие-то спецсимволы, а с мастер-телефоном получается громоздко, думаю сделать проще - кнопку, когда зажата позвонить, если номер есть - удалить, если нет - добавить.
Хотя мучает вопрос почему в википедии ардуино не указаны все эти фишки, что я нахожу на просторах? Ведь меньше бы тупых вопросов было бы.
почему в википедии ардуино не указаны все эти фишки
Если Вы про работу с EEPROM, так всё, что Вам сегодня говорил, написано на сайте производителя Ардуино - https://www.arduino.cc/en/Reference/EEPROM
Англицкий... У нас в деревне есть только учитель немецкого, англицкий только в гугле.
англицкий только в гугле.
Достаточно. Иногда тексты смешные получаются, но если цель понять, а не постебаться, то понять можно.
Я с гуглом даташиты на китайском читаю. Серьёзно.
Это не работает только в самых древних версиях IDE (там старая библиотека EEPROM). В мало-мальски современных - нет проблем.
Простите что внес смуту. Не знал что массивы так писать можно, посоветовал так как делал сам
Не помню от кого услышал, что в ассемблере всего около тридцати команд, а циклов нет вообще, есть метки и ссылки к ним. К чему это я, чем проще, тем надежнее. Сначала попробую самое простое, чтоб "отработать технологию", особенность у меня такая, если не понимаю как это работает на самом низком уровне - чувствую себя макакой с автоматом. Тем более Си язык тяжелый (пробовал пару лет назад), много всего и сразу, не сравним с паскалем (до этого писал еще в школе и в училище на делфи, что по сути тот же паскаль).
Не помню от кого услышал, что в ассемблере всего около тридцати команд,
Вас жестоко обманули. Плюньте этому "не помню кому" в рожу. Это в паскале около 30 конструкций, а в системе команд AtMega328 - 131 команда! Это только система команд, а есть еще пара десятков директив самого ассемблера.
Далеко плевать придется, это было лет шестнадцать назад.
При прошивке ардуино ЕЕПРОМ очищается?
При прошивке ардуино ЕЕПРОМ очищается?
Зависит от фьзов. В стандартном IDE'шном "записать загрузчик" фьюз установлен так, чтобы очищалось. Но это несложно поменять.
Не буду пока ардуинку ломать, программатор еще не пришел, запишу с сетап.
А не, я про кнопку "Загрузка".
Уже не надо, проверил, нет, не перезаписывает. Класс! Можно задать заранее все данные.
нет
Не пойму что я делаю не так. Вроде же читает нормально и сохраняет в массив нормально, почему массив потом пустой? Я опять какую-то фишку не нашел? И откуда эти пробелы берутся?
Пойду поем, а то уже руки трясутся.
Да и поработать надо, всё-таки мне за работу деньги платят :) .
Не пойму что я делаю не так. Вроде же читает нормально и сохраняет в массив нормально, почему массив потом пустой?
Только читайте внимательно, водя пальцем по коду, если надо возвращайтесь и разбирайтесь несколько раз.
Вот смотрите, в строках 22-24 Вы читаете некие данне в массив TelE. Далее в строке 25 вы пытаетесь сохранить прочитанный массив в элементе NumA. массива Tel.
Правильно? Так вот, на самом деле Вы ничего не схраняете. строка 25
Tel[NumA] = TelE;
не копирует массив TelE в массив Tel[NumA]. Она илшь записывает в Tel[NumA] указатель на нулевой элемент TelE .
Потом в строка 26-28 Вы печатаете то, что получилось и всё должно печататься прилично, т.к. Вы по сути печатаете данные с одного и того же адреса.
Но при следующем прохождении цикла (когда NumA уже равно 1), вы в тот же самый TelE. читаете новые данные. Но ведь в в Tel[0] сидит указатель на этот самый TelE !!! Т.е. при втором проходе (при NumA равном 1) Вы первым делом затираете NumA[0]. Затем Вы снова присваиваете Tel[NumA] (то бишь Tel[1]) указатель всё на тот же самый TelE. И снова в строках 26-28 всё печатается прилично.
Когда, наконец у Вас закончится цикл (к строке 36), у Вас все до единой Tel[NumA] (с нулевой по 9-ую) содержат один и тот же указатель на нулевой элемент массива TelE, а в нём находится последний прочитанный номер.
Вот его Вы 10 раз и печатаете в строках 37-39.
То есть, получается что все записывается в нулевую ячейку массива?
Ну по сути получается, что счетчик NumA++; делает не:
Tel[0] - Tel[9], а что-то вроде Tel[0, 0] - Tel[0, 9]?
И как правильно записывать в такие массивы?
Неужели так же посимвольно в цикле?
Я пробовал считывать из ЕЕПРОМ в переменную, а потом в этой переменной искать, но контроллер тупо зависает, поэтому и решил пройти по проторенной дорожке с массивом.
Только в вашем случае Tel [0][0]
Значит запись должна выглядеть типа:
Нет, мусор на выходе.
У меня ощущение, что этот двумерный массив только отдавать может, информации, как в него записывать я найти не могу.
Ну, у Вас как описан Tel?
char
* Tel[]
Вы понимаете эту запись? Это массив указателей на char.
Т.е. Tel[n] у Вас - это указатель на char. Тип у него char *
Вы этот массив проинициализировали
char
* Tel[] = {
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
};
Значит, каждый из 10 элементов массива указывает на пустую строку - "", т.е. на символ '\0'.
Записать туда какую-то другу строку ненулевой длины нельзя, т.к. там не выделено под это место. Записать-то Вы можете, но запишется поверх других переменных и затрёт их.
Если Вам надо хранить там 10-тизначные номера, то любо иницилиазяируйте строкой нужной длины, например
char
* Tel[] = {
"0123456789"
,
"
0123456789"
,
"
0123456789"
, ... и т.д.
Либо объявите его двухмерным массивом
char
Tel[10][11];
В любом из этих случаев, Вы сможете там что-нибудь сохранять, но не так, как Вы это делали
Tel[NumA] = TelE
а вот так
strcpy(Tel[NumA], TelE);
Только имейте в виду, что strcpy не проверяет помещается ли копируемая строка в принимающую и если не помещатеся, то будет писать дальше, затирая другие переменные. Т.е. TelE не должна быть длинее 10 символов и это на Вашей совести - никто тут Вас не страхует.
Значит запись должна выглядеть типа:
Там же память ни хрена не выделена! Но, я уже Вам написал подробно.
ДОБИЛ!!!
Моя идея сразу считывать с ЕЕПРОМ и тут же сравнивать с входящим, разбилась об этот дурацкий ноль в конце массива. Надо было массив char TelE[11] = ""; всего-лишь увеличить на один байт. Если будет впритык получается, что в TelE всегда имеется входящий номер(номер из еепром и без пробела номер из темпа) 90033322229003332222, а не 9003332222 9003332223, значит всегда срабатывает.
Значит запись должна выглядеть типа:
Там же память ни хрена не выделена! Но, я уже Вам написал подробно.
Я так и не понял как работать с этим двумерным массивом, понимаю как он выгляди, это что-то вроде столбцов, в котором по одной строке любой длины, а каждая строка это отдельный массив с набором байтов. Как считывать понятно и описано на сайте, а как записывать неясно.
Завтра буду танцевать с кнопками.
Так в конце строки всегда символ '\0'. Он является признаком конца строки. В моём прошлом посте, когда нужно было 10 строк по 10 символов, я объявлял
char
Tel[10][11];
Вы этого не знали?
Не понял комментария в строке
byte
Adress[10] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90};
//занимаем сотню ячеек для десяти номеров
О какой сотне ячеек речь?
Впрочем, добил, так добил. Поздравляю!
Не понял комментария в строке
byte
Adress[10] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90};
//занимаем сотню ячеек для десяти номеров
О какой сотне ячеек речь?
Впрочем, добил, так добил. Поздравляю!
Ну байтов в еепром, каждый номер занимает десять байтов, я заранее определил начало каждого номера чтоб можно было банальным счетчиком до десяти считать номер в строку.
Получается 0-9 10-19 20-29 --- 90-99 номера ячеек в еепром.
Это, конечно, не экономично, но мне так проще. Я же говорю, что пока чувствую себя обезьяной с автоматом. Мне паяльник и полуготовое решение от производителя как-то ближе.
Ага, нашел выше сообщение, как-то пропустил его.
strcpy(Tel[NumA], TelE);
Я так понимаю переводится как СтрокаКопировать? Тоже нигде не нашел. Надо будет поиграться.
Я так понимаю переводится как СтрокаКопировать? Тоже нигде не нашел. Надо будет поиграться.
Ничего себе! А где искали? Если в гугле набрать strcpy ....
А вообще, полный список С-шной библиотеки AVR есть ... Вы не поверите ... на сайте производителя AVR-ок - http://www.atmel.com/webdoc/AVRLibcReferenceManual/ch20.html
Ничего себе! А где искали? Если в гугле набрать strcpy ....
Для этого нужно знать что набирать, я искал по теме char* и добавление строк в массив и т.п..
Для этого нужно знать что набирать,
Ну, теперь Вы знаете, где лежит описание ВСЕХ функций. Там описания краткие, но если будут непонятки, смело набирайте имя функции в гугле и найдёте много информации - это стандартные функции, они на каждом заборе описаны.
Работает! Работает! (пританцовывая)
Номера добавляются и убираются! Я добавил комментариев, вроде понятно что куда и откуда.
Остальное дело механики, а это уже мой основной хлеб, так что ничего сложного.
С Победой!
Ну прошел почти месяц, работает стабильно, нареканий нет.
Проблему с отправкой СМС я так и не решил, не хочет, зараза, видимо, модем бракованный.
Спасибо, пригодился ваш скетч для доработки сигнализации. Ато мучался с массивами, незнал как использовать несколько номеров.
Значит не зря потел :)
вопрос по ЕЕПРОМ: по вашему коду у меня почему-то сохраняется в ЕЕПРОМ последние 8 цифр номера. в чем может быть проблема?
Код просто скопировали или что-то меняли?
да, переделал немного. и убрал кнопку. никак не могу осилить сохранение и проверку номеров в еепром