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

Lictor
Offline
Зарегистрирован: 01.10.2015

Всем доброго дня, столкнулся с пролемой: собрал клавиатуру из резисторов, прописал промежутки в которых в зависимости от нажатой клавиши переменной присваивается значение. Но никак не могу загнать эти значения в массив. Предполагалось, что программа будет работать так: нажимаю на кнопку, переменной присваивается значение, затем пока нажата кнопка срабатывает последний if (благодаря задержке устраняется дребезг и не учитывается длительность нажатия клавиши). if выполняется 1 раз (тк кнопка уже не нажата, а если она не нжата, то значение на выходе 1020-1023) то for выполнится 1 раз и будет ждать следующего нажатия. Но как-то не сложилось: при нажатии любой клавиши массив сразу заполняеся ее значением на весь свой обьем. 

Так это... помогите кто чем может)) Буду весьма признателен.


byte a ;
byte b ;
byte c ;
byte d ;
byte e ;
byte f ;
byte g ;
byte h ;
int massive1[] = {a, b, c, d};
int massive2[] = {e, f, g, h};
const int analogInPin1 = A2;   // клавиатура 1
const int analogInPin2 = A3;   // клавиатура 2
int analog1 = 0;
int analog2 = 0;
int cifra = 25 ;
#include <LiquidCrystal.h> //Подключаем библиотеку для работы с LCD
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); // инициализируем LCD, указывая управляющие контакты

void setup() {
  // Serial.begin(9600); //монитор порта тестовая строка
  pinMode(analogInPin1, INPUT_PULLUP);
  pinMode(analogInPin2, INPUT_PULLUP);
  lcd.begin(20, 4);// задаем размерность дисплея
}
void loop() {
  analog1 = analogRead(analogInPin1);
  if (analog1 > 100 && analog1 < 300) {
    cifra = 1 ;
   }
  if (analog1 > 350 && analog1 < 440) {
    cifra = 2 ;
  }
  if (analog1 > 450 && analog1 < 510) {
    cifra = 3 ;
  }
  if (analog1 > 520 && analog1 < 580) {
    cifra = 4 ;
  }
  if (analog1 > 585 && analog1 < 645) {
    cifra = 5 ;
  }
 // lcd.setCursor(9, 0); //выставим курсор и введем  фразу тестовая строка
 // lcd.print(cifra);   //тестовая строка
 //  Serial.println(analog1);  //тестовая строка
  if ( analog1 < 999 && cifra != 25) {
    delay(400);
        int i;
    for (i = 0; i < 4; i = i + 1) {
      massive1[i] = cifra;
      lcd.setCursor(i,0); //выставим курсор и введем  фразу
  lcd.print(massive1[i]);

    } }
  } //не трогай!!!

 

 

Lictor
Offline
Зарегистрирован: 01.10.2015

Кажется я нашел решение. Насколько оно корректно и какие могут быть подводные камни?

 

byte a ;
byte b ;
byte c ;
byte d ;
byte e ;
byte f ;
byte g ;
byte h ;
int massive1[] = {a, b, c, d};
int massive2[] = {e, f, g, h};
const int analogInPin1 = A2;   // клавиатура 1
const int analogInPin2 = A3;   // клавиатура 2
int analog1 = 0;
int analog2 = 0;
int cifra = 25 ;
#include <LiquidCrystal.h> //Подключаем библиотеку для работы с LCD
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); // инициализируем LCD, указывая управляющие контакты
int i = 0;
void setup() {
  // Serial.begin(9600); //монитор порта тестовая строка
  pinMode(analogInPin1, INPUT_PULLUP);
  pinMode(analogInPin2, INPUT_PULLUP);
  lcd.begin(20, 4);// задаем размерность дисплея
}
void loop() {
  analog1 = analogRead(analogInPin1);
  if (analog1 > 100 && analog1 < 300) {
    cifra = 1 ;
   }
  if (analog1 > 350 && analog1 < 440) {
    cifra = 2 ;
  }
  if (analog1 > 450 && analog1 < 510) {
    cifra = 3 ;
  }
  if (analog1 > 520 && analog1 < 580) {
    cifra = 4 ;
  }
  if (analog1 > 585 && analog1 < 645) {
    cifra = 5 ;
  }
 // lcd.setCursor(9, 0); //выставим курсор и введем  фразу тестовая строка
 // lcd.print(cifra);   //тестовая строка
 //  Serial.println(analog1);  //тестовая строка
  if ( analog1 < 999 && cifra != 25) {
    delay(400);
        
    if (i < 4 ) {
      massive1[i] = cifra;
      lcd.setCursor(i,0); //выставим курсор и введем  фразу
  lcd.print(massive1[i]);
  i = i + 1;

    } }
  } //не трогай!!!

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Все неправильно.  Во первых посмотрите конструкцию if (...) {}; else if (...) {}; . Это облегчит код. Во вторых предусмотрите код отсутствия нажатия кнопки, который нужно обабатывать как кнопку, иначе вы не сможете получать событие "отпускание кнопки". В третьих - по истечении антидребезговой задержки вы должны вновь опросить порт и убедится, что там сохраняется нажатой та кнопка которая запустила задержку, в противном случае нужно считать, что ничего не нажато. Не сделайте ошибку: фиксировать нужно не показания порта, а именно номер кнопки, потому что показания ADC могут плавать. 

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

