Как обеспечить считывание двойного клика кнопки в теле прерывания?

// функция временной задержки с проверкой кнопки управления
void delay_(int T1)
{
static bool FL_KN=true;  
Y1=millis();  
while(millis()-Y1<T1){
if(digitalRead(KN)==HIGH&&!FL_KN){FL_KN=true;delay(200);}//  
if(digitalRead(KN)==LOW&&FL_KN){//
delay(200);
if(digitalRead(KN)==HIGH){   
FL_=false;
 effekt++;//выбор - номер эффекта
if(effekt> max_eff){effekt=1;}
t=100;M=5;cvet=0;delay(200);
}
else{
 delay(200);
 if(digitalRead(KN)==HIGH){ 
 cvet++;if(cvet>5){cvet=0;}//выбор компонент цвета
 }
 else{
  t=t+30;if(t>210){t=30;}//выбор длительности паузы между кадрами в эффекте  
 FL_KN=false; 
 }   
}
}
}
}

Ну вот, сделал - короткое, длинное и более длинное. Надо именно к нему приноровиться, а то явно долго держу кнопку нажатой.

@lilik, ты явно хочешь странного. По секундомеру тренировать клики будешь? ))

Нет, по руке. Просто ритм всегда плохо запоминаю.

а delay зачем?

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

Лилик у меня такой диссонанс вызывает периодически, хоть стой / хоть падай. :smiley:
То проекты крутые, то с миллис (видите ли) ему работать сложно - забудет быстро :rofl:

3 лайка

Он художник, ему простительно ))

«А девкой был бы краше»? :joy:

Капризнее.
…тут delay не мешает, а наоборот… в самый раз.

А прерывание где ?
Или главная тема ма ушла на второй план ?

1 лайк

Так это, того…

Прерывание использовано на ик приёмник в ёлочке.
…Если серьёзно для кнопки оно избыточно ибо палец не такой шустрый.

:rofl: :rofl: :rofl:
Лилик, вроде не пятница еще, куда с таким напалмом то? :joy:

Так там другой смысл.
Отследить и обработать нажатие, когда МК сильно занят.

Кактус, «не пали кантору» )))

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

Представь цикл вывода эффекта на адресную ленту.
Там тайминги жёсткие, поэтому весь цикл длительностью 5 … 50 секунд происходит в цикле while()
А тут тебе нужно эффект поменять на следующий(одиночный клик) или вернуть предыдущий(двойной клик).
Как ты это будешь делать без прерывания ?

Как обычно. Вот, и кнопка, и ик приёмник, и блютуз, и всё одновременно:

Спойлер
/////////////////////////////////////
/// примеры для ws2812b на ESP32
//голосовое управление и ик управление (плюс кнопка)
////////////////////////////////////
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#define KN   27 // под кнопку 
#define plus 17 //
#define minus 25 //
int IK_PIN = 26;        //Пин подключения выходного сигнала с ИК-приёмника

#include "Adafruit_NeoPixel.h"
#define line_ 96 //число пикселей в ленте
#define max_eff 23 //общее число эффектов
uint8_t dataPin = 5;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_BRG + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.

volatile word keycode_ = 0;// переменная хранения кода кнопки

byte R=0; byte G=0; byte B=0;//составляющие цвета пикселя
int t=70;// пауза между кадрами
int effekt=1;// номер эффекта
int M=10;//коэффициент мощности свечения пикселя 
long Y=0;//переменная хранения моментов времени
byte cvet=0;//
long Y1=0;//переменная хранения моментов времени
int ti = 0;
int ni = 0;
bool FL_=true;//переключение автоматического режима на управление с пульта ИК
bool FL_show=true;//
//
byte kanal_1[8]={0,24,44,60,74,83,89,95};// выделение светодиодов в группы-каналы
byte kanal_2[8]={4,28,48,63,76,81,88,95}; 
byte kanal_3[8]={8,31,50,65,77,85,91,95};  
byte kanal_4[8]={12,34,52,67,78,87,93,95};

