Как можно красивее офрмить эти if'ы
- Войдите на сайт для отправки комментариев
Пт, 12/04/2019 - 20:49
как можно красивее(взрослее) сделать эту логику ?
c while красивее но не хочу т.к. может зависнуть ожидая какогото ответа
обработчик ошибок еще не дописал
bool isModemRegistered(){
if (isModemAlive()){
Serial1.print("ATH\r");
if (Serial1.find("OK")){
Serial1.print("AT+CPAS\r");
if (Serial1.find("0")){
Serial1.print("AT+CREG?\r");
if (Serial1.find("0,1")) return true: return false;
} else return false;
} else return false;
} else return false;
}
bool isModemBootup(){
if (!isModemAlive()){
if (!(PINC & (1 << 6))) delay(5000); //delay if shutdown routine is initiated
//(PINC & (1 << 6)) >> 6
PORTC &= ~(1 << 6); //boot pin low
delay(300); //time by datasheet
PORTC |= (1 << 6); //boot pin high
delay(5000); //delay if it actually is a reset
if (Serial1.find("+PBREADY")) return true: return false;
} else return true;
}
bool isModemAlive(){
Serial1.print("AT\r");
if (Serial1.find("OK")) return true: return false;
}
void modemOn(){
if (isModemBootup()){
if (isModemRegistered()) error no error yes;
} else error yes;
}
т.к. на самом деле мы не знаем физического состояния внешнего устройства то попытался максимально (на сколько хватило мне соображалки) сделать защиту от дурака/случайного выключения/зависания. т.к. нет while и код после обработки ошибки, побежит по второму/третьему кругу и даже несмотряна то что мы пытаемся только включить внешнее устройство, фактически мы можем его и ресетнуть и если с подключением /питанием все ок, то в конце концов должно заработать.
Красивее оформить - инвертировать условие и сразу сделать return false. А вот как умнее сделать - надобно мозг наморщить.
В строчке 8 - дичь написана, там нет тернарного оператора, компилироваться не должно. В строчке 21 - також. Или это - просто псевдокод?
По поводу красивости: всё субъективно. Красиво - это когда код форматирован по одному из стандартов. Как правильно замечено выше - инверсия условия сильно сократит кол-во ненужных else.
Функции типа
bool isModemAlive(){ Serial1.print("AT\r"); if (Serial1.find("OK")) return true: return false; }можно переписать короче:
bool isModemAlive(){ Serial1.print("AT\r"); return !Serial1.find("OK"); }В целом же, исходя из опыта: блокирующая работа с GSM-модемом в реальном более-менее серьёзном проекте - неприемлема, от слова "совсем": ответ на некоторые команды по даташиту может занимать до 80 секунд. Что в это время делать остальному функционалу прошивки - курить бамбук? Единственное верное пмсм решение - это неблокирующий конечный автомат с состояниями, вещь не самая тривиальная к реализации, в своё время убил на отладку этого дела больше месяца.
А что, прежде, чем задавать вопрос о красоте, просто добиться успешной компиляции ... не судьба?
Нет, не зря я Вас в соседней теме медалью наградил! Вы достойны! :)))
DIYMan так вроде у меня не блокирующая я поэтому и убрал while(!serial.find()); ?
а почему
return(!)Serial1.find("OK");когда вроде надоreturnSerial1.find("OK");?"инвертировать условие и сразу сделать return false"
if (!isModemAlive()) return false; else { Serial1.print("ATH\r"); if (Serial1.find("OK")){ Serial1.print("AT+CPAS\r"); if (Serial1.find("0")){ Serial1.print("AT+CREG?\r"); return Serial1.find("0,1") } else return false; } else return false; }вы это имели ввиду?
DIYMan так вроде у меня не блокирующая я поэтому и убрал while(!serial.find()); ?
а почему
return(!)Serial1.find("OK");когда вроде надоreturnSerial1.find("OK");?"инвертировать условие и сразу сделать return false"
if (!isModemAlive()) return false; else { Serial1.print("ATH\r"); if (Serial1.find("OK")){ Serial1.print("AT+CPAS\r"); if (Serial1.find("0")){ Serial1.print("AT+CREG?\r"); return Serial1.find("0,1") } else return false; } else return false; }вы это имели ввиду?
У вас - именно блокирующая, потому что Serial.find не сразу возвращает управление, а по таймауту. К тому же - такой подход не обеспечит правильного реагирования на многие команды: как я писал выше - ответ на некоторые команды может занимать много секунд.
Почему !Serial.find - описка, если имелась в виду функция isModemAlive. В целом же, повторюсь ещё раз: ваш подход - не очень, на простом примере: вы послали команду AT, а в этот момент в порт упала SMS, до прихода ответа OK. С вашим кодом - СМС будет пропущена.
Инвертирование условия - это:
1. Ваш пример:
2. Инвертирование условия:
Второй вариант - короче и читабельней.
По поводу синтаксиса и пр.: очень советую почитать учебник по С++ - многие вопросы отпадут сами собой.
bool isModemRegistered() { if (isModemAlive()) { Serial1.print("ATH\r"); if (Serial1.find("OK")) { Serial1.print("AT+CPAS\r"); if (Serial1.find("0")) { Serial1.print("AT+CREG?\r"); return (Serial1.find("0,1")) ? true : false; } else return false; } else return false; } else return false; } bool isModemBootup() { if (!isModemAlive()) { if (!(PINC & (1 << 6))) delay(5000); //delay if shutdown routine is initiated //(PINC & (1 << 6)) >> 6 PORTC &= ~(1 << 6); //boot pin low delay(300); //time by datasheet PORTC |= (1 << 6); //boot pin high delay(5000); //delay if it actually is a reset return (Serial1.find("+PBREADY")) ? true : false; } else return true; } bool isModemAlive() { Serial1.print("AT\r"); return (Serial1.find("OK")) ? true : false; } void modemOn() { if (isModemBootup()) { error = (isModemRegistered()) ? 0 : 1; } else error = 1; }Евгений теперь компилируется
Инвертирование условия - это:
1. Ваш пример:
2. Инвертирование условия:
Второй вариант - короче и читабельней.
return condition;
не?
если инвертировать:
return !condition;
Инвертирование условия - это:
1. Ваш пример:
2. Инвертирование условия:
Второй вариант - короче и читабельней.
return condition;
не?
если инвертировать:
return !condition;
Зависит от задачи и условий. В моём случае можно добавить дополнительные операторы:
if(!condition) { error("HALT!"); return false; }В случае простого возврата return !condition - так не выйдет. К тому же - ТС нужен условный возврат, а не безусловный - это видно из логики кода. Поэтому именно if.
DIYMan да я заметил что ответ иногда вообще не приходит, ну или ему надо было много больше время. я послал другую команду и ответ пришел сразу на вторую а на первую получилось так и не пришел. да find он таймаут меня это как раз избавляет от while.
про потеряю смс вы правы я даже не подумал об этом. но в данном конкретном проекте это не критично. будут пошаговые операции так сказать. вначале включили. потом настроили модем. птом приняли команду. отправили команду и тд. и когда мы отправляем команду - программе будет - уже пофиг что ктото ждет чтоб мы получили её. опоздал - твои проблеммы :) да это ни рил тайм. не смогу как вы :) но зато (кмк) будет весьма надежно, безотказно. во всяком случае точно интерактивнее и отказоустойчевее чем у многих готовых китайских аналогов.
с инвертированием кажется понял, уже завтра попробую. спасибо
В целом же, исходя из опыта: блокирующая работа с GSM-модемом в реальном более-менее серьёзном проекте - неприемлема, от слова "совсем": ответ на некоторые команды по даташиту может занимать до 80 секунд. Что в это время делать остальному функционалу прошивки - курить бамбук? Единственное верное пмсм решение - это неблокирующий конечный автомат с состояниями, вещь не самая тривиальная к реализации, в своё время убил на отладку этого дела больше месяца.
Вы абсолютно правы. Попытался сделать пасечные весы. Что-бы по звонку от меня и подачи определенных DTMF сигналов "озвучивался" привес за сутки либо за неделю (файлы озвучки в SIM800). Ну и плюс энергосберегающий режим и периодическая проверка регистрации в сети (сеть теряется часто в предполагаемом месте установки устройства), нет сети - отключи радиомоодуль, минут через несколько снова проверь... Это штоба батарейку поберечь. Ну и плюс экранчик с кнопочкой, на месте привес проверить. Ну и RTC с микросхемой памяти, - эти привесы хранить и долгими зимними вечерами анализировать.
Код блокирующий : АТ команда - ждем овет - что-то делаем. Вроде и работает все, но криво как-то. То на звонок не отвечает, то ДТМФ не распознает, то еще какая хрень...
НО! Представив сложность написания конЧЕного автомата (с кучей незапрашиваемых уведомлений, вариантами ответов от SIM) - решил НИАСИЛЮ ;)) Жил же я раньше без умных весов, может и дальше проживу...
kolyn, при таком раскладе нужно было идти в обратную сторону - не по запросу отдавать данные, а пушить куда-нить. Сейчас, как я понимаю, модно на MQTT-сервер выкидывать данные, потом со смартфона клиентом смотреть. А если 3310 в качестве клиентского устройства, то ежедневный смс-репорт - сколько прибавилось за сутки, сколько с начала недели. Заодно будет уверенность, что система не висит.
не по запросу отдавать данные, а пушить куда-нить.
В месте, где хотел пользовать устройство мобильного интернета нет. От слова совсем. Даже EDGE нет! Это первое. Второе - вохдящие бесплатны. Т.е я пополнил карту раз в год и звоню на устройство, не заморачиваясь с проверкой счета, пополнением и т.д. - считаю жирным плюсом при эксплуатации.
Насколько я понял - хотели звонить с бесплатными входящими и пр. пирогами, но не смогли обуздать систему. Так что - или смс или ничего. Выбор Ваш, конечно - мотаться на пасеку чтобы смотреть на экранчик или иногда пополнять баланс.
Выбор Ваш, конечно - мотаться на пасеку чтобы смотреть на экранчик
Летом живу там практически все время - это основное занятие для денг. Ардуина - хобби, тренировка для мозгов, черствеют с годами, знаете ли. Проект пытался замутить не для себя, хотел выложить в свободный доступ. "Умные пчеловодные весы" как коммерчесский проект есть и в Украине и в России, и за далеким бугром, но цена!!! Любителю не по карману, профессионалу по сути не нужны - он и так все видит...
То,что сгородил я, в принципе работает, но... Глюки, такое предлагать для повторения - дурной тон. Может следующей зимой... или никогда...
qwone, писал ранее про логику:
Что-бы по звонку от меня и подачи определенных DTMF сигналов "озвучивался" привес за сутки либо за неделю (файлы озвучки в SIM800).
Квон опять неправильного мёда хлебнул...
А теперь представим ситуацию. Вы находитесь хер-знаете-где. Хотите узнать прирост. Отправляете СМС . И улий озвучивает прирост +5 кг. Замечательно. Но вы из местности хер-знаете-где услышите озвучку находящую на улике,а значит далеко от вас. Вот и выходит, что нужно отправить прирост уже к вам на мобилу, который это и озвучит .
Одно из двух - либо я тупо пояснил, либо до Вас тупо не дошло ;)
Я звоню весам. Они снимают трубу, и говорят мне (человечьим голосом на чистом русском языке): "Хотите узнать привес за сутки - нажмите 1, привес за неделю - нажмите два, хотите послушать свежий анекдот - нажмите 666". Я на своем телефоне нажимаю кнопку 1, весам передается ДТМФ-сигнал и они говорят человечьим языком: "Привес за сутки составил 16 кг. 850 гр." Я переключаюсь с телефона на калькулятор, умножаю на количество семей, на цену меда в долларах и довольный потираю руки.
Позже выясняется, что это был глюк и в реале вместо привеса была убыль...
Значить, Пух приходил, покопаца
В целом же, повторюсь ещё раз: ваш подход - не очень, на простом примере: вы послали команду AT, а в этот момент в порт упала SMS, до прихода ответа OK. С вашим кодом - СМС будет пропущена.
вчера во время эксперементов с модем добавил прерывание для отладки и заметил следующее:
- если прерывания нет, то все что уходит в сериал от модема успешно получается ардуиной. без пропусков.
- если я добавляю короткое и быстрое прерывание, просто зажечь 13 лед, когда чтото пришло в сериал. причем зажигаем через запись в порт а не через digitalWrite(); который в 20 раза медленее, то первые 5 символов пропадают из эфира. как можно словить все символы ?
весь код показывайте.
И вообще непонятно, зачем прерывание для отладки если все что валится из модема вы все равно выводите в монитор.
Уже многократно обсуждалось здесь, максимально отказываться от вских выводов информации во время приема данных, т.е. или делаете большой буфер, в него все кидаете а потом обрабатываете или обрабатывать online но тогда код должен быть максимально коротким
леонардо соеденен с модемом и отправляет на комп все что посылает модем volatile byte flag = 0; void setup(){ pinMode(13, OUTPUT); pinMode(3, INPUT); //в модем while(!Serial); // for leonardo Serial.begin(115200); Serial1.begin(115200); attachInterrupt(0, blink, LOW); } void loop(){ // Копируем Serial1 --> Serial if(Serial1.available()) Serial.write(Serial1.read()); // Копируем Serial --> Serial1 if(Serial.available()) Serial1.write(Serial.read()); if (flag) { PORTC |= (1 << 7); flag = 0; } } void blink() { flag = 1; }код в другом месте, пишу по памяти. может чтот азбыл. но смысл такой.
ну и как сказал уж без прерывания все ок а так первые 5 символов пропадают
ну вопрос то остался: зачем моргать светодиодом со скоростью 115200 при приеме данных?
не, он моргает один раз. согласно низкому уровню на ноге 10 модема.
в кратце. на ноге 10 модема. появляется низкий уровень когда приходит смс. в этоже время одновременно когда приходит смс модем отправляет текст RING в сериал. т.е. одновременно ринг в сериал и ноль на 10 ноге. по этому нулю я зажигаю лед. но не вижу надписб RING в сериал. если закоментить прерывание то RING я вижу.