Как стабилизировать кнопку по прерыванию?

Rimidalw
Offline
Зарегистрирован: 04.04.2012

В своем скетче мне очень нужно использовать кнопку по прерыванию. Так как есть очень длинный и долгий цикл который нужно обрывать в любой момент по нажатию кнопки и запускать другую обработку. Как раз для этого идеально подходит прерывание, которое обрабатывает кнопку не зависимо от основной программы. Есть стандартный код обработки кнопки по прерыванию, но он работает с дребезгом. 

//
// светодиод, подключённый к digital pin 13 будет изменять своё 
// состояние при изменении напряжения на digital pin 2
//
int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);              // порт как выход
  attachInterrupt(0, blink, CHANGE); // привязываем 0-е прерывание к функции blink().
}

void loop()
{
  digitalWrite(pin, state);          // выводим state  
}

void blink()
{
  state = !state;                    // меняем значение на противоположное
}

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

Adno
Offline
Зарегистрирован: 21.09.2012

В обработчике прерываний запретить прерывания в начале и разрешить в конце.

Установить глобальный счетик в обработчике прерываний выполняющий полный код обработчика на 5-тый 10-тый или 20-тый вызов прерывания

 

Adno
Offline
Зарегистрирован: 21.09.2012

Лучше всего читать в обработчике "системное" время ( millis() ) и проверять разницу. По достижении заданного интервала делать полную обработку и записывать актуальное время для последующего сравнения. Учесть преход счётчика millis() через ноль, если включаться будет дольше чем на 50 дней

Rimidalw
Offline
Зарегистрирован: 04.04.2012

А можно пример пожалуйста, а то у меня в голове каша после прочтенного.

Rimidalw
Offline
Зарегистрирован: 04.04.2012

Все решил проблему! А все очень просто. Добавил обычный керамический конденсатор на 1мф мжду контактами кнопки. И вуаля абсолютно никакого дребезга. Кнопку с большой частотой нажимал на сколько мог. Дребезга нет, удивительно)

maksim
Offline
Зарегистрирован: 12.02.2012
int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);              // порт как выход
  attachInterrupt(0, blink, LOW); // привязываем 0-е прерывание к функции blink().
  digitalWrite(2, 1);
}

void loop()
{
  digitalWrite(pin, state);          // выводим state  
}

void blink()
{
  static unsigned long millis_prev;
  if(millis()-100 > millis_prev) state = !state;   // меняем значение на противоположное 
  millis_prev = millis();         
}

 

gena
Offline
Зарегистрирован: 04.11.2012

Rimidalw пишет:

"Все решил проблему! А все очень просто. Добавил обычный керамический конденсатор на 1мф мжду контактами кнопки. И вуаля абсолютно никакого дребезга. Кнопку с большой частотой нажимал на сколько мог. Дребезга нет, удивительно)"  - Вы просто ещё не попали в ситуацию когда дребезг даст о себе знать снова. Да, конденсатор значительно сглаживает сигнал дребезга, но не устраняет полностью.

maksim
Offline
Зарегистрирован: 12.02.2012

Все таки добавить две строки куда проще чем впаивать конденсатор.

RainMan
Offline
Зарегистрирован: 21.06.2011

maksim пишет:



int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);              // порт как выход
  attachInterrupt(0, blink, LOW); // привязываем 0-е прерывание к функции blink().
  digitalWrite(2, 1);
}

void loop()
{
  digitalWrite(pin, state);          // выводим state  
}

void blink()
{
  static unsigned long millis_prev;
  if(millis()-100 > millis_prev) state = !state;   // меняем значение на противоположное 
  millis_prev = millis();         
}

 

отличное решение! А я пошел по другому пути. Установил глубину фильтра - от 8 до 16 единиц. И в том-же обработчике прерывания от кнопки просто считаю сколько подряд проскочило 1 или 0, смотря по какому уровню настроено прерывание. Когда необходимое количество 1 или 0 пришло, выставляю флаг что нажата кнопка.  

