Всем привет! Столкнулся с проблемой: создал массив из 5 кнопок и 5 лампочек, отслеживаю их нажатие и нужно сделать так, чтобы сценарий при нажатии отыгрывался только один раз. Всю ночь вчера просидел и так не разобрался. Как организовать отслеживание нажатия одной кнопки я разобрался, но как это сделать с массивом - пока не понял. Подскажите кто что сможет: PHP: #include <MIDI.h> // Simple tutorial on how to receive and send MIDI messages. // Here, when receiving any message on channel 4, the Arduino // will blink a led and play back a note for 1 second. MIDI_CREATE_DEFAULT_INSTANCE(); const int ledPin = 13; // Pin для встроенного диода const int myPins[] = {2, 3, 4, 5, 6}; //Массив пинов кнопок const int myNote[] = {76, 77, 78, 79, 80}; //Массив передаваемых данных const int myLed[] = {8, 9, 10, 11, 12}; // Массив светодиодов для реакции на нажатие int buttonState = 0; // Переменная состояния нажатия void setup() { pinMode(ledPin, OUTPUT); MIDI.begin(10); // Запускаем библиотеку MIDI на 10 канале Serial.begin(115200); for(int i=0;i<5;i++) { // Определяем пины кнопок как входящие данные pinMode(myPins[i], INPUT_PULLUP); } for(int i=0;i<5;i++) { // определяем пины светодиодов на исходящие данные pinMode(myLed[i], OUTPUT); } } void loop() { for(int i=0;i<5;i++) { // бегам по кнопкам buttonState = digitalRead(myPins[i]); // проверяем их состояние if (buttonState == LOW) { // если нажата, то выполняем сценарий MIDI.sendNoteOn(myNote[i],127,1); //отправляем ноту из массива myNote[], соответствующую кнопке digitalWrite(ledPin, HIGH); //Мигаем 13м пином digitalWrite(myLed[i], HIGH); // Включаем светодиот из массива myLed[], соответствующий нажатой кнопке } } } Сейчас код отправляет выполняет сценарий до тех пор, пока зажата кнопка, а хотелось бы сделать следующий алгоритм: нажимаем и держим кнопку, загорается соответствующая ей лампочка, выполняется сценарий один раз, лампочка продолжает гореть до тех пор, пока не отпустим кнопку. И так со всем массивом кнопок! Жду любых предложений!
Надо просто сохранять состояние кнопки, и запускать сценарий только по изменению этого состояния в сторону нажатия. Получается римерно так (код не проверялся, работа после копипаста не гарантируется): Код (Text): //В начале int buttonStates[5]={HIGH,HIGH,HIGH,HIGH,HIGH}; int pin13Time=0; ... void loop() { for(int i=0;i<5;i++) { // бегам по кнопкам buttonState = digitalRead(myPins[i]); // проверяем их состояние if (buttonState!=buttonStates[i]) // если состояние изменилось if (buttonState == LOW) { // если нажата, то выполняем сценарий MIDI.sendNoteOn(myNote[i],127,1); //отправляем ноту из массива myNote[], соответствующую кнопке digitalWrite(ledPin, HIGH); //Мигаем 13м пином pin13Time=millis(); // запоминаем, когда мигнули digitalWrite(myLed[i], HIGH); // Включаем светодиод из массива myLed[], соответствующий нажатой кнопке } else // кнопка отпущена { digitalWrite(myLed[i], LOW); // Выключаем светодиод из массива myLed[], соответствующий нажатой кнопке } buttonState=buttonStates[i]; // Сохраняем изменившееся значение } } if (millis()-pin13Time>500) // если 13-м мигнули больше полусекунды назад, то пора и загасить { digitalWrite(ledPin, HIGH); //Гасим 13-й } }
Благодарю, но, к сожалению, не работает. Лампочка загарается и залипает в таком состоянии и после отжатия кнопки, а данные MIDI.sendNoteOn(myNote,127,1); так же сыпятся в порт многочисленно. Скрипт, который я привел в топике, рабочий, но там проблема в том, что при зажатой клавише он сыпет MIDI.sendNoteOn(myNote,127,1); без остановки, а хотелось бы, чтобы это происходило один раз. Вот именно над этой проблемой и борюсь. Думаю ввести переменную именно для отслеживания отправки MIDI.sendNoteOn(myNote,127,1); и если отправка происходит один раз, то потом мы эту строку игнорируем и продолжаем светит лампочкой до того момента, когда отпустится кнопка. Могли бы Вы подсказать свое видение ситуации, иначе мое уже иссякает) В любом случае благодарен Вам за отзыв.
Мне кажется, что проблема в цикле: PHP: for(int i=0;i<5;i++) { … } Т.к. код для одной кнопки отрабатывается как нужно: PHP: #include <MIDI.h> // Simple tutorial on how to receive and send MIDI messages. // Here, when receiving any message on channel 4, the Arduino // will blink a led and play back a note for 1 second. MIDI_CREATE_DEFAULT_INSTANCE(); const int ledPin = 13; // Pin для встроенного диода const int buttonPin = 2; // Pin кнопки const int myLed = 8; // Pin контрольной лампы const int myNote = 76; // Pin кнопки int buttonState = 0; //Переменная состояния нажатия int lastButtonState = 0; //Последнее состояние нажатия void setup() { MIDI.begin(10); //Запускаем библиотеку MIDI на 10 канале Serial.begin(115200); pinMode(ledPin, OUTPUT); //13 Pin на выход pinMode(buttonPin, INPUT_PULLUP); //Копка с подтягивающим резистором на вход pinMode(myLed, OUTPUT); //Контрольная лампа на выход } void loop() { buttonState = digitalRead(buttonPin); //Определяем состояние if (buttonState != lastButtonState) { if (buttonState == LOW) { //если нажата digitalWrite(ledPin, HIGH); //Включаем светодиод на 13 Pin digitalWrite(myLed, HIGH); //Включаем контрольную лампу MIDI.sendNoteOn(myNote,127,1); //Отправляем данные } else { // кнопка отпущена digitalWrite(myLed, LOW); //Выключаем контрольный светодиод digitalWrite(ledPin, LOW); //Выключаем светодиод на 13 Pin } } lastButtonState = buttonState; //Запоминаем последнее состояние } Но стоит загнать это все в перебор массива кнопок for(int i=0;i<5;i++) {} как тут же все сыпется. Может есть альтернатива отслеживания нажатия кнопок из массива?
Попробуй библиотеку(описание),ссылка на саму библиотеку,в ней есть три примера использования , тебе надо change . Поиграйся со всеми, увидишь разницу. Спрашивай, если что будет не понятно- что смогу объясню. Из примера: Код (Text): #include <Bounce.h> #define BUTTON 2 // пин на которой кнопка #define LED 13 int ledValue = LOW; // This example changes the state of the LED everytime the button is pushed // Build the circuit indicated here: http://arduino.cc/en/Tutorial/Button Bounce bouncer = Bounce( BUTTON, 5 ); // антидребезг void setup() { pinMode(BUTTON,INPUT); pinMode(LED,OUTPUT); } void loop() { if ( bouncer.update() ) { if ( bouncer.read() == HIGH) { // если кнопка нажата if ( ledValue == LOW ) { // то, если было выключено ledValue = HIGH; // включаем } else { ledValue = LOW; // иначе выключаем } digitalWrite(LED,ledValue); } } }
Может я не заметил, но в программе нет кода для ожидания отпуска кнопки. По моему, после того как кнопка была нажата и сценарий выполнен следует ждать ее отпуска, например: Код (Text): delay(10); while (digitalRead(myPins[i]) {}; в ветке if после выполнения сценария. Задержка нужна для пропуска дребезга. Следующая строка подвешивает плату до тех пор пока нажатая кнопка не будет отпущена. После этого скетч продолжит опрашивать кнопки как обычно.
Всем спасибо! Рашил задачу! Привожу рабочий код ниже: PHP: #include <MIDI.h> // Добавляем библиотеку MIDI MIDI_CREATE_DEFAULT_INSTANCE(); /* Импортируем библиотеки nRF24l01*/ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> /* Обозначаем пины nRF24l01*/ #define CE_PIN 9 #define CSN_PIN 10 int myPins[] = {2, 3, 4, 5, 6}; //Массив пинов кнопок int myNote[] = {76, 77, 78, 79, 80}; //Массив передаваемых данных int myLed[] = {A1, A2, A3, A4, A5}; //Массив светодиодов для реакции на нажатие int sendOn[] = {false,false,false,false,false}; //Массив состояния нажатой кнопки int sendOff[] = {false,false,false,false,false}; //Массив состояния отжатой кнопки int midChannel = 2; //Канал Midi int buttonState = 0; //Переменная состояния нажатия const uint64_t pipe = 0xE8E8F0F0E1LL; // определяем канал связи беспроводных модулей /* Создаем радио канал*/ RF24 radio(CE_PIN, CSN_PIN); /* Создаем массив, который отправлем по радио*/ int MidOUT[3]={0,0,0}; void setup() { radio.begin(); radio.openWritingPipe(pipe); Serial.begin(115200); for(int i=0;i<5;i++) { pinMode(myPins[i], INPUT_PULLUP); //Определяем пины кнопок как входящие данные } for(int i=0;i<5;i++) { pinMode(myLed[i], OUTPUT); //определяем пины светодиодов на исходящие данные } } void loop() { for(int i=0;i<5;i++) { buttonState = digitalRead(myPins[i]); if (buttonState == LOW && sendOn[i] == false) // Нажатие клавиши { MIDI.sendNoteOn(myNote[i],127,midChannel); // Отправляем Миди сигнал в сериал digitalWrite(myLed[i], HIGH); // загорается контрольная лампочка sendOn[i] = true; // Команда Note On послана sendOff[i] = false; // Команда Note Off не послана MidOUT[0]=myNote[i]; // Забиваем массив для радиосигнала MidOUT[1]=127; MidOUT[2]=midChannel; radio.write(MidOUT, sizeof(MidOUT)); // Отправляем Миди сигнал по радио } else if (buttonState == LOW && sendOn[i] == true) // Если клавиша удерживается { digitalWrite(myLed[i], HIGH); // Лампа продолжает гореть sendOn[i] = true; sendOff[i] = false; } else if (buttonState == HIGH && sendOff[i] == false) // Если клавишу отпустили { MIDI.sendNoteOn(myNote[i],0,midChannel); // Отправляем Миди сигнал в сериал digitalWrite(myLed[i], LOW); // Гасим лампу sendOn[i] = false; sendOff[i] = true; MidOUT[0]=myNote[i]; // Забиваем массив для отправки по радио MidOUT[1]=0; MidOUT[2]=midChannel; radio.write(MidOUT, sizeof(MidOUT)); // Отправляем миди сигнал по радио каналу } } } Но вот есть проблема: при отправке сигнала по радиоканалу есть сильное запоздание. Т.е. для того, чтобы сигнал отправился нужно удерживать кнопку. И он не всегда отправляется. Пробовал устанавливать radio.write(MidOUT, sizeof(MidOUT)); перед закрытием цикла loop, скрипт работает как надо, но постоянно сыпет в радиосигнал значения, что не есть хорошо. Хочется отправлять в радио лишь только то, что нужно. Как побороть эту задержу в отправке?