Проблемный код счётчика нажатия тактовой кнопки.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Есть ардуино Уно, в ней такой код

int razrab; //светодиод 1
 int i=0;  
const int r=0; 
  int Lamp=5;

void buttoncontrol()

{

i=i+1; //увеличивает счетчик кнопки на 1, можно так ledState++ , но мне не удобно.
    if (i==2){i=0;}//если счетчик достиг предела положений то его надо обнулить.
}
//функция все светодиоды выключены
void OFF()
{delay(40);
 razrab=0;
}

//функция все светодиоды включены
void ON()
{delay(40);
 razrab=1;
}
void setup() {
  
   pinMode(Lamp, OUTPUT);
   attachInterrupt(0, buttoncontrol, RISING); 
}
void loop() {
  switch (i)
{
 case 0:
 OFF();//выключено
 break;
 case 1:
 ON();//включено
 break;
case 2:
 OFF();//включено
 break;
}

  if(razrab==0){
    delay(40);
    digitalWrite(Lamp,0);
    }
     if(razrab==1){
      delay(40);
    digitalWrite(Lamp,1);
    }
  }

Нажал на тактовую кнопку первый раз появилась на 5 выводе ардуины 1, нажал второй раз на 5 выводе0, оно то всё хорошо работает но вот проблема в том что этот счётчик срабатывает при разряде пьезо зажигалки в воздухе, либо когда снимаешь свитр на выходе появляется лог.1, и это при том что вход прерывания(2 нога Ардуины Уно притянута к земле через 10кОм).  Нужно код что ли другой применить?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Мне помогло 5К к питанию и экранированный провод (экран на землю).

Только вот код у Вас странный. В строке 32 "case 2". А из строки 11 следует, что i никогда не может быть равной 2. Вас это не смущает?

Roman2344
Offline
Зарегистрирован: 09.09.2015

То есть убрать строку 38 и 39? Мне нужно 1 раз нажал на выходе 1 второй раз нажал на выходе 0. 5кОм на +5В, а с какого пина? Экранированный провод это на кнопку на вход?

Roman2344
Offline
Зарегистрирован: 09.09.2015

Убрал в коде 38 и 39 строку не помогло, попробую откинуть кнопку и рядом зажигалкой поклацать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, не 0.5К, а 5К! Да, на тот же второй пин. Сама жила провода соединяет кнопку и пин, а экран припаян к Gnd.

У меня было 5К на плюс, а прерывание я соответсвенно по Falling ловил.

Да и ещё, не забывайте про дребезг. Так, как у Вас сейчас Вы при нажатии кнопки будете несколько нажатий ловить. Поставьте хотя бы конденсатор 100nf между пином 2 и Gnd. Это должно немного помочь. Хотя я делал это (борьбу с дребезгом) программно.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Убрал кнопку на втором пине ардуины( прерывание 0 мой вход), всёравно клацая зажигалку меняется состояние выхода.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Так тут же программно и так есть от дребезга в условиях If в конце кода. Ну у меня вместо 5кило 10кило стоит, ну поставлю вообще кила 2 и посмотрю, по току 2кила со второго пина на землю будет нормально если +5В подать на вход. Кондёр добавлю конечно. А какой у вас код можно посмотреть?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Т.е., пин притянут к питанию резистором в 5К, к нему ничего не подключено и  всё равно срабатывает?

1. Поставьте конденсатор и попробуйте. Если не поможет, то

2. Подключите осциллограф и замерьте время "срабатывания" помехи. Наверняка оно маленькое - микросекунды.

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

Roman2344
Offline
Зарегистрирован: 09.09.2015

Притунял вход на землю вообще через 400Ом, а тоже самое

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да  у меня-то код простой. Я же говорю, что мне помогли 5К и экраинрованный провод и никаких проблем у меня нет.

////////////////////////////////////////
//
//	Обработчик прерывания FALLING на пине PIN_WAND
//
void wandInterrupt(void) {
	if (currentMode == MODE_WAITING) currentMode++;
}


////////////////////////////////////////
//
//	Общая инициализация
//
void setup() {
	pinMode(PIN_FS1000A, OUTPUT);
	pinMode(PIN_WAND, INPUT);	// pulled UP externally
	InitFS1000A();
	forAllLeds(LOW, true);
	attachInterrupt(INTERRUPT_NUMBER, wandInterrupt, FALLING);
}

В setup я его (PIN_WAND) ставлю в режим INPUT и назначаю прерывание. В обработчике изменяю состояние системы (всё заточено на состояния - это конечный автомат).

Кстати, а Вы-то в режим INPUT не поставили. Врядли поможет (они по умолчанию в INPUT), но поставьте, чем чёрт не шутит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Roman2344 пишет:

Притунял вход на землю вообще через 400Ом, а тоже самое

Тогда программно, п.п. 2 и 3

Roman2344
Offline
Зарегистрирован: 09.09.2015

Притянут вход к земле потому как я же в условии сравниваю если 1 то включаю выход. А помеху я же сам создаю зажигалкой с пьезой, так как до этого срабатывало на снятие свитера. Сейчас кнопка припаяна, но не в экране, но провод 20см.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Roman2344, прерывание INT0 может сработать от наводки на любой вход, от наводки на шину питания и землю. Я не вижу что и как у вас включено, так что можно давать только теоритические советы. Попробуйте все свободные ноги перевести в режим OUTPUT.

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

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

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

а, какой вообще сакральный смысл в прерывании на тактовой механической кнопке с дребезгом?

Roman2344
Offline
Зарегистрирован: 09.09.2015

А такой что нужна маленькая тактовая кнопка, на которую раз нажал включил, второй раз нажал выключил.

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

Roman2344 пишет:

А такой что нужна маленькая тактовая кнопка, на которую раз нажал включил, второй раз нажал выключил.

раз нажал и словил 14 тиков дребезга по прерыванию - в результате: выключил. :D

*продолжай пользовать прерывание там, где оно не нужно абсолютно.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Перевёл все ноги в режим выхода ничего не дало

Roman2344
Offline
Зарегистрирован: 09.09.2015

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

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

Roman2344 пишет:

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

ну, ок.

так, зачем прерывание на тактовой механической кнопке?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Roman2344,  попробуйте поменять  БП на другой.

Roman2344
Offline
Зарегистрирован: 09.09.2015

так, зачем прерывание на тактовой механической кнопке?

А как тогда?

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

Roman2344 пишет:

так, зачем прерывание на тактовой механической кнопке?

А как тогда?

boolean b00 = 1; // переменная, хранящая состояние кнопки b00.

void setup() {
// здесь, возможно, потребуется сконфигурировать пин кнопки как вход.
}

void loop() {
BUTTON_00();
// здесь крутятся подпрограммы и-или тело основной программы.
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BUTTON_00() {
boolean nb00 = digitalRead(3);
if (nb00 != b00) {b00 = nb00;
if (b00 == 0) {BUTTON_00_on();} // срабатывает один раз при нажатии кнопки.
if (b00 == 1) {BUTTON_00_of();} // срабатывает один раз при отпускании кнопки.
}
}

void BUTTON_00_on() {} // здесь находится всё, что должно происходить при нажатии кнопки.
void BUTTON_00_of() {} // здесь находится всё, что должно происходить при отпускании кнопки.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#61

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Roman2344 пишет:

так, зачем прерывание на тактовой механической кнопке?

А как тогда?

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

Вы измерили длительность помехи, как я Вам советовал. У меня помехи были микросекундные - можно просто такие микросекундные "нажатия" игнорировать.

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

ЕвгенийП пишет:

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

я не спрашивал, зачем ты используешь прерывание для выхода из спящего режима.

если бы ты, будил-усыплял контроллер одной кнопкой по прерыванию, то спросил бы.

Roman2344
Offline
Зарегистрирован: 09.09.2015
Сделал так, вот только первый раз нажал лог 1. на 5 выводе появилось, а дальше кнопку держишь нажатой 0 на выходе отпускаешь опять 1, а как сделать что бы раз нажал на выходе 1 второй раз нажал на выоде 0?
boolean b00 = 0; // переменная, хранящая состояние кнопки b00.
 int Lamp=5;

void setup() {

// здесь, возможно, потребуется сконфигурировать пин кнопки как вход.
pinMode(Lamp, OUTPUT);
pinMode(b00, INPUT);
}

void loop() {

BUTTON_00();

// здесь крутятся подпрограммы и-или тело основной программы.

}

void BUTTON_00() {

boolean nb00 = digitalRead(2);

if (nb00 != b00) {b00 = nb00;

if (b00 == 0) {BUTTON_00_on();} // срабатывает один раз при нажатии кнопки.

if (b00 == 1) {BUTTON_00_of();} // срабатывает один раз при отпускании кнопки.

}

}

void BUTTON_00_on() { digitalWrite(Lamp,1);} // здесь находится всё, что должно происходить при нажатии кнопки.

void BUTTON_00_of() { digitalWrite(Lamp,0);} // здесь находится всё, что должно происходить при отпускании кнопки.

 

Клапауций 322
Offline
Зарегистрирован: 31.12.2015
boolean b00 = 1; // переменная, хранящая состояние кнопки b00.

void setup() {
// здесь, возможно, потребуется сконфигурировать пин кнопки как вход.
pinMode(3, INPUT); // BUTTON_00
digitalWrite(3, 1);

pinMode(14, OUTPUT); // LED_01
digitalWrite(14, 1);
}

void loop() {
BUTTON_00();
// здесь крутятся подпрограммы и-или тело основной программы.
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BUTTON_00() {
boolean nb00 = digitalRead(3);
if (nb00 != b00) {b00 = nb00;
if (b00 == 0) {BUTTON_00_on();} // срабатывает один раз при нажатии кнопки.
if (b00 == 1) {BUTTON_00_of();} // срабатывает один раз при отпускании кнопки.
}
}

void BUTTON_00_on() {digitalWrite(14, !digitalRead(14));} // здесь находится всё, что должно происходить при нажатии кнопки.
void BUTTON_00_of() {} // здесь находится всё, что должно происходить при отпускании кнопки.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

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

это вам не это pinMode(b00, INPUT);

возможно это pinMode(pin, !b00); если хочется

Roman2344
Offline
Зарегистрирован: 09.09.2015

Спасибо

Roman2344
Offline
Зарегистрирован: 09.09.2015

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

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

Roman2344 пишет:

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

всё можно исправить, прицепив на пин кнопки прерывание. :D

Roman2344
Offline
Зарегистрирован: 09.09.2015

Хотя тоже самое, жаль нет сейчас экранированого провода, завтра куплю, а осциллограф розряжен.

Roman2344
Offline
Зарегистрирован: 09.09.2015

И эта проблема между прочем только когда ардуина запитана от БП, как от ЮСБ всё нормально, нужно будет глянуть уровень пульсаций БП, хотя вроде солидный комповский БП.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Проверил БП как нажимаю кнопку на ардуине так напряжение то поднимается до 12,34В, то опускается до 11,8В. Вот она основная проблема, не зря dimax о БП говорил. Спасибо ему