Опрос кнопок микроконтроллером

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Помогите опросить кнопку

Сообщение FreshMan »

а какого номинала резисторы внутренней подтяжки у AVR ?
Tell Me The Truth
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Помогите опросить кнопку

Сообщение shads »

вроде бы 50-100к
на плате без разговоров этого обычно достаточно, но если помеховая обстановка тяжелая или провода идут дальше или вообще шлейфом уходят с платы, то без раздумий нужно вешать внешнюю подтяжку, да посильнее, например 4,7 - 10к


У меня был случай прикольный:
Я тоже в своем устройстве использовал внутреннюю подтяжку, кнопка всего в 5-ти см от контроллера, кнопка использовалась для программирования устройства, все всегда нормально было, но как то раз...
На этом объекте другая фирма смонтировала рекламный щит, при этом поленились крепить свою коробку для коммутации питания щита, и взяли и засунули всю коммутацию в нашу коробку...
Далее в течение какого то времени нас периодически вызывали по поводу отказа нашего блока... всякий раз оказывалось что блок запрограммирован на несоответствующие функции, его тут же настраивали правильно и на какое то время все было ОК... но потом все повторялось...
Так было до тех пор пока я лично не приехал на объект... я конечно удивился куче проводов в нашей коробке, но не придал этому особого значения... и тут....... прям на моих глазах, блок самолично вошел в режим настроек..... и начал скакать туда сюда... я сначала потерял на время дар речи... но потом сообразил, что это - 10А импульсный блок питания, который стоит рядом, а его силовая проводка проходящая прям под контроллерной платой - так колбасят линию кнопки, что и даже программный антидребезг не помогает отсеть такие наводки...
После освобождения нашей коробки от лишних проводов, мы про этот объект постепенно забыли.....
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Помогите опросить кнопку

Сообщение FreshMan »

shads писал(а):вроде бы 50-100к

нашол все-таки :)
ATmega8
Изображение
выходит чем больше сопротивление резистора подтяжки тем сильнее он ловит всякие помехи ?
Tell Me The Truth
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Помогите опросить кнопку

Сообщение shads »

FreshMan писал(а):выходит чем больше сопротивление резистора подтяжки тем сильнее он ловит всякие помехи ?
Естественно...
Только не резистор ловит помехи, а вход контроллера...
При бесконечном сопротивлении подтяжки - вход вообще будет работать как антенна )))
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Помогите опросить кнопку

Сообщение FreshMan »

тогда я вот что не возьму в толк: почему специ из AVR поставили подтягивающий резистор номиналом в 20-50кОм ?
почему бы не поставить 4,7кОм ?
они что о подобного рода проблемах не ведали ?
навряд...... :roll:
Tell Me The Truth
Аватара пользователя
Oxford
Опытный кот
Сообщения: 819
Зарегистрирован: Вт окт 23, 2012 13:17:25
Откуда: Прокопьевск
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Oxford »

Инженер R@D

Telegram чат: https://t.me/radiowolf или в поиске приложения @radiowolf. Личка:@cncoxford
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Помогите опросить кнопку

Сообщение shads »

FreshMan писал(а):тогда я вот что не возьму в толк: почему специ из AVR поставили подтягивающий резистор номиналом в 20-50кОм ?
почему бы не поставить 4,7кОм ?
Ну просто всему есть разумные пределы... А то можно и продолжить тему, почему они например не сделали внутренний отключаемый последовательный резистор? чтобы можно было сразу светодиод вешать???

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

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

FreshMan писал(а):они что о подобного рода проблемах не ведали ?
Кстати а вы знаете о такого рода проблеме как энергосбережение??? есть же много батарейных устройств... представьте что конкуренты ставят 50к резисторы, а вы поставили 4к7... так вот теперь когда вы будете нажимать на кнопочку своего устройства, ваша батареечка будет садится в 10 раз быстрее чем у конкурентов!!!!! как вам такие перспективы?



Посмотрел у STM8 - примерно та же песня...

Изображение
Вложения
Безымянный.png
(53.61 КБ) 2725 скачиваний
Аватара пользователя
amirus
Открыл глаза
Сообщения: 63
Зарегистрирован: Пт авг 07, 2009 06:55:32
Откуда: Asia.

