ARDUINO Простой руль для ПК. Обсуждение проекта

Oscarmeister

✩✩✩✩✩✩✩
6 Янв 2021
6
2
scheme.png

Сделал все по такой схеме, дописал все, что мне нужно в код.
@s60team, выше указанный код выдает ошибку компиляции:"
C:\Program Files (x86)\Arduino\libraries\Rotary2-main\Rotary2.cpp:16:10: fatal error: Rotary.h: No such file or directory
#include "Rotary.h"
^~~~~~~~~~
compilation terminated.
exit status 1
Ошибка компиляции для платы Arduino Micro."
в этом коде ничего не менял, библиотеки скачал по ссылкам из кода.
Все таки интересно, почему работают только 3 оси, плюс ось Y чуть-чуть двигается, при нажатии педали сцепления.

Мой дописанный код:

// =========== НАСТРОЙКИ ===========
#define DEBUG 0 // режим отладки
#define ENC_TYPE 1 // тип энкодера, 0 или 1
#define INV_WHEEL 0 // инверсия руля

// пины
#define ENC_A 5 // пин энкодера
#define ENC_B 6 // пин энкодера
#define POT_THR A0 // педаль газа
#define POT_BR A1 // педаль тормоза
#define POT_CL A2 // педаль сцепления
#define BUTT_BR 9 // кнопка ручника
#define BUTT_UP 7 // кнопка повышения передачи
#define BUTT_DW 8 // кнопка понижения передачи
#define BUTT_CAL 3 // кнопка калибровки

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(BUTT_BR, INPUT_PULLUP);
pinMode(BUTT_UP, INPUT_PULLUP);
pinMode(BUTT_DW, INPUT_PULLUP);
pinMode(BUTT_CAL, INPUT_PULLUP);
setupTmr();
debug();
calibration();
EEPROM.get(0, throttleMin);
EEPROM.get(2, throttleMax);
EEPROM.get(4, brakeMin);
EEPROM.get(6, brakeMax);
EEPROM.get(8, clutchMin);
EEPROM.get(10, clutchMax);
EEPROM.get(12, wheelMax);
Gamepad.begin();
//Serial.begin(9600);
}

void loop() {
gamepadTick();

// при нажатии кнопки калибровки скидываем позицию руля в 0
if (!digitalRead(BUTT_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);
Gamepad.xAxis(wheel);

int thr, br, cl;
thr = map(analogRead(POT_THR), throttleMin, throttleMax, -128, 127);
thr = constrain(thr, -128, 127);
Gamepad.zAxis(thr);

br = map(analogRead(POT_BR), brakeMin, brakeMax, -128, 127);
br = constrain(br, -128, 127);
Gamepad.rzAxis(br);

cl = map(analogRead(POT_CL), clutchMin, clutchMax, -128, 127);
cl = constrain(cl, -128, 127);
Gamepad.YAxis(cl);

if (!digitalRead(BUTT_BR)) Gamepad.press(1);
else Gamepad.release(1);
Gamepad.write();

if (!digitalRead(BUTT_UP)) Gamepad.press(2);
else Gamepad.release(2);
Gamepad.write();

if (!digitalRead(BUTT_DW)) Gamepad.press(3);
else Gamepad.release(3);
Gamepad.write();
}
}

