Дребезг кнопки

olega88
Offline
Зарегистрирован: 03.04.2012

Привет!

Прошу помочь устранить дребезг кнопки програмным путём. Собрать триггер пока неизчего, установка кондёра в паралель не помогает... замут Блюма недопираю...

Цитата:
const [color=#CC6600]int[/color] buttonPin = 2; const [color=#CC6600]int[/color] ledPin = 13; const [color=#CC6600]int[/color] led2Pin = 12; [color=#CC6600]int[/color] x = 2000000; [color=#CC6600]int[/color] buttonPushCounter = 0; [color=#CC6600]int[/color] buttonState = 0; [color=#CC6600]int[/color] lastButtonState =0; [color=#CC6600]unsigned[/color] [color=#CC6600]long[/color] duration; [color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color]() {   [color=#CC6600]pinMode[/color](buttonPin, [color=#006699]INPUT[/color]);   [color=#CC6600]pinMode[/color](ledPin, [color=#006699]OUTPUT[/color]);   [color=#CC6600]pinMode[/color](led2Pin, [color=#006699]OUTPUT[/color]);   [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]begin[/color](9600); } [color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color]() {   buttonState = [color=#CC6600]digitalRead[/color](buttonPin);   [color=#CC6600]if[/color] (buttonState != lastButtonState)    {     [color=#CC6600]if[/color] (buttonState == [color=#006699]HIGH[/color]) {       buttonPushCounter++;       [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"on"[/color]);       [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]print[/color]([color=#006699]"number of button pushes: "[/color]);       [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](buttonPushCounter);     }      [color=#CC6600]else[/color] {       [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color]([color=#006699]"off"[/color]);     }   }   lastButtonState = buttonState;   [color=#CC6600]if[/color] (buttonPushCounter % 2 == 0) {     [color=#CC6600]digitalWrite[/color](ledPin, [color=#006699]LOW[/color]);   } [color=#CC6600]else[/color] {    [color=#CC6600]digitalWrite[/color](ledPin, [color=#006699]HIGH[/color]);   }    duration = [color=#CC6600]pulseIn[/color](buttonPin, [color=#006699]HIGH[/color]);    [color=#CC6600][b]Serial[/b][/color].[color=#CC6600]println[/color](duration);   [color=#CC6600]if[/color] (duration > x ){  [color=#CC6600]digitalWrite[/color](led2Pin, [color=#006699]HIGH[/color]);  } }

 

olega88
Offline
Зарегистрирован: 03.04.2012
const int  buttonPin = 2;
const int ledPin = 13;
const int led2Pin = 12;
int x = 2000000;
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState =0;
unsigned long duration;


void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  Serial.begin(9600);
}


void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)

   {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    } 
    else {
      Serial.println("off"); 
    }
  }
  lastButtonState = buttonState;

  if (buttonPushCounter % 2 == 0) {
    digitalWrite(ledPin, LOW);
  } else {
   digitalWrite(ledPin, HIGH);
  }
   duration = pulseIn(buttonPin, HIGH);
   Serial.println(duration);
  if (duration > x ){
 digitalWrite(led2Pin, HIGH);

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

 Вы можете описать, что вы хотите от этого кода?

step962
Offline
Зарегистрирован: 23.05.2011

Определяем переменные

int oldStateI, curStateI; // целые числа - текущее и предыдущее состояние кнопки
float curState; // здесь будет храниться среднее арифм. 10 последних опросов состояния кнопки 

В loop():

curState=curState*9/10+digitalRead(ButtonPin)*10;
curStateI=curState*10;  // переводим вещественное число в целое (диапазон 0...10)
if(curStateI==STATE_ON && curStateI!=oldStateI) {
// произошло надежное включение кнопки - выполняем необходимые действия
[...]
// и готовимся к дальнейшему слежению
 oldStateI=curStateI;
}
if(curStateI==STATE_OFF && curStateI!=oldStateI) {
// произошло надежное выключение кнопки - выполняем необходимые действия (если таковые есть)
[...]
// и готовимся к дальнейшему слежению
 oldStateI=curStateI;
}

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

Чтобы кнопка "не западала", в цикле должны стоять обе проверки - и на нажатие, и на отпускание кнопки.

Ну и еще: в цикле не деолжно быть задержек - а то сглаживание не будет успевать происходить. Впрочем, в случае delay-ев мучает уже не проблема дребезга контактов, а "эстонский" тип реакции микроконтроллера ;)

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

 Вы можете описать, что вы хотите от этого кода?