BluetoothSerial SerialBT;
String inputString;// строки данных
byte komanda_=0;//
// 
///RGB
void setup() {
pinMode (KN, INPUT_PULLUP);// кнопка управления 
pinMode(plus,OUTPUT);//
digitalWrite(plus,HIGH);// плюс питания ик приёмника
pinMode(minus,OUTPUT);//
digitalWrite(minus,LOW);// минус питания ик приёмника  
pinMode(IK_PIN, INPUT);  // ir recv
attachInterrupt(26, irread, FALLING);  
SerialBT.begin("ESP32test"); //НАЗВАНИЕ БЛЮТУЗ МОДУЛЯ  
strip.begin();
//Serial.begin(9600); 

}
void loop() {
 
 ///
 //автоматический перебор программ каждые 30 секунд
 if(millis()-Y>30000ul&&FL_){
 Y=millis();
 t=70*random(1,4);//псевдослучайный выбор длительности паузы между кадрами в эффекте
 effekt--; if(effekt==0){effekt= max_eff;}//
 M=random(3,11);//псевдослучайный выбор яркости свечения
 cvet=random(0,6);//псевдослучайный выбор компонент цвета 
 }
  /// 
 // проигрывание программы эффекта
   for ( ti = 0; ti < line_; ti++) {//перебор номеров кадров в ленте
    for ( ni = 0; ni < line_; ni++) {//перебор номеров пикселей в ленте
     cvet_(ti,ni);// функция определения цвета пикселя в зависимости от его номера в ленте и момента времени (кадра анимации)   
     if(cvet==0){strip.setPixelColor(ni, R*M, G*M, B*M);}if(cvet==1){strip.setPixelColor(ni, G*M, B*M, R*M);}if(cvet==2){strip.setPixelColor(ni, B*M, R*M, G*M);}
     if(cvet==3){strip.setPixelColor(ni, R*M, B*M, G*M);}if(cvet==4){strip.setPixelColor(ni, G*M, R*M, B*M);}if(cvet==5){strip.setPixelColor(ni, B*M, G*M, R*M);}
    }
  if(FL_show){strip.show();}  
  // delay_(t);
  delay_(t);CheckSerial();keypressed();
    }
 ///
 }
