Обращние к индексу массива

Re0s
Offline
Зарегистрирован: 08.08.2019

Приветствую!

Новичок, пытаюсь написать свой первый скетч для подключения нескольких кнопок к одному выходу arduino nano.

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

Напряжения перевожу в АЦП и создаю из этого одномерный массив. Соответственно теперь напряжение при нажатии каждой из кнопок соответствует её номеру (индексу) в заданном массиве.

Как мне обратиться к номеру кнопки, а не к значению АЦП, если я хочу чтобы при нажатии определённо кнопки выполнялось действие?

Насколько я понимаю, это должно выполняться через имя переменной NumberToValue (см. часть скетча ниже) 

{
int NumberToValue (int value)
int values[8] = {128, 144, 169, 204, 255, 341, 511, 1023}; //массив для 8 кнопок по значением АЦП
int error = 15; // Погрешность
for (int i = 0; i <= 7; i++)
{
if (value <= values[i] + error && value >= values[i] - error) return i;
}
return -1; // Значение не принадлежит заданному диапазону
}

Но при попытке обращения к ней (см. часть скетча ниже)

if (NumberToValue == 3)

получаю ошибку

C:\ARDUINO\1\1.info: In function 'void loop()':
C:\ARDUINO\1\1.info:180:39: warning iso c++ forbids comparison between pointer and integer [-fpermissive]
if (NumberToValue == 3)

Если же указать значение массива, то ошибок нет и всё компилируется, но это не тот результат, что мне нужен.

Я конечно могу просто задать диапозон для полученных значений АЦП от нажатия кнопки, но с массивом было бы проще..

Подскажите, как правильно решить данную задачу?

b707
Offline
Зарегистрирован: 26.05.2017

приведите скетч полностью, судя по ошибке. вы в скетче обращаетесь к функции не так, как в показанном примере

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

Re0s
Offline
Зарегистрирован: 08.08.2019

Так я и не скрываю что скопипастил с просторов интернета, об этом писал в начале :)

Моё понимание работы это функции вероятно отличается от правильного, скажем так..

Скетч ниже, это программа для универсального пульта от ТВ и ресиверов, там много лишнего, что я ещё только планирую задействовать, просто пока хочу эту задачурешить, а дальше буду решать остальные. 

//подключаю 8 кнопок к порту A0, резисторы 10К
//подключаю ИК к порту D6

#include <IRremote.h> //Библиотека для ИК диода
IRsend irsend;

const int IR = 6; // присваиваю переменной IR порт D6 (один из ШИМ - 3,5,6,9,10,11)
IRrecv irrecv(IR); //присваиваю порт ИК Диоду

//Частоты кнопок для работы с ресивером ONLIME, разбиты на связки из 8, каждая из которых подключается к отдельному порту ардуино (7 портов)

#define O_ONOFF 0x807F807F //Кнопка Включения/Выключения
#define O_MUTE 0x807F48B7 //Кнопка Mute
#define O_1 0x807F00FF //Кнопка 1
#define O_2 0x807F00FF //Кнопка 2
#define O_3 0x807F00FF //Кнопка 3
#define O_4 0x807F00FF //Кнопка 4
#define O_5 0x807F00FF //Кнопка 5
#define O_6 0x807F00FF //Кнопка 6

#define O_7 0x807F00FF //Кнопка 7
#define O_8 0x807F00FF //Кнопка 8
#define O_9 0x807F00FF //Кнопка 9
#define O_TVP 0x807F00FF //Кнопка TV Portal
#define O_0 0x807F00FF //Кнопка 0&@_
#define O_MENU 0x807F00FF //Кнопка MENU
#define O_PLAY 0x807F00FF //Кнопка PLAY
#define O_PAUSE 0x807F00FF //Кнопка PAUSE

#define O_STOP 0x807F00FF //Кнопка STOP
#define O_REC 0x807F00FF //Кнопка REC
#define O_REW 0x807F00FF //Кнопка REWIND
#define O_FOR 0x807F00FF //Кнопка FORWARD
#define O_2REW 0x807F00FF //Кнопка 2xREWIND
#define O_2FOR 0x807F00FF //Кнопка 2xFORWARD
#define O_RED 0x807F00FF //Кнопка RED
#define O_GREEN 0x807F00FF //Кнопка GREEN