Таким образом получается избавиться даже от очень сильного дребезга

xstramento
Offline
Зарегистрирован: 19.10.2013

maksim пишет:

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);              // порт как выход
  attachInterrupt(0, blink, LOW); // привязываем 0-е прерывание к функции blink().
  digitalWrite(2, 1);
}

void loop()
{
  digitalWrite(pin, state);          // выводим state  
}

void blink()
{
  static unsigned long millis_prev;
  if(millis()-100 > millis_prev) state = !state;   // меняем значение на противоположное 
  millis_prev = millis();         
}

  static unsigned long millis_prev;

при объявлении переменная millis_prev инициализируется в ноль или ей просто выделяется неочищенная область памяти ?

 

-------

RainMan пишет:
отличное решение! А я пошел по другому пути. Установил глубину фильтра - от 8 до 16 единиц. И в том-же обработчике прерывания от кнопки просто считаю сколько подряд проскочило 1 или 0, смотря по какому уровню настроено прерывание. Когда необходимое количество 1 или 0 пришло, выставляю флаг что нажата кнопка.  

Таким образом получается избавиться даже от очень сильного дребезга

можете дать код фильтра?

 

axill
Offline
Зарегистрирован: 05.09.2011

Adno пишет:

В обработчике прерываний запретить прерывания в начале и разрешить в конце.

Пустые заботы. Прерывания автоматически запрещаются на время выполнения кода обработчика прерываний

inspiritus
Offline
Зарегистрирован: 17.12.2012
Вообщетто именно для таких случаев есть события прерываний RISING и FALLING , которые срабатывают соответственно по фронту или срезу, отсекая все следующие события , при правильном обращении с обработчиком и железом
 
с железом - поставить керамику до 0.1 мкф , и не забывать, что от качества кнопки тоже многое зависит.
 
с обработчиком - при входе запрещать прерывания, при выходе разрешать, внутри , если особо нечего делать , формировать задержку пустым циклом for, тк. в прерывании delay и millis не работает. 
 
чем качественнее кнопка, тем меньше керамика и короче цикл антидребезга, тем больше времени на основной loop. 
 
ОТ КНОПКИ ОЧНЬ МНОГОЕ ЗАВИСИТ!!!
maksim
Offline
Зарегистрирован: 12.02.2012

inspiritus пишет:

Вообщетто именно для таких случаев есть события прерываний RISING и FALLING , которые срабатывают соответственно по фронту или срезу, отсекая все следующие события , при правильном обращении с обработчиком и железом
 
с железом - поставить керамику до 0.1 мкф , и не забывать, что от качества кнопки тоже многое зависит.
 
с обработчиком - при входе запрещать прерывания, при выходе разрешать, внутри , если особо нечего делать , формировать задержку пустым циклом for, тк. в прерывании delay и millis не работает. 
 
чем качественнее кнопка, тем меньше керамика и короче цикл антидребезга, тем больше времени на основной loop. 
 
ОТ КНОПКИ ОЧНЬ МНОГОЕ ЗАВИСИТ!!!

Вы не читая (или не понимая) ветку и проигнорировав всех людей выше решили изрыгнуть свои бредовые и недалекие умозаключения? Я вас правильно понял?

inspiritus
Offline
Зарегистрирован: 17.12.2012

Я полагаю в техническом форуме не место для персональных оскорблений.

Если Вы хотите критиковать, критикуйте по существу, если не можете , ведите себя достойно

maksim
Offline
Зарегистрирован: 12.02.2012

Оскорблений никаких не было.

А по существу пожалуйста:

inspiritus пишет:
Вообщетто именно для таких случаев есть события прерываний RISING и FALLING

Абсолютно никак не помогает от дребезга. По какой причине в коде выше стоит LOW уже не помню, с таким же успехом будет работать и RISING и FALLING.

