Замените несколько потенциометров кнопками и одиночными потенциометрами.

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

Я создаю 4-тональный секвенсор, в котором я использую 4 потенциометра для изменения высоты каждого тона. Я хочу добавить больше ударов в секвенсор, поэтому я хотел бы иметь элегантное решение вместо того, чтобы продолжать добавлять потенциометры. Моя идея состояла в том, чтобы использовать 1 потенциометр для управления высотой тона и использовать несколько кнопок с одним потенциометром для этого процесса. Вобщем получается так: - Когда переключатель 1 = ВЫСОКИЙ, шаг 1 = аналоговое чтение (A0); - Когда switch2=HIGH, pitch2=analogRead(A0); Проблема в том, что когда я меняю питч1 и питч2, я получаю одинаковые значения, как только я нажимаю их переключатель. Мой код выглядит так:

   if(switch1state==HIGH)
  {
    Tone1Pot=analogRead(A0); // 0 – 1023
    pitch1=Tone1Pot/13;
  }

tone(speakerPin, notes[pitch1], 200);

Serial.print(pitch1);
Serial.print("     ");
delay(tempo);

if(switch2state==HIGH)
  {
    Tone2Pot=analogRead(A0); // 0 – 1023
    pitch2=Tone2Pot/13;  
  }

tone(speakerPin, notes[pitch2], 200);

Serial.print(pitch2);
Serial.print("     ");
delay(tempo);

Мне бы очень хотелось сохранить это значение аналогового показания, когда я нажимаю переключатель 1, и сохранять его до тех пор, пока переключатель 1 снова не перейдет в ВЫСОКОЕ состояние.

ИЗМЕНИТЬ:

Позвольте мне попытаться объяснить проблему лучше: У меня есть 2 кнопки и 1 потенциометр, все они входы. Код, к которому я стремлюсь, должен сделать следующее: 1 - При нажатии кнопки 1 я хочу прочитать значение потенциометра и сохранить его в переменной 1. Когда кнопка 1 не нажата, я хочу сохранить эту переменную. 2 - При нажатии кнопки 2 я хочу прочитать значение потенциометра и сохранить его в переменной 2. Когда кнопка2 не нажата, я хочу сохранить эту переменную. Я успешно добился этого, однако проблема возникает, когда я снова нажимаю кнопку 1, чтобы настроить переменную 1, переменная 2 также настраивается в процессе, даже когда я не нажимаю кнопку 2. Крис: Кнопки правильные, так как я могу изменить состояние цифровых контактов, когда нажимаю их (и я измеряю 5 В при нажатии). Мне не нужно, чтобы кнопки нажимались одновременно. Что мне нужно, так это кнопки для запуска события сохранения данных потенциометра только при соответствующем нажатии одной из них. jsotola - Извините за плохое объяснение. Я надеюсь, что этот лучше. Код:

#include "pitches.h"

int notes[]={

NOTE_B1,
NOTE_C2,
NOTE_CS2,
NOTE_D2,
NOTE_DS2,
NOTE_E2,
NOTE_F2,
NOTE_FS2,
NOTE_G2,
NOTE_GS2,
NOTE_A2,
NOTE_AS2,
NOTE_B2, 
NOTE_C3, 
NOTE_CS3,
NOTE_D3, 
NOTE_DS3,
NOTE_E3, 
NOTE_F3,
NOTE_FS3,
NOTE_G3, 
NOTE_GS3, 
NOTE_A3,  
NOTE_AS3, 
NOTE_B3,  
NOTE_C4,  
NOTE_CS4, 
NOTE_D4,  
NOTE_DS4, 
NOTE_E4,  
NOTE_F4,  
NOTE_FS4, 
NOTE_G4,  
NOTE_GS4, 
NOTE_A4,  
NOTE_AS4, 
NOTE_B4,  
NOTE_C5,  
NOTE_CS5, 
NOTE_D5,  
NOTE_DS5, 
NOTE_E5,  
NOTE_F5,  
NOTE_FS5, 
NOTE_G5,  
NOTE_GS5, 
NOTE_A5,  
NOTE_AS5, 
NOTE_B5,  
NOTE_C6,  
NOTE_CS6, 
NOTE_D6,  
NOTE_DS6, 
NOTE_E6,  
NOTE_F6,  
NOTE_FS6, 
NOTE_G6,  
NOTE_GS6, 
NOTE_A6,  
NOTE_AS6, 
NOTE_B6,  
NOTE_C7,  
NOTE_CS7, 
NOTE_D7,  
NOTE_DS7, 
NOTE_E7,  
NOTE_F7,  
NOTE_FS7, 
NOTE_G7,  
NOTE_GS7, 
NOTE_A7,  
NOTE_AS7, 
NOTE_B7,  
NOTE_C8, 
NOTE_CS8,
NOTE_D8,  
NOTE_DS8
};