#define O_YELLOW 0x807F00FF //Кнопка YELLOW
#define O_BLUE 0x807F00FF //Кнопка BLUE
#define O_MEDIA 0x807F00FF //Кнопка MEDIA
#define O_GUIDE 0x807F00FF //Кнопка GUIDE
#define O_LEFT 0x807F00FF //Кнопка LEFT
#define O_UP 0x807F00FF //Кнопка UP
#define O_RIGHT 0x807F00FF //Кнопка RIGHT
#define O_DOWN 0x807F00FF //Кнопка DOWN

#define O_OK 0x807F00FF //Кнопка OK
#define O_EXIT 0x807F00FF //Кнопка EXIT
#define O_BACK 0x807F00FF //Кнопка BACK
#define O_VOLUP 0x807F00FF //Кнопка VOLUME +
#define O_VOLDWN 0x807F00FF //Кнопка VOLUME -
#define O_LIST 0x807F00FF //Кнопка LIST
#define O_I 0x807F00FF //Кнопка I
#define O_CHUP 0x807F00FF //Кнопка CHANNEL +

#define O_CHDWN 0x807F00FF //Кнопка CHANNEL -
#define O_OPTPLUS 0x807F00FF //Кнопка OPT+
#define O_LANG 0x807F00FF //Кнопка LANGUAGE
#define O_SUB 0x807F00FF //Кнопка SUBTITLE
#define O_RADIO 0x807F00FF //Кнопка TV/RADIO
#define O_TEXT 0x807F00FF //Кнопка TEXT
#define O_SOURCE 0x807F00FF //Кнопка SOURCE
#define O_VF 0x807F00FF //Кнопка V-FORMAT

#define O_WIDE 0x807F00FF //Кнопка WIDE

//Частоты кнопок для работы с телевизором Philips, разбиты на связки из 8, каждая из которых подключается к отдельному порту ардуино (3 порта)

#define P_ONOFF 0x807F807F //Кнопка Включения/Выключения
#define P_MUTE 0x807F48B7 //Кнопка Mute
#define P_SOURCE 0x807F00FF //Кнопка SOURCE
#define P_1 0x807F00FF //Кнопка 1
#define P_2 0x807F00FF //Кнопка 2
#define P_3 0x807F00FF //Кнопка 3
#define P_4 0x807F00FF //Кнопка 4
#define P_5 0x807F00FF //Кнопка 5

#define P_6 0x807F00FF //Кнопка 6
#define P_7 0x807F00FF //Кнопка 7
#define P_8 0x807F00FF //Кнопка 8
#define P_9 0x807F00FF //Кнопка 9
#define P_LEFT 0x807F00FF //Кнопка LEFT
#define P_UP 0x807F00FF //Кнопка UP
#define P_RIGHT 0x807F00FF //Кнопка RIGHT
#define P_DOWN 0x807F00FF //Кнопка DOWN

#define P_OK 0x807F00FF //Кнопка OK
#define P_BACK 0x807F00FF //Кнопка BACK

//Частоты кнопок для работы с ресивером Denon, все 4 подключаются к одному отдельному порту ардуино

#define D_ONOFF 0x807F807F //Кнопка Включения/Выключения
#define D_MUTE 0x807F48B7 //Кнопка Mute
#define D_VOLUP 0x807F00FF //Кнопка VOLUME +
#define D_VOLDWN 0x807F00FF //Кнопка VOLUME -

//Задаю переменные для обозначения портов ардуино
//Сначала аналог - 8 штук

const int A_0 = A0; // присваиваю переменной A0 порт A0
const int A_1 = A1; // присваиваю переменной A1 порт A1
const int A_2 = A2; // присваиваю переменной A2 порт A2
const int A_3 = A3; // присваиваю переменной A3 порт A3
const int A_4 = A4; // присваиваю переменной A4 порт A4
const int A_5 = A5; // присваиваю переменной A5 порт A5
const int A_6 = A6; // присваиваю переменной A6 порт A6
const int A_7 = A7; // присваиваю переменной A7 порт A7

//Теперь цифровые - 12шт

const int D_2 = 2; // присваиваю переменной D2 порт D2
const int D_3 = 3; // присваиваю переменной D3 порт D3
const int D_4 = 4; // присваиваю переменной D4 порт D4
const int D_5 = 5; // присваиваю переменной D5 порт D5
//на 6-м порту уже сидит ИК диод
const int D_7 = 7; // присваиваю переменной D7 порт D7
const int D_8 = 8; // присваиваю переменной D8 порт D8
const int D_9 = 9; // присваиваю переменной D9 порт D9
const int D_10 = 10; // присваиваю переменной D10 порт D10
const int D_11 = 11; // присваиваю переменной D11 порт D11
const int D_12 = 12; // присваиваю переменной D12 порт D12
const int D_13 = 13; // присваиваю переменной D13 порт D13

