From d06c0d42d1f3c4ed3e29c4364fae9d7cc86f52e2 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 2 May 2022 19:14:50 -0400 Subject: [PATCH 1/4] Add support for generic analog handbrakes --- .../HandbrakeJoystick/HandbrakeJoystick.ino | 67 ++++++++++++ .../HandbrakePrint/HandbrakePrint.ino | 63 +++++++++++ src/SimRacing.cpp | 102 ++++++++++++++++++ src/SimRacing.h | 61 +++++++++++ 4 files changed, 293 insertions(+) create mode 100644 examples/Handbrake/HandbrakeJoystick/HandbrakeJoystick.ino create mode 100644 examples/Handbrake/HandbrakePrint/HandbrakePrint.ino diff --git a/examples/Handbrake/HandbrakeJoystick/HandbrakeJoystick.ino b/examples/Handbrake/HandbrakeJoystick/HandbrakeJoystick.ino new file mode 100644 index 0000000..a49ec4d --- /dev/null +++ b/examples/Handbrake/HandbrakeJoystick/HandbrakeJoystick.ino @@ -0,0 +1,67 @@ +/* + * Project Sim Racing Library for Arduino + * @author David Madison + * @link github.com/dmadison/Sim-Racing-Arduino + * @license LGPLv3 - Copyright (c) 2022 David Madison + * + * This file is part of the Sim Racing Library for Arduino. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + + /** + * @brief Emulates the handbrake as a joystick over USB. + * @example HandbrakeJoystick.ino + */ + +// This example requires the Arduino Joystick Library +// Download Here: https://github.com/MHeironimus/ArduinoJoystickLibrary + +#include +#include + +const int Pin_Handbrake = A2; + +SimRacing::Handbrake handbrake(Pin_Handbrake); + +Joystick_ Joystick( + JOYSTICK_DEFAULT_REPORT_ID, // default report (no additional pages) + JOYSTICK_TYPE_JOYSTICK, // so that this shows up in Windows joystick manager + 0, // number of buttons (none) + 0, // number of hat switches (none) + false, false, // no X and Y axes + true, // include Z axis for the handbrake + false, false, false, false, false, false, false, false); // no other axes + +const int ADC_Max = 1023; // max value of the analog inputs, 10-bit on AVR boards + + +void setup() { + handbrake.begin(); // initialize handbrake pins + + // if you have one, your calibration line should go here + + Joystick.begin(false); // 'false' to disable auto-send + + Joystick.setZAxisRange(0, ADC_Max); +} + +void loop() { + handbrake.update(); + + int pos = handbrake.getPosition(0, ADC_Max); + Joystick.setZAxis(pos); + + Joystick.sendState(); +} diff --git a/examples/Handbrake/HandbrakePrint/HandbrakePrint.ino b/examples/Handbrake/HandbrakePrint/HandbrakePrint.ino new file mode 100644 index 0000000..870727c --- /dev/null +++ b/examples/Handbrake/HandbrakePrint/HandbrakePrint.ino @@ -0,0 +1,63 @@ +/* + * Project Sim Racing Library for Arduino + * @author David Madison + * @link github.com/dmadison/Sim-Racing-Arduino + * @license LGPLv3 - Copyright (c) 2022 David Madison + * + * This file is part of the Sim Racing Library for Arduino. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + + /** + * @brief Prints handbrake position percentage over Serial. + * @example HandbrakePrint.ino + */ + +#include + +const int Pin_Handbrake = A2; + +SimRacing::Handbrake handbrake(Pin_Handbrake); + + +void setup() { + handbrake.begin(); // initialize handbrake pins + + // if you have one, your calibration line should go here + + Serial.begin(115200); + while (!Serial); // wait for connection to open + + Serial.println("Starting..."); +} + +void loop() { + // send some serial data to run conversational calibration + if (Serial.read() != -1) { + handbrake.serialCalibration(); + delay(2000); + } + + handbrake.update(); + + Serial.print("Handbrake: "); + + int pos = handbrake.getPosition(); + Serial.print(pos); + Serial.print("%"); + Serial.println(); + + delay(100); +} diff --git a/src/SimRacing.cpp b/src/SimRacing.cpp index c05134d..2994aa4 100644 --- a/src/SimRacing.cpp +++ b/src/SimRacing.cpp @@ -902,4 +902,106 @@ LogitechShifter::LogitechShifter(uint8_t pinX, uint8_t pinY, uint8_t pinRev, uin this->setCalibration({ 490, 440 }, { 253, 799 }, { 262, 86 }, { 460, 826 }, { 470, 76 }, { 664, 841 }, { 677, 77 }, 0.70, 0.50, 0.70); } +//######################################################### +// Handbrake # +//######################################################### + +Handbrake::Handbrake(uint8_t pinAx, uint8_t detectPin) + : analogAxis(pinAx), detector(detectPin) +{} + +void Handbrake::begin() { + update(); // set initial handbrake position +} + +bool Handbrake::update() { + bool changed = false; + + detector.poll(); + if (detector.getState() == DeviceConnection::Connected) { + changed = analogAxis.read(); + } + else if (detector.getState() == DeviceConnection::Unplug) { + analogAxis.setPosition(analogAxis.getMin()); + } + + return changed; +} + +long Handbrake::getPosition(long rMin, long rMax) const { + return analogAxis.getPosition(rMin, rMax); +} + +int Handbrake::getPositionRaw() const { + return analogAxis.getPositionRaw(); +} + +void Handbrake::setCalibration(AnalogInput::Calibration newCal) { + analogAxis.setCalibration(newCal); + analogAxis.setPosition(analogAxis.getMin()); // reset to min +} + +void Handbrake::serialCalibration(Stream& iface) { + if (isConnected() == false) { + iface.print(F("Error! Cannot perform calibration, ")); + iface.print(F("handbrake")); + iface.println(F(" is not connected.")); + return; + } + + const char* separator = "------------------------------------"; + + iface.println(); + iface.println(F("Sim Racing Library Handbrake Calibration")); + iface.println(separator); + iface.println(); + + AnalogInput::Calibration newCal; + + // read minimum + iface.println(F("Keep your hand off of the handbrake to record its resting position")); + iface.println(F("Send any character to continue.")); + waitClient(iface); + + analogAxis.read(); + newCal.min = analogAxis.getPositionRaw(); + iface.println(); + + // read maximum + iface.println(F("Now pull on the handbrake and hold it at the end of its range")); + iface.println(F("Send any character to continue.")); + waitClient(iface); + + analogAxis.read(); + newCal.max = analogAxis.getPositionRaw(); + iface.println(); + + // set new calibration + this->setCalibration(newCal); + + // print finished calibration + iface.println(F("Here is your calibration:")); + iface.println(separator); + iface.println(); + + iface.print(F("handbrake.setCalibration(")); + iface.print('{'); + iface.print(newCal.min); + iface.print(F(", ")); + iface.print(newCal.max); + iface.print("});"); + iface.println(); + + iface.println(); + iface.println(separator); + iface.println(); + + iface.print(F("Paste this line into the setup() function. The ")); + iface.print(F("handbrake")); + iface.print(F(" will be calibrated with these values on startup.")); + iface.println(F("\nCalibration complete! :)\n\n")); + + flushClient(iface); +} + }; // end SimRacing namespace diff --git a/src/SimRacing.h b/src/SimRacing.h index b67a647..80943ea 100644 --- a/src/SimRacing.h +++ b/src/SimRacing.h @@ -662,6 +662,67 @@ namespace SimRacing { /// @} Shifters + /** + * @brief Interface with analog handbrakes that use hall effect sensors + */ + class Handbrake : public Peripheral { + public: + /** + * Class constructor + * + * @param pinAx analog pin number for the handbrake axis + * @param detectPin the digital pin for device detection (high is detected) + */ + Handbrake(uint8_t pinAx, uint8_t detectPin = NOT_A_PIN); + + /** + * Initializes the pin for reading from the handbrake. + */ + virtual void begin(); + + /** + * Polls the handbrake to update its position. + * + * @return 'true' if the gear has changed, 'false' otherwise + */ + virtual bool update(); + + /** + * Retrieves the buffered position for the handbrake axis, rescaled to a + * nominal range using the calibration values. + * + * By default this is rescaled to an integer percentage (0 - 100) + * + * @param rMin the minimum output value + * @param rMax the maximum output value + * + * @return the handbrake position, buffered and rescaled + */ + long getPosition(long rMin = 0, long rMax = 100) const; + + /** + * Retrieves the buffered position for the handbrake, ignoring the + * calibration data. + * + * @return the handbrake position, buffered + */ + int getPositionRaw() const; + + /// @copydoc AnalogInput::setCalibration() + void setCalibration(AnalogInput::Calibration newCal); + + /// @copydoc AnalogShifter::serialCalibration() + void serialCalibration(Stream& iface = Serial); + + /** @copydoc Peripheral::isConnected() */ + bool isConnected() const { return detector.isConnected(); } + + private: + AnalogInput analogAxis; ///< axis data for the handbrake's position + DeviceConnection detector; ///< detector instance for checking if the handbrake is connected + }; + + /** * @brief Interface with the Logitech pedals (Gas, Brake, and Clutch) * @ingroup Pedals From 110b7a3d1ad6f4fc72a738251531d93a2bc1d738 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 2 May 2022 19:54:59 -0400 Subject: [PATCH 2/4] Update supported devices documentation Added the handbrake, simplified this list, and added generic devices to the main README. --- README.md | 9 ++++++++- docs/pages/supported_devices.md | 20 +++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d60b505..0141d5a 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,15 @@ Run one of the library examples in the Arduino IDE by going to `File -> Examples ## Supported Devices -* [Logitech Three Pedal Peripheral (Gas, Brake, Clutch)](http://dmadison.github.io/Sim-Racing-Arduino/docs/logitech_pedals.html) +### Generic Devices +* [Two pedal peripherals (gas + brake)](https://dmadison.github.io/Sim-Racing-Arduino/docs/class_sim_racing_1_1_two_pedals.html) +* [Three pedal peripherals (gas, brake, clutch)](https://dmadison.github.io/Sim-Racing-Arduino/docs/class_sim_racing_1_1_three_pedals.html) +* [Analog shifters](https://dmadison.github.io/Sim-Racing-Arduino/docs/class_sim_racing_1_1_analog_shifter.html) +* [Analog handbrakes](https://dmadison.github.io/Sim-Racing-Arduino/docs/class_sim_racing_1_1_handbrake.html) + +### Commercial Devices * [Logitech Two Pedal Peripheral (Gas, Brake)](http://dmadison.github.io/Sim-Racing-Arduino/docs/logitech_pedals.html) +* [Logitech Three Pedal Peripheral (Gas, Brake, Clutch)](http://dmadison.github.io/Sim-Racing-Arduino/docs/logitech_pedals.html) * [Logitech Driving Force Shifter](http://dmadison.github.io/Sim-Racing-Arduino/docs/logitech_shifter.html) ## License diff --git a/docs/pages/supported_devices.md b/docs/pages/supported_devices.md index 8afa60c..9a40dee 100644 --- a/docs/pages/supported_devices.md +++ b/docs/pages/supported_devices.md @@ -1,19 +1,13 @@ # Supported Devices -### Commercial Devices: - -- @subpage logitech_pedals -- @subpage logitech_shifter - ### Generic Devices -#### Pedals +* Two pedal peripherals (gas + brake) using `SimRacing::TwoPedals` +* Three pedal peripherals (gas, brake, clutch) using `SimRacing::ThreePedals` +* Analog shifters using `SimRacing::AnalogShifter` +* Analog handbrakes using `SimRacing::Handbrake` -The library supports generic pedal devices that connect via the microcontroller's analog to digital converter (ADC). +### Commercial Devices -* Two pedal setups (gas + brake) use the `SimRacing::TwoPedals` class. -* Three pedal setups (gas, brake, clutch) use the `SimRacing::ThreePedals` class. - -#### Shifters - -The library supports generic shifting devices that record gear position using a pair of potentiometers. These are supported as part of the `SimRacing::AnalogShifter` class. +- @subpage logitech_pedals +- @subpage logitech_shifter From e4aebce3efb3ccbf698279d160773089b2831a58 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 2 May 2022 20:08:07 -0400 Subject: [PATCH 3/4] Add handbrake keywords Also added the getPosition keywords for the other classes, as they are technically different functions. [skip ci] --- keywords.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/keywords.txt b/keywords.txt index 932f403..f80890b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -35,6 +35,9 @@ AnalogShifter KEYWORD1 LogitechShifter KEYWORD1 +# Handbrake Classes +Handbrake KEYWORD1 + ####################################### # Peripheral Class Methods and Functions (KEYWORD2) ####################################### @@ -65,6 +68,9 @@ setCalibration KEYWORD2 # Pedal Methods and Functions (KEYWORD2) ####################################### +getPosition KEYWORD2 +getPositionRaw KEYWORD2 + hasPedal KEYWORD2 getNumPedals KEYWORD2 @@ -84,11 +90,24 @@ gearChanged KEYWORD2 getGearMin KEYWORD2 getGearMax KEYWORD2 +getPosition KEYWORD2 +getPositionRaw KEYWORD2 + getReverseButton KEYWORD2 setCalibration KEYWORD2 serialCalibration KEYWORD2 +####################################### +# Handbrake Methods and Functions (KEYWORD2) +####################################### + +getPosition KEYWORD2 +getPositionRaw KEYWORD2 + +setCalibration KEYWORD2 +serialCalibration KEYWORD2 + ####################################### # Instances (KEYWORD2) ####################################### From dda95c1d2d7b4fb99a3e7a35c39671431104d536 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 2 May 2022 20:09:00 -0400 Subject: [PATCH 4/4] Add handbrakes to library description [skip ci] --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 76b22a9..3164f7c 100644 --- a/library.properties +++ b/library.properties @@ -2,7 +2,7 @@ name=Sim Racing Library version=1.0.0 author=David Madison maintainer=David Madison -sentence=Interface with sim racing peripherals including pedals and gear shifters. +sentence=Interface with sim racing peripherals including pedals, gear shifters, and handbrakes. paragraph=Works out of the box with the Logitech pedals and Logitech Driving Force gear shifter. Supports easy USB joystick output. category=Signal Input/Output url=https://github.com/dmadison/Sim-Racing-Arduino