Skip to content

Instantly share code, notes, and snippets.

@S60Team
Last active March 30, 2021 06:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save S60Team/ae28179d7c751d0f55094d24256ef632 to your computer and use it in GitHub Desktop.
Save S60Team/ae28179d7c751d0f55094d24256ef632 to your computer and use it in GitHub Desktop.
Простой руль для ПК: Руль энкодер, Газ, Тормоз, Сцепление, КПП, Установка угла поворота руля - библиотека NicoHood (HID)
/* Простой руль для ПК:
Основан на: https://is.gd/gyverwheel и https://is.gd/udubon
Изменён: Гендель Владимир aka S60Team
Скачай и поставь библиотеки:
https://github.com/PaulStoffregen/Encoder
https://github.com/NicoHood/HID
КПП (5 пинов - 8 передач) основана на проекте: https://soo.gd/XRgt
3: X влево; 4: X вправо
5: X экстремально вправо
6: X вверх; 7: Y вниз.
Пины: 8,9,10,11,12, 14,15,16 - кнопки */
// Подключаем геймпад (джойстик):
// Библиотека поддерживает 32 кнопки, 1 крестовину, 6 осей (X,Y,Z,Rz,Rx,Ry)
#include "HID-Project.h"
// Указываем Оси:
#define Axe_Throttle A0 // Газ
#define Axe_Brake A1 // Тормоз
#define Axe_Clutch A2 // Сцепление
#define Axe_HBrake A3 // Ручной тормоз
#define BTN_CAL 2 // Кнопка калибровки
// Подключаем энкодер:
//#define ENCODER_OPTIMIZE_INTERRUPTS
//#define ENCODER_USE_INTERRUPTS
#include <Encoder.h>
long encVal = 0; // Значения энкодера
Encoder myEnc(0, 1); // Пины энкодера
// Переменные значений осей:
int16_t Axis1_ = 0, Axis2_ = 0, Axis3_ = 0, Axis4_ = 0;
// Переменные ВКЛ определения осей:
bool handbrake_present = true, throttle_present = true;
bool brake_present = true, clutch_present = true;
// Перменные КПП:
int8_t Gear1Flg = 0, Gear2Flg = 0, Gear5Flg = 0, Gear6Flg = 0, Gear7Flg = 0, Gear8Flg = 0;
// Переменная режима угла поворота руля:
bool racing_mode = false;
//
void setup() {
pinMode(13, OUTPUT); // Встроенный светодиод
digitalWrite(13, LOW); // Встроенный светодиод ВЫКЛ
pinMode(BTN_CAL, INPUT_PULLUP); // Кнопка сброса позиции энкодера
if(digitalRead(BTN_CAL) == HIGH){
digitalWrite(13, LOW);
racing_mode = false;} // Кнопка сброса ВЫКЛ. Режим симулятора
else{
digitalWrite(13, HIGH);
racing_mode = true;} // Кнопка сброса ВКЛ. Гоночный режим
// Циклы для указания цифровых пинов как вход для обработки нажатия кнопок:
for (int thisPin = 3; thisPin < 13; thisPin++) { // Leonardo:
pinMode(thisPin, INPUT_PULLUP); } // 3,4,5,6,7,8,9,10,11,12
for (int thisPin = 14; thisPin < 17; thisPin++) {
pinMode(thisPin, INPUT_PULLUP); } // 14, 15, 16
// Инициализация джойстика:
Gamepad.begin();
// Определяем, подключены ли педали и ручник к аналоговым входам:
int16_t ap1 = analogRead(Axe_Throttle),
ap2 = analogRead(Axe_Brake),
ap3 = analogRead(Axe_Clutch),
ap4 = analogRead(Axe_HBrake);
delay(10);
if(abs(ap1-analogRead(Axe_Throttle)) > 10){ throttle_present = false; }
if(abs(ap2-analogRead(Axe_Brake)) > 10){ brake_present = false; }
if(abs(ap3-analogRead(Axe_Clutch)) > 10){ clutch_present = false; }
if(abs(ap4-analogRead(Axe_HBrake)) > 10){ handbrake_present = false; }
}
//
void loop() {
// Сбрасываем значение осей: (на всякий случай)
Axis1_ = 0, Axis2_ = 0, Axis3_ = 0, Axis4_ = 0;
// Руль энкодер:
int16_t rotMax = 0; // обнуляем макс. значение поворота
int16_t rotMid = (rotMax>>1); // середина руля
if(racing_mode == false){ // Если не зажата кнопка сброса (пин 2):
// rotMax это Значение поворота, например:
// 4320=1080°, 3600=900°, 1440=360°, 1080=270°, 720=180°
rotMax = 3600;
rotMid = (rotMax>>1);}
// Если зажата кн. калибровки и кн. на пин 10: 600°
else if(racing_mode == true && digitalRead(10) == LOW){
rotMax = 2400;
rotMid = (rotMax>>1);}
// Если зажата кн. калибровки и кн. на пин 11: 270°
else if(racing_mode == true && digitalRead(11) == LOW){
rotMax = 1080;
rotMid = (rotMax>>1);}
// Если зажата кн. калибровки: 180°
else{
rotMax = 720;
rotMid = (rotMax>>1);}
// Сброс позиции энкодера кнопкой на пине 2:
if(!digitalRead(BTN_CAL)){ myEnc.write(rotMid); }
encVal = myEnc.read() - rotMid; // Читаем показания энкодера
encVal = (encVal * 65535) / rotMax; // Вычисляем поворот
encVal = constrain(encVal, -32768, 32767); // Указываем границы значений
Gamepad.xAxis(encVal); // Записываем значения в ось.
//
// Педаль Газа:
if (throttle_present == true) {
Axis1_ = analogRead(Axe_Throttle);
Axis1_ = map(Axis1_,0,1023,-32768,32767);
Gamepad.rxAxis(Axis1_);}
else{Gamepad.rxAxis(0);}
//
// Педаль Тормоза:
if (brake_present == true) {
Axis2_ = analogRead(Axe_Brake);
Axis2_ = map(Axis2_,0,1023,-128,127);
Gamepad.zAxis(Axis2_);}
else{Gamepad.zAxis(0);}
//
// Педаль Сцепления:
if (clutch_present == true) {
Axis3_ = analogRead(Axe_Clutch);
Axis3_ = map(Axis3_,0,1023,-128,127);
Gamepad.rzAxis(Axis3_);}
else{Gamepad.rzAxis(0);}
//
// Ручной тормоз:
if (handbrake_present == true) {
Axis4_ = analogRead(Axe_HBrake);
Axis4_ = map(Axis4_,0,1023,-32768,32767);
Gamepad.ryAxis(Axis4_);}
else{Gamepad.ryAxis(0);}
//
// Коробка передач:
if(!digitalRead(3) && !digitalRead(6)){
Gamepad.release(4);
Gamepad.press(1);
Gear1Flg = 1;}
else{
Gamepad.release(1);
Gear1Flg = 0;}
if(!digitalRead(3) && !digitalRead(7)){
Gamepad.release(3);
Gamepad.press(2);
Gear2Flg = 1;}
else{
Gamepad.release(2);
Gear2Flg = 0;}
if(!digitalRead(4) && !digitalRead(6)){
Gamepad.release(4);
Gamepad.press(5);
Gear5Flg = 1;}
else{
Gamepad.release(5);
Gear5Flg = 0;}
if(!digitalRead(4) && !digitalRead(7)){
Gamepad.release(3);
Gamepad.press(6);
Gear6Flg = 1;}
else{
Gamepad.release(6);
Gear6Flg = 0;}
// Far right
if(!digitalRead(4) && !digitalRead(5) && !digitalRead(6)){
Gamepad.release(4);
Gamepad.release(5);
Gamepad.press(7);
Gear7Flg = 1;}
else{
Gamepad.release(7);
Gear7Flg = 0;}
if(!digitalRead(4) && !digitalRead(5) && !digitalRead(7)){
Gamepad.release(3);
Gamepad.release(6);
Gamepad.press(8);
Gear8Flg = 1;}
else{
Gamepad.release(8);
Gear8Flg = 0;}
if(!digitalRead(6) && Gear1Flg == 0 && Gear5Flg == 0 && Gear7Flg == 0){ Gamepad.press(3); }
else{ Gamepad.release(3); }
if(!digitalRead(7) && Gear2Flg == 0 && Gear6Flg == 0 && Gear8Flg == 0){ Gamepad.press(4); }
else{ Gamepad.release(4); }
//
for (int8_t thisPind = 8; thisPind < 13; thisPind++) {
if(!digitalRead(thisPind)){ Gamepad.press(thisPind+1); }
else{ Gamepad.release(thisPind+1); } }
// Пины: 14, 15, 16 (ещё 3 кнопки!)
for (int8_t thisPindd = 14; thisPindd < 17; thisPindd++) {
if(!digitalRead(thisPindd)){ Gamepad.press(thisPindd); }
else{ Gamepad.release(thisPindd); } }
// Отправляем значения в ПК:
Gamepad.write();
//
delay(10); // а надо ли?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment