Как использовать потенциометр для доступа к данным в двумерном массиве?

Я пытаюсь создать двухмерный массив нот, разделенных на 3 гаммы. В каждой гамме по 3 ноты. Есть 3 кнопки для воспроизведения каждой ноты, и я хочу использовать доступный потенциометр для выбора каждой из воспроизводимых гамм.

Несмотря на мои поиски, я не могу понять, как это сделать правильно. Пока это то, что у меня есть.

Использование Arduino Uno:

// музыкальные ноты
int C = 1046;
int D = 1175;
int E = 1319;
int F = 1397;
int G = 1598;
int A = 1760;
int B = 1976;
int C1 = 2093;
int D1 = 2349;

const int numScales = 3;
const int numNotesPerScale = 3;

const int  notes[numScales][numNotesPerScale] = {
  {C, D, E},
  {F, G, A},
  {B, C1, D1}  
};


const int numberOfButtons = 3;
int buttonPin[numberOfButtons] = {2, 7, 4};
//int notes[numberOfButtons] = {C, D, E};
int ledPin[numberOfButtons] = {11, 10, 9};

int buttonState = 0;         // переменная для чтения статуса кнопки
int speaker = 3;                 // название клавиши динамика

void setup() {

  for (int i = 0; i < numberOfButtons; i++) {
    pinMode(buttonPin[i], INPUT);
    pinMode(ledPin[i], OUTPUT);
  }
  pinMode(speaker, OUTPUT);     // устанавливаем динамик в качестве выхода
}

void loop() {
  int numScales = map(analogRead(A2), 0, 1023, 0, 2);
  //int numScales = AnalogRead(A2/341);

  for (int i = 0; i < numberOfButtons; i++) {
    checkButton(buttonPin[i], notes[i], ledPin[i]);
  }
}

void checkButton(int buttonPin, int note, int ledPin)
{
  // прочитать состояние значения кнопки:
  buttonState = digitalRead(buttonPin);

  // проверяем, нажата ли кнопка. Если да, то состояние кнопки ВЫСОКОЕ:
  if (buttonState == HIGH){ 
    digitalWrite(ledPin, HIGH);
    tone(speaker, note);                 // воспроизвести ноту
    delay(100);                       // ждем 1/10 секунды
  }  } else {
    digitalWrite(ledPin, LOW);
    noTone(speaker);                  // остановить воспроизведение ноты
  }
}

, 👍1

Обсуждение

что ты не в состоянии понять? ... создать 2d-массив, прочитать статус кнопки, прочитать положение горшка или что-то еще? ... вам нужно определить, в чем заключается реальная проблема ... никто не сможет вам помочь, пока вы не узнаете, в чем вам нужна помощь, @jsotola

Я думаю, что мой горшок не распознается и вместо этого к моему массиву 2d обращаются как к одному массиву. Вот почему я не получаю никакой истинной последовательности нот. Мой вопрос в том, как мне взять «int numScales = map (analogRead (A2), 0, 1023, 0, 2);» и использовать его для доступа к весам?, @Robbie Perry


2 ответа


3

Использование функции Arduino map() кажется разумным подходом к этому, однако у вас есть проблема с индексацией.

