Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Скетч к проекту "Простой руль для ПК": страница проекта (схемы, описания)
- https://alexgyver.ru/GyverWheel/ https://github.com/AlexGyver/GyverWheel/
- PS: стандартный тестер геймпада в Win10: поиск/joy.cpl
- */
- /*
- В библиотеке:
- xAxis(int16_t a); -32768, 32767 Руль (Влево-Вправо, Левый гриб)
- yAxis(int16_t a); -32768, 32767 Сцепление (Вверх-вниз, Левый гриб)
- rzAxis(int8_t a); -128 до 127 Тормоз
- zAxis(int8_t a); -128 до 127 Газ
- rxAxis(int16_t a); -32768, 32767
- ryAxis(int16_t a); -32768, 32767
- В реале:
- xAxis(int16_t a); -32768, 32767 Руль (Влево-Вправо, Левый гриб)
- yAxis(int16_t a); -32768, 32767 (Вверх-вниз, Левый гриб)
- rzAxis(int8_t a); -32768, 32767 (Вверх-вниз, Правый гриб)
- zAxis(int8_t a); -32768, 32767 (Влево-Вправо, Правый гриб)
- rxAxis(int16_t a); -32768, 32767 скорее всего левый
- ryAxis(int16_t a); -32768, 32767 и правый курок (shoulder).
- */
- //
- // =========== НАСТРОЙКИ ===========
- // ВНИМАНИЕ! Максимум 8 осей и 32 кнопки!
- #define DEBUG 0 // режим отладки
- #define ENC_TYPE 0 // тип энкодера, 0 или 1
- #define INV_WHEEL 1 // инверсия руля
- // Пины: Руль
- #define ENC_A 2 // пин энкодера (энкодер, тип 2)
- #define ENC_B 3 // пин энкодера
- //
- #define POT_THR A0 // педаль газа Z
- #define POT_BR A1 // педаль тормоза rZ
- #define POT_CLU A2 // педаль сцепления Y
- //
- #define BTN_CAL 4 // кнопка калибровки (энкодер)
- #define BTN_1 5 // кнопка ручника (Handbrake)
- //
- #define BTN_2 6 // передача вверх (Gear UP)
- #define BTN_3 7 // передача вниз (Gear DOWN)
- //
- #define BTN_4 8
- #define BTN_5 9
- #define BTN_6 10
- #define BTN_7 11
- #define BTN_8 12
- //
- // Рычаг КПП (H-shifter) нужно 6 (7) кнопок: A4 (5 кнопок)
- //
- volatile int encCounter = 0;
- volatile boolean state0, lastState, turnFlag;
- int throttleMin, throttleMax, brakeMin, brakeMax, clutchMin, clutchMax, wheelMax;
- uint32_t timer;
- //
- #include <EEPROM.h>
- #include "HID-Project.h"
- //
- void setup() {
- pinMode(BTN_1, INPUT_PULLUP);
- pinMode(BTN_2, INPUT_PULLUP);
- pinMode(BTN_3, INPUT_PULLUP);
- pinMode(BTN_4, INPUT_PULLUP);
- pinMode(BTN_5, INPUT_PULLUP);
- pinMode(BTN_6, INPUT_PULLUP);
- pinMode(BTN_7, INPUT_PULLUP);
- pinMode(BTN_8, INPUT_PULLUP);
- setupTmr();
- debug();
- calibration();
- EEPROM.get(0, throttleMin);
- EEPROM.get(2, brakeMin);
- EEPROM.get(4, throttleMax);
- EEPROM.get(6, brakeMax);
- EEPROM.get(8, wheelMax);
- EEPROM.get(10, clutchMin);
- EEPROM.get(12, clutchMax);
- Gamepad.begin();
- //Serial.begin(9600);
- }
- //
- void loop() {
- gamepadTick();
- // при нажатии кнопки калибровки скидываем позицию руля в 0
- if (!digitalRead(BTN_CAL)) {
- encCounter = 0;
- }
- }
- //
- void encTick() {
- state0 = digitalRead(ENC_A);
- if (state0 != lastState) {
- #if (ENC_TYPE == 1)
- turnFlag = !turnFlag;
- if (turnFlag)
- encCounter += (digitalRead(ENC_B) != lastState) ? -1 : 1;
- #else
- encCounter += (digitalRead(ENC_B) != lastState) ? -1 : 1;
- #endif
- lastState = state0;
- }
- }
- //
- void gamepadTick() {
- if (millis() - timer > 10) {
- timer = millis();
- int wheel;
- if (INV_WHEEL) wheel = constrain(-encCounter, -wheelMax, wheelMax);
- else wheel = constrain(encCounter, -wheelMax, wheelMax);
- //
- wheel = map(wheel, -wheelMax, wheelMax, -32768, 32767); // Left: -32768 ~ 0; Right: 0 ~ 32767
- Gamepad.xAxis(wheel); // X
- //
- int thr, br, clu;
- thr = map(analogRead(POT_THR), throttleMin, throttleMax, -128, 127);
- thr = constrain(thr, -128, 127);
- Gamepad.zAxis(thr); // Z Left: -128 ~ 0; Right: 0 ~ 127
- //
- br = map(analogRead(POT_BR), brakeMin, brakeMax, -128, 127);
- br = constrain(br, -128, 127);
- Gamepad.rzAxis(br); // rZ Left: -128 ~ 0; Right: 0 ~ 127
- //
- clu = map(analogRead(POT_CLU), clutchMin, clutchMax, -32768, 32767); // Left: -32768 ~ 0; Right: 0 ~ 32767
- clu = constrain(clu, -32768, 32767);
- Gamepad.yAxis(clu); // Y
- //
- if(!digitalRead(BTN_1)){Gamepad.press(1);} // кнопка ручника (Handbrake)
- else{Gamepad.release(1);}
- if(!digitalRead(BTN_2)){Gamepad.press(2);} // передача вверх (Gear UP)
- else{Gamepad.release(2);}
- if(!digitalRead(BTN_3)){Gamepad.press(3);} // передача вниз (Gear DOWN)
- else{Gamepad.release(3);}
- if(!digitalRead(BTN_4)){Gamepad.press(4);}
- else{Gamepad.release(4);}
- if(!digitalRead(BTN_5)){Gamepad.press(5);}
- else{Gamepad.release(5);}
- if(!digitalRead(BTN_6)){Gamepad.press(6);}
- else{Gamepad.release(6);}
- if(!digitalRead(BTN_7)){Gamepad.press(7);}
- else{Gamepad.release(7);}
- if(!digitalRead(BTN_8)){Gamepad.press(8);}
- else{Gamepad.release(8);}
- //
- // "5 кнопок на одном аналоговом входе" модуль:
- // https://www.keyestudio.com/u_file/1811/products/16/6f26658eed.jpg
- /*
- // Читаем данные с пина A3
- int BTN_YELLOW = analogRead(A3);
- // Для 1 кнопки:
- if (BTN_YELLOW>=735 && BTN_YELLOW<=738){} // SW5
- // Для 2 кнопки:
- if (BTN_YELLOW>=500 && BTN_YELLOW<=505){} // SW4
- // Для 3 кнопки:
- if (BTN_YELLOW>=320 && BTN_YELLOW<=325){} // SW3
- // Для 4 кнопки:
- if (BTN_YELLOW>=140 && BTN_YELLOW<=145){} // SW2
- // Для 5 кнопки:
- if (BTN_YELLOW>=0 && BTN_YELLOW<=5){} // SW1
- // Ничего не нажато - отпускаем все кнопки:
- else{}
- */
- // "Матрица кнопок 4 на 4" модуль:
- // https://images-na.ssl-images-amazon.com/images/I/71eBL3JkT9L._AC_SL1500_.jpg
- // Честно говоря, понятия не имею, что тут написать...
- //
- Gamepad.write();
- }
- }
- //
- // калибровка
- void calibration() {
- if (!digitalRead(BTN_CAL)) { // нажата кнопка
- while (!digitalRead(BTN_CAL)); // пока кнопка удерживается
- Serial.begin(9600);
- delay(100);
- Serial.print(F("Calibration start"));
- encCounter = 0;
- int zeroTHR = analogRead(POT_THR);
- int zeroBR = analogRead(POT_BR);
- int zeroCL = analogRead(POT_CLU);
- int maxTHR, maxBR, maxCL, maxWHEEL;
- //
- EEPROM.put(0, zeroTHR);
- EEPROM.put(2, zeroBR);
- EEPROM.put(10, zeroCL);
- delay(100); // дебаунс
- while (true) { // крутимся
- if (!digitalRead(BTN_CAL)) break;
- maxTHR = analogRead(POT_THR);
- maxBR = analogRead(POT_BR);
- maxCL = analogRead(POT_CLU);
- Serial.println(encCounter);
- }
- EEPROM.put(4, maxTHR);
- EEPROM.put(6, maxBR);
- EEPROM.put(12, maxCL);
- EEPROM.put(8, abs(encCounter));
- //
- Serial.println(F("Calibration end"));
- Serial.print(F("Wheel: "));
- Serial.println(abs(encCounter));
- Serial.print(F("Throttle: "));
- Serial.print(zeroTHR);
- Serial.print(" - ");
- Serial.println(maxTHR);
- Serial.print(F("Brake: "));
- Serial.print(zeroBR);
- Serial.print(" - ");
- Serial.println(maxBR);
- Serial.print(F("Clutch: "));
- Serial.print(zeroCL);
- Serial.print(" - ");
- Serial.println(maxCL);
- Serial.println();
- }
- Serial.end();
- delay(3000); // задержка чтобы кнопку отпустить
- }
- //
- // Отладка:
- void debug() {
- #if (DEBUG == 1)
- Serial.begin(9600);
- uint32_t timer;
- while (true) {
- encTick();
- if (millis() - timer > 100) {
- timer = millis();
- Serial.print(encCounter);
- Serial.print("\t");
- Serial.print(analogRead(POT_THR));
- Serial.print("\t");
- Serial.print(analogRead(POT_BR));
- Serial.print("\t");
- Serial.print(analogRead(POT_CLU));
- Serial.print("\t");
- Serial.print(!digitalRead(BTN_1));
- Serial.print("\t");
- Serial.println(!digitalRead(BTN_CAL));
- }
- }
- Serial.end();
- #endif
- }
- //
- // опрос энкодера в прерывании
- ISR(TIMER3_COMPA_vect) {
- encTick();
- }
- //
- // ставим таймер 3, канал А, период 0.5 мс. Для опроса энкодера
- void setupTmr() {
- TCCR3B = 0b00001001;
- TIMSK3 = 0b00000010;
- OCR3AH = highByte(15999 / 2);
- OCR3AL = lowByte(15999 / 2);
- }
Advertisement
Add Comment
Please, Sign In to add comment