Вместо ЛЕД будут реле. Должны работать по алгоритму --- при кратком нажатии кнопки срабатывает реле1, если удерживать кнопку 2 сек или более, сработать должны оба реле.

olega88
Offline
Зарегистрирован: 03.04.2012

step962 , спасибо сейчас попробую!

olega88
Offline
Зарегистрирован: 03.04.2012
const int  buttonPin = 2;
const int ledPin = 13;
const int led2Pin = 12;
int x = 2000000;
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState =0;
unsigned long duration;
int oldStateI, curStateI; // целые числа - текущее и предыдущее состояние кнопки
float curState; // здесь будет храниться среднее арифм. 10 последних опросов состояния кнопки 
int STATE_ON(buttonState == HIGH);
int STATE_OFF(buttonState == LOW);

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  Serial.begin(9600);

}

void loop()
{

curState=curState*9/10+digitalRead(buttonPin)*10;
curStateI=curState*10; 
// переводим вещественное число в целое (диапазон 0...10)
if (curStateI==STATE_ON && curStateI!=oldStateI) {
// произошло надежное включение кнопки - выполняем необходимые действия
    digitalWrite(ledPin, HIGH); 
       duration = pulseIn(buttonPin, HIGH);
   Serial.println(duration);
  if (duration > x ){
 digitalWrite(led2Pin, HIGH);
  }
  
// и готовимся к дальнейшему слежению
 oldStateI=curStateI;
}
if(curStateI==STATE_OFF && curStateI!=oldStateI) {
// произошло надежное выключение кнопки - выполняем необходимые действия (если таковые есть)
    
// и готовимся к дальнейшему слежению
 oldStateI=curStateI;
}
}
olega88
Offline
Зарегистрирован: 03.04.2012