int Tone = 0;
int speakerPin = 3;

int switch1=6;
int switch2=7;
int switch3=8;
int switch4=9;
int switch5=10;
int switch6=11;
int switch7=12;
int switch8=13;


void setup() {

Serial.begin(9600);

pinMode(switch1, INPUT);
pinMode(switch2, INPUT);
pinMode(switch3, INPUT);
pinMode(switch4, INPUT);
pinMode(switch5, INPUT);
pinMode(switch6, INPUT);
pinMode(switch7, INPUT);
pinMode(switch8, INPUT);


}

void loop() {

 // получаем входы потенциометров
//int TonePot = AnalogRead(A0); // 0 – 1023
//int DurationPot = AnalogRead(A1); // 0 – 1023
int TempoPot = analogRead(A2); // 0 – 1023

int Tone1Pot;
int Tone2Pot;
int Tone3Pot;
int Tone4Pot;
int Tone5Pot;
int Tone6Pot;
int Tone7Pot;
int Tone8Pot;

int Duration1Pot;
int Duration2Pot;
int Duration3Pot;
int Duration4Pot;
int Duration5Pot;
int Duration6Pot;
int Duration7Pot;
int Duration8Pot;


// вычисляем соответствующее, делим на 13, так как у нас 77 шагов. 1023/77 ~ 13
int pitch1;
int pitch2;
int pitch3;
int pitch4;
int pitch5;
int pitch6;
int pitch7;
int pitch8;

int pitch1stored;
int pitch2stored;

int noteduration1 = Duration1Pot/8;
int noteduration2 = Duration2Pot/8;
int noteduration3 = Duration3Pot/8;
int noteduration4 = Duration4Pot/8;
int noteduration5 = Duration5Pot/8;
int noteduration6 = Duration6Pot/8;
int noteduration7 = Duration7Pot/8;
int noteduration8 = Duration8Pot/8;

int tempo = TempoPot;


//Получить состояние переключателей, если ВЫСОКИЙ или НИЗКИЙ
int switch1state=digitalRead(switch1);
int switch2state=digitalRead(switch2);
int switch3state=digitalRead(switch3);
int switch4state=digitalRead(switch4);
int switch5state=digitalRead(switch5);
int switch6state=digitalRead(switch6);
int switch7state=digitalRead(switch7);
int switch8state=digitalRead(switch8);


////////////////////////////////////////Код генерации звука /////// ///////////////////////////

if(switch1state==HIGH)
  {
    Tone1Pot=analogRead(A0); // 0 – 1023
    pitch1=Tone1Pot/13;
  }

tone(speakerPin, notes[pitch1], 200);

//tone(speakerPin, 0, 200);}// отключаем звук

Serial.print("pitch1= ");
Serial.print(pitch1);
Serial.print("     ");
delay(tempo);



if(switch2state==HIGH)
  {
    Tone2Pot=analogRead(A0); // 0 – 1023
    pitch2=Tone2Pot/13;  
  }

tone(speakerPin, notes[pitch2], 200);

Serial.print("pitch2= ");
Serial.print(pitch2);
Serial.print("     ");
delay(tempo);



if(switch3state==HIGH)
  {
    Tone3Pot=analogRead(A0); // 0 – 1023
    pitch3=Tone3Pot/13;  
  }

tone(speakerPin, notes[pitch3], 200);

Serial.print("pitch3= ");
Serial.print(pitch3);
Serial.print("     ");
delay(tempo);
}

, 👍1

Обсуждение

чем вызвано это состояние? переключатель 1=ВЫСОКИЙ, @jsotola

Описание вашей проблемы мне непонятно, пожалуйста, уточните. Также, пожалуйста, предоставьте полный код, а не только небольшую его часть., @chrisl

«сохранить это значение аналогового показания, когда я нажимаю переключатель 1, и удерживать его до тех пор, пока переключатель 1 снова не станет ВЫСОКИМ» ... что это значит? ... что на самом деле означает «переключатель 1 снова становится ВЫСОКИМ»? ... я думаю, что ваша главная проблема в том, что вы на самом деле не знаете, как вы хотите, чтобы устройство работало, @jsotola


2 ответа


Лучший ответ:

1

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

У вас есть 8 кнопок, что кричит об использовании массивов (IMO, вы всегда должны использовать массивы, если у вас более 2 или 3 одинаковых кнопок). Сначала поместите контакты кнопок в массив:

#define N_BUTTONS 8
int button_pins[N_BUTTONS] = {6, 7, 8, 9, 10, 11, 12, 13};

Затем определите массив для хранения измеренных шагов (здесь он инициализирован 0):