inspiritus пишет:
с железом - поставить керамику до 0.1 мкф ,

#4

inspiritus пишет:
с обработчиком - при входе запрещать прерывания, при выходе разрешать,

http://arduino.ru/forum/programmirovanie/vopros-po-preryvaniyam#comment-34127

inspiritus пишет:
формировать задержку пустым циклом for,
Бред.

inspiritus пишет:
тк. в прерывании delay и millis не работает.
Все об этом и так знают, а в коде выше к вашему непониманию используется millis() внутри обработчика и все замечательно работает.

inspiritus пишет:
ОТ КНОПКИ ОЧНЬ МНОГОЕ ЗАВИСИТ!!!
Что зависит? Длительность дребезга? Без разницы какой длины дребезг, если он есть.

Клапауций
Offline
Зарегистрирован: 10.02.2013

maksim пишет:

Что зависит? Длительность дребезга? Без разницы какой длины дребезг, если он есть.

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

две кнопки или тумблер - одна кнопка(положение тумблера) что-то включает, вторая - выключает.

 

com
Offline
Зарегистрирован: 06.09.2013

http://www.elsfera.ru/components/com_jshopping/files/img_products/full__________________49f24aa48fa63.jpg

 

и никакого дребезга!

maksim
Offline
Зарегистрирован: 12.02.2012

inspiritus пишет:

Я полагаю в техническом форуме не место для персональных оскорблений.

И я специально переспросил:

maksim пишет:

Я вас правильно понял?

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

axill
Offline
Зарегистрирован: 05.09.2011

мой вариант борьбы с дребезгом при использовании прерываний такой:

- на кнопку настраиваем прерывание (одно из INT0/INT1 или PCINT). Только для INT0/INT1 можно установить то на какое событие мы будем срабатывать (any, zero, high, rasing, faling), для PCINT можно выбрать только вариант any, но это не страшно - прочитав первой строчкой кода прерывания статус кнопки в порту мы сразу поймем из-за чего произошло прерывание и можем его проигнорировать, если оно нам не интересно.

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

- объявляем две volatile переменные одна для работы таймера кнопки, вторая для фиксации факта успешного (уже после обработки дребезга) нажатия кнопки. По второй переменной мы будет делать что нам нужно в loop() и после обработки будет сбрасывать в ноль значение этой переменной. Для многих случаев полезно игнорировать новые нажатия кнопки до тех пор, пока предыдущее нажатие не обработано.

- первую переменную выставляем в прерывании от нажатия кнопки (не забываем проверять состояние порта для обработки PCINT). Выставляем ее в количество циклов срабатывания таймера которые мы считаем надежным нажатием. Подбирается экспериментально. Из моей практики время до истечения таймера должно быть между 400 и 100 мсек. Делим это время на период срабатывания обработчика таймера и полученно число после округдения записываем в нашу первую переменную

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

все. пример есть в моем коде здесь http://arduino.ru/forum/proekty/igrushechnyi-svetofor

Malko4
Offline
Зарегистрирован: 15.02.2015

А что если в обработчике прерываний первой строкой вписать запрет обработки прерывания? А в конце, если надо, разрешить.

 

OSBoy
Offline
Зарегистрирован: 22.12.2016

maksim пишет:

int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);              // порт как выход
  attachInterrupt(0, blink, LOW); // привязываем 0-е прерывание к функции blink().
  digitalWrite(2, 1);
}

void loop()
{
  digitalWrite(pin, state);          // выводим state  
}

void blink()
{
  static unsigned long millis_prev;
  if(millis()-100 > millis_prev) state = !state;   // меняем значение на противоположное 
  millis_prev = millis();         
}

 

Отлично работает! Перепробовал разные варианты, похоже этот пока самый простой и стабильный.

bandirom
Offline
Зарегистрирован: 26.09.2017
//В сетапе
attachInterrupt(0, butt1, FALLING);  // Кнопка // или rising