int keyValue = 0; //состояние покоя (эта переменная это значение напряжения при нажатии кнопки)

void setup()
{
  //переключаю порты ардуино на считывание и прием информации

  pinMode(A_0, INPUT); //порт A0 работает на считывание данных
  pinMode(A_1, INPUT); //порт A1 работает на считывание данных
  pinMode(A_2, INPUT); //порт A2 работает на считывание данных
  pinMode(A_3, INPUT); //порт A3 работает на считывание данных
  pinMode(A_4, INPUT); //порт A4 работает на считывание данных
  pinMode(A_5, INPUT); //порт A5 работает на считывание данных
  pinMode(A_6, INPUT); //порт A6 работает на считывание данных
  pinMode(A_7, INPUT); //порт A7 работает на считывание данных
  pinMode(D_2, INPUT); //порт D2 работает на считывание данных
  pinMode(D_3, INPUT); //порт D3 работает на считывание данных
  pinMode(D_4, INPUT); //порт D4 работает на считывание данных
  pinMode(D_5, INPUT); //порт D5 работает на считывание данных

  pinMode(IR, OUTPUT); //порт D6 теперь работает на считывание данных

  pinMode(D_7, INPUT); //порт D7 работает на считывание данных
  pinMode(D_8, INPUT); //порт D8 работает на считывание данных
  pinMode(D_9, INPUT); //порт D9 работает на считывание данных
  pinMode(D_10, INPUT); //порт D10 работает на считывание данных
  pinMode(D_11, INPUT); //порт D11 работает на считывание данных
  pinMode(D_12, INPUT); //порт D12 работает на считывание данных
  pinMode(D_13, INPUT); //порт D13 работает на считывание данных

  irsend.enableIROut(36); //режим ИК передатчика (ещё варианты: 38,40)

  Serial.begin(9600); //открываем последовательный порт, устанавливаем скорость 9600 бит/c
}

void loop() {
 int newKeyValue = GKV(); // Получаем актуальное состояние кнопок с коррекцией дребезга
    if (keyValue != newKeyValue) {        // Если новое значение не совпадает со старым - реагируем на него
      keyValue = newKeyValue;       // Актуализируем переменную хранения состояния
      if (keyValue > 0) // Если значение больше 0, значит кнопка нажата
      {
      if (GetButtonNumberByValue == 0)
        {
          delay(50);
          irsend.sendNEC(O_ONOFF, 32);
          delay(50);
                  }
        if (GetButtonNumberByValue == 1)
        {
          delay(50);
          irsend.sendNEC(O_MUTE, 32);
          delay(50);
                  }

        if (GetButtonNumberByValue == 2)
        {
          delay(50);
          irsend.sendNEC(O_1, 32);
          delay(50);
                  }

        if (GetButtonNumberByValue == 3)
        {
          delay(50);
          irsend.sendNEC(O_2, 32);
          delay(50);
                  }

        if (GetButtonNumberByValue == 4)
        {
          delay(50);
          irsend.sendNEC(O_3, 32);
          delay(50);
                  }

        if (GetButtonNumberByValue == 5)
        {
          delay(50);
          irsend.sendNEC(O_4, 32);
          delay(50);
                 }

        if (GetButtonNumberByValue == 6)
        {
          delay(50);
          irsend.sendNEC(O_5, 32);
          delay(50);
                  }

        if (GetButtonNumberByValue == 7)
        {
          delay(50);
          irsend.sendNEC(O_6, 32);
          delay(50);
                  }
      }}}
    
    int GKV() {         // Функция устраняющая дребезг
      static int   count;
      static int   oldKeyValue; // Переменная для хранения предыдущего значения состояния кнопок
      static int   innerKeyValue;

      // Здесь уже не можем использовать значение АЦП, так как оно постоянно меняется в силу погрешности
      int actualKeyValue = GetButtonNumberByValue(analogRead(A_0));  // Преобразовываем его в номер кнопки, тем самым убирая погрешность

      if (innerKeyValue != actualKeyValue) {  // Пришло значение отличное от предыдущего
        count = 0;                            // Все обнуляем и начинаем считать заново
        innerKeyValue = actualKeyValue;       // Запоминаем новое значение
      }
      else {
        count += 1;                           // Увеличиваем счетчик
      }

      if ((count >= 10) && (actualKeyValue != oldKeyValue)) {
        oldKeyValue = actualKeyValue;         // Запоминаем новое значение
      }
      return    oldKeyValue;
    }

    int GetButtonNumberByValue(int value) {   // Новая функция по преобразованию кода нажатой кнопки в её номер
      int values[8] = {128, 144, 169, 204, 255, 341, 511, 1023};
      int error     = 15;                     // Величина отклонения от значений - погрешность
      for (int i = 0; i <= 7; i++) {
        // Если значение в заданном диапазоне values[i]+/-error - считаем, что кнопка определена
        if (value <= values[i] + error && value >= values[i] - error) return i;
      }
      return -1; // Значение не принадлежит заданному диапазону
    }
