Включение пина на определенное время
- Войдите на сайт для отправки комментариев
Пнд, 10/10/2016 - 09:41
Добрый день, товарищи. разибраюсь с кодом Ардуины, и вот наткнулся на проблему. Прошу вас помочь
Хочу, чтобы при достижении условия1 через заданное1 время включался цифровой пин на выход, удерживался включенным на протяжении нужного периода, а потом выключался. При этом, если условие1 еще истинно, то снова через заданное1 время повторялось. Задержку в виде delay() не нужно, т.к. есть параллельные процессы, которые выполняются
К примеру что у меня есть, но это совсем не работает как надо:
if(OKNO_AVT && p1<p2) { if(flagA==1) { if(millis()-previousMillisA >= 10000) { digitalWrite(oknoPin,LOW); previousMillisB=millis(); } if(millis()-previousMillisB>=20000) { previousMillisA=millis(); digitalWrite(oknoPin,HIGH); } } }
Ждем условие на время Delay0, потом на время Delay1 включаем, потом выключаем на время Delay2 и повторяем, как то так.
GarryC,
вот здесь
спрятаны грабли, связанные с переходом millis через переполнение.
Если верить документации на Ардуино, то раз в 48 суток.
А вообще то Вы правы, правильнее будет использовать макросы Unix для Jiffies, но стоит ли ТАК пугать молодежь?
да, нет, достаточно не прибавлять период к начальному значению, а наоборот, вычитать его из текущего и сравнивать с начальным. и тогда всё будет в порядке.
К сожалению, не будет все в порядке. Приходится из беззнакового переводить в знаковый и там вычитать, тогда основная проблема исчезает.
К сожалению, не будет все в порядке. Приходится из беззнакового переводить в знаковый и там вычитать, тогда основная проблема исчезает.
как может исчезнуть то, чего нет?
спрятаны грабли, связанные с переходом millis через переполнение.
Грабли есть. Но для реального устройства с watch dog и перезагрузкой раз в сутки - их нет )
Мой код такой
А вот как лучше будет через 48 решать вам
if (millis() >=future1) или if (millis()- future1>=0)
спрятаны грабли, связанные с переходом millis через переполнение.
Грабли есть. Но для реального устройства с watch dog и перезагрузкой раз в сутки - их нет )
Ну и с перезагрузкой раз в час их тоже нет. Только зачем это огород, когда достаточно "переставить местами слагаемые" и никаких вочдогов не нужно.
Если верить документации на Ардуино, то раз в 48 суток.
каким боком документация Дуино к факту того что 4294967295 миллисекунд - это где-то там 50 суток?
Мой код такой
[въезжает на титановом
бульдозеревелосипеде] алё! гараж, это здесь выставка одновибраторов?Евгений! Вы же как-то в контакте с модераторами, если я правильно понял.
Тема про "переполнение" достала капитально. И главное, что каждый месяц находятся новые адепты секты "48-ого дня".
Нужно в "прикрепленные" вывесить и примерчик, где Вы показали, что можно и со знаком и без знака, все равно. Он у меня где-то лежит. Нашел.
Вы уж поясните неверующим, что и к чему в примере.
Там в #define можно что со знаком, что без знака поставить - все едино.
Нужно в "прикрепленные" вывесить и примерчик, где Вы показали, что можно и со знаком и без знака, все равно.
прошло мимо меня - о каком знаке и беззнаке речь идёт?
пример простой:
Нужно в "прикрепленные" вывесить и примерчик, где Вы показали, что можно и со знаком и без знака, все равно.
Там в #define можно что со знаком, что без знака поставить - все едино.
и так будет работать
но, зачем так делать, если мы работаем с millis(), которая возвращает unsigned long, а не long или что иное?
но, зачем так делать, если мы работаем с millis(), которая возвращает unsigned long, а не long или что иное?
Просто тогда, в контексте той беседы, так получилось. Я посоветовал человеку что почитать, чтобы разобраться с этим, а он ответитл "Теперь понял, всё дело в unsigned", на что я ответил. то мол "таки не понял, разбирайся ещё, т.к. там пофигу signed или unsigned" и продемонстрировал это, чтобы не быть голослловным.
А вне того контекста - да, незачем.
Просто тогда, в контексте той беседы, так получилось. Я посоветовал человеку что почитать, чтобы разобраться с этим, а он ответитл "Теперь понял, всё дело в unsigned", на что я ответил. то мол "таки не понял, разбирайся ещё, т.к. там пофигу signed или unsigned" и продемонстрировал это, чтобы не быть голослловным.
А вне того контекста - да, незачем.
талант запутывать студентов не пропьёшь - теперь к тому, что не понимал ничего, прибавился ещё один, который понял наполовину - теперь он считает, что время может быть как положительным так и отрицательным, но не смотря на это через 48 суток День Сурка не наступает.
Попытаюсь прояснить ситуацию. На самом деле все очень просто и подробно описано в книгах по внутреннему устройству Unix.
Первый возможный и совершенно правильный вариант - это запоминать начало отсчета интервала и его величину и сравнивать разницу текущего и запомненного с ожидаемым
( (Текущее-Начало) >{=} Ожидание ).
Никакие переполнения работу не нарушат, но есть разница в используемых типах. Если у нас тип знаковый, то мы не можем заказать интервал длиннее половины возможного, поскольку Ожидание в этом случае будет отрицательным и условие сработает сразу. Если тип беззнаковый, то все намного лучше и мы можем заказать любой интервал, умещающийся в разрядную сетку. Поэтому когда кое-кто заявляет, что данный подход будет работать при любых типах, неплохо бы понимать разницу.
Поскольку порождаемый код для знакового и беззнакового типа идентичен и изменяется только собственно сравнение (анализ бита знака либо бита переполнения) нет никаких оснований выбирать знаковый тип для реализации.
Тем не менее такой подход не закрепился в Unix системах в силу того, что есть альтернативный, обладающий определенными преимуществами. Для его получения преобразуем исходную формулу к виду
( (Текущее-(Начало+Ожидание) ) >{=} 0 ), что приводит к выражению
( (Текущее-Окончание) >{=} 0 ) при условии
Окончание=Начало+Ожидание.
Этот метод полностью эквивалентен первому с точки зрения правильной обработки переполнения, но включает сравнение с нулем, что автоматически приводит к знаковым типам, и при этом мы видим то же самое ограничение - невозможность заказать более половины возможного интервала.
Однако теперь обращение к знаковым типам оправденно, поскольку такой метод имеет преимущество перед исходным
1) мы должны хранить только Окончание - экономим память и
2) процесс обработки включает одно вычитание вместо двух по первому способу - экономим время.
Да, при этом появились дополнительные операции при формировании интервала, но они проводятся только один раз. Учитывая, что заказ большего, чем допустимый, интервала можно отследить при формировании интервала, и было принято подобное решение. В Unix системах определены макросы вида
#define time_after_eq(unknown, known) ((long)(unknown) - (long)(known) >= 0), которые данный подход реализуют.
А что касается отрицательного времени, то не следует путать физический процесс и модель, его описывающую, это грубая методологическая ошибка, связанная с отсутствием систематического образования.
Никакие переполнения работу не нарушат, но есть разница в используемых типах. Если у нас тип знаковый, то мы не можем заказать интервал длиннее половины возможного, поскольку Ожидание в этом случае будет отрицательным и условие сработает сразу.
снова за рыбу деньги - читаем описалово функции millis()
Возвращаемое значение
Количество миллисекунд с момента начала выполнения программы. (unsigned long)
*привяжи свой груз образования к ноге и спрыгни с моста - здесь обсуждают millis(), а не Unix time.
никаких вочдогов не нужно.
Watch dog по жизни нужен. Без него надежность работы устройства сильно понижается.
Некий Клапауций в своем комментарии утверждал что и тип char будет так же работать, а выяснилось, что не также, вот он и занервничал.
А обе реализации прекрасно работают совместно с данной конкретной millis(), и сама по себе эта функция никакой реализации своего использования не навязывает.
Ну и так, для сведения, все изложенное в комменте никоим образом с Unix time не связано, поскольку формирует более тонкие отсчеты, а связано с переменной jiffies и особенностями ее использования в связи с переполнениями. Переполнение же упомянутого атрибута кончно, тоже произойдет, но вряд ли оно должно волновать сегодняшних программистов.
Некий Клапауций в своем комментарии утверждал что и тип char будет так же работать, а выяснилось, что не также, вот он и занервничал.
А обе реализации прекрасно работают совместно с данной конкретной millis(), и сама по себе эта функция никакой реализации своего использования не навязывает.
мой комментарий про char относился к коду, упоминаемому в #14
почему там работает лонг, но не будет работать чар?
какая такая сакральная причина?
чем лонг отличается от чар, кроме диапазона возможных значений?
*с чего бы это мне волноваться? - я не несу ответсвенности за факт наличия в этой реальности типов переменных.
Именно диапазоном и отличается. Речь идет о том, что для беззнакового числа диапазон допустимых задержек составляет полную разрядную сетку, а для знаковых - только половину ее, вот и все отличие. Оно не существенно в данной конкретной задаче ввиду значительных размеров диапазона, но оно есть и это надо учитывать.
А разницы между long и char действительно нет, Вы правы, они оба знаковые и в этом смысле одинаково плохи с указанной точки зрения. Да, с точки зрения комментария к приведенному коду, использующему long, Ваше утверждение верно. Единственное, относительно типа boolean я не был бы столь уверен, не видя его реализации, но это уже придирки.
...для беззнакового числа диапазон допустимых задержек составляет полную разрядную сетку, а для знаковых - только половину ее...
...относительно типа boolean я не был бы столь уверен...
а, мне странно, почему ты урезаешь диапазон вполовину, но не желаешь уменьшить диапазон до единицы. :D
почему можно резать пополам, но нельзя до минимально возможного?
GarryC,
большая просьба, давайте Вы сначала разберётесь как работает арифметика в дополнительном коде, а потом уж будете с высокоучёным видом обучать нас - сирых и убогих.
Сначала Вы в посте №2 написали неправильный код. Затем, в посте №6 предложили какой-то космический вариант решения проблемы которой (проблемы) вообще-то и нет вовсе.
А уж дальше Вас и свосем понесло
Если у нас тип знаковый, то мы не можем заказать интервал длиннее половины возможного, поскольку Ожидание в этом случае будет отрицательным и условие сработает сразу.
Говорите за себя. Я вот не знаю, что Вы можете, а что нет, потому за Вас ничего и не утверждаю. За себя могу сказать, что я могу. Вам код показать? В котором тип знаковый, а задержка больше половины (т.е. отрицательная) или сами проверите?
Изучите всё-таки как устроена арифметика. Тогда поймёте. что дополнитеьный код для того и создан, чтобы процессору было фиолетово знаковый тип или нет - всё работает абсолютно одинаково в обоих случаях.
Был тут уже один знаток, который уверял, что допустимость записи unsigned a = -1; есть косяк компилятора, а когда его ткнули в стандарт языка, стал кричать, что это косяк языка. Не уподобляйтесь ему.
Вам код показать? В котором тип знаковый, а задержка больше половины (т.е. отрицательная) или сами проверите?
почему только больше половины, а не убить наповал жертву знаковых типов переменных и Юникс времени - заюзать весь без остатка диапазон от -2147483648 до 2147483647 ?
очевидно, что диапазон long -2147483648 - 2147483647 равен (внезапно! о, ужос!) unsigned long 4294967295.
как так?
где же наша, обещанная GarryC, половинка, одну из которых мы можем юзать, а вторую не можем?
внезапно, не можем? - нужно проверить:
ок. что напечатало:
вот так...
Жду кода в котором проверка (Текущее-Начальное)>Задержка будет работать при знаковых типах и значении Задержка отрицательном. Может все таки будет читать то, что написано в посте?
Я в первом посте написал упрощенный код, а в следующем показал как пишется правильный. Это абсолютно земной вариант решения конкретной проблемы, апробированный сообществом. Если у Вас есть решение лучше этого то с Вашей стороны жестоко держать мир в неведении, так что жду с нетерпением Вашего кода.
И так, между прочим, я действительно знаю, как работает дополнительный код, и в чем разница в обработке знаковых и беззнаковых типов, а у Вас, похоже, с этим проблемы.
Читаем пост и видим
"Первый возможный и совершенно правильный вариант - это запоминать начало отсчета интервала и его величину и сравнивать разницу текущего и запомненного с ожидаемым ( (Текущее-Начало) >{=} Ожидание ). Никакие переполнения работу не нарушат, но есть разница в используемых типах. Если у нас тип знаковый, то мы не можем заказать интервал длиннее половины возможного, поскольку Ожидание в этом случае будет отрицательным и условие сработает сразу."
Читаем реплику в отчет на этот пост
"Говорите за себя. Я вот не знаю, что Вы можете, а что нет, потому за Вас ничего и не утверждаю. За себя могу сказать, что я могу. Вам код показать? В котором тип знаковый, а задержка больше половины (т.е. отрицательная) или сами проверите?"
Читаем реплику в ответ на реплику "Жду кода в котором проверка (Текущее-Начальное)>Задержка будет работать при знаковых типах и значении Задержка отрицательном. Может все таки будет читать то, что написано в посте?"
Читаем ответ на реплику в ответ на реплику "Уже пошли передёргивания. Нигде в этом топике такого неравенста не было - появляется впервые."
Смотрим ЕЩЕ раз на первый пост и ВИДИМ это неравенство - я его сделал жирным. Вы по прежнему уверены, что оно появлось впервые? То есть дело в том что Ожидание и Задержка отличаются по написанию? Или Вас смутило Начало и Начальное? Хорошо, я согласен, напишите, пожалуйста, код для выделенного неравенства с знаковыми типами.
Особенно умиляет фраза "Разумеется, что-то придётся поменять". То есть я в первом посте утверждаю, что для знаковых типов такой подход неприемлем и мы не сможем заказать задержку более половниы разрядной сетки, а Вы возражаете, что можем, только придется что-то поменять (привести к беззнаковым типам) - немного странноватая логика, не находите.
А что касается надуманности проблемы, прошу в студию другой код (не совпадающий с приведенным мной), который требует столько же места (или меньше, что было бы еще лучше) для организации очереди таймеров и работает с такой же скоростью (или быстрее, что было бы просто замечательно) и при этом не имеет указанного мною ограничения, связанного со знаковостью.
Читаем пост и видим
"Первый возможный ...
И снова передёргивания.
Ну, вот, скажите, зачем передёргивать, всё же лежит на виду.
Я писал
Сначала Вы в посте №2 написали неправильный код. Затем, в посте №6 предложили какой-то космический вариант решения проблемы которой (проблемы) вообще-то и нет вовсе.
Теперь, как Вы выражаетесь, "читаем пост" №6, на который я ссылался, и видим совсем не то, что Вы цитируете сейчас:
К сожалению, не будет все в порядке. Приходится из беззнакового переводить в знаковый и там вычитать, тогда основная проблема исчезает.
Тогда Вы дали не "свершенно правильный вариант", а какую-то космическую ахинею про какую-то исчезающую проблему при переходе к знаковым вычислениям.
И только в посте №20, после того, как Вам уже всё объяснили, Вы начали что-то писать по "совершенно правильные варианты" и в качестве такового взяли готовое решение, которое Вам приводили в посте №14.
Ну, зачем бабушку-то лохматить? Зачем выставлять себя на посмешище? Знаете, как-то становится неинтересно с Вами разговаривать.
Ещё раз. Я говорил о проблеме из Вашего поста №6 и явно говорил об этом. А тот код, что привели в посте №20 (вернее, скопировали из поста №14) - против него у меня возражений нет.
Смотрим ЕЩЕ раз на первый пост и ВИДИМ это неравенство
Вообще то, для особо продвинутых, там нестрогость заключена в фигурные скобки, что подчеркивает необязательность строгости. Я готов посмотреть на любой вариант, хоть со строгим, хоть с нестрогим неравенством, который будет работать при знаковых типах и значении задержки более половины разрядности. Вы сказали что он возможен, так предъявите. Теперь Вам помешала строгость неравенства - снимите ее, если Вам это поможет. Вы действительно не понимаете, что там дело не в знаке равенства, а в знаке сравнения или прикидываетесь? Просто НЕТ такого варианта и не надо лохматить бабушку.
Поскольку в посте 4 я сразу упомянул макросы для jiffies, для которых характерен подход, показанный в моем посте 2, связанный с прибавлением и сравнением с результатом, поэтому в посте 6 я писал именно об этой реализации задержек и там перевод в знаковый совершенно необходим и там есть проблема и она отнюдь не космическая. Вы в своем посте 5 обсуждали совсем другой подход, свойственный Ардуино, а я продолжал обсуждать свой, что и вызвало определенное недопонимание. В посте 20 данный вопрос был рассмотрен весьма подробно, если Вам так и осталось непонятна природа вопроса, ничем не могу помочь.
До сих пор жду подтверждения Вашего заявления" За себя могу сказать, что я могу. Вам код показать? В котором тип знаковый, а задержка больше половины (т.е. отрицательная) или сами проверите?", но, видимо, не дождусь.
До сих пор жду подтверждения Вашего заявления" За себя могу сказать, что я могу. Вам код показать? В котором тип знаковый, а задержка больше половины (т.е. отрицательная) или сами проверите?", но, видимо, не дождусь.
Ну, знаете, у меня осталось впечатление, что "Вы всегда правы", поскольку после неправильного кода в посте №2, Вы начали нести какой-то бред в посте №6, а теперь отмазываетесь каким-то UNIX'ом (почему не ОС-360?). Можно подумать, что там арифметика другая. По уму, мне бы прекратить это разговор, потому как я отлично знаю, что последует дальше.
Но, тем не менее, я приведу кусочек кода. Не для Вас - Вы ведь А) всегда правы; и Б) итак всё знаете. Я приведу его для тех, кто пока ещё не всё знает.
Итак, коллеги, первое и главное. Плюньте на этот дурацкий спор и просто используйте беззнаковый long, который выдаёт millis(), только делайте это правильно, как приведено в примере "Блинк без делэй", в постах Лешака, в посте №14 данного топика и вообще, везде у грамотных людей. Никогда не делайте как предложил GarryC в посте №2. И всё у вас будет работать долго и правильно.
Всё, что написано ниже есть извращение - неэффективное и некрасивое. Написано оно не для того, чтобы Вы ему следовали, а только лишь в опровержение тезису, что со знаковыми переменными невозможно исрользовать отрицательные интервалы.
Итак, в чём собственно проблема?
Если переменные знаковые, то их значения бывают отрицательнми. И это не всегда очевидно. Например, переменная а в данном примере
будет отрицательной и равной -106. Напечатайте и проверьте.
Но тогда в программе
условие станет истинным сразу, т.к. левая часть сравнения сначала равна 0, а потом растёт и понятное дело будет больше любого отрицательного числа.
Непонятно зачем может понадобиться такое извращение (знаковые числа в задержках), но чисто из любви к искусству обойти это можно.
Для начала нужно понимать, что (это важно!!!) любые вычисления происходят одинаково (абсолютно!!!) для знаковых и беззнаковых переменных. Разница в нашем случае только в операции сравнения!
Поэтому, чтобы победить ситуацию, нужно что-то сделать с операцией сравнения.
Ну, самое простое, что Вы должны сразу же заметить - это то, что если вычисления идут одинаково, то нам достаточно сравнивать на равенсто (== вместо >=) - всё отлично сравнится и будет замечательно работать, при условии, что длительность Вашего loop не превышает 1 мс. Поробуйте сами - всё отлично сработает.
Но это плохая идея. Это >= туда не зря пихают. А ну как попадётся долгий loop ... Если таки хочется, чтобы работало и при более долгих loop'ах, то надо просто немного поменять условие. Есть миллион способов это сделать, например, вот так:
Кстати, можете попробовать вместо 150 поставить что-нибудь положительное, например 120 (в обоих примерах) и убедиться. что с положительными тоже работает.
Зачем это нужно? Не знаю. Просто для демонстрации, что такое возможно.
Жду кода в котором проверка (Текущее-Начальное)>Задержка будет работать при знаковых типах и значении Задержка отрицательном.
так вот же! #29
переведи 4294967295 в тип long и убедись, что оно отрицательное.
Вообще то, для особо продвинутых...
поясни для особо продвинутых, зачем ты упорно настаиваешь, что результат операции с двумя переменными типа long нужно переводить в так же тип long, даже в том случае, когда значение этой операции всегда имеет тип unsigned long?
--------------------------------------
факт:
для описания свойств переменных типа long нужно использовать переменные типа unsigned long, в том числе.
пример: диапазоном значений переменной long является значение типа unsigned long.
--------------------------------------
логика:
даже, если ты желаешь использовать переменные типа long для хранения значения времени, из этого никак не следует, что операции с этими переменными должны иметь аналогичный тип - тип зависит от контекста операций.
--------------------------------------
Ну вот я и дождался ).
Сразу скажу что я допустил 2 ошибки - первая была в исходном посте, даже если делаешь набросок кода, не следует писать небрежно, это несомненно так. Тем не менее, если писать правильное условие с преобразованием в знаковый тип, то вполне можно использовать подход с немедленным прибавлением "и все у вас будет работать долго, правильно" и чуть быстрее. А вот вторая моя ошибка не столь очевидна - когда я просил код в студию, следовало уточнить, что нужен правильный и разумный код, а не какой-нибудь, поскольку моим оппонентом такой вид кода не подразумевался.
Но это преамбула, а теперь обратимся собственно к коду. Поскольку для решения изначально поставленной задачи (использованию задержки более половины диапазона) необходимо беззнаковое сравнение, а автором кода постулировалась возможность реализации на знаковых типах, перед ним встала проблема беззнакового сравнения знаковых чисел. В принципе, она решается (конечно решается) очень просто, путем явного преобразования и можно было написать
(unsigned BasicType) diff >= (unsigned BasicType) theInterval
, но такой путь слишком явно наводит на мысль о том, что беззнаковое действительно необходимо. Поэтому автором кода было принять решение замаскировать беззнаковое сравнение и сделать его на знаковых операциях. Такое решение (одно из миллиона способов почесать правое ухо левой рукой, просунув ее под коленкой) и приведено в рассматриваемом коде. Обратим на него внимание и подумаем, как мы можем превратить знаковое сравнение в беззнаковое. Для этого нам потребуется рассмотреть различные сочетания операндов, здесь возможны 4 варианта
1) оба сравниваемых числа положительны - можно просто сравнить,
2) первое положительно, второе отрицательно - всегда меньше,
3) первое отрицательно, второе положительно - всегда больше,
4) оба отрицательны - можно просто сравнить.
Вот и истоки столь замысловатого кода, но в нем не реализована 3 вариант, что приводит к неправильному выполнению при пропуске равенства при определенных значениях задержки. Следовало бы добавить еще одно условие
... ((theInterval > 0) && ((diff >= theInterval) || (diff < 0)))
, тогда код становился бы правильным, но разумным его бы это не делало, поскольку разумный (и правильный) написан чуть выше.
Разумеется, можно придумать еще много способов реализации безнакового сравнения, например перевести в float с учетом знака и сравнивать float, наверное, можно придумать еще что-нибудь более экзотичное, но вряд ли существует способ, который докажет, что беззнаковое сравнение не нужно, хотя с интересом жду.
"зачем ты упорно настаиваешь, что результат операции с двумя переменными типа long нужно переводить в так же тип long, даже в том случае, когда значение этой операции всегда имеет тип unsigned long?" - Что Я Делаю Не Так, если думаю, что результат операции на long будет иметь тип long, и что характерно, описания языка со мной согласно?
Что Я Делаю Не Так, если думаю, что результат операции на long будет иметь тип long, и что характерно, описания языка со мной согласно?
почему ты не думаешь, что результатом операции с long будет boolean?
описание переменной long с тобой не согласно - диапазон переменной возможно описать числом типа unsigned long, и никак иначе.
хватит уже тупить - возможно, ты как-то кем-то образован, но правильно применить свои знания тебе мешает отсутствие логики.
Ну, в целом я и ожидал воплей "несчитова!", когда писал
я отлично знаю, что последует дальше.
Только вот есть загводка, даже две.
1. Я не преобразовывал к беззнаковому сравнению, обошёлся знаковыми - а требовалось только это и ничего другого. Так, что всё остальное - мимо кассы. Ваше выражение "правильный и разумный код" несколько странно в данном контексте. Код, который правильно решает поставленную задачу правилен и разумен. Т.е. данный код намного правильнее и разумнее того, что привели Вы во втором посте. Если у Вас другие критерии правильности и разумности - это Ваша проблема. То, что он несколько "извращение", так задача была такая.
2. Вы не разобрались в коде. Ваше третье условие учтено, просто Вы по-прежнему демонстрируете незнание устройства арифметики в этом языке. Собака зарыта в 23-ей строке. Собственно 23-я строка это своего рода жульничество, но чтобы это понять нужно знать как устроена арифметика в тонкостях, а не "вообще".
Считаю инцидент исчерпанным.
Да, это верно, у меня не достаточно логики, чтобы понять, каким именно образом компилятор может догадаться, как ему нужно модифицировать операцию сравнения в зависимости от полученного значения. Мне казалось, что для беззнакового типа будет сформирована команда BRSH, а для знакового - BGE независимо от количества единиц в результате вычитания и почему то используемый мною компилятор так и делает. Значит, мы оба неправы, но если относительно меня данное предположение вполне может быть справедливо, то относительно компилятора - это сильное утверждение, требующее доказательств.
Я догадывался, что Вы не поймете своей ошибки, и рад, что не ошибся. Если Вы сможете внятно объяснить, каким именно образом 23 строка спасет Вас в случае, когда заказан интервал 127 единиц, сравнение равенства пропущено из за внешней задержки и Вы начинаете выполнять ветвь (127>0) && (-1>=127) и получаете верный результат, то Вы меня очень обяжете.
Оказывается, это я продемонстрировал незнание арифметики, как интересно. Боюсь, что с человеком, искренне считающим, что -1>=127 при знаковом сравнении, разговаривать особо не о чем.
Мощная реплика, правда на вопрос не отвечает, но ведь это и не важно. Наверное, у меня и у Вас разные компиляторы, тогда дальше разговор становится слегка бессмысленным.
Да, это верно, у меня не достаточно логики, чтобы понять, каким именно образом компилятор может догадаться, как ему нужно модифицировать операцию сравнения в зависимости от полученного значения. Мне казалось, что для беззнакового типа будет сформирована команда BRSH, а для знакового - BGE независимо от количества единиц в результате вычитания и почему то используемый мною компилятор так и делает. Значит, мы оба неправы, но если относительно меня данное предположение вполне может быть справедливо, то относительно компилятора - это сильное утверждение, требующее доказательств.
надоело с упоротым спорить... уже компиллятор у него типы переменных изменяет в зависимости от действий с этими переменными.
Надоело спорить с упоротым, у которого компилятор изменяет типы переменных в зависимости от полученных значений - К&R для понимания.
Надоело спорить с упоротым, у которого компилятор изменяет типы переменных в зависимости от полученных значений - К&R для понимания.
ну, хватит уже...
формула (Текущее-Начальное)>Задержка содержит три переменных: Текущее, Начальное, Задержка.
по какой причине компиллятор должен изменить своё мнение о типе этих переменных, если ты явно в коде указал тип этих переменных?
Никогда я не был столь низкого мнения о своих умственных способностях, как в эти 10 минут. Как же так я очевидно вижу ошибку, понимаю причину ее возникновения и методы устранения и вдруг оказывается, что все это мираж и я не понимаю как работает компилятор языка С. Ведь человек, которому я на ошибку указал, проверил свою программу и убедился в том, что я не прав и никакой ошибки нет. Конечно же, я не тестировал его программу и мое предсталение о наличии ошибки было вызвано исключительно моим пониманием и мысленным экспериментом. Неужели старческий маразм наступил столь неожиданно, ведь вроде ничего не предвещало ... а до пенсии еще далеко и чем я буду зарабатывать на жизнь? Ведь я подробно разъяснил, в чем проблема, причем два раза, ведь не мог мой оппонент просто не понять о чем речь.
Но, собрав всю волю в кулак, решаюсь убедиться в своей умственной неполноценности, переношу предложенный скетч в транслятор и запускаю и ... о ужас ... все действительно работает, хотя я продолжаю считать, что работать не должно. На последних силах начинаю смотреть код и ... забрезжила надежда. Автор почему то дайствительно НИЧЕГО не понял из моих указаний на ошибку и проверяет СОВСЕМ не то, что надо. Слегка модифицируем код и обнаруживаем, что прав таки я и ошибка имеет место быть. Для этого достаточно модифицировать действия запрещенной а РФ организации и в строке 25 поставить
if (currentMillis !=127) { ...
и все становится на свои места. Строку 23 можно и оставить, пропуск срабатывания таймера не влияе ни на что, то есть совсем. Проведение эксперимента оставляем заинтересованному читателю.
Ну и теперь немного выводов:
Смешной Вы парень. Вы бы хоть попробовали запустить мой код с этим интервалом! - нет, не пробовал, грешен.
Ну, ведь я Вам говорю - там трюк-фокус, Вы его не понимаете. - ну не дано мне понимание, как -1 станет >=127 для int8_t.
Ну, вот честное слово, на Вашем месте, прежде чем постить такой пост, я бы проверил, а вдруг там и впрямь фокус, чем чёрт не шутит. - я верю в математику, иногда излишне, но не в таком случае
Проверил бы просто на всякий случай, чтобы не сесть в лужу. - ну верю я в математику.
Но Вы, похоже, любите там сидеть. - оставим без комментариев, Вам виднее
Что, ж извольте заплатить за излишнюю самоуверенность ... - итак, карты на стол, у меня флэш рояль, у Вас что?
Вы согласны с тем, что правильный результат получен? - НЕТ
Вы согласны с тем, что это тот самый скетч, что был опубликован ранее, и я не жульничаю? - ДА
Я Вас уже обязал? Или пока ещё не очень? - НЕТ
А вот что касается первой части Вашей просьбы - "внятно объяснить" - увольте. - увольняю, нельзя объяснить необъяснимое. Заниматься Вашим обучением я готов только на коммерческой основе. - бесконечно благодарен, но воздержусь.
Я и так уже подсказал Вам в какой именно строке фокус, разумному достаточно - сам разберётся. - именно в ней, о как.
Но Вы, в своей самоуверенности, даже не потрудились проверить как оно работает. - да я положился на свой разум, рад, что он меня не подвел.
Нам с Вами действительно не особо есть о чём разговаривать, т.к. мы в разных весовых категориях. - согласен.
У нас разный уровень знаний и понимания. - совершенно согласен.
Надеюсь, сейчас-то Вы уже согласны с этим? - я уже согласился, но сделаю это еще раз.
А с людьми, которые всё знают я как-то стараюсь дискутировать поменьше. - и правильно делаете, как показал этот несложный пример.
То есть Вы сделали рекомендованные мною исправления с целью продемонстрировать ошибку и у Вас по прежнему все работает?
Я то, устыженный Вашими поучениями, это сделал, чтобы не "сесть в лужу" и так далее по тексту. А Вы это сделали? У меня сильное подозрение, что нет.
Если да, ну значит, у нас разные компиляторы, разные языки С и разные вселенные. В Вашей условие ((127>0) && (-1>127)) может сработать если тремя строками выше применить хитрый фокус-покус, в моей это условие не срабатывает никогда, от слова совсем. Хотя, может быть в Вашей вселенной при определенных условиях может сработать (127<0) && (dd>=0) если dd посчитать некоторым хитрым способом, у меня так не получается.
"Вы, знаете, просто признать свою ошибку - это совсем не стыдно и не плохо. А вот вертеться, как Вы это делаете ... не знаю, ну если Вам нравится быть посмешищем...." - золотые слова, жаль что не по адресу, так что не "прекращайте юродствовать".
В общем, мне это надоело. Я потёр свои посты и прекращаю эту дискуссию. Всего хорошего!
"Вы, знаете, просто признать свою ошибку - это совсем не стыдно и не плохо. А вот вертеться, как Вы это делаете ... не знаю, ну если Вам нравится быть посмешищем...." - золотые слова, жаль что не по адресу, так что не "прекращайте юродствовать".
так, признай факт того, что ты одеваешь сову на глобус.
millis() возвращает Количество миллисекунд с момента начала выполнения программы. (unsigned long)
каким здесь боком знаковые типы переменных?
то, что тебе пытались объяснить, что если очень нужно, то можно делать трюки с типами переменных, но объясни каким боком здесь millis() ?
"Я потёр свои посты и прекращаю эту дискуссию" - интересный способ признать свою ошибку, жаль, что Вы прибегнули именно к такому.
Скорее ЕвгенийП осознал свою ошибку. Надо было прямо вам сказать- Мне не интересует мнение первоклассника о таблице умножения. Вот он на вас потратил очень много времени. И это было его ошибкой.
"Я потёр свои посты и прекращаю эту дискуссию" - интересный способ признать свою ошибку, жаль, что Вы прибегнули именно к такому.
ты лучше объясни читателям темы, зачем ты набредил про знаковые переменные, придумал проблему и всех победил в войне с несуществующим врагом?
К сожалению, не будет все в порядке. Приходится из беззнакового переводить в знаковый и там вычитать, тогда основная проблема исчезает.
как может исчезнуть то, чего нет?
Надеюсь, Вы спросили именно для того, чтобы получить ответ.
Объясняю еще раз. Да, Вы совершенно правы, millis() возвращет тип unsigned long. Используя этот факт, мы можем ждать окончание задержки так, как это принять в Ардуино, то есть запомнить начало отсчета и ждать выполнения условия
(millis()-Начало)>=Задержка
При этом все работает из коробки, никаких других типов не надо, все переменные типа unsigned long, не нужно учитывать переполнение, все хорошо.
Но для вычислений по этой формуле Вам надо знать 2 переменные - Начало и Задержка. Если у вас каждый модуль работает только за себя, то он их знает по умолчанию. Но в Unix системах приняты очереди таймеров (так они называют задержки), когда Вы заказываете задержку и назначаете функцию обработки, которая будет вызвана в свое время. Кстати, такой способ можно реализовать и в Ардуино, и иногда он может быть удобным. При указанном способе ожидания задержки Вам придется хранить 2 переменные в очереди задержек - это и есть недостаток данного способа. Поэтому здесь принят другой способ хранения информации о требуемом моменте времени, а именно при запуске задержки вычисляется unsigned long Окончание=millis()+Задержка и условие изменяется
(millis()-Окончание)>0, но для беззнакового типа данное выражение бессмысленно, поскольку любое беззнековое число больше нуля, и мы вынуждены сделать приведение
((long)millis()-(long)Окончание)>0. Здесь тоже все работает и можно не беспокоиться о переполнениях, но, если внимательно проанализировать, мы не можем заказать интервал более половины диапазона, потому что он отработается мгновенно. При этом, как Вы видите, мы по прежнему используем millis() с его возвращаемым типом, но для нашего удобства явно его приводим.
Достоинство этого метода, что нам нужно хранить только одно значение для каждого таймера в очереди, проще сортировать их по возрастанию, и сама проверка становится проще и быстрее, поскольку приведение типов в данном случае на стоит ничего на этапе исполнения.