void butt1() {
  detachInterrupt(0);//отключаем прерывание
  interrupts();

  if(millis()- last_time >= 100 )
{
  // Чето делаем

  last_time = millis();
}
     attachInterrupt(0, butt1, FALLING);//активируем прерывание   
}

как по мне самый простой вариант, можно еще тригер поставить для большей надежности, тот же шмитта. Ставил DS, то тоже норм сбивает дребезг

zhekaus
Offline
Зарегистрирован: 17.04.2018

maksim пишет:

Все таки добавить две строки куда проще чем впаивать конденсатор.

Ваше программное решение не защищает от брезга при отпускании кнопки. Пользователь может нажать, подержать, а потом отпустить. И вот тут-то при дребезге будет лишнее срабатывание.

А обычно хочется отрабатывать именно нажатие на кнопку, а не отпускание. В том числе, продолжительное.

 

zhekaus
Offline
Зарегистрирован: 17.04.2018

Rimidalw пишет:

Все решил проблему! А все очень просто. Добавил обычный керамический конденсатор на 1мф мжду контактами кнопки. И вуаля абсолютно никакого дребезга. Кнопку с большой частотой нажимал на сколько мог. Дребезга нет, удивительно)

... и потеряли энергоэффективность, надо полагать.  Кондей можно поставить и поменьше.

Logik
Offline
Зарегистрирован: 05.08.2014

Зачетного мракобеса к нам занесло! Это ж надо было раскопать тему и отвечать на сообщения пятилетней давности. Какая нах энергоэффективность нажатия кнопки ))) Какое длительное отпускание?! Почти усцался от смеха))

ПС. примеры годные, но деатач/атач в обработчике лишние. Кондей, тригер и пр. лабудень на кнопке - показатель неумения человека писать код. Еще важно чтобы один месный не заметил что паузу на 100мсек в коде, он свято верит что умеет нажать и отпустить кнопку быстрей и воспринимает такое как личное унижение ;) 

zhekaus
Offline
Зарегистрирован: 17.04.2018

Logik пишет:

Какая нах энергоэффективность нажатия кнопки ))) Какое длительное отпускание?! Почти усцался от смеха))

;) 

не нажатия кнопки, а зарядки/разрядки кондея. Разумеется, программно множно и нужно. Но приведенный здесь пример далек от совершенства.

По поводу длительно нажатия:

Кнопки нажимаются не только для того чтобы тут же отпустить. По-моему, это очевидно.

 

ПС. Написал в древнюю тему, потому что искал готовое решение. Его, к сожалению, годного, пока не нашлось.

 

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

Logik пишет:

Еще важно чтобы один месный не заметил... 

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

алё. когда код будет, пустобрёх?

Logik
Offline
Зарегистрирован: 05.08.2014

А один местный заказ уже оплатил?

ПС. Я знал что он обязательно клюнет! )))

Logik
Offline
Зарегистрирован: 05.08.2014

zhekaus пишет:

 пример далек от совершенства.

а совершенство - штука скорей хилосовская;)

zhekaus пишет:

Кнопки нажимаются не только для того чтобы тут же отпустить. По-моему, это очевидно.

А вот тут по разному бывает. Кнопка лифта, кнопка мышки, кнопка бояна - все сильно специфично.

zhekaus пишет:

 искал готовое решение.  Его, к сожалению, годного, пока не нашлось.

разумеется. Нет проблемы - нет решения.

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

Logik пишет:

А один местный заказ уже оплатил?

ПС. Я знал что он обязательно клюнет! )))

тред был не в рубрике "Ищу исполнителя", и ты обещал без условий оплаты, а что бы доказать, как нужно делать - б-а-л-а-б-о-л

*я знал, что Логик - пустобрёх.

Logik
Offline
Зарегистрирован: 05.08.2014