Интервал нажатия кнопки.

Сообщение amirus »

Всем доброго времени суток.
Подскажите пожалуйста начинающему, как реализовать программную обработку условия нажатой кнопки. К примеру, нажата кнопка ST1 - 1 сек, выполняем функцию 1, если время вышло, функцию 2. . Заранее благодарен.
Спойлерif(BUT1==0) // если нажата кнопка BUT1
{
if(BUT2==1)// если отжата кнопка BUT2
delay_ms(50);
OUT6=0; // тушим левый
delay_ms(50);
OUT5=1; // зажигаем правый
}
else
{
if(ST1==0)//если нажали ST1
{
delay_ms(50);
OUT5=0; //тушим правый
delay_ms (300);
OUT5=1;
}
}
if(BUT2==0) // если нажата кнопка BUT1
{
if(BUT1==1) //если отжата but1
delay_ms(50);
OUT5=0; // тушим правый
if(BUT1==1)// если отжата кнопка BUT2
delay_ms(50);
OUT6=1; // зажигаем левый
}
else
{
if(ST2==0)//если нажали ST1
{
delay_ms(50);
OUT6=0; //тушим левый
delay_ms (300);
OUT6=1;
}
}

}
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Интервал нажатия кнопки.

Сообщение Ivanoff-iv »

тут посмотри
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Аватара пользователя
amirus
Открыл глаза
Сообщения: 63
Зарегистрирован: Пт авг 07, 2009 06:55:32
Откуда: Asia.

Re: Интервал нажатия кнопки.

Сообщение amirus »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3332308#p3332308"]тут посмотри[/uquote]
Спасибо. Так как я начинающий, очень с трудом дался вариант со сбросом счетчика после выполнения условия. Для одной кнопки.Но не смог я сделать это для двух кнопок. Мне бы кусок кода глянуть. Пробовал таким методом.
Спойлерif(KEY==0) // если нажата кнопка
{
if(counter!=255)counter++; //начинаем счет
OUT4=1;
delay_ms(150); //Мигаем индикатором нога №3
OUT4=0;
if(counter==LONGKEY) //Если длительное по длительности нажатие
{
if(OUT1)OUT1=0; else OUT1=1;eep_1=OUT1; //Включаем, запоминаем PORTB.1 нога №6
}
}
else // иначе
{
if(counter>=1) //если был начат счет
{
if(counter<midkey) // и это короткое по длительности нажатие
{
if(OUT2)OUT2=0;else OUT2=1;eep_2=OUT2; //Включаем, запоминаем PORTB.2 нога №7
}
else
{
if(counter<longkey) //среднее по длительности нажатие
{
if(OUT3)OUT3=0;else OUT3=1;eep_3=OUT3; //Включаем, запоминаем PORTB.3 нога №2
}
}
}
counter=0; //Сброс подсчитанного
}
}
Аватара пользователя
amirus
Открыл глаза
Сообщения: 63
Зарегистрирован: Пт авг 07, 2009 06:55:32
Откуда: Asia.

Re: Помогите опросить кнопку

Сообщение amirus »

Голову готов расшибить себе... Подскажите пожалуйста где ошибка? Код с этого топика. Работает только на короткое нажатие.
Вложения
butt1.rar
(62.64 КБ) 517 скачиваний
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Помогите опросить кнопку

Сообщение Аlex »

А где в коде обработка события длинного нажатия ?
Аватара пользователя
amirus
Открыл глаза
Сообщения: 63
Зарегистрирован: Пт авг 07, 2009 06:55:32
Откуда: Asia.

Re: Помогите опросить кнопку

Сообщение amirus »

