Shadowcat

GyverWheel_My

Jul 2nd, 2020
1,982
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Скетч к проекту "Простой руль для ПК": страница проекта (схемы, описания)
  3.         https://alexgyver.ru/GyverWheel/ https://github.com/AlexGyver/GyverWheel/
  4.     PS: стандартный тестер геймпада в Win10: поиск/joy.cpl
  5. */
  6. /*
  7.         В библиотеке:
  8.     xAxis(int16_t a);   -32768, 32767 Руль      (Влево-Вправо, Левый гриб)
  9.     yAxis(int16_t a);   -32768, 32767 Сцепление (Вверх-вниз, Левый гриб)
  10.     rzAxis(int8_t a);   -128 до 127 Тормоз
  11.     zAxis(int8_t a);    -128 до 127 Газ
  12.     rxAxis(int16_t a);  -32768, 32767
  13.     ryAxis(int16_t a);  -32768, 32767
  14.         В реале:
  15.     xAxis(int16_t a);   -32768, 32767 Руль       (Влево-Вправо, Левый гриб)
  16.     yAxis(int16_t a);   -32768, 32767            (Вверх-вниз, Левый гриб)
  17.     rzAxis(int8_t a);   -32768, 32767            (Вверх-вниз, Правый гриб)
  18.     zAxis(int8_t a);    -32768, 32767            (Влево-Вправо, Правый гриб)
  19.     rxAxis(int16_t a);  -32768, 32767 скорее всего левый
  20.     ryAxis(int16_t a);  -32768, 32767  и правый курок (shoulder).
  21. */
  22. //
  23. // =========== НАСТРОЙКИ ===========
  24. // ВНИМАНИЕ! Максимум 8 осей и 32 кнопки!
  25. #define DEBUG 0       // режим отладки
  26. #define ENC_TYPE 0    // тип энкодера, 0 или 1
  27. #define INV_WHEEL 1   // инверсия руля
  28. // Пины: Руль
  29. #define ENC_A 2       // пин энкодера (энкодер, тип 2)
  30. #define ENC_B 3       // пин энкодера
  31. //
  32. #define POT_THR A0    // педаль газа        Z
  33. #define POT_BR A1     // педаль тормоза     rZ
  34. #define POT_CLU A2    // педаль сцепления   Y
  35. //
  36. #define BTN_CAL 4     // кнопка калибровки (энкодер)
  37. #define BTN_1 5      // кнопка ручника (Handbrake)
  38. //
  39. #define BTN_2 6     // передача вверх (Gear UP)
  40. #define BTN_3 7     // передача вниз (Gear DOWN)
  41. //
  42. #define BTN_4 8
  43. #define BTN_5 9
  44. #define BTN_6 10
  45. #define BTN_7 11
  46. #define BTN_8 12
  47. //
  48. // Рычаг КПП (H-shifter) нужно 6 (7) кнопок:  A4 (5 кнопок)
  49. //
  50. volatile int encCounter = 0;
  51. volatile boolean state0, lastState, turnFlag;
  52. int throttleMin, throttleMax, brakeMin, brakeMax, clutchMin, clutchMax, wheelMax;
  53. uint32_t timer;
  54. //
  55. #include <EEPROM.h>
  56. #include "HID-Project.h"
  57. //
  58. void setup() {
  59.     pinMode(BTN_1, INPUT_PULLUP);
  60.     pinMode(BTN_2, INPUT_PULLUP);
  61.     pinMode(BTN_3, INPUT_PULLUP);
  62.     pinMode(BTN_4, INPUT_PULLUP);
  63.     pinMode(BTN_5, INPUT_PULLUP);
  64.     pinMode(BTN_6, INPUT_PULLUP);
  65.     pinMode(BTN_7, INPUT_PULLUP);
  66.     pinMode(BTN_8, INPUT_PULLUP);
  67.     setupTmr();
  68.     debug();
  69.     calibration();
  70.     EEPROM.get(0, throttleMin);
  71.     EEPROM.get(2, brakeMin);
  72.     EEPROM.get(4, throttleMax);
  73.     EEPROM.get(6, brakeMax);
  74.     EEPROM.get(8, wheelMax);
  75.     EEPROM.get(10, clutchMin);
  76.     EEPROM.get(12, clutchMax);
  77.     Gamepad.begin();
  78.     //Serial.begin(9600);
  79. }
  80. //
  81. void loop() {
  82.     gamepadTick();
  83.     // при нажатии кнопки калибровки скидываем позицию руля в 0
  84.     if (!digitalRead(BTN_CAL)) {
  85.         encCounter = 0;
  86.     }
  87. }
  88. //
  89. void encTick() {
  90.     state0 = digitalRead(ENC_A);
  91.     if (state0 != lastState) {
  92. #if (ENC_TYPE == 1)
  93.         turnFlag = !turnFlag;
  94.         if (turnFlag)
  95.             encCounter += (digitalRead(ENC_B) != lastState) ? -1 : 1;
  96. #else
  97.         encCounter += (digitalRead(ENC_B) != lastState) ? -1 : 1;
  98. #endif
  99.         lastState = state0;
  100.     }
  101. }
  102. //
  103. void gamepadTick() {
  104.     if (millis() - timer > 10) {
  105.         timer = millis();
  106.         int wheel;
  107.         if (INV_WHEEL) wheel = constrain(-encCounter, -wheelMax, wheelMax);
  108.         else wheel = constrain(encCounter, -wheelMax, wheelMax);
  109. //
  110.         wheel = map(wheel, -wheelMax, wheelMax, -32768, 32767); // Left: -32768 ~ 0; Right: 0 ~ 32767
  111.         Gamepad.xAxis(wheel);                                                 // X
  112. //
  113.         int thr, br, clu;
  114.         thr = map(analogRead(POT_THR), throttleMin, throttleMax, -128, 127);
  115.         thr = constrain(thr, -128, 127);
  116.         Gamepad.zAxis(thr);                                                   // Z Left: -128 ~ 0; Right: 0 ~ 127
  117. //
  118.         br = map(analogRead(POT_BR), brakeMin, brakeMax, -128, 127);
  119.         br = constrain(br, -128, 127);
  120.         Gamepad.rzAxis(br);                                                   // rZ Left: -128 ~ 0; Right: 0 ~ 127
  121. //
  122.         clu = map(analogRead(POT_CLU), clutchMin, clutchMax, -32768, 32767); // Left: -32768 ~ 0; Right: 0 ~ 32767
  123.         clu = constrain(clu, -32768, 32767);
  124.         Gamepad.yAxis(clu);                                                   // Y
  125. //
  126.         if(!digitalRead(BTN_1)){Gamepad.press(1);}  // кнопка ручника (Handbrake)
  127.         else{Gamepad.release(1);}
  128.         if(!digitalRead(BTN_2)){Gamepad.press(2);} // передача вверх (Gear UP)
  129.         else{Gamepad.release(2);}
  130.         if(!digitalRead(BTN_3)){Gamepad.press(3);} // передача вниз (Gear DOWN)
  131.         else{Gamepad.release(3);}
  132.         if(!digitalRead(BTN_4)){Gamepad.press(4);}
  133.         else{Gamepad.release(4);}
  134.         if(!digitalRead(BTN_5)){Gamepad.press(5);}
  135.         else{Gamepad.release(5);}
  136.         if(!digitalRead(BTN_6)){Gamepad.press(6);}
  137.         else{Gamepad.release(6);}
  138.         if(!digitalRead(BTN_7)){Gamepad.press(7);}
  139.         else{Gamepad.release(7);}
  140.         if(!digitalRead(BTN_8)){Gamepad.press(8);}
  141.         else{Gamepad.release(8);}
  142. //
  143.     // "5 кнопок на одном аналоговом входе" модуль:
  144.     //   https://www.keyestudio.com/u_file/1811/products/16/6f26658eed.jpg
  145. /*
  146.     // Читаем данные с пина A3
  147.     int BTN_YELLOW = analogRead(A3);
  148.     // Для 1 кнопки:
  149.     if (BTN_YELLOW>=735 && BTN_YELLOW<=738){} // SW5
  150.     // Для 2 кнопки:
  151.     if (BTN_YELLOW>=500 && BTN_YELLOW<=505){} // SW4
  152.     // Для 3 кнопки:
  153.     if (BTN_YELLOW>=320  && BTN_YELLOW<=325){} // SW3
  154.     // Для 4 кнопки:
  155.     if (BTN_YELLOW>=140  && BTN_YELLOW<=145){} // SW2
  156.     // Для 5 кнопки:
  157.     if (BTN_YELLOW>=0  && BTN_YELLOW<=5){} // SW1
  158.     // Ничего не нажато - отпускаем все кнопки:
  159.     else{}
  160. */
  161.     // "Матрица кнопок 4 на 4" модуль:
  162.     //   https://images-na.ssl-images-amazon.com/images/I/71eBL3JkT9L._AC_SL1500_.jpg
  163.     // Честно говоря, понятия не имею, что тут написать...
  164. //
  165.         Gamepad.write();
  166.     }
  167. }
  168. //
  169. // калибровка
  170. void calibration() {
  171.     if (!digitalRead(BTN_CAL)) {     // нажата кнопка
  172.         while (!digitalRead(BTN_CAL)); // пока кнопка удерживается
  173.         Serial.begin(9600);
  174.         delay(100);
  175.         Serial.print(F("Calibration start"));
  176.         encCounter = 0;
  177.         int zeroTHR = analogRead(POT_THR);
  178.         int zeroBR = analogRead(POT_BR);
  179.         int zeroCL = analogRead(POT_CLU);
  180.         int maxTHR, maxBR, maxCL, maxWHEEL;
  181. //
  182.         EEPROM.put(0, zeroTHR);
  183.         EEPROM.put(2, zeroBR);
  184.         EEPROM.put(10, zeroCL);
  185.         delay(100);                     // дебаунс
  186.         while (true) {                  // крутимся
  187.             if (!digitalRead(BTN_CAL)) break;
  188.             maxTHR = analogRead(POT_THR);
  189.             maxBR = analogRead(POT_BR);
  190.             maxCL = analogRead(POT_CLU);
  191.             Serial.println(encCounter);
  192.         }
  193.         EEPROM.put(4, maxTHR);
  194.         EEPROM.put(6, maxBR);
  195.         EEPROM.put(12, maxCL);
  196.         EEPROM.put(8, abs(encCounter));
  197. //
  198.         Serial.println(F("Calibration end"));
  199.         Serial.print(F("Wheel: "));
  200.         Serial.println(abs(encCounter));
  201.         Serial.print(F("Throttle: "));
  202.         Serial.print(zeroTHR);
  203.         Serial.print(" - ");
  204.         Serial.println(maxTHR);
  205.         Serial.print(F("Brake: "));
  206.         Serial.print(zeroBR);
  207.         Serial.print(" - ");
  208.         Serial.println(maxBR);
  209.         Serial.print(F("Clutch: "));
  210.         Serial.print(zeroCL);
  211.         Serial.print(" - ");
  212.         Serial.println(maxCL);
  213.         Serial.println();
  214.     }
  215.     Serial.end();
  216.     delay(3000);  // задержка чтобы кнопку отпустить
  217. }
  218. //
  219. // Отладка:
  220. void debug() {
  221. #if (DEBUG == 1)
  222.     Serial.begin(9600);
  223.     uint32_t timer;
  224.     while (true) {
  225.         encTick();
  226.         if (millis() - timer > 100) {
  227.             timer = millis();
  228.             Serial.print(encCounter);
  229.             Serial.print("\t");
  230.             Serial.print(analogRead(POT_THR));
  231.             Serial.print("\t");
  232.             Serial.print(analogRead(POT_BR));
  233.             Serial.print("\t");
  234.             Serial.print(analogRead(POT_CLU));
  235.             Serial.print("\t");
  236.             Serial.print(!digitalRead(BTN_1));
  237.             Serial.print("\t");
  238.             Serial.println(!digitalRead(BTN_CAL));
  239.         }
  240.     }
  241.     Serial.end();
  242. #endif
  243. }
  244. //
  245. // опрос энкодера в прерывании
  246. ISR(TIMER3_COMPA_vect) {
  247.     encTick();
  248. }
  249. //
  250. // ставим таймер 3, канал А, период 0.5 мс. Для опроса энкодера
  251. void setupTmr() {
  252.     TCCR3B = 0b00001001;
  253.     TIMSK3 = 0b00000010;
  254.     OCR3AH = highByte(15999 / 2);
  255.     OCR3AL = lowByte(15999 / 2);
  256. }
Advertisement
Add Comment
Please, Sign In to add comment