step962, попробовал ваш пример, без изменений :(

 

step962
Offline
Зарегистрирован: 23.05.2011

 А это вы что такое делаете:

  digitalWrite(ledPin, HIGH);
  duration = pulseIn(buttonPin, HIGH);
  Serial.println(duration);

 

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

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

Так как х, buttonPin, ledPin, led2Pin не меняются лучше использовать #define:
 

#define led2Pin 12
#define x 2000000

 

olega88
Offline
Зарегистрирован: 03.04.2012

1. Зажигает ЛЕД

2. Измеряет время нажатия на кнопку (кнопка без фиксации)

3. для отладки, выводит на терминал время нажатия

ЛЕД1 работает как надо, но ЛЕД2, который по условию должен загорется через 2 сек, не загорается( если установить х=0,1 сек, загорается через раз)

olega88
Offline
Зарегистрирован: 03.04.2012

int х время нажатия кнопки

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

И? 

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

Вспомнил вроде, переменная типа int принимает целые значения от -32767 до 32767, а вы пытаетесь туда засунуть 2000000

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

И? 

if (duration > x ){
digitalWrite(led2Pin, HIGH);
}

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

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

olega88 пишет:

maksim пишет:

 Вы можете описать, что вы хотите от этого кода?

Вместо ЛЕД будут реле. Должны работать по алгоритму --- при кратком нажатии кнопки срабатывает реле1, если удерживать кнопку 2 сек или более, сработать должны оба реле.

А по какому алгоритму реле должны выключаться?

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

Еще раз, читайте внимательно:

Переменная типа int принимает целые значения от -32767 до 32767, а вы пытаетесь туда засунуть 2000000

Вы понимаете, что число 2000000 больше, чем 32767. Этим кодом:

int x = 2000000;

вы пытаетесь в отверстие диаметром 32767мм засунуть шар диаметром 2000000мм. Так понятнее?

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

olega88 пишет:

maksim пишет:

 Вы можете описать, что вы хотите от этого кода?

Вместо ЛЕД будут реле. Должны работать по алгоритму --- при кратком нажатии кнопки срабатывает реле1, если удерживать кнопку 2 сек или более, сработать должны оба реле.

А по какому алгоритму реле должны выключаться?

 

при втором нажатии на кноку, не стал дописывать пока с этим не разобрался

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

При следующем коротком нажатии отключаются оба реле? или так же как и включаются - при коротком нажатии отключается только первое реле, а при длинном оба

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

Еще раз, читайте внимательно:

Переменная типа int принимает целые значения от -32767 до 32767, а вы пытаетесь туда засунуть 2000000

Вы понимаете, что число 2000000 больше, чем 32767. Этим кодом:

int x = 2000000;

вы пытаетесь в отверстие диаметром 32767мм засунуть шар диаметром 2000000мм. Так понятнее?

ГЫ-ГЫ, пробовал и 1000, всё равно не работает... реле1 будет вкл. зажигание, реле2 стартер

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

При следующем коротком нажатии отключаются оба реле? или так же как и включаются - при коротком нажатии отключается только первое реле, а при длинном оба

да оба

olega88
Offline
Зарегистрирован: 03.04.2012

olega88 пишет:

maksim пишет:

При следующем коротком нажатии отключаются оба реле? или так же как и включаются - при коротком нажатии отключается только первое реле, а при длинном оба

да оба

соврал, реле2 откл от внешнего сигнала

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

Старт-кнопка? 

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

Старт-кнопка? 

точно!!!

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

А такой алгоритм не хотите?

Нажимаем только на кнопку:
первое нажатие кнопки запуска- включается режим АСС(работает только магнитола и прикуриватель)
второе нажатие- дополнительно включается зажигание.
Третие нажатие -OFF, выключает АСС и зажигание

Удерживая педаль тормоза, нажимаем кнопку engine start: 
короткое нажатие на кнопку включает АСС, зажигание и стартер( на 0,8(примерно) секунды). Если двигатель запускается хорошо- этого времени работы стартера вполне достаточно. Если двигатель холодный, то:
более длительное нажатие кнопки - включается АСС, зажигание и стартер(на время удержания кнопки запуска)

www.a-pik.ru/catalog/moduli_start_engine/engine-start-new-v.2

 

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

Можно из алгоритма убрать АСС.

olega88
Offline
Зарегистрирован: 03.04.2012

хочется именно свой алгоритм, чужих полно например http://www.rlocman.ru/forum/showthread.php?t=1370&page=7

вся проблема в дребезге, остальное вроде мелочи

olega88
Offline
Зарегистрирован: 03.04.2012

olega88 пишет:

хочется именно свой алгоритм, чужих полно например http://www.rlocman.ru/forum/showthread.php?t=1370&page=7

вся проблема в дребезге, остальное вроде мелочи

а может и не в нём? ну не понимает ардуишка, что я жму кнопку долго...

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

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

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

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

 тоже самое, что ключом крутить

olega88
Offline
Зарегистрирован: 03.04.2012

1
31
14
0
14
0
144767
31
0
0
1729
0
0
0
0
 

вот такие значения выдаёт

duration = pulseIn(buttonPin, HIGH);
Serial.println(duration)

на терминале при нажатии на кнопку, причём нули - это длинные нажатия

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

 

#define buttonPin 2
#define relePin1 13
#define relePin2 12
#define x 1000 // время удержания кнопки

unsigned long duration = 0;
boolean stateButton, relestate1 = 0;

void setup() {
  pinMode(relePin1, OUTPUT);
  pinMode(relePin2, OUTPUT);

}

void loop(){
  if(digitalRead(buttonPin) && !stateButton){
    relestate1 = !relestate1;
    stateButton = 1;
    duration = millis();
  }
  if(!digitalRead(buttonPin)){
    stateButton = 0;
  }
  if(stateButton && millis()-duration > x){
    digitalWrite(relePin2, HIGH);
  }
  if(relestate1){
    digitalWrite(relePin1, HIGH); 
  }
  else{
    digitalWrite(relePin1, LOW);
   digitalWrite(relePin2, LOW); 
  }
}

Проверить сейчас не начем, попробуйте и отпишитесь по результату

 

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

 Перекопируйте еще раз

olega88
Offline
Зарегистрирован: 03.04.2012

:))))

