Официальный сайт компании Arduino по адресу arduino.cc
Энкодер меняет значение после второго поворота.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Чт, 04/07/2019 - 20:25
Приветствую всех. Програмист я не очень, поэтому прошу помощи.
Нужно что-то попровить или добавить, чтобы при одном повороте энкодера менялось значение(громкость+/-), а не как сейчас при втором.
Работа энкодера описана внизу, строка 432
П.С. Скетч компелируется только в старой IDE (1.0.5)
/// Для работы требуется модифицированный HID.cpp отсюда https://github.com/aduitsis/ardumultimedia /// Заменить им оригинал в папке C:\Program Files\Arduino\hardware\arduino\cores\arduino /// Проект: http://pccar.ru/showthread.php?t=19903 /// Контакты: icq - 266-666. ////////Библиотеки//////// #include <Bounce.h> // Устраняет дребезг кнопок #include <Timer.h> // Таймер ////////Входы//////// /// Входы энкодера int EncButtonPin = 2; //Кнопка энкодера const int pin_A = 3; //вход энкодера А const int pin_B = 4; //вход энкодера В /// Входы джойстика int JoyUp = 7; //UP int JoyLeft = 6; //LEFT int JoyDown = 5; //DOWN int JoyRight = 8; //RIGHT ////////Убираем дребезг//////// Bounce EncButton = Bounce(EncButtonPin, 50); //Убираем дребезг кнопки энкодера Bounce JoyUpButton = Bounce(JoyUp, 50); //Убираем дребезг Bounce JoyLeftButton = Bounce(JoyLeft, 50); //Убираем дребезг Bounce JoyDownButton = Bounce(JoyDown, 50); //Убираем дребезг Bounce JoyRightButton = Bounce(JoyRight, 50); //Убираем дребезг ////////END Убираем дребезг//////// ////////Переменные//////// int longPressStickVal; //НЕ МЕНЯТЬ//Положение стика boolean powerOn = LOW; //Девайс вкл/выкл boolean needEnter = LOW; //Надо ли посылать код кнопки ENTER boolean pPowerOff = LOW; //Зажигание выключено, запущен таймер отключения boolean joystickPress = LOW; boolean joystickLongPress = LOW; boolean altTabFirstPress = HIGH; //Первое нажатие alt+tab boolean longIrPress = LOW; //Долгое нажатие кнопок с двойной функцией на ИК-пульте boolean changeVolEnable = HIGH; //Можно посылать следующее нажатие кнопки громкость (для энкодера) boolean muted = LOW; //Надо ли приглушать звук /// Для энкодера unsigned long currentTime; unsigned long loopTime; unsigned char encoder_A; unsigned char encoder_B; unsigned char encoder_A_prev=0; ////////Таймеры//////// Timer timer; int encBtnPressTimer; //Таймер нажатия кнопки энкодера int joyTimer; //Таймер джойстика int longPressStickTimer; //Таймер длинного нажатия на стик int altTabTimer; //Таймер ALT+TAB int releaseVolTimer; //Отпустить кнопку громкости int changeVolTimer; //Чтобы не посылать медиакоды слишком часто при вращении энкодера int longIrTimer; //Долгое нажатие кнопок с двойной функцией на ИК-пульте int sendShortIrTimer; //Короткое нажатие кнопок с двойной функцией на ИК-пульте int longIrCounterTimer; //Таймер сброса длинного нажатия кнопок с двойной функцией на ИК-пульте ////////Для медиакодов//////// struct kr { uint8_t modifiers; uint8_t reserved; uint8_t keys[6]; }; struct kr r1; struct cr { uint16_t code; uint8_t data[5]; }; struct cr r2; /// Запускается единожды при включении устройства void setup() { //Для энкодера pinMode(EncButtonPin, INPUT); digitalWrite(EncButtonPin, HIGH); // подключить подтягивающий резистор pinMode(pin_A, INPUT); digitalWrite(pin_A, HIGH); // подключить подтягивающий резистор pinMode(pin_B, INPUT); digitalWrite(pin_B, HIGH); // подключить подтягивающий резистор currentTime = millis(); loopTime = currentTime; //Для джойстика pinMode(JoyUp, OUTPUT); digitalWrite(JoyUp, HIGH); pinMode(JoyLeft, OUTPUT); digitalWrite(JoyLeft, HIGH); pinMode(JoyDown, OUTPUT); digitalWrite(JoyDown, HIGH); pinMode(JoyRight, OUTPUT); digitalWrite(JoyRight, HIGH); //Для клавиатуры Keyboard.begin(); r2.code=0x0000; for(int j=0;j<5;j++) r2.data[j] = 0x00; r1.modifiers=0x00; for(int j=0;j<6;j++) r1.keys[j] = 0x00; //Serial.begin(9600); } // Медиакоды // Тут немного понятнее #define HID_VOLUP 0x00E9 #define HID_VOLDOWN 0x00EA #define HID_PLAY 0x00CD // Play/Pause #define HID_NEXT 0x00B5 #define HID_PREV 0x00B6 #define HID_TRACK_INC 0x00B3 // don't work #define HID_TRACK_DEC 0x00B4 // don't work /////////////////////////////// #define HID_STOP 0x00B7 #define HID_MUTE 0x00E2 #define HID_HOME 0x0223 #define HID_CALC 0x0192 #define HID_MAIL 0x018A #define HID_POWER 0x0034 #define HID_WWW_SEARCH 0x0221 /////////////////////////////// #define KEY_ENTER 0xB0 #define KEY_UP 0xDA #define KEY_DOWN 0xD9 #define KEY_LEFT 0xD8 #define KEY_RIGHT 0xD7 #define KEY_ESC 0xB1 #define KEY_MENU 0xED #define KEY_ALT 0x82 #define KEY_TAB 0xB3 uint16_t command = 0; ////////////////////////////////////////////////////////////////////////////////////////////// /// Настройка действий джойстика и энкодера ////////////////////////////////////////////////////////////////////////////////////////////// /* Если нужно сэмулировать нажатие обычной кнопки: Keyboard.write(KEY_LEFT); //Serial.println("PRESS LEFT"); Если нужно сэмулировать нажатие медиа кнопки: command = HID_PREV; pressMediaKey(); */ ///////////////////////////////////////////////////////////////////////////////////////////// /// Короткие нажатия void Joy_Up() { Keyboard.write(KEY_UP); } void Joy_Left() { command = HID_PREV; pressMediaKey(); } void Joy_Down() { Keyboard.write(KEY_DOWN); } void Joy_Right() { command = HID_NEXT; pressMediaKey(); } void Enc_Left() { changeVolEnc(0); // Vol- } void Enc_Right() { changeVolEnc(1); // Vol+ } void Enc_Press() { //Keyboard.write(KEY_ENTER); command = HID_PLAY; pressMediaKey(); } /// Длительные нажатия void Joy_Up_Long() { Keyboard.write(KEY_ESC); } void Joy_Left_Long() { command = HID_TRACK_DEC; pressMediaKey(); } void Joy_Down_Long() { Keyboard.write(KEY_MENU); } void Joy_Right_Long() { command = HID_TRACK_INC; pressMediaKey(); } void Enc_Press_Long() { Keyboard.write(KEY_ENTER); } void Enc_Press_Left() { //Serial.println("<__"); /* needEnter = LOW; timer.stop(encBtnPressTimer); //Обнуляем таймер если крутится энкодер //Если до этого делали ALT+TAB отпускаем if(boolean(altTabFirstPress)==LOW){ altTabFirstPress=HIGH; Keyboard.press(KEY_ESC); Keyboard.release(KEY_ESC); Keyboard.release(KEY_ALT); Keyboard.releaseAll(); return; } else{ //Serial.println("<__"); command = HID_HOME; pressMediaKey(); } //*/ } void Enc_Press_Right() { //Serial.println("__>"); /* needEnter = LOW; timer.stop(encBtnPressTimer); // Обнуляем таймер, если крутится энкодер doAltTab(); //*/ } ///////////////////////////////////////////////////////////////////////////////////////////// /// END Настройка действий джойстика и энкодера ///////////////////////////////////////////////////////////////////////////////////////////// /// Основной цикл, выполняется все время, пока работает устройство void loop() { //ACC_Control(); //Rear_Control(); Enc_Btn_Control(); Encoder(); timer.update(); } //Обработчик нажатия кнопки энкодера и джойстика void Enc_Btn_Control() { if(JoyUpButton.update()){ if(JoyUpButton.read()==LOW){ longPressStickVal = 0; //Serial.println("PressUp"); timer.stop(encBtnPressTimer); //Обнуляем таймер выключения при длительном удержании кнопки timer.stop(joyTimer); joystickPress = HIGH; longPressStickTimer = timer.after(1000, longStickPress); //Запуск таймера длинного нажатия на стик } if(JoyUpButton.read()==HIGH){ timer.stop(longPressStickTimer); //Обнуляем таймер длительного нажатия if(boolean(joystickLongPress)==LOW){ /// Нажатие кнопки джойстика UP Joy_Up(); } else{ joystickLongPress=LOW; } joyTimer = timer.after(250, joyPressToggle); } } if(JoyLeftButton.update()){ if(JoyLeftButton.read()==LOW){ longPressStickVal = 1; //Serial.println("PressLeft"); timer.stop(encBtnPressTimer); //Обнуляем таймер выключения при длительном удержании кнопки timer.stop(joyTimer); joystickPress = HIGH; longPressStickTimer = timer.after(1000, longStickPress); //Запуск таймера длинного нажатия на стик } if(JoyLeftButton.read()==HIGH){ timer.stop(longPressStickTimer); //Обнуляем таймер длительного нажатия if(boolean(joystickLongPress)==LOW){ /// Нажатие кнопки джойстика LEFT Joy_Left(); } else{ joystickLongPress=LOW; } joyTimer = timer.after(250, joyPressToggle); } } if(JoyDownButton.update()){ if(JoyDownButton.read()==LOW){ longPressStickVal = 2; //Serial.println("PressDown"); timer.stop(encBtnPressTimer); //Обнуляем таймер выключения при длительном удержании кнопки timer.stop(joyTimer); joystickPress = HIGH; longPressStickTimer = timer.after(1000, longStickPress); //Запуск таймера длинного нажатия на стик } if(JoyDownButton.read()==HIGH){ timer.stop(longPressStickTimer); //Обнуляем таймер длительного нажатия if(boolean(joystickLongPress)==LOW){ /// Нажатие кнопки джойстика DOWN Joy_Down(); } else{ joystickLongPress=LOW; } joyTimer = timer.after(250, joyPressToggle); } } if(JoyRightButton.update()){ if(JoyRightButton.read()==LOW){ longPressStickVal = 3; //Serial.println("PressRight"); timer.stop(encBtnPressTimer); //Обнуляем таймер выключения при длительном удержании кнопки timer.stop(joyTimer); joystickPress = HIGH; longPressStickTimer = timer.after(1000, longStickPress); //Запуск таймера длинного нажатия на стик } if(JoyRightButton.read()==HIGH){ timer.stop(longPressStickTimer); //Обнуляем таймер длительного нажатия if(boolean(joystickLongPress)==LOW){ /// Нажатие кнопки джойстика RIGHT Joy_Right(); } else{ joystickLongPress=LOW; } joyTimer = timer.after(250, joyPressToggle); } } if(EncButton.update()){ /// Если до этого делали ALT+TAB - отпускаем if(boolean(altTabFirstPress)==LOW){ altTabFirstPress=HIGH; Keyboard.releaseAll();//На всякий случай отпустим все кнопки)) }; if(( (JoyUpButton.read() == HIGH) && (JoyLeftButton.read() == HIGH) && (JoyDownButton.read() == HIGH) && (JoyRightButton.read() == HIGH) && (boolean(joystickPress) == LOW) )){ if(EncButton.read()==LOW){ longPressStickVal = 10; timer.stop(encBtnPressTimer); //Обнуляем таймер выключения при длительном удержании кнопки timer.stop(joyTimer); //////joystickPress = HIGH; // Обязательно должно быть закомментировано - иначе обычное и долгое нажатия вместе не работают!!! longPressStickTimer = timer.after(1000, longStickPress); //Запуск таймера длинного нажатия на стик } if(EncButton.read()==HIGH){ timer.stop(longPressStickTimer); //Обнуляем таймер длительного нажатия if(boolean(joystickLongPress)==LOW){ /// Короткое нажатие центральной кнопки энкодера Enc_Press(); } else{ joystickLongPress=LOW; } joyTimer = timer.after(250, joyPressToggle); } } } // END EncButton.update() } /// Длинные нажатия джойстика в стороны void longStickPress() { if(longPressStickVal == 0){ //Serial.println("PRESS UP LONG"); Joy_Up_Long(); } if(longPressStickVal == 1){ //Serial.println("PRESS LEFT LONG"); Joy_Left_Long(); } if(longPressStickVal == 2){ //Serial.println("PRESS DOWN LONG"); Joy_Down_Long(); } if(longPressStickVal == 3){ //Serial.println("PRESS RIGHT LONG"); Joy_Right_Long(); } if(longPressStickVal == 10){ /// Длинное нажатие центральной кнопки энкодера Enc_Press_Long(); } joystickLongPress = HIGH; } /// Переключалка состояния переменной джойстика void joyPressToggle() { //Serial.println("joyPressToggle"); joystickPress = LOW; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Обработчик энкодера - реализуем принцип работы инкрементного энкодера//////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Encoder() { currentTime = millis(); if(currentTime >= (loopTime + 0.5)){ // проверяем каждые 5мс (200 Гц) encoder_A = digitalRead(pin_A); // считываем состояние выхода А энкодера encoder_B = digitalRead(pin_B); // считываем состояние выхода B энкодера if((!encoder_A) && (encoder_A_prev)){ // если состояние изменилось с положительного к нулю if(encoder_B) { if ( EncButton.read() == HIGH) { //Serial.println("<--"); /// Крутим энкодер влево //Enc_Left(); changeVolEnc(0); // Vol- } if ( EncButton.read() == LOW) { //Serial.println("<__"); /// Нажатие кнопки энкодера + поворот энкодера влево Enc_Press_Left(); } } else { if ( EncButton.read() == HIGH) { //Serial.println("-->"); /// Крутим энкодер вправо //Enc_Right(); changeVolEnc(1); // Vol+ } if ( EncButton.read() == LOW) { //Serial.println("__>"); /// Нажатие кнопки энкодера + поворот энкодера вправо Enc_Press_Right(); } } } encoder_A_prev = encoder_A; // сохраняем значение А для следующего цикла loopTime = currentTime; } } ///////////////////////////////////////////////////////////// /// Различные служебные функции ///////////////////////////////////////////////////////////// /// Меняем громкость с энкодера: /// changeVolEnc(0) = Vol- /// changeVolEnc(1) = Vol+ void changeVolEnc(boolean arg){ timer.stop(changeVolTimer); changeVolTimer = timer.after(170, toggleChangeVolEnable); //Serial.println(arg) ; if(arg==0){ if(boolean(changeVolEnable)==HIGH){ muted = LOW; changeVolEnable = LOW; command = HID_VOLDOWN; r2.code = command; HID_SendReport(3,&r2,sizeof(struct cr)); //Serial.println("VOL -"); } } if(arg==1){ if(boolean(changeVolEnable)==HIGH){ muted = LOW; changeVolEnable = LOW; command = HID_VOLUP; r2.code = command; HID_SendReport(3,&r2,sizeof(struct cr)); //Serial.println("VOL +"); } } } void toggleChangeVolEnable(){ timer.stop(changeVolTimer); changeVolEnable = HIGH; r2.code = 0x0000; HID_SendReport(3,&r2,sizeof(struct cr)); //Serial.println("VOL R"); } /// Эмуляция нажатия медиа кнопок void pressMediaKey(){ //onPress r2.code = command; HID_SendReport(3,&r2,sizeof(struct cr)); //onRelease r2.code = 0x0000; HID_SendReport(3,&r2,sizeof(struct cr)); } /// Функционал ALT+TAB void doAltTab(){ if(boolean(altTabFirstPress)==HIGH){ altTabFirstPress = LOW; Keyboard.press(KEY_ALT); Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); } else{ Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); } }
код большой так просто не найти. Тем более в программе есть явные ошибки. Например, прямо в самом начале работы с энкодером - строка 434 - написана чушь, так со временем не работают
Писали его в далеком 2013 году. Он загружается и работает, только проблема с поворотами.
только проблема с поворотами.
В этом коде много проблем. Обратитесь к его автору. Разребать их все просто так врядли найдутся охотники.