int pitches[N_BUTTONS] = {0};

В вашей функции setup() вы можете перебрать массив button_pins, чтобы установить их в качестве входных данных:

for(int pin : button_pins) pinMode(pin, INPUT);

В функции loop() вы снова перебираете контакты кнопок, но на этот раз проверяете, нажата ли текущая кнопка. Если да, вы измеряете аналоговое напряжение, вычисляете шаг и сохраняете его в соответствующий элемент массива pitch:

for(int button=0;button < N_BUTTONS;button++){
    if(digitalRead(button_pins[button])){
        pitches[button] = analogRead(A0)/13;
    }
}

Это всегда работает для нескольких нажатых кнопок одновременно.

Также вам следует избегать вызовов delay() в вашей функции loop(). Вот только время, когда Ардуино ничего не может сделать, в том числе проверить ваши кнопки. Если вы хотите сделать что-то по времени, вам следует использовать неблокирующий стиль кодирования, как в примере BlinkWithoutDelay, который поставляется с Arduino IDE. По сути, он использует функцию millis() как часы, регулярно проверяя, прошло ли нужное время, и делая что-то только в том случае, если оно прошло; разрешить выполнение другого кода, если нет. В Интернете есть множество руководств по этому поводу.

Как вы видели выше, я не включил в свой ответ функцию tone(). Это потому, что вы должны отделить свой входной и выходной код. Приведенный выше код является входным кодом. Он сохраняет желаемые смолы в соответствующий массив. Затем, после этого кода, вы можете написать весь код, необходимый для вывода высоты тона в виде тонов (однако вы на самом деле хотите их выводить). Единственная реальная логическая связь между этими двумя частями кода — это массив pitch. Это упрощает использование большего количества различных входов (например, если вы хотите иметь кнопку сброса, которая устанавливает все высоты тона сразу на предопределенное значение). Также функция входного кода (который должен очень регулярно проверять кнопки, чтобы реагировать) не нарушается выходным кодом.

,

Большое спасибо за поддержку. Я соответствующим образом изменю свой код и свяжусь с вами, чтобы показать результаты., @Sushyoshi

Я пытаюсь скомпилировать ваш код, но столкнулся с проблемой, которую не могу решить для (кнопка int = 0; кнопка < N_BUTTONS; кнопка ++) { if(digitalRead(button_pins[button])){ высота тона[кнопка] = AnalogRead(A0)/13; } } Приведенный выше код дает мне следующую ошибку: _"статус выхода 1 ожидаемое основное выражение перед ';' токен"_ Есть предположения?, @Sushyoshi

Часть кода, который вы показываете, в порядке. Ошибка должна быть в остальной части кода, скорее всего выше, @chrisl

Я не могу найти, где ошибка. Я искал весь код, может быть, я что-то упустил. Код ошибки: **Arduino: 1.8.10 (Windows 10), плата: «Arduino/Genuino Uno» C:\Users\teclast\Documents\Arduino\Sequencer_Project_Version0.1\Sequencer_Project_Version0.1.ino: В функции 'void loop()': Sequencer_Project_Version0.1:105:36: ошибка: ожидаемое первичное выражение перед ';' жетон для (целая кнопка = 0; кнопка <N_BUTTONS; кнопка ++) { ^ статус выхода 1 ожидаемое основное выражение перед ';' токен**, @Sushyoshi

Я пытался заставить этот бит кода работать, и он не позволяет мне использовать код: 'для (кнопка int = 0; кнопка < N_BUTTONS; кнопка ++) {' Если я изменю **N_BUTTONS** на **8**, код будет принят. При этом я могу изменить значение высоты тона [0] с помощью аналогового считывания и кнопки [0], однако впоследствии я не могу изменить значение высоты тона [1] и так далее., @Sushyoshi

О, черт, я забыл установить определение на 8, вы совершенно правы. Конечно, он должен быть определен как 8. Я изменил код в своем ответе, теперь он должен работать, @chrisl

Спасибо. Это исправило это. Теперь он работает, как и ожидалось. Очень рад, что обратился за помощью, так как не думаю, что доберусь туда сам., @Sushyoshi


0

Итак, исходя из предоставленной вами информации, я понимаю, что проблема заключается в том, что операторы if(switch1state==HIGH) и `if(switch2state==HIGH)' оцениваются как истинные, если либо переключатель перевернут. Это означает, что происходит одно из следующих событий:

1) Где-то в коде вы смешиваете их значения и присваиваете одно значение другому

2) Ваша конфигурация контактов digitalRead неверна (либо неправильные контакты, либо неправильная конфигурация pupdr, поскольку я видел, как неправильные подтягивающие и подтягивающие резисторы распространяют неожиданное поведение по земле)

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

,