Last active
April 12, 2021 06:01
-
-
Save S60Team/b759443008300798ccd690d611175614 to your computer and use it in GitHub Desktop.
Простой руль для ПК: Руль энкодер, Газ, Тормоз, Сцепление, Установка угла поворота руля - библиотека MHeironimus (ArduinoJoystickLibrary)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Простой руль для ПК: | |
Основан на: https://is.gd/gyverwheel и https://is.gd/udubon | |
Изменён: Гендель Владимир aka S60Team | |
Скачай и поставь библиотеки: | |
https://github.com/MHeironimus/ArduinoJoystickLibrary | |
https://github.com/S60Team/Rotary2 | |
Пины: 3,4,5,6,7,8,9,10,11,12, 14,15,16 - кнопки. | |
*/ | |
// Если у вас Arduino Pro Micro (0 для Arduino Leonardo): | |
#define ProMicro 1 | |
// Если ось идёт вправо а руль крутится влево, | |
// меняем направление (0 или 1): | |
#define Direction 1 | |
// Указываем Оси: | |
#define Axe_Throttle A0 // Газ | |
#define Axe_Brake A1 // Тормоз | |
#define Axe_Clutch A2 // Сцепление | |
#define Axe_HBrake A3 // Ручной тормоз | |
#define BTN_CAL 2 // Кнопка калибровки | |
// Количество подключенных кнопок: | |
int8_t Btnz = 16; | |
// Подключаем энкодер: | |
/* Настройки переехали в файл библиотеки Rotary2.h | |
Тут только подсказки: | |
#define DWF // Включить быструю версию DigitalWrite. | |
#define ENABLE_PULLUPS // Включить встроенный резистор подтяжки. | |
#define ENCODER2 // Включить другой тип энкодера. | |
#define HALF_STEP // Включить другой шаг энкодера. | |
*/ | |
#include <Rotary2.h> | |
#define outA 0 // пин 0 (PD2) | |
#define outB 1 // пин 1 (PD3) | |
Rotary2 rotary = Rotary2(outA, outB); | |
volatile int16_t counter = 0; | |
int16_t encVal = 0; | |
// Подключаем геймпад (джойстик): | |
// Библиотека поддерживает 128 кнопок, 2 крестовины, 7 осей (X,Y,Z,Rz,Rx,Ry,Throttle) | |
#include <Joystick.h> | |
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, | |
//JOYSTICK_TYPE_GAMEPAD, | |
//JOYSTICK_TYPE_MULTI_AXIS, | |
JOYSTICK_TYPE_JOYSTICK, | |
Btnz, 0, // Кол-во кнопок, кол-во крестовин | |
true, false, true, // X, Y, Z | |
true, true, true, // Rx, Ry, Rz | |
false, false, // Rudder(руль высоты), Throttle(Газ) | |
false, false, false); // Accelerator(Ускорение), brake(Тормоз), steering(Руль) | |
//const bool testAutoSendMode = true; | |
const bool testAutoSendMode = false; | |
// Переменные значений осей: | |
int16_t Axis0_ = 0, Axis1_ = 0, Axis2_ = 0, Axis3_ = 0, Axis4_ = 0; | |
// Переменные фильтра: | |
int16_t Filtr = 0, filt = 0; | |
// Переменные ВКЛ определения осей: | |
bool handbrake_present = true, throttle_present = true; | |
bool brake_present = true, clutch_present = true; | |
// Переменная режима угла поворота руля: | |
bool racing_mode = false; | |
void setup() { | |
pinMode(13, OUTPUT); // Встроенный светодиод | |
digitalWrite(13, LOW); // Встроенный светодиод ВЫКЛ | |
// Настраиваем энкодер: | |
pinMode(outA, INPUT_PULLUP); // пин энкодера | |
pinMode(outB, INPUT_PULLUP); // пин энкодера | |
//CHANGE для срабатывания прерывания если пин меняет значение: | |
attachInterrupt(digitalPinToInterrupt(outA),rotate,CHANGE); | |
attachInterrupt(digitalPinToInterrupt(outB),rotate,CHANGE); | |
// Кнопка для сброса позиции энкодера/установки значения поворота руля: | |
pinMode(BTN_CAL, INPUT_PULLUP); | |
// Проверяем положение кнопки при включении USB: | |
// (по-умолчанию режим выключен - 900°) | |
// при зажатой кнопке (при подсоединении к ПК): ВКЛ (270°) | |
if(digitalRead(BTN_CAL) == HIGH){ | |
digitalWrite(13, LOW); | |
racing_mode = false;} // Кнопка сброса ВЫКЛ. Режим симулятора | |
else{ | |
digitalWrite(13, HIGH); | |
racing_mode = true;} // Кнопка сброса ВКЛ. Гоночный режим | |
// Циклы для указания цифровых пинов как входы для обработки нажатия кнопок: | |
for (int8_t thisPin = 2; thisPin < 13; thisPin++) { // Leonardo: | |
pinMode(thisPin, INPUT_PULLUP); } // 3,4,5,6,7,8,9,10,11,12 | |
for (int8_t thisPin = 14; thisPin < 17; thisPin++) { | |
pinMode(thisPin, INPUT_PULLUP); // 14, 15, 16 | |
} | |
// Указываем угол поворота руля: | |
// По-умолчанию: 900° | |
if(racing_mode == false){ | |
Joystick.setXAxisRange(-450,450);} | |
// Если зажата кн. калибровки и кн. на пин 10: 600° | |
else if(racing_mode == true && digitalRead(10) == LOW){ | |
Joystick.setXAxisRange(-300,300);} | |
// Если зажата кн. калибровки и кн. на пин 11: 180° | |
else if(racing_mode == true && digitalRead(11) == LOW){ | |
Joystick.setXAxisRange(-90,90);} | |
// Если зажата кн. калибровки: 270° | |
else{Joystick.setXAxisRange(-135,135);} | |
// Указываем границы осей: | |
Joystick.setZAxisRange(-128,127); | |
Joystick.setRzAxisRange(-128,127); | |
Joystick.setRyAxisRange(-128,127); | |
Joystick.setRxAxisRange(-128,127); | |
// Инициализация библиотеки джойстика: | |
if (testAutoSendMode){Joystick.begin();} | |
else{Joystick.begin(false);} | |
// Определяем, подключены ли педали и ручник к аналоговым входам: | |
int16_t a1 = analogRead(Axe_Throttle), | |
a2 = analogRead(Axe_Brake), | |
a3 = analogRead(Axe_Clutch), | |
a4 = analogRead(Axe_HBrake); | |
delay(10); | |
if(abs(a1-analogRead(Axe_Throttle)) > 10){ throttle_present = false; } | |
if(abs(a2-analogRead(Axe_Brake)) > 10){ brake_present = false; } | |
if(abs(a3-analogRead(Axe_Clutch)) > 10){ clutch_present = false; } | |
if(abs(a4-analogRead(Axe_HBrake)) > 10){ handbrake_present = false; } | |
} | |
void loop() { | |
// Сбрасываем значение осей: (на всякий случай) | |
Axis0_ = 0, Axis1_ = 0, Axis2_ = 0, Axis3_ = 0, Axis4_ = 0; | |
// Руль энкодер (360ppr/1140ppr): | |
if(!digitalRead(BTN_CAL)){ counter = 0;Joystick.setXAxis(0); } | |
encVal = counter; | |
Joystick.setXAxis(counter); | |
// Педаль Газа: | |
if (throttle_present == true) { | |
Axis1_ = analogRead(Axe_Throttle); | |
Axis1_ = map(Axis1_,0,1023,-128,127); | |
Joystick.setRxAxis(Axis1_);} | |
else{Joystick.setRxAxis(0);} | |
// Педаль Тормоза: | |
if (brake_present == true) { | |
Axis2_ = analogRead(Axe_Brake); | |
Axis2_ = constrain(Axis2_,235,800); | |
Axis2_ = map(Axis2_,235,800,-128,127); | |
Joystick.setZAxis(Axis2_);} | |
else{Joystick.setZAxis(0);} | |
// Педаль Сцепления: | |
if (clutch_present == true) { | |
Axis3_ = analogRead(Axe_Clutch); | |
Axis3_ = map(Axis3_,0,1023,-128,127); | |
Joystick.setRzAxis(Axis3_);} | |
else{Joystick.setRzAxis(0);} | |
// Ручной тормоз: | |
if (handbrake_present == true) { | |
Axis4_ = analogRead(Axe_HBrake); | |
Axis4_ = map(Axis4_,0,1023,-128,127); | |
Joystick.setRyAxis(Axis4_);} | |
else{Joystick.setRyAxis(0);} | |
// Перебираем оставшиеся пины и задаём их как кнопки: | |
#if (ProMicro == 0) | |
// Leonardo: | |
// Пины: 3,4,5,6, 7,8,9,10, 11,12 | |
for (int thisPind = 3; thisPind < 13; thisPind++) { | |
if(!digitalRead(thisPind)){ Joystick.pressButton(thisPind-2); } | |
else{ Joystick.pressButton(thisPind-2); } } | |
#else | |
// Pro Micro: | |
// Пины: 3,4,5,6, 7,8,9,10 | |
for (int thisPind = 3; thisPind < 11; thisPind++) { | |
if(!digitalRead(thisPind)){ Joystick.pressButton(thisPind-2); } | |
else{ Joystick.pressButton(thisPind-2); } } | |
#endif | |
// Пины: 14, 15, 16 (ещё кнопки!) | |
for (int thisPindd = 14; thisPindd < 17; thisPindd++) { | |
if(!digitalRead(thisPindd)){ Joystick.pressButton(thisPindd-2); } | |
else{ Joystick.pressButton(thisPindd-2); } } | |
// Отправляем значения в ПК: | |
if (testAutoSendMode == false){ | |
Joystick.sendState(); | |
delay(10); | |
} | |
} | |
// Функция для считывания показаний энкодера: | |
void rotate() { | |
unsigned char result = rotary.process(); | |
#if (Direction == 0) | |
if (result == DIR_CW){counter++;} | |
else if (result == DIR_CCW){counter--;} | |
#else | |
if (result == DIR_CW){counter--;} | |
else if (result == DIR_CCW){counter++;} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment