Hello all,
Please excuse my ignorance as I am still very new to programming for Arduinos.
What I am trying to achieve is using my 600P/R encoders as an axis for a gamepad. The gamepad interfaces with a 6 axis robot and ideally I would like to move the individual axis with each encoder.
I have been able to successfully move an axis with the following sketch:
/* Simple HSI Knobs Sketch for Falcon BMS / DCS / FSX
* for Arduino Micro/Leonardo / Sparkfun Pro Micro or equiv. clones
* by SemlerPDX June2019
* VETERANS-GAMING.COM
* ( https://veterans-gaming.com/blogs/entry/32-diy-custom-game-controller-2-dial-hsi-course-and-heading-knobs/ )
*
* Pins:
* Rotary Encoder 1 - (OUTA-OUTB-SW) = Arduino Pins (0,1,15)
* Rotary Encoder 2 - (OUTA-OUTB-SW) = Arduino Pins (2,3,6)
*
* Encoder Library
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* Joystick Library
* by Matthew Heironimus
* https://github.com/MHeironimus/ArduinoJoystickLibrary
*/
#define ENCODER_USE_INTERRUPTS
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
#include <Joystick.h>
//Tell the Encoder Library which pins have encoders
Encoder axisXRotation(0, 1);
Encoder axisYRotation(2, 3);
//Rotary Encoder Push Button Pins
int buttonArray[2] = {15, 6};
//Rotary Encoder Interrupt Pins
int EncoderPin0 = 0;
int EncoderPin1 = 1;
int EncoderPin2 = 2;
int EncoderPin3 = 3;
//Delay Time between loops
int debounceDelay = 0;
//Variables to compare current to old values
int oldX = 0;
int oldY = 0;
int RxAxis_Value = 1;
int RyAxis_Value = 1;
//Intervals for Jump/Warp Speed Rotations
int JumpSpeed = 18;
int WarpSpeed = 36;
//Set generic joystick with id 42 with 2 buttons and 2 axes
Joystick_ Joystick(0x42,
0x04, 2, 0,
true, true, false, true, true, false,
false, false, false, false, false);
void setup() {
//Set Encoder Pins as Pullups
pinMode(EncoderPin0, INPUT_PULLUP);
pinMode(EncoderPin1, INPUT_PULLUP);
pinMode(EncoderPin2, INPUT_PULLUP);
pinMode(EncoderPin3, INPUT_PULLUP);
//Loop through buttons and set them as Pullups
for (int x = 0; x < sizeof(buttonArray); x++) {
pinMode(buttonArray[x], INPUT_PULLUP);
}
//Set Range of custom Axes
Joystick.setRxAxisRange(0, 359);
Joystick.setRyAxisRange(0, 359);
// Initialize Joystick Library
Joystick.begin(false);
}
void loop() {
// Loop through button pin values & set to Joystick
for (int x = 0; x < sizeof(buttonArray); x++) {
byte currentButtonState = !digitalRead(buttonArray[x]);
Joystick.setButton(x, currentButtonState);
}
// Read "Heading" X Axis Rotation Encoder Knob
int newX = axisXRotation.read();
if (newX > oldX) {
//Determine speed of increment & set output
int difX = newX - oldX;
RxAxis_Value = speedVal(difX, RxAxis_Value, 1);
Joystick.setRxAxis(RxAxis_Value);
axisXRotation.write(newX);
oldX = newX;
}else if (newX < oldX) {
//Determine speed of decrement & set output
int difX = oldX - newX;
RxAxis_Value = speedVal(difX, RxAxis_Value, 0);
Joystick.setRxAxis(RxAxis_Value);
axisXRotation.write(newX);
oldX = newX;
}
// Read "Course" Y Axis Rotation Encoder Knob
int newY = axisYRotation.read();
if (newY > oldY) {
//Determine speed of increment & set output
int difY = newY - oldY;
RyAxis_Value = speedVal(difY, RyAxis_Value, 1);
Joystick.setRyAxis(RyAxis_Value);
axisYRotation.write(newY);
oldY = newY;
}else if (newY < oldY) {
//Determine speed of decrement & set output
int difY = oldY - newY;
RyAxis_Value = speedVal(difY, RyAxis_Value, 0);
Joystick.setRyAxis(RyAxis_Value);
axisYRotation.write(newY);
oldY = newY;
}
//Send Joystick info through USB
Joystick.sendState();
delay(debounceDelay);
}
//Function to set Rotation value adjusted for the turning speed
int speedVal(int dif, int val, int dir) {
if (dif >= WarpSpeed) {
if (dir == 1) {
val = val + WarpSpeed;
}else{
val = val - WarpSpeed;
}
}else if (dif >= JumpSpeed) {
if (dir == 1) {
val = val + JumpSpeed;
}else{
val = val - JumpSpeed;
}
}else{
if (dir == 1) {
val = val + 1;
}else{
val = val - 1;
}
}
//Correct Rotation within 360 deg.
if (val < 0) {
val = val + 0;
}else if (val >= 360) {
val = val - 0;
}
return val;
}
The issue I am having is with this program, the axis will continue to move in either direction unless I set the encoder to its 0 point. I reached out to the devs for the software I am using to interface the robot and they made this suggestion:
"In general the robot software expects the joystick axis value being inputed to be representative of the velocity with which the robot should move. As you mentioned, with a joystick this works as the joystick will spring back to 0 when released thus causing the robot to stop moving.
In your case, I’m guessing the behavior you want is for the robot to move based on the speed at which you are rotating your handwheel. As such, the value you should feed to the robot software is actually the speed of your encoder and not it’s position. This can be obtained by taking the difference between the current and last encoder position in the loop on your Arduino and then scaling it to the [-1,1] range. This will make it so that the robot will move whenever you move the handwheel (Difference between current and last position will be positive or negative based on the direction of rotation) and stop when the handwheel is stopped (As the difference between current and last position will now be 0)"
I have searched the forum but have not yet found a solution for this, and was hoping someone might have some insight on how I can achieve this?
Thanks!