| Alex15BV | 
			17.01.2019 11:13 | 
		 
		 
		 
		
		
		Доброго времени суток Всем. 
Поскольку в этой теме энкодер уже обсуждался, а резистивные кнопки - это основа конструкции: выложу пока здесь... Доведу до конечного вида - положу в "манипуляторы" 
... короче джойстик i-Drive из говна и палок: 
- Ардуино ПроМикро 
- жменька радиодеталек 
- энкодер за 50 рублей 
- крутилка
 
Функционал и принцип - на картинках. Имеет два режима работы, распознает длительность нажатия, в итоговом варианте имеет подсветку кнопок и индикацию режима работы. На фото прототип, созданный для проверки догадочек и отладки кода. Сам скетч:
 
	PHP код: 
	
		 
		
		
			
#include <avr/wdt.h>
 #include <Mouse.h>
 #include <Keyboard.h>
 #include <Tablet.h>
 
 // ----- пины Ардуино -----------------
 
 #define KeyAppPin 0     // кнопка APPs
 #define KeyModePin 1    // кнопка Mode
 #define KeyEncPin 2     // кнопка энкодера
 #define EncAcPin 3      // энкодер - канал А
 #define EncBcPin 5      // энкодер - канал В
 #define KeysPin A0      // кнопки управления
 #define MousePin A1     // кнопки джойстика
 #define LedPin 6        // светодиод медиа-режима
 
 // ----- рабочие переменные -----------
 
 unsigned long EventStart = 0;         // момент нажатия
 unsigned long TimePress = 0;          // длительность нажатия
 
 // ----- различные флаги --------------
 
 volatile bool RightMove = false;      // направления вращения энкодера
 volatile bool LeftMove = false;    
 volatile bool EncPress = false;       // нажатия кнопки энкодера
 volatile bool AppPress = false;       // кнопки APPs
 volatile bool MediaMode = false;      // кнопки MODE
 
 // ----- обработчики прерываний -------
 
 void EncoderMove() {        // вращение энкодера
   if (digitalRead(EncBcPin) == HIGH) {
     RightMove = true;
   }
   else {
     LeftMove = true;
   }
 }
 
 void KeyEncPress() {        // кнопка энкодера
   EncPress = true;
 }
 
 void KeyAppPress() {        // кнопка APPs
   AppPress = true;
 }
 
 void KeyModePress() {       // кнопка MODE
   MediaMode = !MediaMode;
   if (MediaMode){
     digitalWrite(LedPin, HIGH);
   }
   else {
     digitalWrite(LedPin, LOW);
   }
 }
 
 void setup() {
   pinMode(KeyModePin, INPUT_PULLUP);                                          // кнопка "Mode" - управляем интерфейсом / медиа-функциями
   attachInterrupt(digitalPinToInterrupt(KeyModePin), KeyModePress, FALLING);
   pinMode(KeyAppPin, INPUT_PULLUP);                                           // кнопка "APP" - при нажатии список запущеных приложений (ALT/TAB)
   attachInterrupt(digitalPinToInterrupt(KeyAppPin), KeyAppPress, FALLING);
   pinMode(KeyEncPin, INPUT_PULLUP);                                           // кнопка энкодера - при нажатии PLAY/PAUSE либо ENTER/ESCAPE
   attachInterrupt(digitalPinToInterrupt(KeyEncPin), KeyEncPress, FALLING);
   pinMode(EncAcPin, INPUT_PULLUP);                                            // канал-А энкодера - для отслеживания вращения
   attachInterrupt(digitalPinToInterrupt(EncAcPin), EncoderMove, FALLING);
   pinMode(EncBcPin, INPUT_PULLUP);                                            // канал-В энкодера - для определения направления вращения
   pinMode(LedPin, OUTPUT);
   digitalWrite(LedPin, LOW);
 
   analogReference(DEFAULT);           // Aref = 5V, подтягивающий резистор на линии кнопок - 4,7 кОм
 
   Keyboard.begin();                   // инициализация USB-HID интерфейсов
   Mouse.begin();
   wdt_enable(WDTO_4S);                // Активируем сторожевой таймер с интервалом 4 секунд
 }
 
 void loop() {
   
   static bool FindKey;                // признак найденной кнопки
   static int DataKey;                 // значение ADC-кнопки
   
   if (RightMove) {                    // обработка вращения энкодера: если вращаем вправо - увеличить громкость/стрелка вверх
     if (MediaMode) {
       Tablet.vol_up();
       Tablet.clear();
     }
     else {
       Keyboard.press(KEY_UP_ARROW);
       Keyboard.release(KEY_UP_ARROW);
     }
     RightMove = false;
   }
 
   if (LeftMove) {                     // если вращаем влево - уменьшаем громкость/стрелка вниз
     if (MediaMode) {
       Tablet.vol_down();
       Tablet.clear();
     }
     else {
       Keyboard.press(KEY_DOWN_ARROW);
       Keyboard.release(KEY_DOWN_ARROW);
     }
     LeftMove = false;
   }
 
   if (AppPress) {                     // кнопка "APPs"
     Keyboard.press(KEY_LEFT_ALT);
     while (digitalRead(KeyAppPin) == LOW) {
       Keyboard.press(KEY_TAB);
       Keyboard.release(KEY_TAB);
       delay(1000);
       wdt_reset();
     }
     Keyboard.release(KEY_LEFT_ALT);
     AppPress = false;
   }  
     
   if (analogRead(MousePin) > 800 && analogRead(KeysPin) > 800 && !EncPress) {   // пока кнопки не нажаты взводим на всякий случай таймер обработки нажатия
     EventStart = millis();
   }
  
   if (EncPress) {                               // обнаружили факт нажатия кнопки энкодера - определяем длительность нажатия
     delay(20);
     while (digitalRead(KeyEncPin) == LOW) {     // пока не отпустим -
       TimePress = millis() - EventStart;        // считаем время нажатия
       delay(10);
       wdt_reset();
     }
     if (TimePress <= 200) {                     // действуем по длительности нажатия, если короткое:
       if (MediaMode) {                          // в медиа-режиме - play/pause
         Tablet.play_pause();
         Tablet.clear();
       }
       else {
         Keyboard.press(KEY_RETURN);        // в режиме интерфейса - enter
         Keyboard.release(KEY_RETURN);        
       }
     }
     else {                                 // если длинное:
       if (MediaMode) {                     // в медиа-режиме - mute
         Tablet.mute();
         Tablet.clear();
       }
       else {                               // в режиме интерфейса - escape
         Keyboard.press(KEY_ESC);
         Keyboard.release(KEY_ESC);        
       }
     }
     EncPress = false;                      // сбрасываем флаг нажатия
   }
 
   if (analogRead(MousePin) < 800) {        // обнаружили факт нажатия кнопки джойстика
     delay(20);
     FindKey = false;
     DataKey = analogRead(MousePin);
     if (DataKey < 100 && !FindKey) {       // кнопка "UP" - резистор 1 кОм
       if (MediaMode) {
         Tablet.forward();
         Tablet.clear();
         delay(100);
       }
       else {
         Mouse.move(0, -10, 0);
       }
     FindKey = true;
     }
     if (DataKey < 350 && !FindKey) {       // кнопка "LEFT" - резистор 2 кОм
       if (MediaMode) {
         Tablet.previous();
         Tablet.clear();
         delay(100);
       }
       else {
         Mouse.move(-10, 0, 0);
       }
     FindKey = true;
     }
     if (DataKey < 600 && !FindKey) {       // кнопка "RIGHT" - резистор 3,9 кОм
       if (MediaMode) {
         Tablet.next();
         Tablet.clear();
         delay(100);
       }
       else {
         Mouse.move(10, 0, 0);
       }
     FindKey = true;
     }
     if (DataKey < 800 && !FindKey) {       // кнопка "DOWN" - резистор 10 кОм
       if (MediaMode) {
         Tablet.rewind();
         Tablet.clear();
         delay(100);
       }
       else {
         Mouse.move(0, 10, 0);
       }
     }
   }
   
   if (analogRead(KeysPin) < 800) {         // обнаружили факт нажатия кнопки управления
     delay(20);
     FindKey = false;
     DataKey = analogRead(KeysPin);
     while (analogRead(KeysPin) < 800) {
       TimePress = millis() - EventStart;
       delay(10);
       wdt_reset();
     }
     if (DataKey < 100) {                   // кнопка "Home/Menu" - на землю
       if (TimePress <= 200) {                     
         Tablet.home();
         Tablet.clear();
       }
       else {
         Keyboard.press(KEY_LEFT_CTRL);
         Keyboard.press(KEY_ESC);
         Keyboard.releaseAll();      
       }
     FindKey = true;  
     }
     if (DataKey < 350 && !FindKey) {      // кнопка "Enter/Esc" - резистор 1 кОм
       if (TimePress <= 200) {                     
         Mouse.click(MOUSE_LEFT);
       }
       else {
         Mouse.click(MOUSE_RIGHT);
       }
     }                      
   }
   wdt_reset();                            // производим периодический сброс таймера
 } 
 
		 
		
		 
	 
 За код не пинайте сильно - это ПЕРВАЯ моя программа для Ардуино в жизни. Скетч немножко не соответствует прототипу, а соответствует заказанным в Китае платам, уже скоро доедут :big:
 
Исходники все здесь:  информация по пульту управления 
	 |