if (numScales == 3); {

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

Учитывая только релевантное измерение, вы представляете массив из трех элементов, в котором будут допустимые номера элементов 0, 1 и 2

Вы вызываете map(analogRead(A2), 0, 1023, 0, 2);, который может выдавать результат в диапазоне 0-2, пока все хорошо.

Но затем проверьте значение 3, которое не только недопустимо, как в индексе массива из 3 элементов, но и не может быть создано вашим кодом.

Кроме того, вам, вероятно, следует прекратить попытки использовать переменную numScales для выполнения двойной задачи, сохраняя как начальный размер, так и позже также текущий индекс. И вам, вероятно, следует передать это как аргумент, а не делать его глобальной переменной.

Вы также не можете использовать текущий масштаб в качестве индекса в массиве заметок. Синтаксис двойного индексирования массива будет следующим: notes[x][y], но, конечно, это следует делать только с указателями на существующие элементы.

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

,

Я боюсь, что дерьмо в программировании на самом деле не позволяет мне правильно усвоить некоторые из этих ответов. Если я удалю "int numScales = map(analogRead(A2), 0, 1023, 0, 2);" и раскомментируйте "//int notes[numberOfButtons] = {C, D, E};" тогда каждая кнопка будет играть C, D или E. Это работает нормально, пока я не решил добавить способ изменения гаммы. Является ли двумерный массив лучшим способом сделать это, и это очень сложная проблема?, @Robbie Perry

Массив 2d не является необоснованным, используйте синтаксис индексации, указанный в этом посте, и убедитесь, что ваши индексы являются законными. Может быть, сначала сделать версию, которая распечатывает индексы, которые она будет использовать, но на самом деле их не использует. Поэкспериментируйте со своими кнопками и ручкой и убедитесь, что то, что они *будут* делать, разумно. Затем добавьте, чтобы он действительно это делал., @Chris Stratton

Вы также можете сгладить массив [x][y] до чего-то вроде array[x+(3*y)], @Chris Stratton

Одно упоминание о разумности меня пугает!!!!, @Robbie Perry

Как мне добавить свой обновленный код для анализа и дальнейших комментариев, пожалуйста?, @Robbie Perry


1
// музыкальные ноты
int C = 1046;
int D = 1175;
int E = 1319;
int F = 1397;
int G = 1598;
int A = 1760;
int B = 1976;
int C1 = 2093;
int D1 = 2349;

const int columns = 3;
const int scales = 3;
int potVal = 0;
const int  notes[scales][columns] = {
  {C, D, E},
  {F, G, A},
  {B, C1, D1}
};

const int numberOfButtons = 3;
int buttonPin[numberOfButtons] = {2, 7, 4};
int ledPin[numberOfButtons] = {11, 10, 9};

int buttonState = 0;         // переменная для чтения статуса кнопки
int speaker = 3;                 // название клавиши динамика

void setup() {
  Serial.begin(9600);

  for (int i = 0; i < numberOfButtons; i++) {
    pinMode(buttonPin[i], INPUT);
    pinMode(ledPin[i], OUTPUT);
  }
  pinMode(speaker, OUTPUT);     // устанавливаем динамик в качестве выхода
}

void loop() {
  int potVal = map(analogRead(A2), 0, 1024, 0, 3);
  Serial.println(notes[2][2]);
  for (int i = 0; i < numberOfButtons; i++) {
    //checkButton(buttonPin[i], notes[scales][columns], ledPin[i]);
    checkButton(potVal,i);
  }
}

void checkButton(int scaleNum, int buttonNum)
{
  // прочитать состояние значения кнопки:
  buttonState = digitalRead(buttonPin[buttonNum]);

  // проверяем, нажата ли кнопка. Если да, то состояние кнопки ВЫСОКОЕ:
  if (buttonState == HIGH) {
    digitalWrite(ledPin[buttonNum], HIGH);
    tone(speaker, notes[scaleNum][buttonNum]);                 // воспроизвести ноту
    delay(100);                       // ждем 1/10 секунды
  } else {
    digitalWrite(ledPin[buttonNum], LOW);
    noTone(speaker);                  // остановить воспроизведение ноты
  }
}
,

Ок, спасибо всем за помощь! Вот завершенный и работающий код для всех, кто может найти его полезным. Почему так сложно загрузить код на этот сайт?, @Robbie Perry

Этот код неверен. Как объяснялось ранее, 3 не является допустимым индексом в массиве из 3 элементов. Вы должны вернуть максимум вашей функции карты к 2, как это было раньше, а не к 3., @Chris Stratton

Извините, Крис, я продолжаю зацикливаться на этом, но недавно мне было указано, что это создает равномерный спред по всему диапазону банка и на самом деле никогда не дает значение 3. Я по-старому сопоставил его с 2, используя максимум 1023, и это создает проблемы, потому что 1 простирается почти до конца диапазона банков и продолжает чередоваться с 2, поэтому нет стабильности. ....... "1023/1024 составляет 2,9999 с чем-то, и поэтому округляется до 2. Отображение от 0 до 2 будет означать, что только самая последняя позиция будет отображаться до 2"., @Robbie Perry