///////////////////////////////////////
void cvet_ (int it,int in){
 
 switch (effekt) {
     case 0:
     R=0;G=0;B=0;//выключение ёлки
     break;
    case 1:
     R=7;G=1;B=0;
     if(in==it){R=0;G=14;B=2;}//бегущий по оранжевой ленте -> цвета бирюзового пиксель ->
      break;
    case 2:
     { byte mnogo=9; R=5*((in+it%mnogo)%mnogo);G=5*((mnogo-1-(in+it%mnogo)%mnogo));B=0;}// бегущая по ленте <-палитра от зелёного до красного (переход из 9 штук)<-
      break;
    case 3:
      if(in<=it){R=5;G=0;B=10;}else{R=0;G=10;B=0;}// ->полоса фиолетового цвета набегает на полосу зелёного ->
      break;
     case 4:
      if(in%(it+1)==0){R=15;G=15;B=10;}else{R=7;G=1;B=1;}// -> выстрел белыми пикселями с их взаиморазлётом -> на розовом фоне 
      break;
      case 5:
        if(in==line_-it||in+1==line_-it||in+2==line_-it||in+3==line_-it||in+4==line_-it){R=15;G=3;B=0;}else{R=0;G=0;B=7;}//бегущий по синей ленте -> цвета оранжевого 5 пикселей ->
      break;
    case 6:
     { byte mnogo=10; R=5*((in+it%mnogo)%mnogo);G=0;B=5*((mnogo-1-(in+it%mnogo)%mnogo));}// бегущая по ленте <-палитра от синего до красного (переход из 10 штук)<-
      break;
    case 7:
      if(in<=line_-it){R=10;G=10;B=0;}else{R=0;G=7;B=7;}// <-полоса голубого цвета набегает на полосу жёлтого <-
      break;
     case 8:
      if((line_-in)%(it+1)==0){R=15;G=15;B=10;}else{if(in%(it+3)==0){R=10;G=3;B=0;}else{R=0;G=2;B=2;}}// -> выстрел белыми пикселями и оранжевыми с их взаиморазлётом -> на голубом фоне 
      break;
    case 9:
     { byte mnogo=32; R=3;G=1*(mnogo-1-(it%mnogo));B=1*((it%mnogo));t=200;}// плавный переход цвета ленты от "зеленоватого к синеватому"
      break;  
    case 10:
     { byte mnogo=32; R=1*(mnogo-1-(it%mnogo));G=1;B=1*((it%mnogo));t=200;}// плавный переход цвета ленты от "красноватого к синеватому"
      break; 
    case 11:
     { byte mnogo=7; R=0*((mnogo-1-(in+it%mnogo)%mnogo));G=2*((mnogo-1-(in+it%mnogo)%mnogo));B=5*((mnogo-1-(in+it%mnogo)%mnogo));}// бегущая по ленте <-поток метеоров (переход из 7 штук)<-
      break; 
     case 12:
     {if(in==it){R=0;G=1;B=0;}if(in+1==it){R=10;G=0;B=0;}if(in+2==it){R=10;G=3;B=0;}if(in+3==it){R=10;G=10;B=0;}if(in+4==it){R=0;G=10;B=0;}
     if(in+5==it){R=0;G=10;B=10;}if(in+6==it){R=0;G=0;B=15;}if(in+7==it){R=3;G=0;B=10;} }// бегущая по ленте ->радуга (переход из 7 штук)->
      break;
     case 13:  
     {if(in<=line_-it){R=0;G=1;B=0;}if(in+2==line_-it){R=10;G=0;B=0;}if(in+4==line_-it){R=10;G=3;B=0;}if(in+6==line_-it){R=10;G=10;B=0;}if(in+8==line_-it){R=0;G=10;B=0;}
     if(in+10==line_-it){R=0;G=10;B=10;}if(in+12==line_-it){R=0;G=0;B=15;}if(in+14==line_-it){R=3;G=0;B=10;} }// бегущая по ленте <-радуга (переход из 7 штук через 1)<-
      break; 
      case 14:  
    {if(in-2<(line_+2*it)/2&&in+2>(line_-2*it)/2&&it<line_/2){R=0;G=7;B=7;}else{if((in>it||in<line_-it)&&it>=line_/2){R=5;G=1;B=5;}else{R=7;G=7;B=1;}} }//<-разбегание от центра поочерёдное полосы синеватого и сиреневого цветов - подобие волны->
      break; 
   case 15:  
    {if(in-2<(line_+2*it)/2&&in+2>(line_-2*it)/2&&it<line_/2){R=0;G=7;B=1;}else{if((in>it||in<line_-it)&&it>=line_/2){R=15;G=2;B=0;}else{R=7;G=2;B=2;}} }//<-разбегание от центра поочерёдное полосы зеленоватого и оранжевого цветов - подобие волны->
      break; 
     case 16:  
    { if((in>=it-3&&in<=it+3)||(in>=it-3+8&&in<=it+3+8)){R=0;G=0;B=0;}else{ R=2*(it%2);G=2*((it%4)/2);B=2*((it%8)/4);} t=70;}//-> бег тень 6 пикселей, светящиеся 1 пиксель, тень 6 пикселей -> на фоновом радужном переливе 
      break;
       case 17:
     if(in%(it/(line_/3)+1)==0){R=random(0,(in+it)%7+2); G=random(0,in%10+2); B=random(0,it%10+2);}if(R==0&&G==0&&B==0){R=5;G=5;B=5;}// рандом пикселей 
      break; 
       case 18:
     {R=(in/16+it)%2;G=((in/16+it)/2)%2;B=((in/16+it)/4)%2;M=40;if(R==0&&G==0&&B==0){R=7;G=1;B=0;M=5;}t=140;}//радужное движение групп по 16 пикселей с добавкой оранжевого
      break; 
       case 19:
     {R=((it+in)/(5))%2;G=(((it+in)/(5))/2)%2;B=(((it+in)/(5))/4)%2;M=40;if(R==0&&G==0&&B==0){R=7;G=1;B=0;M=5;}t=70;if(in==it||in+1==it||in+2==it||in+3==it){R=0;G=0;B=0;}}//радужное движение групп по 16 пикселей с добавкой оранжевого 2 вариант
      break; 
       case 20:
      if(it<line_/2){R=1;G=2;B=3;}else{R=2;G=3;B=1;}  
     for( byte w=0;w<8;w++){
      if(in==kanal_1[w]||in==kanal_2[w]||in==kanal_3[w]||in==kanal_4[w]){R=1;G=0;B=0;}// маятник эффект
      if(it%6==0&&in==kanal_1[w]){R=8;G=5;B=5;}
      if(it%6==1&&in==kanal_2[w]){R=8;G=5;B=5;}
      if(it%6==2&&in==kanal_3[w]){R=8;G=5;B=5;}
      if(it%6==3&&in==kanal_4[w]){R=8;G=5;B=5;}
      if(it%6==4&&in==kanal_3[w]){R=8;G=5;B=5;}
      if(it%6==5&&in==kanal_2[w]){R=8;G=5;B=5;}
       }
     break; 
       case 21:
   if(it<line_/2){R=1;G=1;B=0;}else{R=2;G=3;B=0;}  
    if(it<8&&(in==kanal_1[7-it%8]||in==kanal_4[it%8])){R=8;G=5;B=5;}//бегущие точки по каналам
    if(it>=8&&it<16&&(in==kanal_2[it%8]||in==kanal_3[7-it%8])){R=8;G=8;B=5;}
    if(it>=16&&it<24&&(in==kanal_3[7-it%8]||in==kanal_2[it%8])){R=8;G=8;B=5;}
    if(it>=24&&it<32&&(in==kanal_4[it%8]||in==kanal_1[7-it%8])){R=8;G=8;B=5;} 
    if(it>=32&&it<40&&(in==kanal_1[7-it%8]||in==kanal_4[it%8])){R=8;G=8;B=5;}
    if(it>=40&&it<48&&(in==kanal_2[it%8]||in==kanal_3[7-it%8])){R=8;G=8;B=5;}
    if(it>=48&&it<56&&(in==kanal_3[7-it%8]||in==kanal_2[it%8])){R=8;G=8;B=5;}
    if(it>=56&&it<64&&(in==kanal_4[it%8]||in==kanal_1[7-it%8])){R=8;G=8;B=5;}
    if(it>=64&&it<72&&(in==kanal_1[7-it%8]||in==kanal_4[it%8])){R=8;G=8;B=5;}
    if(it>=72&&it<80&&(in==kanal_2[it%8]||in==kanal_3[7-it%8])){R=8;G=8;B=5;}
    if(it>=80&&it<88&&(in==kanal_3[7-it%8]||in==kanal_2[it%8])){R=8;G=8;B=5;}
    if(it>=88&&it<96&&(in==kanal_4[it%8]||in==kanal_1[7-it%8])){R=8;G=8;B=5;}
    if(in==it){R=14;G=3;B=0;}//бегущие точки по спирали ёлки
    if(in==line_-it){R=3;G=14;B=0;}//
    break; 
     case 22:
   if(it<line_/4){if(abs(in-random(0,line_))<6){R=3;G=6;B=9;}else{R=1;G=2;B=3;}} //отрисовка пикселей ёлки 
   if(it>=line_/4&&it<line_/2){if(abs(in-random(0,line_))<6){R=6;G=9;B=3;}else{R=2;G=3;B=1;}}
   if(it>=line_/2&&it<line_*3/4){if(abs(in-random(0,line_))<6){R=6;G=12;B=0;}else{R=2;G=4;B=0;}}
   if(it>=line_*3/4&&it<line_){if(abs(in-random(0,line_))<6){R=3;G=9;B=6;}else{R=1;G=3;B=2;}} 
     if(it%16<8){
     for( int w=0;w<8;w++){
      if(in==kanal_1[w]||in==kanal_2[w]||in==kanal_3[w]||in==kanal_4[w]){R=1;G=0;B=0;}//отрисовка пикселей каналов 
      if(it%8==w&&(in==kanal_1[w]||in==kanal_2[w]||in==kanal_3[w]||in==kanal_4[w])){R=8;G=5;B=5;}
       }
     }
    else{
      for( int w=0;w<8;w++){
      if(in==kanal_1[w]||in==kanal_2[w]||in==kanal_3[w]||in==kanal_4[w]){R=1;G=0;B=0;}//отрисовка пикселей каналов 
      if(w!=0&&(line_-it)%8==w&&(in==kanal_1[w]||in==kanal_2[w]||in==kanal_3[w]||in==kanal_4[w])){R=8;G=5;B=5;}
       }
    }
     break;
     case 23:
    R=2+it%2;G=2+it%2;B=2+it%2;
    if(random(0,abs(line_/2-it)+2)==0) {R=2;G=5;B=0;}
    if(random(0,abs(line_/2-it)+2)==0) {R=3;G=2;B=0;}
    if(random(0,abs(line_/2-it)+2)==0) {R=1;G=0;B=5;}
     break;     
    default:
      { R=0;G=0;B=0;}//выключаем пиксели если не выбран эффект
  } 
}
/////////////////////////////////////////
//ФУНКЦИИ ПРИЁМА И ОБРАБОТКИ КОМАНД-ДАННЫХ
void CheckSerial()
{
  //////////////////////////////////////////////////////////////////////////////
  while (SerialBT.available())//считываем строку данных пока они поступают
  {
    char inChar = (char)SerialBT.read();
    if (inChar == '\n'||inChar == ' ')     //если окончание строки или пробел
    {
      MakeCmd();//обрабатываем её данной функцией
      break;
    }
    else inputString += inChar;// иначе удлиняем строку на один символ
  }
 
}
/////////////////////////////////////////////////////////////////////////////////
void MakeCmd()
{
  int y = inputString.length(); // присваиваем переменной у число символов в строке
  String cmd = inputString; // передаём строку другой переменной
  inputString = "";//"обнуляем переменную"
  //////
// Serial.print(cmd);
 if(cmd=="ВЫКЛЮЧИ"){ effekt=0;//выключение ёлки 
 }
 //
  if(cmd=="ЭФФЕКТ"||cmd=="EFFECT"){komanda_=1;}
  if(cmd=="ЯРКОСТЬ"){komanda_=2;}
  if(cmd=="ПАУЗА"){komanda_=3;}
  if(cmd=="ЦВЕТ"||cmd=="СВЕТ"){komanda_=4;}
  if(cmd=="КАДР"){komanda_=5;}
  if(cmd=="АВТОМАТ"){komanda_=6;}
//
 int pos=cmd.toInt();//преобразовать строку в число 
 if(komanda_==1&&pos>0&&pos<=23){effekt=pos;pos=0;komanda_=0;}
 if(komanda_==2&&pos>0&&pos<=10){M=pos;pos=0;komanda_=0;}
 if(komanda_==3&&pos>=30&&pos<=210){t=pos;pos=0;komanda_=0;}
 if(komanda_==4&&pos>0&&pos<7){cvet=pos-1;pos=0;komanda_=0;}
 if(komanda_==5&&cmd=="СТОП"){FL_show=false;pos=0;komanda_=0;}
 if(komanda_==5&&cmd=="ПУСК"){FL_show=true;pos=0;komanda_=0;}
 if(komanda_==6&&cmd=="ДА"){FL_=true;pos=0;komanda_=0;}
 if(komanda_==6&&cmd=="НЕТ"){FL_=false;pos=0;komanda_=0;}                                
//
}

