Перетягивание каната arduino. 14 светодиодов.

Тема в разделе "Arduino & Shields", создана пользователем mono, 16 мар 2022.

Метки:
  1. mono

    mono Нуб

    Нужна помощь с кодом для 14-ти светодиодов. Чтобы каждый последующий загорался только после 4-х нажатий.

    Схема:
    [​IMG]
    Код:
    Код (C++):
    #define BUZZER_PIN 0
    #define FIRST_BAR_PIN 4
    #define BAR_COUNT 14
    #define MAX_SCORE 20
    volatile int score = 0;

    void pushP1() { ++score; }
    void pushP2() { --score; }

    void setup()
    {
        for (int i = 0; i < BAR_COUNT; ++i)
               pinMode(i + FIRST_BAR_PIN, OUTPUT);
     
           pinMode(BUZZER_PIN, OUTPUT);
        attachInterrupt(INT1, pushP1, FALLING);
        attachInterrupt(INT0, pushP2, FALLING);
        Serial.begin(9600);
    }

    void loop()
    {
          int bound;
          int left;
          int right;
     
        tone(BUZZER_PIN, 400, 100);
     
        while (abs(score) < MAX_SCORE) {
            bound = map(score, -MAX_SCORE, MAX_SCORE, 0, BAR_COUNT);
               left = min(bound, BAR_COUNT / 2 - 1);
            right = max(bound, BAR_COUNT / 2);
         
               
              Serial.println(left);
             Serial.println(right);
         
            for (int i = 0; i < BAR_COUNT; ++i)
                   digitalWrite(i + FIRST_BAR_PIN, i >= left && i <= right);
        }

        tone(BUZZER_PIN, 4000, 1000);
        while (true) {}
    }
     
  2. User248

    User248 Нерд

    Похоже, в симуляторе Tinkercad не работают внешние прерывания. Предлагаю такой вариант.

    tug of war - circuit.png

    Код (C++):

    /**************
      Tug of War
    **************/


    #define BUZZER_PIN 0
    #define NUM_LEDS 5 // number of leds
    #define PIN_OFFSET 2
    #define NUM_CLICKS 4 // number of clicks

    enum controls
    {
      kLeft = 0,
      kRight,

      kNum
    };
    uint8_t button[kNum] = {15, 14}; // Left and Right pins

    bool swOn[kNum], end = false;
    int counter[kNum];
    int n = NUM_LEDS / 2., n_old = -1;

    void setup()
    {
      for (int i = 0; i < NUM_LEDS; i++)
        pinMode(i + PIN_OFFSET, OUTPUT);

      for (int i = 0; i < kNum; i++)
      {
        swOn[i] = false;
        counter[i] = 0;
        pinMode(button[i], INPUT_PULLUP);
      }

      pinMode(BUZZER_PIN, OUTPUT);
      tone(BUZZER_PIN, 400, 100);
    }

    void reset()
    {
      for (int i = 0; i < kNum; i++) counter[i] = 0;
    }

    void loop()
    {
      // switches
      for (int i = 0; i < kNum; i++)
      {
        bool butt = digitalRead (button[i]);
        // trigger
        if (butt == 0 && !swOn[i])
        {
          swOn[i] = true;
          // buttons action
          if (i == kRight) counter[kRight]++;
          if (i == kLeft) counter[kLeft]++;
        }
        if (butt == 1 && swOn[i]) swOn[i] = false;
      }

      if (n > 0 && n < (NUM_LEDS - 1))
      {
        if (counter[kRight] >= NUM_CLICKS)
        {
          //n < (NUM_LEDS - 1) ? n++ : n = 0; // loop
          n++;
          reset();
        }
        if (counter[kLeft] >= NUM_CLICKS)
        {
          //n > 0 ? n-- : n = NUM_LEDS - 1; // loop
          n--;
          reset();
        }
      }
      else if (!end)
      {
        tone(BUZZER_PIN, 4000, 1000);
        end = true;
      }

      if (n_old != n)
      {
        digitalWrite(n_old + PIN_OFFSET, LOW);
        digitalWrite(n + PIN_OFFSET, HIGH);
        n_old = n;
      }
    }
     
     
    Последнее редактирование: 20 мар 2022
  3. Ariadna-on-Line

    Ariadna-on-Line Гуру

    1. Не буду соваться в код, но в схеме на рисунке - ошибки. Например крайний левый резистор внизу - обоими концами на минусе. СпАлите пин A3.
    2. В прерываниях получаете значения, а в цикле используйте не значения, а целое от деления значения на 4.
    X1 = int (X/4);
    Как-то так.
     
    Последнее редактирование: 20 мар 2022
  4. b707

    b707 Гуру

    похоже что кто-то просто не в курсе, что у Уно на ногах А0 А1 нет никаких "внешних прерываний"
     
  5. Ariadna-on-Line

    Ariadna-on-Line Гуру

    У ТСа кнопки на 2 и 3 пинах. Там есть прерывания. А у Юзера248 в коде не задействованы прерывания, если мне очки не врут.
     
  6. User248

    User248 Нерд

    Ariadna-on-Line, всё так. Внешние прерывания я проверял на D2 и D3 - не работают. Или на них сигнал как-то особенно нужно подавать?
     
  7. SergeiL

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

    А зачем "2." ? Почему не просто "2" ?
    Код (C++):
    int n = NUM_LEDS / 2., n_old = -1;
    Дребезг не устраняется? Тут он может сильно подпортить.
     
  8. User248

    User248 Нерд

    Ошибся. Прерывания в Tinkercad работают. Просто, в случае кнопки, нужно делать подтяжку резистором. Иначе не работает.
     
  9. User248

    User248 Нерд

    На всякий случай. Там дробное число требуется в результате, а потом округлить.
     
  10. b707

    b707 Гуру

    удивительно. правда? :)
     
  11. User248

    User248 Нерд

    Когда я изучал эту тему, нашёл пример, в котором нет ни слова о подтяжке. Какой смысл в примере ТС городить лишнюю микросхему, если можно поставить кнопку с подтяжкой?
     
  12. SergeiL

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

    А я подтяжку почти никогда не ставил, использую всегда pull up, и не замечал, что что то не так работает :)
     
    Feofan, DetSimen и Ariadna-on-Line нравится это.
  13. b707

    b707 Гуру

    судя по типу результата int никакое "дробное число" там не требуется :)
     
    SergeiL нравится это.
  14. User248

    User248 Нерд

    Ну я же по русски написал, что сначала нужно получить дробное число, а потом округлить. Чтобы компилятор не стал делить целое, я сделал ему намёк в виде "2."
     
  15. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Это правильно ?
    attachInterrupt(INT1, pushP1, FALLING);
    attachInterrupt(INT0, pushP2, FALLING);
    ???
    Может правильно так -
    attachInterrupt(2, pushP1, FALLING);
    attachInterrupt(3, pushP1, FALLING);

    Да и сконфигурировать пины как входы надо, иначе в тандеме с мостовыми выходами микры спалятся и пины и микра. А для совсем гарантии - надо микру с пинами через 100-омные резисторы соединять. Береженого бог... как известно.
    ПС. Зачем здесь микра только ТСу известно.
     
    Последнее редактирование: 21 мар 2022
  16. b707

    b707 Гуру

    а есть разница - сразу поделить в целых числах или поделить в дробных, а потом взять целую часть?
    Точнее разница-то есть - второй вариант ощутимо медленнее и требует больше кода, если только оптимизатор не выкинет ваш запрос на вещественное деление.
    Но в смысле результата - одинаково.
     
  17. User248

    User248 Нерд

    Правильно. Можно и так:
    Код (C++):
    attachInterrupt(1, pushP1, FALLING);
    attachInterrupt(0, pushP2, FALLING);
     
  18. SergeiL

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

    В данном конкретном случае дело даже до кода не дойдет.
    Константа будет получена на этапе работы препроцессора. Причем целочисленная.
     
    Feofan, DetSimen и b707 нравится это.
  19. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Под нулем и единицей здесь заданы номера прерываний или пины ? Может быть номера прерываний, но я такого в справочнике не видел. На пинах 0,1 прерываний нет. В справочнике многократно указано что именно номера пинов должны стоять. Но ХЗ - не спорю.
     
    Последнее редактирование: 21 мар 2022
  20. b707

    b707 Гуру

    номера прерываний
    если хотите через номера пинов, то надо так:
    Код (C++):
    attachInterrupt(digitalPinToInterrupt(3), pushP1, FALLING);
    attachInterrupt(digitalPinToInterrupt(2), pushP2, FALLING);
     
    Feofan, DetSimen, User248 и ещё 1-му нравится это.