Lictor,

1. Что означает глубокомысленная конструкция в строка 1-9?

2. Для чего объявлен массив в строке 10, если он не используется?

3. Зачем переменные в строках 13-15 и 18 объявлены глобально, если они используются только в одной функции?

4. Строки 27-41 - почему, если допустим, сработает первый if, всё ревно выполняются все остальные, хотя они заведомо ложны?

5. Строки 27-41 - если прочитанное значение попало вне интервалов (например 301), то не выполнится ничего. Вамс это устраивает?

6. Строка 45. Я так понимаю, это условие, что что-то нажато? Но если хоть раз что-то было нажато, тот после этого переменная cifra уже никогда не становится равной 25. Значит "cifra != 25" будет истинно всегда. Вас это не смущает?

7. строка 46. Это что, задержка от дребезга? А почему не 40 000? Скорость работы на клавиатуре хорошего тайписта - 10Hz. За время Вашей задержки он уже четыре новые клавиши нажать успеет.

8. Строки 48-49. А что будет, i когда  достигнет значения 4? Всё просто перестанет работать?

 

 

Lictor
Offline
Зарегистрирован: 01.10.2015

1 Строки 1 -9 таки правда лишние.

2 массив будет использоваться в дальнейшем

3Верно, моя ошибка

4,5 Не понял, а почему остальные if выполнятся? Интервалы поправил.

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

7 это по сути кодовый замок, скорости набора не требуется. Поэтому 400

8 Нет там стоит if который при i == 4 будет выполнять прочие действия, я его здесь не показал, что бы не загромождать пример

Lictor
Offline
Зарегистрирован: 01.10.2015

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

Конструкцию if else расмотрю, благодарю

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015
Lictor пишет:
4,5 Не понял, а почему остальные if выполнятся? Интервалы поправил.
А с чего бы им не исполняться? Ну, допустим, сработало условие в строке 27, и cifra стала 1. Что должно помешать Вашему коду продолжать работать и честно проверять условия в строках 30, 33, 36 и 39? Ничего не помешает. Условия заведомо ложны, но он будет честно их проверять.
 
Lictor пишет:
7 это по сути кодовый замок, скорости набора не требуется. Поэтому 400
Это Вам так кажется. А любой человек, набирающий код будет набирать быстрее, чем одно нажатие в полсекунды. У него ничего не будет срабатывать. Он будет пробовать ещё и ещё, и называть Вас такими словами, повторять которые здесь я не решаюсь.
 
Почему не сделать нормальный фильтр дребезга? Хоть аппаратный, хоть программный?
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Lictor пишет:

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

Конструкцию if else расмотрю, благодарю

Волшебно :) Напрягитесь и прикинте что будет, если в вашем коде от замка будет две одинаковых цифры подряд ! А другие отличные от этих двух.

Кстати было бы интересно услышать что это за алгоритм подавлния дребезга, отличный от процедуры использования задержек ? 

 

Lictor
Offline
Зарегистрирован: 01.10.2015

использование керамических конденсаторов

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

brokly]</p> <p>[quote=Lictor пишет:

Кстати было бы интересно услышать что это за алгоритм подавлния дребезга, отличный от процедуры использования задержек ? 

Задержек в 400ms?

Вот ознакомьтесть, там нет чистых задержек, а есть периодические опросы - http://arduino.ru/forum/obshchii/drebezg-mozhet-komu-nibud-prigoditsya

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Мда... Что такое "чистые задержки " !? Переодический опрос без задержек , это как ? Не важно как отсчитываются промежутки между чтениями - ламерским delay или засечкой времени таймером, я например в случае резистивной клавиатуры использую для отсчета прерывания по результату ADC конвертации. 

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

Можно реализовать смешной алгоритм частотной фильтрации. Можнопридумать какую нибудь производную чухню, типа измерения периода дребезга. Но зачем ? Если есть нормальное и вменяемое простое решение.

А использование конденсатора в резистивной клавиатуре искажает результат, да и не алгоритм это вовсе.

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

brokly пишет:

Мда... Что такое "чистые задержки " !?

Вы решили поспорить о терминологии? Это не со мной. Мне неинтересно

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