//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////
// функция временной задержки с проверкой кнопки управления
void delay_(int T1)
{
static bool FL_KN=true;  
Y1=millis();  
while(millis()-Y1<T1){
if(digitalRead(KN)==HIGH&&!FL_KN){FL_KN=true;delay(200);}//  
if(digitalRead(KN)==LOW&&FL_KN){//
delay(200);
if(digitalRead(KN)==HIGH){   
FL_=false;
 effekt++;//выбор - номер эффекта
if(effekt> max_eff){effekt=1;}
t=100;M=5;cvet=0;delay(200);
}
else{
 delay(200);
 if(digitalRead(KN)==HIGH){ 
 cvet++;if(cvet>5){cvet=0;}//выбор компонент цвета
 }
 else{
  t=t+30;if(t>210){t=30;}//выбор длительности паузы между кадрами в эффекте  
 FL_KN=false; 
 }   
}
}
}
}
////////////////////////////////////////////////
/////////////////////////////////////////
void irread() {
volatile static byte n = 0;
volatile static word keycode = 0;
volatile static unsigned long tm = 0;
volatile static unsigned long last = 0;

  tm = micros() - last; 
  last = micros();
  n += 1;
  if (tm > 3000) {
    keycode = 0;
    n = 0;
    }
  if (n >8&&n<=32) {
    if (tm > 1500) {keycode += 1;}
    keycode = keycode << 1;
  }
  if(n==32){keycode_ = keycode;keycode = 0;n=0;}
}
//////////////////////////////////////////
void keypressed() {
 if(keycode_!=0){
  //Serial.println(keycode_, HEX);// печатаем код кнопки 
  //код по обработке значений keycode_
   switch (keycode_) {
    case 0x15906E:
    effekt++;//выбор - номер эффекта
    if(effekt> max_eff){effekt=1;}
      break;
    case 0x1451AE:
    effekt--;//выбор - номер эффекта
    if(effekt<1){effekt= max_eff;}
      break;
   case 0x1550AE:
     M=M+2;if(M>10){M=10;}//выбор яркости свечения 
      break;
    case 0x14D12E:
      M=M-2;if(M<0){M=1;}//выбор яркости свечения
      break; 
      case 0x15C03E:
      cvet++;if(cvet>5){cvet=0;}//выбор компонент цвета  
      break; 
       case 0x14A15E:
       t=t+30;if(t>210){t=30;}//выбор длительности паузы между кадрами в эффекте 
      break;
      case 0x14817E:
       FL_=! FL_;//переключение с автоматического перебора на ручное эффектов
      break; 
      case 0x15D02E:
       FL_show=! FL_show;//стоп кадр
      break;
       case 0x15609E:
       effekt=0;//выключение ёлки
      break; 
    
      default:
      ti=ni=line_;      
    }
  keycode_ = 0;delay(100);
   }  
 }