Ничего подобного, я профи, пишу код за деньги. И если кому надо коду от меня - так не за так. И об этом изначально я те писал, влом только искать. Но учитывая чтот ты настырно клянчиш уже который месяц и беря во внимание, что недавно был день дурака, а заслуженого подарка на форуме ты так и нифига не получил, то дарю. Но не все ;) Интересные методы классов я позатираю, поля данных оставлю для подсчета. Так до поступления финансов на счет.

#ifndef cbi
#define cbi(sfr, bit) (sfr &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif 

enum KBD_EVENT
{
  // физические события изменения состояния кнопок
    KBD_EVENT_DONE,
    KBD_EVENT_UP,
  //логические события  
    KBD_EVENT_LONG,
    KBD_EVENT_SHORT,
    KBD_EVENT_DBL,
    KBD_EVENT_PRESS,
    
    KBD_EVENT_TIME,

};

void setup(void)
{
  Serial.begin(9600);
  PORTC=0x1f;
  DDRC=0x1f;
  PORTD=0xfc;
  PORTB=0x03;
}

#define MAX_STROBE  5

#define KEY_TIME_MAX 4  //столько кнопок одновременно можно нажать 

//Сканирование матрицы, поиск нажатий и отправка их в SelectPress. Генерация  KBD_EVENT_TIME
class PhisicalKBD 
{
 
  virtual void SetStrob(byte n, byte s)=0;
  virtual byte GetReturn(void)=0;
  
  //Ищем изменения в состоянии матрицы и уведомляем о них уровень выше
  //Про завершение сканирования уведомляем сообщением KBD_EVENT_TIME
  void Select(void)
  {
   byte r;
   byte rez;
   byte a;

   rez=0;
   for(byte i=0;i<MAX_STROBE;i++)
   {
    a=KbdScrean[i];
    r=KbdOldScrean[i] ^ a;
    KbdOldScrean[i]=a;

    SelectPress(i, r, a);
   }
   SelectLongPress(KBD_EVENT_TIME, 0);
 }
 
 protected:
   byte Strob;
   byte OldTime;
   byte KbdScrean[MAX_STROBE];
   byte KbdOldScrean[MAX_STROBE];

   //сюда класс отправит все состояния возвратов для каждого строба
   //i-строб
   //r-маска кнопок изменивших состояние
   //ф-маска текущих состояний кнопок
   virtual  void SelectPress(byte i, byte r, byte a) {};
   //выделяем короткие и длинные нажатия, обработка комбинаций
   virtual void SelectLongPress(byte evnt, byte Key, byte FlCombi = false) =0;
  
 public:
   PhisicalKBD()
   {
    Strob=0xff;
   }
   
  //Выполняем очередную фазу сканирования и опроса кнопок
  //Если цикл сканирования завершился - анализируем кнопки в Select()
  void Scaning(void)
  {
    if(Strob==0xff)
    {
     for(byte i=0;i<MAX_STROBE;i++) 
     {
       SetStrob(i, HIGH); 
     }
     Strob=0;
    }
    else
      KbdScrean[Strob]=~GetReturn();  //храним с инверсией для удобства при старте
    
    SetStrob(Strob, HIGH); 
    Strob++;
    if(Strob>MAX_STROBE)
    {
     Strob=0;
     Select(); 
    }
    SetStrob(Strob, LOW); 
  }

// Процесс формирования временных интервалов сканирования и опроса кнопок
// Достаточно часто вызываем из loop.  
  byte Process(byte t)
  {
    if(byte(t-OldTime)<20)
      return 0;
    
    OldTime=t;
    Scaning();
  }
};

//Класс формирования физических сообщений - KBD_EVENT_DONE и KBD_EVENT_UP
class BaseKBD : public PhisicalKBD
{
  куку! ;)
};


class LongPressKBD : public BaseKBD
{
  struct  KyeTime
  {
    byte Key;
    byte Time;
  };