// калибровка
void calibration() {
if (!digitalRead(BUTT_CAL)) { // нажата кнопка
while (!digitalRead(BUTT_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_CL);
int maxTHR, maxBR, maxCL, maxWHEEL;

EEPROM.put(0, zeroTHR);
EEPROM.put(4, zeroBR);
EEPROM.put(8, zeroCL);
delay(100); // дебаунс
while (true) { // крутимся
if (!digitalRead(BUTT_CAL)) break;
maxTHR = analogRead(POT_THR);
maxBR = analogRead(POT_BR);
maxCL = analogRead(POT_CL);
Serial.println(encCounter);
}
EEPROM.put(2, maxTHR);
EEPROM.put(6, maxBR);
EEPROM.put(10, maxCL);
EEPROM.put(12, abs(encCounter));

Serial.println(F("Calibration end"));
Serial.print(F("Wheel: "));
Serial.println(abs(encCounter));
Serial.print(F("Throat: "));
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_CL));
Serial.print("\t");
Serial.print(!digitalRead(BUTT_BR));
Serial.print("\t");
Serial.print(!digitalRead(BUTT_UP));
Serial.print("\t");
Serial.print(!digitalRead(BUTT_DW));
Serial.print("\t");
Serial.println(!digitalRead(BUTT_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);
}

и еще вопрос, что это за "racing_mode" в вашем коде, когда он включен, а когда выключен?
 
Изменено:
  • Лойс +1
Реакции: s60team

s60team

★✩✩✩✩✩✩
Прошу прощения, надо было сначала библиотеку перепроверить несколько раз, прежде чем выкладывать.
Залил исправленную версию: https://github.com/S60Team/Rotary2

Все таки интересно, почему работают только 3 оси, плюс ось Y чуть-чуть двигается, при нажатии педали сцепления.
Попробуйте всё таки откалибровать и в Windows: Жмём Win+R и пишем joy.cpl и жмём ОК.
PS: У меня тоже были проблемы с добавлением сцепления в прошивку Алекса, потому решил переписать всё.
PPS: если можно, уберите код под спойлер.

И еще вопрос, что это за "racing_mode" в вашем коде, когда он включен, а когда выключен?
Гоночный режим (выключен по-умолчанию) - руль 900 градусов.
Включен (зажата кнопка сброса(пин 2) при вставке USB кабеля к ПК) - 270 градусов.

PS: Куплен руль Б/У за 200грн, энкодер за 300, Arduino Leonardo за 130, (Dupont) дюпон-папа 10грн,
4 потенциометра на 10кОм 160грн (да, дурак - не надо было брать модули), переключатель - бесплатно,
МГТФ провод 0.12 100грн, оплётка для кабеля МГТФ (ПВХ) 16грн,
кабель витой от телефона (4 жилы) 10грн, 7 микриков 21грн,
3D-Печать КПП и Ручника - бесплатно, педалей 200грн.
Общая сумма Потрачена: 1147грн (~3000 рублей или ~40$)

Вот фото текущего состояния (педали пока печатаются):
 
Изменено:

Andrey_kapacb

✩✩✩✩✩✩✩
20 Мар 2021
2
2
Как сделать чтобы сцепление нормально работало по прошивке Алекса?
 

Oscarmeister

✩✩✩✩✩✩✩
6 Янв 2021
6
2
никак, если бы был рабочий вариант, то он бы здесь был опубликован, а так есть другие прошивки, которые работают
Для работы дорогого энкодера на плате микро могут понадобится 2 резистора от VCC к пинам, даже на пинах с прерыванием он не заработал, так что, если не работает энкодер, берем 2 резистора на 10 кОм. В прошивке, @s60team, при калибровке смотрим на значения( надо поставить галочку на "показывать значения"), должно быть примерно -32к и 32к на полный оборот, иначе в одну сторону будет 1 оборот, а в другую 0.7, крутим руль и жмем на кнопку сброса, пока не получим значения 32к в обе стороны.
 
Изменено:
  • Лойс +1
Реакции: alemastas

Andrey_kapacb

✩✩✩✩✩✩✩
20 Мар 2021
2
2
Путём объединения прошивок Алекса и s60team, удалось создать руль на Arduino Pro Micro со сцеплением и с калибровкой рабочего угла.
 

Walther_ts

✩✩✩✩✩✩✩
11 Апр 2021
2
2
Доброго времени суток, дописал под себя скетч взяв за основу s60team. Огромное тебе спасибо(y). Скетч получился рабочий . Суть дороботки была в подключении 8 скоростной коробки резистивным методом для освобождения пинов. Схему спаял на подстроечных резисторах. Очень бы хотел добавить сюда простейшую отдачу, чтобы был возврат в нулевое положение и ограничение крайних положений руля, но увы незнаю как прописать правильно. Допустим крайние положения мы знаем, и можно тормозить электродвигателем по достижению крайних меток. А как быть с возвратом руля в среднее положение... Кто ни будь писал такие скетчи? Прошу, поясните что к чему. Прикладываю видоизмененный скетч от s60team . Прошу прощения если нарушил авторские права.
 

Вложения

  • Лойс +1
Реакции: s60team

s60team

★✩✩✩✩✩✩
Walther_ts
Нет, не нарушили. Исправьте у себя: вы кучу раз отправляете данные на ПК!

Для тех, у кого руль крутится в одну, а ось в другую сторону: я уже исправил примеры GyverWheel-Simple и PCWheel-Simple .

Добавить FFB пока возможности нет (но уже потихоньку работаю над этим).
А пока: пробуем код из сообщения №43...
 

Вложения

Изменено:
  • Лойс +1
Реакции: Walther_ts

Oscarmeister

✩✩✩✩✩✩✩
6 Янв 2021
6
2
Для FFB есть утилита, написанная немцами( или не немцами), там все есть. Не вижу смысла делать супер слабый FFB, лучше уж делать что-то посерьезнее, потому что дальше больше. У меня не было опыта в автосимах, пока я не сделал этот руль. Мне очень понравилось, и я захотел попробовать, что такое FFB, набрал в ютубе "custom ffb steering wheel" и вдохновился. Люди давно уже делают свои кастомные рули и у кого то проекты очень и очень серьезные, поэтому слабый FFB лучше не делать, а сделать сразу хороший, переняв чужой опыт. Это так, личное мнение.
 

blasphemous

✩✩✩✩✩✩✩
15 Май 2021
2
0
День добрый. Хочу попробовать сам собрать руль и написать код для него. Скажите, пожалуйста, где мне взять информацию о том, как программировать данные устройства?
 

s60team

★✩✩✩✩✩✩
blasphemous, если хотите начать с нуля, то Вам надо будет освоить USB HID и всё, то с этим связано.
Выбрать для себя микроконтроллер, который будете программировать.

Если же хотите пойти по уже натоптанному и сделать под свой проект:
есть Arduino на Atmega32u4 (MMJOY2, USB HID library, Arduino Joystick library, Logitech G25, EbolzMagy),
STM32F103C8T6 BluePill (FreeJoy), STM32F407VET6 (Caravangoes).
 

blasphemous

✩✩✩✩✩✩✩
15 Май 2021
2
0
Избыточное цитирование
blasphemous, если хотите начать с нуля, то Вам надо будет освоить USB HID и всё, то с этим связано.
Выбрать для себя микроконтроллер, который будете программировать.

Если же хотите пойти по уже натоптанному и сделать под свой проект:
есть Arduino на Atmega32u4 (MMJOY2, USB HID library, Arduino Joystick library, Logitech G25, EbolzMagy),
STM32F103C8T6 BluePill (FreeJoy), STM32F407VET6 (Caravangoes).
Я взял за основу Ваши данные:

1. Загружаем прошивку GyverWheel-Simple или PCWheel-Simple
2. Подключаем всё по схеме.
Можно оставить только энкодер (пин 0 и 1), кнопка сброса (пин 2),
кнопку (доступны пины 3-12,14-16), педали (газа A0, тормоза A1, и сцепления A2).
3. Открываем управление игровыми устройствами: Win+R (Выполнить) joy.cpl
4. Открываем "Калибровка" и крутим руль, жмём педали. Готово!
5. Настраиваем в игре Оси Руля, Газа, Тормоза и т.д. под себя.

Но мне хочется не только тупо прошить и запустить, а попробовать разобраться в коде, чтобы в дальнейшем можно было самому добавлять свои изменения. Но для этого нужно понять код. А где взять информацию я не знаю. Может Вы посоветуете какие-нибудь книги или сайт.
 

vviktor51

✩✩✩✩✩✩✩
31 Май 2021
3
0
Делал игровой руль по проекту "GyverWheel" подключил энкодер который дороже на странице проекта но он работает так, что кручу его влево программа показывает влево, но кручу вправо программа считает, что я всё равно кручу влево. Как это можно исправить и из-за чего это может быть? Если нужна какая-то ещё информация - напишите.
 
Изменено:

vviktor51

✩✩✩✩✩✩✩
31 Май 2021
3
0
вообще ничего не меняется я это уже несколько раз пробовал:(
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Проверьте правильность подключения, скорее всего дело в этом.
 

kostyamat

★★★★★★✩
29 Окт 2019
1,098
632
@vviktor51, такое может происходить, когда путают C канал (который как правило на массу идет) с A/B.
 

vviktor51

✩✩✩✩✩✩✩
31 Май 2021
3
0
я подключал всё по схеме: оранжевым резисторы по 600 ом, так как без них сигнала не хватает и энкодер вообще не работает

@kostyamat, а "С" это какой канал?
 

Вложения

kostyamat

★★★★★★✩
29 Окт 2019
1,098
632

@vviktor51,
Тот от которого все и пляшет, его в большинстве схем подключения на массу сажают, но бывает и на питание, а каналы A/B наоборот к массе подтягивают. Тогда энкодер формирует "зеркальный" сигнал на выводах. Тут уже от конкретной схемы зависит. Но такое включение возможно для механических энкодеров. У вас видимо оптический? Вы бы на него ссылку дали.
 

Pon4ik

✩✩✩✩✩✩✩
30 Окт 2020
8
0
Посоветуйте расширяющий модуль кнопок (тобешь вместо 16 кнопок, будет к примеру 32 кнопки) для ардуино про микро
 

s60team

★✩✩✩✩✩✩
Pon4ik, держи!

Регистры, SPI (очень быстрый отклик):
CD4021BE (1 регистр = 8 кнопок, итого: 64 кнопки максимум), нет готового модуля.
74HC165 (1 регистр = 8 кнопок, итого: 64 кнопки максимум), нет готового модуля.

Расширители портов, i2c (медленно):
MCP23017 (1шт = 16 кнопок, 128 кнопки максимум), продаётся готовый модуль.
PCF8575 (1шт = 16 кнопок, 128 кнопки максимум), продаётся готовый модуль (ДОРОГО). У меня не заработал. Возможно, нужна подтяжка кнопок.
PCF8574/PCF8574T (1шт = 8 кнопок, 64 кнопки + T версия: ещё столько же, максимум 128 кнопок), продаётся готовый модуль.
MPR121 (1шт = 12 сенсорных кнопок, 48 сенсорных кнопок максимум), продаётся готовый модуль.

Прочее, SPI (нет возможности проверить скорость):
74HC4067 (1шт = 16 аналоговых входов (кнопок)), продаётся готовый модуль.
MCP23S17 (1шт = 16 кнопок, 128 кнопки максимум), нет готового модуля.
 
Изменено:
  • Лойс +1
Реакции: Pon4ik

TuttiFrutti

✩✩✩✩✩✩✩
17 Авг 2021
1
0
Здравствуйте. Подскажите, плиз а прошивка с энкодером который подороже 600pr будет работать? Или надо под этот тип энкодера писать код?
 

s60team

★✩✩✩✩✩✩
TuttiFrutti, Если у вас энкодер 600 вместо 360, то вам просто надо определить количество тиков за оборот.
У 360 получается: 900° руль это (-1800,1800) без библиотеки Rotary2, и (-450,450) с библиотекой.
У вас получится большее число. Не забудьте его вписать в границы вашего руля.

Encoder_test.ino:
// Качаем и ставим библиотеку: https://github.com/S60Team/Rotary2

// Подключаем энкодер:
/* Настройки переехали в файл библиотеки 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;
void setup() {
  Serial.begin(115200);
  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);
}
void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(encVal);
  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
}

1. Подключаем всё по схеме.
1.1. Прошиваем скетч. Запоминаем значения, которые получим, когда крутим руль на нужный вам угол поворота.
2. Загружаем и открываем прошивку GyverWheel-Simple или PCWheel-Simple
2.1. Указываем в прошивке угол поворота руля, полученый в пункте 1.1. Прошиваем.
Можно оставить только энкодер (пин 0 и 1), кнопка сброса (пин 2),
кнопку (доступны пины 3-12,14-16), педали (газа A0, тормоза A1, и сцепления A2).
3. Открываем управление игровыми устройствами: Win+R (Выполнить) joy.cpl
4. Открываем "Калибровка" и крутим руль, жмём педали. Готово!
5. Настраиваем в игре Оси Руля, Газа, Тормоза и т.д. под себя.

Постскриптум: попробуйте ещё такое чудо:
Encoder_test2.ino:
//Сделано по примеру с https://github.com/mateo-cz/steering_wheel
// Подключаем энкодер:
#define outA 0 // пин 0 (PD2)
#define outB 1 // пин 1 (PD3)
volatile long encoder = 0; // volatile, потому что используем прерывания.
//
void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT); // Встроенный светодиод
  digitalWrite(13, LOW); // Встроенный светодиод ВЫКЛ

  // Настраиваем энкодер:
  pinMode(outA, INPUT_PULLUP); // пин энкодера
  pinMode(outB, INPUT_PULLUP); // пин энкодера
  //CHANGE для срабатывания прерывания если пин меняет значение:
  attachInterrupt(digitalPinToInterrupt(outA),outAChange,CHANGE);
  attachInterrupt(digitalPinToInterrupt(outB),outBChange,CHANGE);
}
void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(encoder);
  delay(10);
}
// Если outA меняется, outA==outB значит - (влево)
void outAChange(){ encoder += digitalRead(outA) == digitalRead(outB) ? -1 : 1; }
// Если outB меняется, outA==outB значит + (вправо)
void outBChange() { encoder += digitalRead(outA) == digitalRead(outB) ? 1 : -1; }
 
Изменено:
6 Янв 2022
1
0
Товарищи, тут такая проблема : получается прошить ардуинку, но экран порта включить не выходит и в целом пишет, что COM3 недоступен. Скачал все драйвера и даже несколько раз переустанавливал, потом вышла ошибка Lufa avrisp mkll clone. Ну я установил драйверы на него, теперь неизвестных устройств нет, но ардуино не отображается, а arduino ide выбрать порт нельзя, а прошивка загружается... Постоянно горят жёлтый и красный индикаторы. Подскажите, пожалуйста, что нужно тут сделать? Впервые работаю с arduino, товарищи, нужна помощь