b707
Offline
Зарегистрирован: 26.05.2017

слушайте, вы совсем чтоли в этом коде ничего не понимаете?

У вас текущий номер кнопки уже сидит в переменной keyValue - так и используйте его! зачем вы в своих условиях (строка 165 и далее) снова вызываете GetButtonNumberByValue, да еще и с неправильным синтаксисом?

Re0s
Offline
Зарегистрирован: 08.08.2019

разве keyvalue, в данном случае, это не значение АЦП?

GetButtonNumberByValue я использую чтобы присвоить значению АЦП номер в массиве.

И соответтвенно по его значению хочу чтобы ИК диод посылал нужный код.

Что не так с синтаксисом?

b707
Offline
Зарегистрирован: 26.05.2017

Re0s пишет:

разве keyvalue, в данном случае, это не значение АЦП?

к чему эти вопросы - код ведь перед вами. Посмотрите сами, откуда берется значение keyvalue в строчках 160 и 162

Цитата:

Что не так с синтаксисом?

GetButtonNumberByValue - это функция. Синтаксис вызова функции смотрите в учебнике

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
C:\ARDUINO\1\1.info: In function 'void loop()':
C:\ARDUINO\1\1.info:180:39: warning iso c++ forbids comparison between pointer and integer [-fpermissive]
if (NumberToValue == 3)

в третьей строке должно быть NumberToValue(какое то начение или переменная)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пух, вылазь своими лямбдами фарцовать, без тебя тут не обойтись.

Re0s
Offline
Зарегистрирован: 08.08.2019

Спасибо, я сам себя запутал, когда решил, что keyvalue это значение АЦП.

Буду дальше допиливать код...

nik182
Offline
Зарегистрирован: 04.05.2015

Меня вот вопрос беспокоит. Сколько не пробовал кнопки на резисторах нажимать всегда разные значения дает. Но 1-2 разряда, но всё же. Выходил из положения тем, что делил результат на 64 и получал значения от 0 до 16 сразу значение нопки, которое использовал в программе без всяких переназначений и массивов.

Re0s
Offline
Зарегистрирован: 08.08.2019

Я правильно понимаю, что Вы значение АЦП делите на 64 ?

Если не сложно, можете покзазать пример кода?

nik182
Offline
Зарегистрирован: 04.05.2015

Простите не понял. key = analogRead(analogPin) / 64; Что тут может быть непонятного? Единственное что я делал, это в экселе посчитал номиналы резисторов так, что бы при нажатии кнопки напяжение на получившемся делителе после оцифровки попало точно в середину диапазона шага по 64 бита. Чтобы специально не подбирать номиналы резисторов. Получилось с первого раза, резисторы из стандартного ряда уложились в погрешность измерения. Ошибок определения кнопок не было.

Re0s
Offline
Зарегистрирован: 08.08.2019

Но значение же будет не целое, а Вы говорире про целые числа (0-16)

Допустим при 5v 1023/65=15,98

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Re0s пишет:

Но значение же будет не целое, а Вы говорире про целые числа (0-16)

Допустим при 5v 1023/65=15,98

если переменная результата описана как int - то  результат деления будет целым.

int key = 1023/65=15

Rostislav_lv
Offline
Зарегистрирован: 12.02.2019
Re0s
Offline
Зарегистрирован: 08.08.2019

Опять моя невнимательность....

спасибо!

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