Всегда ли delay () - признак дурного вкуса?
- Войдите на сайт для отправки комментариев
Вопрос чисто академический. Понятно, что использования delay () следует избегать: останавливает выполнение скетча. Но является ли вообще его применение признаком недостаточной образованности программиста (типа "дурной тон" и "правильные пацаны" использовать delay () не должны)? В качестве примера: в своем скетче счел нужным перед выполнением программы проводить кратковременое включение периферии с целью теста ее готовности и исправности (моторы, калпана, индикаторы...). Сунул это все в сетап (все равно проверка выполняется один раз), интервалы между проверками устройств определил посредством delay (). Не сойду ли за лоха (пардон за сквернословие) с этим delay ()? Хотя, если честно, не знаю ему альтернативы в однократно исполняемом блоке.
Давайте уже без преувеличений ... Так и до маразма не далеко ...
Стоит ли бояться человека с delay()? ;))))))
После того, как ты понял, чему и когда мешает делей, а написал ты всё верно, не надо доходить до маразма, это верно замечено постом выше! Не мешает - используй на здоровье!
А чем девайс будет заниматься, если вместо дилэя будет что-то неблокирующий?
бесконечно проверять
1
if
(millis() - prev_millis > interval)
Или спать, если уложишь.
Да используй , если код позволяет, нормальная практика.
Главное без фанатизма.
Всегда ли delay () - признак дурного вкуса?
Нет.
А вот проверка "говнокод или нет?" путём контекстного поиска delay (goto, или любого другого контекста) - всегда признак отсутствия мозгов.
Нет.
А вот проверка "говнокод или нет?" путём контекстного поиска delay (goto, или любого другого контекста) - всегда признак отсутствия мозгов.
Я уже понял, что не всегда (спасибо соконфетникам). Делэи и гото в лупе и функциях не применяю (расту же в программировании!). А вот в сетапе после всех объявлений и инициаций однократную проверку периферии сделал с интервалами, определяемыми делэем. Ну, и зачесалось.... :) Кстати, так и не понял, чем в сетапе паузу можно организовать кроме делэя? Миллис, вроде требует зацикливания программы, не пойдеть. А что еще?.
Миллис, вроде требует зацикливания программы
нет, не требует, но смысла не имеет.
Если подразумевается, что инициализация чего либо потребуется в будущем и не один раз, например полностью сбросить модем и заново инициализировать, то все эти инициализации делать так же в loop, добавить некую переменную в программу - т е сначала шаги инициализации, потом основная работа.
типа так
1
byte
modem_step = 100;
// current work mode mode in table of command
2
// static steps:
3
// 100 - delay 30 sec for registration modem in net
4
// 101 - not wait response, wait incomming call or other commands
Функция delay() - это то же самое зацикливание программы на определённое время, с единственной проверкой, на микросекунды.
https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/delay.c#L64
Када буите апсуждать макаронный, спагетти и кенгуру --- код ???
Када буите апсуждать макаронный ... код ???
Для пастафарианцев это богохульство! Негоже коду уподобляться Божеству!
Setup() всё стерпит ИМХО
Каждый строчит как хочет.
присоединюсь к #3 комменту, если есть что делать, то делай вреден, а, если просто блинк и ничего кроме блинка, то полезен, ибо позволяет экономить время и моск.
Друзья, чтобы не заводит новую тему - вопрос более обширный, но и довольно конкретный. Сообщество уже давно знает, что я новичок (порой, туповатый). Постепенно обучаюсь (медленно, блин...). А размеры скетчей растут и растут. Уже, иной раз самому в них разбираться, быстро находить нужное и т.д. стало если не проблемой, то некоей сложностью. Попрошу вот о чем: дайте ссылочку, что надо прочитать относительно общих правил правильной организации скетча (оптимальная последовательность операций, что следует заносить в циклы, что - в отдельные фукнции и т.д.). Большую часть я "умственно" уже понимаю. Но хотелось бы устаканить всё это в мозгах. Понимаю, что подобного рода информации вагон, только гугли. Однако, сразу оценить полезность и понятность информации трудно. А прочесть всё - жизни не хватит. Поэтому, большая просьба в первую очередь подсказать источники, предназначенные для идиётов - все-таки, пока я еще не силен в программировании. Заранее спасибо!
Не претендую на истину, но вроде вот так:
https://habr.com/ru/post/280764/
https://www.cyberforum.ru/cpp-beginners/thread2518182.html
https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BE%D0%BB%D0%BE%D0%B2%D0%BE%D1%87%D0%BD%D1%8B%D0%B9_%D1%84%D0%B0%D0%B9%D0%BB
01
//dmfmod.h
02
#ifndef DMFDMF_H
03
#define DMFDMF_H
04
05
void
initDMFint(
void
);
06
unsigned
int
processDMFappart(
void
);
07
void
TIM2_IRQHandler(
void
);
08
09
#endif /* DMFDMF_H */
10
11
12
//dmfmod.c
13
#include "dmfcomm.h"
14
#include "stm32f30x.h"
15
#include "dmfuart.h"
16
17
.................
Не претендую на истину, но вроде вот так
Спасибо, вечером дома посмотрю: на работе чортова платформа все три адреса объявляет как недоступные.
Там про разбиение на файлы. Я так понимаю что ТС сейчас о другом спрашивает...
Там про разбиение на файлы. Я так понимаю что ТС сейчас о другом спрашивает...
Если там про это, то я действительно вопрошаю о другом. У АлексГивера выудил насчет применения нужного типа перемнных, констант и прочего. Но этого маловато: многому по этим крохам меня уже тут научили. Я как раз про оптимизацимю структуры кода спрашивал. Чорт, знаний не хватает даже для того, чтобы грамотно задать вопрос :(
Гивер и типы переменных это несочетаемая окрошка.
Для него в порядке вещей int'ом миллисы ловить
Сначала надо на ватмане квадратиками и связями между ними нарисовать АЛГОРИТМ.
Для него в порядке вещей int'ом миллисы ловить
Да, про это я тоже читал. Но я про разумную достаточность при использовании разных типов переменных. Собственно, в этом сам Гивер и его особенности ни при чем.
Собственно об этом давно написано в атмеловских аппнотах, которые лежат переведенным на microsin-e. А гивер - это фотокопия фотокопии фотокопии.
Сначала надо на ватмане квадратиками и связями между ними нарисовать АЛГОРИТМ.
Так и делаю (это уже давно, начиная с программирования на ВижуалБэйсик). Даже в Сплане понаписал в библиотеку фрагменты, чтоб их как кубики раскладывать.
А че не так? Наверно переполнения ;)
Умеючи и байтом ловятся )))
Сунул это все в сетап (все равно проверка выполняется один раз), интервалы между проверками устройств определил посредством delay (). Не сойду ли за лоха (пардон за сквернословие) с этим delay ()?
Нет, не сойдете. Но как только захотите сделать выход из процесса этих проверок по нажатию кнопки, то взгляд на delay () в сетапе несколько пересмотрите ;) А прекращение проверок таки захочется сделать. Зачем что проверять при очередном ребуте если и так уже проверено? Если же просто свет моргнет, ребутнется, то эти проверки еще и на основной процесс могут негативно повлиять.
Нет, не сойдете. Но как только захотите сделать выход из процесса этих проверок по нажатию кнопки, то взгляд на delay () в сетапе несколько пересмотрите ;) А прекращение проверок таки захочется сделать. Зачем что проверять при очередном ребуте если и так уже проверено? Если же просто свет моргнет, ребутнется, то эти проверки еще и на основной процесс могут негативно повлиять.
Я все это учитываю. Проверка примитивная, занимает 3 секунды, так что, выходить из нее принудительно на практике нет нужды. Более того, я сдуру (спижонил) сделал проверку последовательно, хотя все устройства и индикацию можно с тем же успехом тестировать одновременно, что ее еще более укоротит. Свет не моргнет :) На такой случай питаю управление от БП+аккумулятор (накушался этих "радостей" на даче). Понятное дело, высоковольтная часть "моргнет", но страшного ничего не произойдет, а перенастраивать ардуину уже не надо.
Свет не моргнет
ну да, молния не пролетит, помеха не прискачет, мышь кабель не съест, аккумулятор не сдохнет, транзистор в ИБП не взорвется.....
P.S. Я тоже наивным был лет десять назад, когда в деревню купил дорогущий стабилизатор на котел, типа отечественного производства, но из китайских деталей.....такая помеха прилетела в один прекрасный момент, что ничего не помогло. Понравился ответ поддержки производителя стабилизаторов Штиль: "вероятно внешний импульс был коротким по длительности и высоким по мощности, не соответствующий тех.характеристикам стабилизатора".
разрядники нада ставить перед тонко организованной душевно китайской техникой.
разрядники нада ставить перед тонко организованной душевно китайской техникой.
теперь то много что стоит перед котлом......это выходит дешевле чем плату управляющую менять.
теперь то много что стоит
Так опыт и приходит...
Сначала надо на ватмане квадратиками и связями между ними нарисовать АЛГОРИТМ.
и стрелочками
разрядники нада ставить перед тонко организованной душевно китайской техникой.
теперь то много что стоит перед котлом......это выходит дешевле чем плату управляющую менять.
В своё время выкинул настенник со всей этой постоянно проблемной хероборой, поставил напольник, насос, и - ляпота. Никаких геморов с помехами, там фактически ломаться-то и нечему, чистая механика.
Щас как вспомню все эти судороги - то с платой управления, то с пультом, то теплообменник потёк, то клапану захудало - так вздрогну. Чур меня больше электронных котлов - я лучше за эти деньги куплю несколько напольников про запас, и буду менять их, если вдруг. Думаю, жизни на три хватит, учитывая цены всяких раскрученных брендов.
Конечно, всё имхо, но по мне чем проще и надёжней система отопления и ГВС - тем лучше. И ардуина там (в тематику форума) - вот уж точно не нужна.
В своё время выкинул настенник со всей этой постоянно проблемной хероборой, поставил напольник, насос, и - ляпота. Никаких геморов с помехами, там фактически ломаться-то и нечему, чистая механика.
А чё за настенник? У меня Висман-100 стоит уже лет 10-11 (может, и чуть больше). В первые годы его эксплуатации чего только в сети не случалось. Напряжение и отрубалось и возрастало до 270-280 вольт. Молоньей не шарахало, чего не было - того не было.При проблемах (очень низкое или очень высокое напряжение или отключат газ) котел уходил в спячку, по возврату напруги и газа - снова включался. 333 раза тьфу На всякий случай питаю через примитивный стабилизатор Ресанта (похоже, он - чистая бутафория, но для успокоения нерьвов...). Единственая поломка - перестал работать трехходовой кран. Гарантийный случай. Заменили за 10 минут без ворчания и заморочек (даже удивился на газовиков). Других проблем нет. 3333 раза тьфу!
Goto - признак криворукости. Использовать можно только в одном случае - когда критично закрыть общий ресурс или освободить память при сбое. Тогда или дерево if () будет, или goto в конец функции, за основной return. Получается некий аналог try{} catch(){} из жавы.
Задержки - абсолютная норма. Даже в циклах. Другой вопрос, что использование зависит от контекста, и там, где событие можно поймать через прерывание, лучше оное и использовать. Прерывание ставит флаг - в главном цикле этот флаг проверяется и при поднятии происходит обработка/сброс. Там, где можно решить через опрос регистра, тоже самое. А вот если пилим ногодрыг - там задержки норм, ибо без вариантов. Или если идет обращение к железу, у которого есть константная задержка выполнения. Короче, тут головой думать надо.
Goto - признак криворукости.
Значит, Кнут - криворукий, так и запишем :-)
аналог try{} catch(){} из жавы.
Скорее уж из С++. В яве try{} catch(){} немного отличается.
Значит, Кнут - криворукий, так и запишем :-)
Кнут, он по тем временам мыслил Фортрановскими категориями, а там goto один из основных апираторов, как в Васике.
Goto - признак криворукости.
Чо здесь криворукого?
01
void
AM2320::internalRead(
void
)
override
{
02
uint8_t data[DEV_MEMORY_SIZE];
03
int
error = 0;
04
05
if
(!WakeUpDevice(FDevAddress)) {
06
error = err_i2c_DeviceNotFound;
07
goto
err_exit;
08
}
09
10
Wire.beginTransmission(FDevAddress);
11
Wire.write(CMD_READ);
12
Wire.write(0x00);
13
Wire.write(0x04);
14
if
(Wire.endTransmission() > 0) {
15
error = err_i2c_ReadError;
16
goto
err_exit;
17
}
18
19
Wire.requestFrom(FDevAddress, DEV_MEMORY_SIZE);
20
if
(Wire.readBytes(data, DEV_MEMORY_SIZE) != DEV_MEMORY_SIZE) {
21
error = err_i2c_ReadError;
22
goto
err_exit;
23
}
24
25
if
(!CheckCRC(data,DEV_MEMORY_SIZE-2)) {
26
error = err_i2c_CRCError;
27
goto
err_exit;
28
}
29
30
Check(data);
31
32
return
;
33
34
err_exit:
35
if
(error == err_i2c_CRCError) {
36
PostMessage(msg_Error, error);
37
}
38
else
{
39
Error(error);
40
}
41
}
>> Чо здесь криворукого?
Я же написал про этот случай как исключение. Но некоторые лепят GOTO внутри суперфункции на тысячу строк как оператор вызова подфункций или ветвления - вот это действительно зло и лапша.
Я же написал про этот случай как исключение.
А я к тому, что из любой конструкции языка можно сделать зло и лапшу, а можно применять наглядно и правильно. На то нам образование дадено, чтоб отличать одно от другова.
Goto - признак криворукости.
Чо здесь криворукого?
01
void
AM2320::internalRead(
void
)
override
{
02
uint8_t data[DEV_MEMORY_SIZE];
03
int
error = 0;
04
05
if
(!WakeUpDevice(FDevAddress)) {
06
error = err_i2c_DeviceNotFound;
07
goto
err_exit;
08
}
09
10
Wire.beginTransmission(FDevAddress);
11
Wire.write(CMD_READ);
12
Wire.write(0x00);
13
Wire.write(0x04);
14
if
(Wire.endTransmission() > 0) {
15
error = err_i2c_ReadError;
16
goto
err_exit;
17
}
18
19
Wire.requestFrom(FDevAddress, DEV_MEMORY_SIZE);
20
if
(Wire.readBytes(data, DEV_MEMORY_SIZE) != DEV_MEMORY_SIZE) {
21
error = err_i2c_ReadError;
22
goto
err_exit;
23
}
24
25
if
(!CheckCRC(data,DEV_MEMORY_SIZE-2)) {
26
error = err_i2c_CRCError;
27
goto
err_exit;
28
}
29
30
Check(data);
31
32
return
;
33
34
err_exit:
35
if
(error == err_i2c_CRCError) {
36
PostMessage(msg_Error, error);
37
}
38
else
{
39
Error(error);
40
}
41
}
насчет криворукости не берусь судить, но я бы это написал без goto.
Меня учили, что goto - зло безусловное и что нет таких ситуаций, где его нужно применять. Я и не применяю.... за все годы ни в одной моей программе нет ни одного goto и меток, за исключением switch - case :)
но я никому ничего не навязываю :)))
При обучении новичка вполне допустимо некоторые вещи демонизировать, чтобы избежать злоупотребления. Вырастет в профессии - поймет, что нет ничего абсолютно хорошего или абсолютно плохого, есть лишь границы применимости. Но если дать ему молоток и отвертку сразу, то шурупы он с большой вероятностью будет заколачивать - это проще и быстре, да и держится вроде.
Кнут, он по тем временам мыслил
Ну, почему? Примеры в той его знаменитой статье вполне себе на Паскале.
Ему принадлежит знаменитая фраза: "И чего они прицепились к этому goto? Может потому, что слово четырёхбуквенное?".
Знакомый рассказывал, как один его товарищ написал программу ООП использую gotu и перекрестные . Убил год... А после этого потребовалась ее доработка и модификация - оказалась проще написать новую программу, чем переделать якобы базовую...
удобство в малом привело к бездарно загубленному году работы...
Что то я не понял. Залезем в ассемблер, там goto или jmp по другому постоянно встречается. Все if case while и прочие ветвления через goto, вернее jmp реализуются. А си goto нельзя? Криворукость?
Goto - признак криворукости.
Чо здесь криворукого?
Почти все что по теме . Не порадовал ты, дед.
Сравнивай.
01
int
AM2320::internalReadErr(
void
) {
02
uint8_t data[DEV_MEMORY_SIZE];
03
04
if
(!WakeUpDevice(FDevAddress))
return
err_i2c_DeviceNotFound;
05
06
Wire.beginTransmission(FDevAddress);
07
Wire.write(CMD_READ);
08
Wire.write(0x00);
09
Wire.write(0x04);
10
if
(Wire.endTransmission() > 0)
return
err_i2c_ReadError;
11
12
Wire.requestFrom(FDevAddress, DEV_MEMORY_SIZE);
13
if
(Wire.readBytes(data, DEV_MEMORY_SIZE) != DEV_MEMORY_SIZE)
return
err_i2c_ReadError;
14
15
if
(!CheckCRC(data,DEV_MEMORY_SIZE-2))
return
err_i2c_CRCError;
16
17
Check(data);
18
19
return
0;
20
21
22
}
23
24
void
AM2320::internalRead(
void
)
override
{
25
int
error;
26
error= internalReadErr(
void
);
27
if
(error == err_i2c_CRCError) {
28
PostMessage(msg_Error, error);
29
}
30
else
{
31
Error(error);
32
}
33
}
Logic, ничего не имею против твоей интерпретации.
Я писал к тому, что каждый инструмент нужно применять по-разному, в зав-ти от ситуации. Мой вариант проще, твой - по научному. Ну так я и не спец, мне бы как пропроще и чтоб не сильно "лапшить" код. Функция в один экран влезает - и щастье. :)
Ну, почему? Примеры в той его знаменитой статье вполне себе на Паскале.
Cтатью читал в 1990м. Сделал для себя вывод, что можно и на Паскале как на Фортране писать. :-)
Мои первые программы на Паскале были так и написаны, с goto, ибо привык. :-) Потом разглядел прелести языка, отошел.
Ну так я всегда и говорил, я игрушечный программист, без спицального образования, самоучка. Если чему-то и научился, то тока случайно. :-) Про С++ никада раньше не слышал, кропал авнакод на Дельфи. :-)
Асм это чуть другая тема. Во-первых, на нем сейчас пишут только критичные участки, либо участки с DSP-инструкциями, о которых компиляторы обычно не знают. Ну еще в реверсинге используют. То есть используют люди с большим опытом кодинга как такового. Если на нем кто-то пишет простой системный код, то это обычно либо поехавший кукухой перфекционист, не доверяющий компилятору, либо столетний динозавр, привыкший так делать во времена каменных топоров. Во-вторых, не комментированные простыни асма читаются как... ну ты понел. Никак не читаются, их чтением врагов пытать можно.
Теперь к вопросу goto. Люди на goto реализуют циклы, ветвления, функции... Получается write-only лапша, читать которую невозможно без кровавых слез и матов в адрес аффтара.