Работа с кнопкой

Тема в разделе "Arduino & Shields", создана пользователем Baltika-9, 3 дек 2019.

  1. Daniil

    Daniil Гуру

    Да напишите уже, что хотите чтобы вам написали код. Все сразу отправят вас в "закажу проект", престанут флудить и будут ждать когда объявится альтруистичный рыцарь.
     
    Последнее редактирование: 10 апр 2020
  2. jr.Bush

    jr.Bush Нерд

    Код мне не нужен,
    Я спросил как поймать нажатие кнопки,
    Мне ответили, что нужно больше учить и заниматься программированием, с нуля писать правильный код.
    Если я научусь правильно писать код у меня Не останутся вопросы по работе с кнопкой,
     
  3. Daniil

    Daniil Гуру

    вы не на том акцентируете свое внимание
     
  4. akl

    akl Гуру

    поймать то можно по прерыванию или по таймеру. но как уже раньше написали - надо его еще и обработать, а если цикл занимает кучу времени, то толку будет немного
     
  5. b707

    b707 Гуру

    разве это плохо? :) - по мне так двойной выигрыш - и проблему решите, и новому научитесь

    А насчет прерываний... Поскольку Вы нам не верите - проведите эксперимент, посадите кнопку на прерывание.
    Вы переживаете, что у вас не хватит прерываний на все кнопки - так сделайте для начала только одну..
    Мой опыт говорит мне, что вам это никак не поможет убыстрить отклик на нажатие - но вдруг я ошибаюсь.
    Пробуйте. тестируйте, это же интересно...
     
  6. parovoZZ

    parovoZZ Гуру

    Опрос кнопок по таймеру. 50 раз в секунду достаточно.
     
  7. jr.Bush

    jr.Bush Нерд

    Спасибо
     
  8. jr.Bush

    jr.Bush Нерд

    Я не могу использовать аппаратные прерывания, так как даже если будет работать то на примере одной кнопки у меня их 7+датчики, это направление значит не подходит.
    Остается прерывание/опрос по таймеру,
    Значит буду капать в этом направлении и удивительно что этой функции нет в библиотеках работы с кнопками, в которых основной упор делается на дребезг, но он устраняется тем же таймером.
    Я считаю что если код компилируется и выполняет свои функции значит он написан правильно, и не стоит вгонять нубов в рамки которые вы себе установили, не существует правил которые определяют время выполнения кода, я указал что код длится 150мс это по моим личным ощущениям а как вы определили, что он длится больше 10мс?
     
  9. jr.Bush

    jr.Bush Нерд

    Есть ли смысл использовать такой подход если код будет длиться менее 20мс?
     
  10. b707

    b707 Гуру

    чтоб еще больше вас запутать - даже в Уно аппаратные прерывания есть на всех пинах. А у вас. как я вижу. Мега...
    а вам не приходит в голову. что если в стольких библиотеках работы с кнопками нет опроса по таймеру - тут что-то не так? может он и не нужен. если все обходятся без него?
     
  11. parovoZZ

    parovoZZ Гуру

    там прерывание даёт регистр порта, а не отдельный пин.

    это всё от того, что создатели ардруины не предусмотрели такую возможность. К тому же опрос матричной клавиатуры возможен только по таймеру.
     
  12. b707

    b707 Гуру

    чей-та? Кто тебе запрещает в ардуине опрашивать кнопки по таймеру? - да опрашивай запросто.
    Другой вопрос. что проблемы ТС это не решит,
     
  13. b707

    b707 Гуру

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

    Учиться писать хороший код вы отказались - это вас не ведет к решению :) Аппаратные прерывания отмели, ибо "их все равно мало".


    Даже если аппаратные прерывания вам в итоге не подойдут - пробуя их вы бы многому научились. Путь обучения - это пробовать разные варианты и сравнивать. А так даже если вы и соберете свою поделку кое-как - все равно останетесь неучем.
     
  14. jr.Bush

    jr.Bush Нерд

    https://tsibrov.blogspot.com/2019/05/arduino-interrupts-part1.html
    я же не сам придумываю.
     
  15. b707

    b707 Гуру

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

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

    Так а что нужно то?
    Я делаю так:
    Код (C++):
    #define PIN_READ_TO 10L   // 10 ms  периодичность проверки входов. Оптимальным является интервал 5-10мс. соответственно в результате сигнал о нажатии будет получен через 20-40мс  (в данном случае 40мс)
    #define PIN_IN_NUMB 4     // количество используемых входов значение от 1 до 8.


    //------------------ ФУНКЦИЯ УСТР. ДРЕБЕЗГА --------------------------------------
    // Глобальные переменные

    // биты в байтах ниже взводятся обработчике дребезга, можно в в прерывании от таймера и сбрасываются программой обработчиком событий
    byte LATCH_ON   = 0;     // вход перешел в 1
    //byte LATCH_OFF  = 0;     // вход вернулся в 0

    uint8_t vc_debounce(uint8_t SWKEYS)        // Verical_Couners_debounce, вызывается каждые 10 мсек, можно из таймера
    {                                          // в SWKEYS состояние вводов
        static uint8_t SLATCH = 0;             // текущее устоявшееся значение входов после устранения дребезга
        static uint8_t VCBIT0 = 0;             // счетчик бит 0
        static uint8_t VCBIT1 = 0;             // счетчик бит 1
        uint8_t        vcmask = 0;             // Маска
        uint8_t        vctemp = 0;             //
        vcmask = SWKEYS ^ SLATCH;              // скинем счетчики для установившихся и неактивных значений
        VCBIT0 &= vcmask;
        VCBIT1 &= vcmask;
                                                      //  Каждая '1' в SLATCH представляет установившееся значение  
                                                      //  каждый '0' установившееся нулевое значение                
        SLATCH ^= (vctemp = vcmask & VCBIT0 & VCBIT1);

        if( vctemp )                                  // есть изменения входов, взведем флаги
      {
         LATCH_ON  |= vctemp &  SWKEYS;               // взведем биты нажатых кнопок и сработавших входов.
    //     LATCH_OFF |= vctemp & ~SWKEYS;               // Биты сбрасываются в обработчиках.
      }
       
        VCBIT1 ^= (vcmask & VCBIT0);                   // инкрементируем счетчик.
        VCBIT0 ^= (vcmask);
    }

    void setup()
    {
        DDRC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)); //A0 A1 A2 A3 вход
    }


    void Input_On(byte number)
    {
        // выполним действие по нажатию на кнопку.  номер кнопку в переменной "number"
    }
    /*
    void Input_Off(byte number)
    {
    // ЕСЛИ НУЖНО! выполним действие по отпусканию кнопки.  номер кнопку в переменной "number"
    }

    */

    void loop()
    {
       static uint32_t    LastPinReadMs = 0 ;      // переменная для сохранения времени, когда были считаны значения с цифорвых входов
       uint8_t            current_state;           // переменная для текущего состояние по кнопкам

       byte j,i;
     
       if ((millis() - LastPinReadMs) > PIN_READ_TO)          // выполняется каждые 10мс (PIN_READ_TO)
       {   //-----------------------
          current_state= PINC & ((1<<0)|(1<<1)|(1<<2)|(1<<3));  // читаем значение
          vc_debounce(current_state);                         //  2) отбросим дребезг по всем входам, на основании предыдущих проверок (игнорируем состояния, держащиеся на входе менее 4 проверок подряд)
          LastPinReadMs = millis();                           // запомним время
       
    //      if (LATCH_ON != 0 || LATCH_OFF != 0  )          // Если есть изменения на входах - обработаем.
          if (LATCH_ON != 0   )          // Если есть изменения на входах - обработаем.
          {  
            for (i=1,j=0; j < PIN_IN_NUMB; j++,i=i<<1)   // пробежимся по всем входам
            {
              if (LATCH_ON & i)                          // Если копка была нажата или вход перешел в ON
              {
                Input_On(j);
                LATCH_ON &= ~i;                          // Обязательно сбросим бит, так как данное событие обработано
              }
    /*      
              if (LATCH_OFF & i)                         // Если копка была отпущена или вход перешел в OFF  ЕСЛИ НУЖНО.
              {
                Input_Off(j);
                LATCH_OFF &= ~i;                         // Обязательно сбросим бит, так как данное событие обработано
              }
    */
           
            }
         }
       } //  ---------------------


      //   ваш код....
     
    }
     
  17. parovoZZ

    parovoZZ Гуру

    какой механизм для этого предусмотрен?
     
  18. SergeiL

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

    таймер
     
  19. parovoZZ

    parovoZZ Гуру

    вот прерывания для attiny841
    Код (C++):

    /* Interrupt vectors */
    /* Vector 0 is the reset vector */
    /* External Interrupt Request 0 */
    #define INT0_vect            _VECTOR(1)
    #define INT0_vect_num        1

    /* Pin Change Interrupt Request 0 */
    #define PCINT0_vect            _VECTOR(2)
    #define PCINT0_vect_num        2

    /* Pin Change Interrupt Request 1 */
    #define PCINT1_vect            _VECTOR(3)
    #define PCINT1_vect_num        3

    /* Watchdog Time-out Interrupt */
    #define WDT_vect            _VECTOR(4)
    #define WDT_vect_num        4

    /* Timer/Counter1 Capture Event */
    #define TIMER1_CAPT_vect            _VECTOR(5)
    #define TIMER1_CAPT_vect_num        5

    /* Timer/Counter1 Compare Match A */
    #define TIMER1_COMPA_vect            _VECTOR(6)
    #define TIMER1_COMPA_vect_num        6

    /* Timer/Counter1 Compare Match B */
    #define TIMER1_COMPB_vect            _VECTOR(7)
    #define TIMER1_COMPB_vect_num        7

    /* Timer/Counter1 Overflow */
    #define TIMER1_OVF_vect            _VECTOR(8)
    #define TIMER1_OVF_vect_num        8

    /* TimerCounter0 Compare Match A */
    #define TIMER0_COMPA_vect            _VECTOR(9)
    #define TIMER0_COMPA_vect_num        9

    /* TimerCounter0 Compare Match B */
    #define TIMER0_COMPB_vect            _VECTOR(10)
    #define TIMER0_COMPB_vect_num        10

    /* Timer/Couner0 Overflow */
    #define TIMER0_OVF_vect            _VECTOR(11)
    #define TIMER0_OVF_vect_num        11

    /* Analog Comparator 0 */
    #define ANA_COMP0_vect            _VECTOR(12)
    #define ANA_COMP0_vect_num        12

    /* ADC Conversion Complete */
    #define ADC_vect            _VECTOR(13)
    #define ADC_vect_num        13

    /* EEPROM Ready */
    #define EE_RDY_vect            _VECTOR(14)
    #define EE_RDY_vect_num        14

    /* Analog Comparator 1 */
    #define ANA_COMP1_vect            _VECTOR(15)
    #define ANA_COMP1_vect_num        15

    /* Timer/Counter2 Capture Event */
    #define TIMER2_CAPT_vect            _VECTOR(16)
    #define TIMER2_CAPT_vect_num        16

    /* Timer/Counter2 Compare Match A */
    #define TIMER2_COMPA_vect            _VECTOR(17)
    #define TIMER2_COMPA_vect_num        17

    /* Timer/Counter2 Compare Match B */
    #define TIMER2_COMPB_vect            _VECTOR(18)
    #define TIMER2_COMPB_vect_num        18

    /* Timer/Counter2 Overflow */
    #define TIMER2_OVF_vect            _VECTOR(19)
    #define TIMER2_OVF_vect_num        19

    /* Serial Peripheral Interface */
    #define SPI_vect            _VECTOR(20)
    #define SPI_vect_num        20

    /* USART0, Start */
    #define USART0_START_vect            _VECTOR(21)
    #define USART0_START_vect_num        21

    /* USART0, Rx Complete */
    #define USART0_RX_vect            _VECTOR(22)
    #define USART0_RX_vect_num        22

    /* USART0 Data Register Empty */
    #define USART0_UDRE_vect            _VECTOR(23)
    #define USART0_UDRE_vect_num        23

    /* USART0, Tx Complete */
    #define USART0_TX_vect            _VECTOR(24)
    #define USART0_TX_vect_num        24

    /* USART1, Start */
    #define USART1_START_vect            _VECTOR(25)
    #define USART1_START_vect_num        25

    /* USART1, Rx Complete */
    #define USART1_RX_vect            _VECTOR(26)
    #define USART1_RX_vect_num        26

    /* USART1 Data Register Empty */
    #define USART1_UDRE_vect            _VECTOR(27)
    #define USART1_UDRE_vect_num        27

    /* USART1, Tx Complete */
    #define USART1_TX_vect            _VECTOR(28)
    #define USART1_TX_vect_num        28

    /* Two-wire Serial Interface */
    #define TWI_SLAVE_vect            _VECTOR(29)
    #define TWI_SLAVE_vect_num        29
     
  20. SergeiL

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

    Это из учебника?