  KyeTime KT[KEY_TIME_MAX]; //храним нажатия кнопок
   //по содержимому KT выявляем код комбинации, если его нет возвращаем 0

 куку! ;)

protected:
  byte TimeKbd; //счетчик тактов сканирования кнопок
};

class DblPressKBD : public LongPressKBD
{
  byte Key_SH;
  byte Key_SH_Time;  

 куку! ;)
};

#define DBG
#ifdef DBG 
byte Tic;
byte Key=0xff;
byte Key1=0xff;
#endif


class KBD : public DblPressKBD
//class KBD : public BaseKBD
{
 public:
 // KBD(byte s) : PhisicalKBD(s)  {  };
  KBD(byte s) : DblPressKBD(s)  {  };
  
 private:
 // работаем напрямую с портом
  void SetStrob(byte n, byte s)  
{
#ifdef DBG  
  if((n==3) && (s==LOW))
  {
  Key1=Key;
  }
  else 
    Key1=0xff;
#else  
  s?sbi(PORTC,n):cbi(PORTC,n);         
#endif
  } 
  byte GetReturn(void)           
  {
#ifdef DBG  
    byte r=Key1;Key1=0; return r; 
#else     
  return (PIND & 0xfc) | (PINB & 0x3); 
#endif
  }
  
  byte SelectCombiKey(void){ return 0;}
  void KeyEvent(byte evnt, byte key)
  {
#ifdef DBG 
    if(evnt==KBD_EVENT_TIME)
      Tic++;
    if(!(Tic&63))  
    {
    Serial.println("Tic!!");
      Key=0xf9; 
      Tic++;
    }
    if((Tic&63)==3)
     Key=0xf8;
    if((Tic&63)==7)
     Key=0xf9;
    if((Tic&63)==9)
     Key=0xfd;
     
    if((Tic&63)==12)
     Key=0xff;
    
    if(evnt==KBD_EVENT_TIME)
     return;
     
 #endif
     
    Serial.print("Event=");
    Serial.print(evnt);
    Serial.print(" Key=");
    Serial.println(key, HEX);
  };
};

KBD kbd(MAX_STROBE);

void loop(void)
{
  static byte OldTime;
 // static byte KbdScrean[MAX_STROBE];
  byte Time;  
  
  Time=millis();
  
  switch(kbd.Process(Time))
  {
    case KBD_EVENT_DONE: break;
    case KBD_EVENT_UP: break;
    case KBD_EVENT_LONG: break;
    case KBD_EVENT_SHORT: break;
    case KBD_EVENT_DBL: break;
  }
}

Ну и вывод при полном наличии иерархии классов 

Event=0 Key=19
Event=0 Key=1A
Event=0 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=1 Key=19
Event=3 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=1A
Event=5 Key=1B
Event=1 Key=1B
Event=2 Key=1B
Event=5 Key=1A
Event=5 Key=1A
Event=5 Key=1A
Event=1 Key=1A
Event=2 Key=1A
Tic!!
Event=0 Key=1A
Event=0 Key=1B
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=1A
Event=5 Key=1B
Event=0 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=19
Event=1 Key=19
Event=3 Key=19
Event=5 Key=1A
Event=5 Key=1B
Event=5 Key=1A
Event=5 Key=1B
Event=1 Key=1B
Event=2 Key=1B
Event=5 Key=1A
Event=5 Key=1A
Event=5 Key=1A
Event=1 Key=1A
Event=2 Key=1A
Tic!!

 

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

Logik пишет:

Ничего подобного, я профи, пишу код за деньги. И если кому надо коду от меня - так не за так. И об этом изначально я те писал, влом только искать. 

ты не профи - у тебя долгосрочной памяти как у канарейки, ты не помнишь, что начал мне рассказывать, как нужно... и, когда я тебе предложил показать, как нужно - ты сказал, что выкатишь код и я буду посрамлён.

когда я тебе напомнил о твоих обещаниях - ты-сука слился.