//////////////////////////////////////////////
 

Накидал кнопку с антидребезгом, пока одинарный клик.

#include <GyverWDT.h>
volatile bool push,oldPush,Click = false;

void setup() {
  DDRB |= (1<<PB5);   //светодиод
  PORTB &= ~(1<<PB5); 
  EICRA &= ~((1<<ISC01)|(1<<ISC00));
  EICRA |= (1<<ISC01)|(1<<ISC00); 
  EIMSK |= (1<<INT0);  //вкл прерывание
  Serial.begin(9600);
}
ISR(INT0_vect) {
  EIMSK &= ~(1<<INT0); //выкл прерывание
  push = !push;
}
ISR(WATCHDOG) {
  Watchdog.disable();
  Click = !Click;
  PINB = (1<<PB5);
}
void loop() {
  if(push != oldPush) { //на изменение флага
    oldPush = push;
    Watchdog.enable(INTERRUPT_MODE, WDT_PRESCALER_8); //ставим прерывание вдт , которое и генерирует клик
    Serial.print(Click);
    EIFR &= ~(1<<INTF0); 
    EIMSK |= (1<<INT0);  //включаем внешнее прервыние обратно
  }
}

В регистрах ватчдог еще не разбирался, поэтому через либу.
Почему в сериал долбит сериями из нулей или единиц? Не правильный дребезг, когда чередуется 010101 а сплошным массивом 1 или 0. Или где-то ошибся, не соображу. Может улучшить как-то?

Ну так и делайте, чтобы не пересекались.
Впрочем, смотря что Вы называете событиями.
Есть множество событий интерфейса и есть множество команд, которые надо выполнить.
Вот и нужно так спроектировать связи между ними, чтобы не возникало конфликтов.

Это физически невозможно - одиночный щелчок ВСЕГДА предваряет двойной. Даже если двойной щелчок подразумевается одновременно по двум клавишам, все равно один из них произойдет чуть раньше другого: человек физически не может сделать их одновременно.
А попытка преодолеть объективную реальность (в которой двойной щелчок - это ВСЕГДА два следующих один за другим одиночных), как правило, ведет либо к полной, либо к частичной неработоспособности. Под последней может подразумеваться низкая надежность.
Т.е. плохо спроектированный интерфейс будет либо часто приводить к ошибкам оператора, либо существенно ограничит темп его работы, либо и то и другое.

Сам-то понимаешь, что эта фраза никак не может служить ни доказательством, ни аргументом?

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

1 лайк