Since that i am now using multiple encoders and interrupts, i am now using direct port manipulation to read the pin states as it is many times faster than regular digitalReads.
I found a way better way to write the Arduino values to the virtual joystick; PPJoyCom. It is a add-on type program for the PPJoy virtual joystick driver. PPJoyCom waits for a initialization byte over the serial port from the Arduino(print a byte value 240+number of channels). then the encoder values range from 0 to 255(max value of a byte) and are sent to PPJoyCom and written to the joystick. way easier than a C# app. :) basic sample PPJoyCom arduino sketch below, along with encoder code.
basic flow:
1. arduino reads HDD encoders for position, button states etc. sends the data to the PPJoyCom program.
3. PPJoyCom program "writes" the values from the Arduino to the virtual joystick.
3. racing game reads the virtual joystick; X axis is turning, Y is throttle, Z is brake, buttons for shifting, menu keys...
#define Xpin 2
#define Ypin 3
#define Btn1Pin 11
#define Btn2Pin 12
byte Xaxis;
byte Yaxis;
byte Btn1 = 0;
byte Btn2 = 0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
Btn1 = digitalRead(Btn1Pin);
Btn2 = digitalRead(Btn2Pin);
Xaxis = analogRead(Xpin) / 4;
Yaxis = analogRead(Ypin) / 4;
Serial.print(244,BYTE); // 240 + # of channels, 2 Buttons and 2 axis
Serial.write(0);
Serial.print(Btn1,BYTE);
Serial.print(Btn2,BYTE);
Serial.print(x,BYTE);
Serial.print(y,BYTE);
delay(25);
}
#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>
#define WheelPinA 2
#define WheelPinB 3
#define GasPinA 4
#define GasPinB 5
#define BrakePinA 6
#define BrakePinB 7
#define ClutchPinA 8
#define ClutchPinB 9
#define Gear1pin 10
#define Gear2pin 11
#define Gear3pin 12
#define Gear4pin 13
#define Gear5pin 14 //A0
#define Gear6pin 15 //A1
#define ShiftModepin 16 //A2, real shifting or speed shift
#define Aux1pin 17 //A3
#define Aux2pin 18 //A4
#define Aux3pin 19 //A5
volatile unsigned int Encoders[3] = {0}; //wheel, gas, brake, clutch
volatile boolean ButtonStates[3] = {0}; //current gear, shift mode, aux: 1, 2, or 3
void setup()
{
// 76543210
//(PIND & B00001000) check only the pin '1' (in this case digital 3) in this line for low or high, & means dont check any others
//would be the same as: PIND & (1 << 3);
//1111111 checking for true would be 128+64+32+16+8+4+2+1
//(PIND & B00001000) checking for true would be 8
//goes from left to right
// 76543210
DDRD = B00000000; //sets 2 through 7 as inputs
PORTD &= B11111100; //enable pullups on all but tx/rx
// ..13...8
DDRB &= B11000000; //sets through 13 as inputs excpet for crytsl pins
PORTB &= B00111111; //enable pullups on all but crystal pins
// ..543210
DDRC = B00000000; //sets analog 0 through 5 as inputs
PORTC &= B00111111; //enable pullups on all but analog 6 an 7 (6 and 7 arent avaliable on atmega 328)
PCattachInterrupt(WheelPinA, WheelTrigA, CHANGE);
PCattachInterrupt(WheelPinB, WheelTrigB, CHANGE);
PCattachInterrupt(GasPinA, GasTrigA, CHANGE);
PCattachInterrupt(GasPinB, GasTrigB, CHANGE);
PCattachInterrupt(BrakePinA, BrakeTrigA, CHANGE);
PCattachInterrupt(BrakePinB, BrakeTrigB, CHANGE);
PCattachInterrupt(ClutchPinA, ClutchTrigA, CHANGE);
PCattachInterrupt(ClutchPinB, ClutchTrigB, CHANGE);
PCattachInterrupt(Gear1pin, GearItrig, CHANGE);
PCattachInterrupt(Gear2pin, GearIItrig, CHANGE);
PCattachInterrupt(Gear3pin, GearIIItrig, CHANGE);
PCattachInterrupt(Gear4pin, GearIVtrig, CHANGE);
PCattachInterrupt(Gear5pin, GearVtrig, CHANGE);
PCattachInterrupt(Gear6pin, GearVItrig, CHANGE);
PCattachInterrupt(Aux1pin, AuxItrig, CHANGE);
PCattachInterrupt(Aux2pin, AuxIItrig, CHANGE);
PCattachInterrupt(Aux3pin, AuxIIItrig, CHANGE);
PCattachInterrupt(ShiftModepin, ShiftTrig, CHANGE);
Serial.begin (115200);
}
void loop()
{
for(int x=0; x<4; x++)
{
Serial.print(Encoders[x]);
Serial.print(","); //delimiter
}
for(int x=0; x<4; x++)
{
Serial.print(ButtonStates[x]);
Serial.print(","); //delimiter
}
Serial.println();
}
void GearItrig()
{
ButtonStates[0]=1;
}
void GearIItrig()
{
ButtonStates[0]=2;
}
void GearIIItrig()
{
ButtonStates[0]=3;
}
void GearIVtrig()
{
ButtonStates[0]=4;
}
void GearVtrig()
{
ButtonStates[0]=5;
}
void GearVItrig()
{
ButtonStates[0]=6;
}
void ShiftTrig()
{
ButtonStates[1]=~ButtonStates[1];
}
void AuxItrig()
{
ButtonStates[2]=1;
}
void AuxIItrig()
{
ButtonStates[2]=2;
}
void AuxIIItrig()
{
ButtonStates[3]=3;
}
void WheelTrigA()
{
// look for a low-to-high on pin A
if ((PIND & B00000100) == 4)
{
// check pin B to see which way encoder is turning
if ((PIND & B00001000) == 0)
{
Encoders[0] -= 1; // CW
}
else
{
Encoders[0] += 1; // CCW
}
}
else // must be a high-to-low edge on pin A
{
// check pin B to see which way encoder is turning
if ((PIND & B00001000) == 8)
{
Encoders[0] -= 1; // CW
}
else
{
Encoders[0] += 1; // CCW
}
}
//Serial.println (Encoders[0], DEC);
// use for debugging - remember to comment out
}
void WheelTrigB()
{
// look for a low-to-high on pin B
if ((PIND & B00001000) == 8)
{
// check pin A to see which way encoder is turning
if ((PIND & B00000100) == 4)
{
Encoders[0] -= 1; // CW
}
else
{
Encoders[0] += 1; // CCW
}
}
// Look for a high-to-low on pin B
else
{
// check pin B to see which way encoder is turning
if ((PIND & B00000100) == 0)
{
Encoders[0] -= 1; // CW
}
else
{
Encoders[0] += 1; // CCW
}
}
}
void GasTrigA()
{
// look for a low-to-high on pin A
if ((PIND & B00010000) == 16)
{
// check pin B to see which way encoder is turning
if ((PIND & B00100000) == 0)
{
Encoders[1] -= 1; // CW
}
else
{
Encoders[1] += 1; // CCW
}
}
else // must be a high-to-low edge on pin A
{
// check pin B to see which way encoder is turning
if ((PIND & B00100000) == 32)
{
Encoders[1] -= 1; // CW
}
else
{
Encoders[1] += 1; // CCW
}
}
//Serial.println (Encoders[1], DEC);
// use for debugging - remember to comment out
}
void GasTrigB()
{
// look for a low-to-high on pin B
if ((PIND & B00100000) == 32)
{
// check pin A to see which way encoder is turning
if ((PIND & B00010000) == 16)
{
Encoders[1] -= 1; // CW
}
else
{
Encoders[1] += 1; // CCW
}
}
// Look for a high-to-low on pin B
else
{
// check pin B to see which way encoder is turning
if ((PIND & B00010000) == 0)
{
Encoders[1] -= 1; // CW
}
else
{
Encoders[1] += 1; // CCW
}
}
}
void BrakeTrigA()
{
// look for a low-to-high on pin A
if ((PIND & B01000000) == 64)
{
// check pin B to see which way encoder is turning
if ((PIND & B10000000) == 0)
{
Encoders[2] -= 1; // CW
}
else
{
Encoders[2] += 1; // CCW
}
}
else // must be a high-to-low edge on pin A
{
// check pin B to see which way encoder is turning
if ((PIND & B10000000) == 128)
{
Encoders[2] -= 1; // CW
}
else
{
Encoders[2] += 1; // CCW
}
}
//Serial.println (Encoders[2], DEC);
// use for debugging - remember to comment out
}
void BrakeTrigB()
{
// look for a low-to-high on pin B
if ((PIND & B10000000) == 128)
{
// check pin A to see which way encoder is turning
if ((PIND & B01000000) == 64)
{
Encoders[2] -= 1; // CW
}
else
{
Encoders[2] += 1; // CCW
}
}
// Look for a high-to-low on pin B
else
{
// check pin B to see which way encoder is turning
if ((PIND & B01000000) == 0)
{
Encoders[2] -= 1; // CW
}
else
{
Encoders[2] += 1; // CCW
}
}
}
void ClutchTrigA()
{
// look for a low-to-high on pin A
if ((PINB & B00000001) == 1)
{
// check pin B to see which way encoder is turning
if ((PINB & B00000010) == 0)
{
Encoders[3] -= 1; // CW
}
else
{
Encoders[3] += 1; // CCW
}
}
else // must be a high-to-low edge on pin A
{
// check pin B to see which way encoder is turning
if ((PINB & B00000010) == 2)
{
Encoders[3] -= 1; // CW
}
else
{
Encoders[3] += 1; // CCW
}
}
//Serial.println (Encoders[3], DEC);
// use for debugging - remember to comment out
}
void ClutchTrigB()
{
// look for a low-to-high on pin B
if ((PINB & B00000010) == 2)
{
// check pin A to see which way encoder is turning
if ((PINB & B00000001) == 1)
{
Encoders[3] -= 1; // CW
}
else
{
Encoders[3] += 1; // CCW
}
}
// Look for a high-to-low on pin B
else
{
// check pin B to see which way encoder is turning
if ((PINB & B00000001) == 0)
{
Encoders[3] -= 1; // CW
}
else
{
Encoders[3] += 1; // CCW
}
}
}