код для КНОПОК - помогите разобраться

Тема в разделе "Микроконтроллеры AVR", создана пользователем Alexandro77, 26 сен 2019.

Метки:
  1. Daniil

    Daniil Гуру

    Как у вас тут весело)
    На вопрос "может ли", задающий должен понимать, что речь идёт про вероятность, а все мы понимаем, что вероятность события стремится к 1, при пределе когда время стремится к бесконечности, поэтому может быть все (гуглить тервер).
    При ЭМИ ЯВ залипнет все.
    какая цель у этой учебной задачи? Если печатать буковки, то так себе. Если продумать алгоритм на абстрактном устройстве то норм. Но при его использовании в реальности будут проблемы, задача звучит незавершенной без реальных ограничений.
    Причем вы постите код к на форум, где сталкиваются с прикладными задачи.
    Ваши отклонения от темы, типа "может ли код зависнуть вообще" проигнорированы, т.к. код приводите для ардуино. Т.е. никто и не рассматривает ваш код как алгоритмическую задачу.
     
    Последнее редактирование: 20 ноя 2019
    Andrey12 нравится это.
  2. b707

    b707 Гуру

    Вы даже не понимаете, насколько верно это замечание. Или понимаете?
    На самом деле не успел поправить, ответ на второй вопрос тоже "да". только вероятность этого события крайне мала.
    В отличие от варианта, описанного в первом вопросе. где такое будет происходить сплошь и рядом...

    В обоих случаях причина этого - то что миллис целое число и вычисляется округлением.
     
    Andrey12 нравится это.
  3. offigate

    offigate Нерд

    Вот прям-таки нельзя? Никогда-никогда? Вот это, значит, тоже не будет работать?
    Код (C++):
    void loop(void)
    {
      unsigned long currMillis = millis();
      if ((currMillis >= button.ts) || (currMillis < 10))
      {
        button.ts += 10; // +10 мс
        button.shreg <<= 1;
        if (digitalRead(pinButton)) // читаем пин
          button.shreg |= 1;
        if (button.shreg == 0)
          button.pressed = false; // все нули, кнопка отжата
        if (button.shreg == 0xFF)
          button.pressed = true; // все единицы, кнопка нажата
      }
    }
     
  4. b707

    b707 Гуру

    не вижу разницы с предыдущим кодом. если честно. Может слепой...
    Все, что написано про тот код - относится и к этому
     
  5. offigate

    offigate Нерд

    Угу. Однако округляется-то 1.024 мс, то есть, четное число. Какие там получатся "биения" с millis(), я лично сходу не решусь сказать. Именно это причина, по которой я не знаю точного ответа на оба вопроса. Думаю, что за счет этого скорей всего ответы "нет" и "нет", но не уверен.
     
  6. Asper Daffy

    Asper Daffy Иксперд

    Ну, если тебе недостаточно, что он глючит в момент переполнения, а нужно ещё и чтобы "навечно" завис, давай конкретизировать.

    Ты говоришь о конкретно, точно этом коде или о таком методе работы с интервалами? Если второе, то запросто проскочит мимо твоего условия - вообще без вопросов. Достаточно в сетапе что-нибудь проинициализировать, чтобы такая инициализация заняла 1 мс (а лучше - 5) и от чётности и следа не останется.
     
    Andrey12 нравится это.
  7. offigate

    offigate Нерд

    Во-первых, интервал всегда 10 мс, стабильный (с джиттером, конечно). Во-вторых, залипания не будет. Правда, проскакивание осталось.
     
  8. Asper Daffy

    Asper Daffy Иксперд

    Не, ну почему, делай, я не запрещаю, но стабильных интервалов не получится.
    Работать будет любая программа. Другое дело. что будет делать. Если нужны интервалы в 10мс, то таким образом их не получить. Хотя бы в самом начале (в первые 10мс) уже будут какие попало
     
    Andrey12 нравится это.
  9. b707

    b707 Гуру

    округляется 1024 мкс до 1мс, поэтому с некоторой (немалой) вероятностью два соседних вызова millis() вернут числа. отличающиеся не на один, а на два. Так ваши четные значения button.ts превратятся в нечетные. Это ответ на первый вопрос.

    А для получения "да" во втором вопросе нужно чтобы этот "проскок" значений миллис попал на значение 0xfffffffe
     
    Andrey12 нравится это.
  10. akl

    akl Гуру

    работать будет, но не более того (с) :D
     
    Andrey12 и Daniil нравится это.
  11. Asper Daffy

    Asper Daffy Иксперд

    Да, неужели? В первые 10мс (пока миллис меньше 10) тоже стабильный интервал в 10мс? Или может в каждом проходе loop будет "интервал" выдавать? И точно также после каждого переполнения. Давайте уже прекратим бредить.
     
    Последнее редактирование: 20 ноя 2019
    Andrey12 нравится это.
  12. offigate

    offigate Нерд

    В середине диапазона это случается много раз. Но речь-то о вполне конкретном значении millis() = 0xFFFFFFF5 . Получится ли - на это ответ неочевиден.
     
  13. offigate

    offigate Нерд

    Ага. Будет в среднем стабильный интервал 10 мс, за исключением проскакивания в самом конце. В отличие от первого варианта, где за счет внешних задержек интервал в среднем будет больше, чем 10 мс. Насчет того, чтобы прекратить бредить - у меня нет возражений, прекращайте.
     
    Последнее редактирование: 20 ноя 2019
  14. Asper Daffy

    Asper Daffy Иксперд

    Т.е. ты смотришь на этот код
    Код (C++):
    unsigned long currMillis = millis();
      if ((currMillis >= button.ts) || (currMillis < 10)) {
           ...........
      }
    и на голубом глазу утверждаешь, что в самом начале (а также, после каждого переполнения), пока millis() ещё меньше 10, он не будет исполнять внутренность if при каждом проходе loop?

    Мужики, или нас жёстко троллят, или человек просто не понимает, что написано в этих строках.

    По-моему, пора расходится, ибо

     
    Последнее редактирование: 20 ноя 2019
    Andrey12 и DetSimen нравится это.
  15. Unixon

    Unixon Оракул Модератор

    Код (C++):

    uint32_t timePassed(uint32_t t1, uint32_t t2)
    {
    if (t2>=t1) return t2-t1;
    else return ((1<<(8*sizeof(t1)) - 1) - t1) + t2;
    }
     
    На один раз хватит, а потом опять...
     
    ИгорьК нравится это.
  16. SergeiL

    SergeiL Оракул Модератор

    Спасибо! :(
     
  17. Unixon

    Unixon Оракул Модератор

    Можно еще так
    Код (C++):

    uint32_t super_millis = 0;

    uint32_t timePassed(uint32_t t1, uint32_t t2)
    {
    if (t2>=t1) return t2-t1;
    else
    {
      super_millis++;
      return ((1<<(8*sizeof(t1)) - 1) - t1) + t2;
     }
    }
     
    Но это тоже баловство, нужно честный длинный таймер в прерывание вешать.
     
    ИгорьК нравится это.
  18. Asper Daffy

    Asper Daffy Иксперд

    1. Компилятор испредупреждался весь на выражение "((1<<(8*sizeof(t1)) - 1) - t1) + t2;"

    2. Чем это отличается от вот такого?
    Код (C++):
    uint32_t tp(uint32_t t1, uint32_t t2) { return t2-t1; }
     
    b707 нравится это.
  19. Unixon

    Unixon Оракул Модератор

    Попробуйте так:
    Код (C++):
    (((1ULL<<(8*sizeof(t1))) - 1) - t1) + t2
    Корректным результатом, если t2<t1 из-за переполнения uint32_t.
     
  20. Unixon

    Unixon Оракул Модератор

    Если счетчик перекрутился через максимум, то реальное прошедшее время это не t2-t1, а (MAX_MILLIS-t1) + t2. т.е. сколько оставалось до переполнения (MAX_MILLIS-t1) + cколько прошло после переполнения (t2-0).

    Код (C++):
    (((1ULL<<(8*sizeof(t1))) - 1)
    - это максимальное значение беззнакового целого (MAX_MILLIS). Можно было написать так:
    Код (C++):
    (((1ULL<<(8*sizeof(uint32_t))) - 1)
    но это было бы верно только для uint32_t.
    Если millis dсегда останется 32битным, тогда можно и вовсе написать
    Код (C++):
    #define MAX_MILLIS 0xFFFFFFFFUL
     
    Последнее редактирование: 21 ноя 2019