[uquote="Аlex",url="/forum/viewtopic.php?p=3333146#p3333146"]А где в коде обработка события длинного нажатия ?[/uquote]
Спасибо за столь быстрый ответ. Я поудалял все, за сутки этих пробных версий ведро написал :(( Вот теперь думаю в самой инициализации ошибки допустил.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Помогите опросить кнопку

Сообщение pyzhman »

Спойлер//Chip type : ATtiny13
//Clock frequency : 9,600000 MHz

#include <tiny13.h>
#include <delay.h>

bit oldButton, Button;
unsigned char timeout;

void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Port B initialization
PORTB=0x01;
DDRB=0x18;
// Clock value: Timer 0 Stopped
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;


Button= PINB.0; // считываем состояние кнопки

while (1)
{
delay_ms(10); // задержка 10 мсек

oldButton= Button; // предыдущее состояние кнопки
Button= PINB.0; // текущее состояние кнопки

if(oldButton && !Button) timeout= 100; // взводим таймаут на 1 сек при нажатии кнопки
if(!oldButton && !Button && timeout) --timeout; // уменьшаем таймаут при удержании кнопки
if(!oldButton && Button) // если кнопка отжата
{
if(timeout) PORTB^= 0x08; // если прошло менее 1 сек, то инвертируем выход РВ3
else PORTB^= 0x10; // если прошло более 1 сек, то инвертируем выход РВ4
}
};
}

Изображение
Docendo discimus
Аватара пользователя
amirus
Открыл глаза
Сообщения: 63
Зарегистрирован: Пт авг 07, 2009 06:55:32
Откуда: Asia.

Re: Помогите опросить кнопку

Сообщение amirus »

pyzhman Спасибо огромное! :beer:
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Помогите опросить кнопку

Сообщение pyzhman »

Пожалуйста.
Docendo discimus
Аватара пользователя
Мокренькая кисонька
Открыл глаза
Сообщения: 59
Зарегистрирован: Вт сен 27, 2011 07:28:44
Откуда: Москва
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение Мокренькая кисонька »

Господа, помогите разобраться, третий день мучаюсь.
Имеется три кнопки и три светодиода контрольных. Дребезг победил, но проблема в том, когда держишь одну кнопку нажатой (допустим первую), то любой другой кнопкой можно выполнить действие для первой кнопки, при этом действие прописанное для самой этой кнопки, которую нажимаешь к уже нажатой не выполняется. Сумбурно, но вроде понятно.
Спойлер

Код: Выделить всё

#include <avr/io.h>   /* Device specific include file */
#include "hd44780.h"  /* EZ-LCD include file (библиотека по японской технологии) */
#include <util/delay.h> //Delay library
#include <avr/interrupt.h> //Interrupt library
//#include "xprintf.h"
//#include <avr/pgmspace.h>
//#include <stdio.h>
//#include <string.h>
//#include <avr/eeprom.h>

#define RED PD7
#define YELLOW PD6
#define GREEN PD5
#define BTN1 PD0
#define BTN2 PD1
#define BTN3 PD2

static volatile uint8_t divider, state=0, keys=0, btns=0, flags=0;

void toggle (uint8_t color)
{
    if (~PIND&(1<<color))
    {
        PORTD|=(1<<color);
    }
    else
    {
        PORTD&=~(1<<color);
    }
}

void buttons (void)
{
   btns=~PIND; //читаем PIND в переменную и инвертируем прочитанное
   btns=btns&((1<<BTN1)|(1<<BTN2)|(1<<BTN3)); //отсекаем лишние разряды, оставляем только кнопки

   switch(btns)
   {
      case (1<<BTN1): //если нажата кнопка 1
        if(~flags&(1<<BTN1)) //если флаг первой кнопки не установлен, то
           {
              flags|=(1<<BTN1); //устанавливаем флаг
            toggle(RED); //что-то делаем
         }   
          break; //и на выход

      case (1<<BTN2): //если нажата кнопка 2
        if(~flags&(1<<BTN2)) //если флаг второй кнопки не установлен, то
          {
               flags|=(1<<BTN2); //устанавливаем флаг
            toggle(YELLOW); //что-то делаем
          }
         break; //и на выход

      case (1<<BTN3): //если нажата кнопка 3
        if (~flags&(1<<BTN3)) //если флаг третьей кнопки не установлен, то
           {
            flags|=(1<<BTN3); //устанавливаем флаг
            toggle(GREEN); //что-то делаем
           }
         break; //и на выход

      default: //если не нажата ни одна кнопка
         flags=0; //сбрасываем все флаги
    break; //и на выход
   }
   keys=0; //сбрасываем флаг разрешения опроса кнопок
}

/*void button (void)
{         
    if (~PIND&(1<<BTN1) && state==0) // если кнопка нажата и флаг не установлен, то
    {
        toggle(RED); // вызываем переключалку красного светодиода
      //toggle(GREEN);
    }
    if (~PIND&(1<<BTN1)) // если кнопка нажата, то
    { state=1; } // устанавливаем флаг
    else
    { state=0; } // если отпущена, то опускаем флаг
   keys=0;
}
*/

ISR(TIMER0_OVF_vect) //прерывание по переполнению
{
    divider++; //увеличиваем щоччик
   if (divider==3) // 61Гц/3=20Гц (или 50 мс)
   {   
        divider=0; //сбрасываем щоччик
      keys=1; //устаналиваем флаг разрешения опроса кнопок
   }

}

int main (void)
{
   //Инициализация портов I/O
    //PORTB это LCD порт, инициализируется в файле hd44780.c
    //Ноги PB0 и PB1 свободны
   ACSR|=(1<<ACD); //отключение компаратора
   DDRD|=(1<<PD7)|(1<<PD6)|(1<<PD5); //ноги PD7, PD6, PD5 на выход
    PORTD|=(1<<PD0)|(1<<PD1)|(1<<PD2); //подключение подтягивающих резисторов
    //Инициализируем таймер для кнопок
   TCCR0|=(1<<CS02)|(0<<CS01)|(1<<CS00); //таймер0 с предделителем 1024, т.е. 8000000/1042=7812,5Гц (или 128мс)
   TCNT0=128; //значение щ0ччика 7812,5/128=61Гц (или 16мс)
   TIMSK|=(1<<TOIE0); //разрешаем прерывание таймера0 по переполнению
   
   //Баловство-приветствие
   lcd_init(); /* Initialize LCD */
   _delay_ms(200);
   lcd_putc(0x56); //V
   _delay_ms(200);
   lcd_putc(0x41); //A
   _delay_ms(200);
   lcd_putc(0x44); //D
   _delay_ms(200);
   lcd_putc(0x45); //E
   _delay_ms(200);
   lcd_putc(0x47); //G
    _delay_ms(200);
   lcd_locate(1,3); //ставим курсор на вторую строку, 4-е знакоместо
   lcd_putc(0x44); //D
   _delay_ms(200);
   lcd_putc(0x41); //A
   _delay_ms(200);
   lcd_putc(0x44); //D
   _delay_ms(200);
   lcd_putc(0x45); //E
    _delay_ms(200);
   lcd_putc(0x47); //G
    _delay_ms(500);
   lcd_locate(0,0); //почему-то нужен возврат на нулевую позицию, я х.з?
    lcd_putc('\f'); //очистка экрана и возврат курсора "домой"

    sei(); //сеем

    while(1) //бесконечный цикл
    {
        if(keys==1) //если флаг разрешения опроса кнопок поднят, то
        {
         buttons(); //опрашиваем кнопки
        }
    }       
}
ИзвЕните от слова - веник, ИзвИните от слова - вина.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15545
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Обработка нажатия кнопки в AVR...

Сообщение BOB51 »

Необходим алгоритм для определения последней устойчивой КОМБИНАЦИИ нажатых/активных кнопок, а не "поштучное" оценивание каждой кнопы в отдельности.
8)
Без схемотехники кноп затруднительно подсказать...
:dont_know:
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Обработка нажатия кнопки в AVR...

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15545
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Обработка нажатия кнопки в AVR...

Сообщение BOB51 »

Под ассемблером...
буфер статуса ЛВК получает значение при первом обнаружении какого-либо нажатия
при контроле антидребезга снова чтение
если комбинация совпала с предыдущей - исполняем
если иная - замена содержимого в буфере и повтор антидребезга
если ВСЕ сброшены - возврат в исходное состояние.
:roll:
Ну а по завершении обработки цикл ожидания "полного отпускания".
Как под Си... ешшо не пробовал...
:dont_know:
Ответить

Вернуться в «Периферия»