работает хаотично, но ЛЕД2 зажигается ровно по времени!!!

olega88
Offline
Зарегистрирован: 03.04.2012

завтра попробую разобратся, сегодня нет сил уже, пойду спать. Спасибо Максим!!!!!!

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

Что значит хаотично?

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

 

#define buttonPin 2
#define relePin1 13
#define relePin2 12
#define x 1000 // время удержания кнопки

unsigned long duration = 0;
boolean stateButton, relestate1 = 0;

void setup() {
  pinMode(relePin1, OUTPUT);
  pinMode(relePin2, OUTPUT);
}

void loop(){
  if(digitalRead(buttonPin) && !stateButton){
    relestate1 = !relestate1;
    stateButton = 1;
    delay(150);
    duration = millis();
  }
  if(!digitalRead(buttonPin)){
    delay(50);
    stateButton = 0;
  }
  if(stateButton && millis()-duration > x){
    digitalWrite(relePin2, HIGH);
  }
  if(relestate1){
    digitalWrite(relePin1, HIGH); 
  }
  else{
    digitalWrite(relePin1, LOW);
   digitalWrite(relePin2, LOW); 
  }
}

 а так? и если что-то не так пишите подробнее

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

Что значит хаотично?

каждый раз цикл проходит по разному

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

 еще раз перекопируйте

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

 

#define buttonPin 2
#define relePin1 13
#define relePin2 12
#define x 1000 // время удержания кнопки

unsigned long duration = 0;
boolean stateButton, relestate1 = 0;

void setup() {
  pinMode(relePin1, OUTPUT);
  pinMode(relePin2, OUTPUT);
}

void loop(){
  if(digitalRead(buttonPin) && !stateButton){
    relestate1 = !relestate1;
    stateButton = 1;
    delay(150);
    duration = millis();
  }
  if(!digitalRead(buttonPin)){
    delay(50);
    stateButton = 0;
  }
  if(stateButton && millis()-duration > x){
    digitalWrite(relePin2, HIGH);
  }
  if(relestate1){
    digitalWrite(relePin1, HIGH); 
  }
  else{
    digitalWrite(relePin1, LOW);
   digitalWrite(relePin2, LOW); 
  }
}

 а так? и если что-то не так пишите подробнее

теперь супер!!!!!!

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

Должно работать так: короткое нажатие включает реле1 последующее короткое нажатие выключает реле1, длинное нажатие сразу влючает реле1 и через секунду реле2, последующее короткое нажатие выключает оба реле.

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

Должно работать так: короткое нажатие включает реле1 последующее короткое нажатие выключает реле1, длинное нажатие сразу влючает реле1 и через секунду реле2, последующее короткое нажатие выключает оба реле.

верно, так и работает, то чтоя хотел

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

Есть недочет - если сначала влючить реле1 коротким нажатием, а потом попытаться включить реле2 длинным нажатием, то сначала выключится реле1 и через секунду включится реле2. Есть такой недочет?

olega88
Offline
Зарегистрирован: 03.04.2012

временами при нажатии диод загорается, и при отпускании кнопки тухнет, как будто кнопку 2 раза нажал, хотя щелчок один

olega88
Offline
Зарегистрирован: 03.04.2012

maksim пишет:

Есть недочет - если сначала влючить реле1 коротким нажатием, а потом попытаться включить реле2 длинным нажатием, то сначала выключится реле1 и через секунду включится реле2. Есть такой недочет?

есть

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

попродуйте в 22 строке увеличить задержку с 50 до 100

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

olega88 пишет:

maksim пишет:

Есть недочет - если сначала влючить реле1 коротким нажатием, а потом попытаться включить реле2 длинным нажатием, то сначала выключится реле1 и через секунду включится реле2. Есть такой недочет?

есть

замените 25 строку на это:

if(stateButton && relestate1 && millis()-duration > x){

 

olega88
Offline
Зарегистрирован: 03.04.2012

там есть только 150 задержка, менял в обе стороны, только хуже

olega88
Offline
Зарегистрирован: 03.04.2012

не помогло

 

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

 я же вам писал перекопируйте еще раз

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

Что не помогло?