давай код, прохфесианал!

Logik
Offline
Зарегистрирован: 05.08.2014

Заметь, кстати непосредственно стробирование и опрос реализуется в пользовательском классе KBD, функции SetStrob и GetReturn. А это означает что? Правильно, ты ниче не понял... Это означает что клаву легко и не принужденно можна вынести в расширители портов. И ничего от этого не поменяется в базовых классах. Обем памяти сам посчитаеш, там просто, структурка в массиве. А я  - спать. Пока. С прошедшим праздником ;)

Logik
Offline
Зарегистрирован: 05.08.2014

Клапауций 555 пишет:

Logik пишет:

Ничего подобного, я профи, пишу код за деньги. И если кому надо коду от меня - так не за так. И об этом изначально я те писал, влом только искать. 

ты не профи - у тебя долгосрочной памяти как у канарейки, ты не помнишь, что начал мне рассказывать, как нужно... и, когда я тебе предложил показать, как нужно - ты сказал, что выкатишь код и я буду посрамлён.

когда я тебе напомнил о твоих обещаниях - ты-сука слился.

давай код, прохфесианал!

Прикольно получилось)))  А код то - вон он, выше! Но самое вкусное - за бабло. Увы это жизнь такая. Не злись. Думаю в коде ты всеравно нихера не поймеш.

ПС. еще раз тя с прошедшим праздником.

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

Logik пишет:
А код то - вон он, выше!

ты бы ещё ссылку на блинк без делая дал, а отсальное - за бабло попросил, клоун.

это не раздел Ищу исполнителя - публикация цитат из секретного кода здесь считается тупым балабольством.

alexbmd
Offline
Зарегистрирован: 15.01.2016

maksim пишет:

inspiritus пишет:
тк. в прерывании delay и millis не работает.
Все об этом и так знают, а в коде выше к вашему непониманию используется millis() внутри обработчика и все замечательно работает.

в референс, Гаммон и другие умные дядьки говорят не использовать милис,сериал и прочее внутри ISR.  а) почему вы всетаки использовались милис именно внутри ?

б) почему оно работает если умные дядьки говорят что внутри ISR это не будет работать ?

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Надо понимать, что такое "не работает". В ISR millis() не изменяет своего значения, выдавая все время одно и то же. Но, при двух разнесенных во времени вызовах обработчика, величина millis() в нем будет отличаться. Данный факт применен в этом коде "антидребезга".

alexbmd
Offline
Зарегистрирован: 15.01.2016

понял спасиб

alexbmd
Offline
Зарегистрирован: 15.01.2016

Господа, ок а можно же просто отключить прерывание?  (вопрос в целях самооброзования а не подвоха который почемуто все тут ждут)

setup{
flag = false
}

loop{
if (!flag) attachInterrupt

if(flag) {
interrupt handler
flag = false
}
}

ISR{
detach
flag=true
}

 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Так отключайте, никто не запрешает (пока).

alexbmd
Offline
Зарегистрирован: 15.01.2016

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Правильно "отключать" прерывания путем их запрещения. Не всех скопом, а конкретное.

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

так detach как раз и отключает конкретное а не все скопом...

(не осуждаю умения и навыки maksim, он знает что делает)  но новичков хотел бы предостиречь от использования millis(), Serial внутри ISR (обработчика прерываний) во избежания непонятных глюков

  • Don't attempt to delay, eg: delay (100);
  • You can get the time from a call to millis, however it won't increment, so don't attempt to delay by waiting for it to increase.
  • Don't do serial prints (eg. Serial.println ("ISR entered"); )
  • Don't try to do serial reading.

подробнее тут http://www.gammon.com.au/interruptshttp://arduino.ru/forum/programmirovanie/vopros-po-preryvaniyam#comment-34127http://arduino.ru/forum/programmirovanie/vnutrennie-preryvaniya?page=1#comment-446383