6 axis 12 button usb with "bigjoystick" HID firmware

I’m trying to make an UNO R3 into a 6 axis 12 button USB HID controller. I was able to modify some code to get from 3 axis to 6. I have hardware for testing and the analog portion works. I’m having trouble getting the buttons down.

The button press indicates under the game controllers properties when the pin is pulled LOW, but once returned it stays “on” (PULLUP is set). I can cycle through all 12 buttons (pins 2-13), but all 12 stay lit until i recycle power or reset. What am I missing?

/* Arduino USB Joystick HID demo */
/* Author: Darran Hunt
* Released into the public domain.
* Update by RICLAMER in 25/03/2014 to use Analog ports and digital ports
* This code is to be used with Arduino UNO (6 axis and 13 Button )
* This code is compatible with Arduino Mega. 
*/

/* INSTALLATION
Just install POT in each analog port. Using the _GND _Analog _5V Arduino.
Like this image: http://arduino.cc/en/uploads/Tutorial/joy_sch_480.jpg
To setup the buttons, just install you prefered button switch under GND and Port Digital 02~13.
Use Flip to erease and burn this firmware DFU: https://github.com/harlequin-tech/arduino-usb/blob/master/firmwares/Arduino-big-joystick.hex
I used Arduino R3 with Atmega 16U2.
*/

#undef DEBUG

#define NUM_BUTTONS  40 // you don't need to change this value
#define NUM_AXES  8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO, don't need to change this value.

typedef struct joyReport_t {
int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS+7)/8]; // 8 buttons per byte
} joyReport_t;

joyReport_t joyReport;

uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);

void setup() 
{ 
//set pin to input Button 
for( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
Serial.begin(115200);
delay(200);

for (uint8_t ind=0; ind<8; ind++) {
joyReport.axis[ind] = ind*1000;
}
for (uint8_t ind=0; ind<sizeof(joyReport.button); ind++) {
joyReport.button[ind] = 0;
}
}

// Send an HID report to the USB interface
void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
Serial.write((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind=0; ind<NUM_AXES; ind++) {
Serial.print("axis[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->axis[ind]);
Serial.print(" ");
}
Serial.println();
for (uint8_t ind=0; ind<NUM_BUTTONS/8; ind++) {
Serial.print("button[");
Serial.print(ind);
Serial.print("]= ");
Serial.print(report->button[ind], HEX);
Serial.print(" ");
}
Serial.println();
#endif
}

// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button/8;
uint8_t bit = button - 8*index;

joy->button[index] |= 1 << bit;
}

// turn a button off
void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button/8;
uint8_t bit = button - 8*index;

joy->button[index] &= ~(1 << bit);
}

/* 
* Read Digital port for Button
* Read Analog port for axis
*/
void loop() 
{ 
// Create Matriz with value off switch button 
for(int bt = 1; bt < 13; bt ++)
{
btn[bt]= digitalRead(bt+1);
} 
// Power ON button if it is press. buton 17 at 28
for(int on=01; on < 13; on++)
{
if (btn[on] == LOW)
{
setButton(&joyReport, on+16);
// Serial.println("botao ON");
// Serial.println(on+16);
}else{
fulloff = fulloff++;
} //Power off all Button, if all button are not press
if(fulloff == 13)
{
for(uint8_t cont=0; cont<40; cont++)
{ 
clearButton(&joyReport, cont);
}
// Serial.println("Every buttons is off");
}
}

/* Move all of the Analogic axis */
/* Arduino UNO have only 6 port. Will be necessary set to 0; the not used port */
/* In this example, i will use just 3 axis. X, Y, Z */
/* if you will use all 6 analog ports, set axis < 3, to axis < 5 */
for (uint8_t axis = 0; axis < 6; axis++) {
joyReport.axis[axis] = map(analogRead(axis), 0, 1023, -32768,32767 );
}
//Set to 0; the not used analog port.
//if you will use all 6 analog ports, exclude the lines, axis[3] at axis [5] */
//joyReport.axis[3] = 0;
//joyReport.axis[4] = 0;
//joyReport.axis[5] = 0;
//joyReport.axis[6] = 0;
//joyReport.axis[7] = 0;
//joyReport.axis[8] = 0;

//Send Data to HID
sendJoyReport(&joyReport);

delay(100);
fulloff = 0;
}

Capture.JPG

That's how it works because the Arduino has internal pull-up resistors.

Instead of reading the pins directly you could just invert their states. In other words, if you detect that a button is LOW then just send a HIGH to your code. Else if you detect that a button is HIGH then send a LOW to your code.

Edit: Now that I reread your question I'm not sure I answered it properly. Sorry.

I think the hardware is setup correct. Digital input with pullup, switched to low. perhaps something in the code that isn’t clearing the switch state? The switches “turn-on”, but don’t clear to off after the switch contact is opened.

Ok, maybe I understand a little better.

After a quick look I don't see anything obvious. I'm at work right now so it will have to wait until I get home to really take a look.

Thanks. That would be a huge help!

Never mind if you saw this post before I edited it away.

Got it! You have two errors that are working together to cause the problem.

    if (btn[on] == LOW)
    {
      setButton(&joyReport, on + 16);
      // Serial.println("botao ON");
      // Serial.println(on+16);
    } else {
      fulloff = fulloff++;      // <---- This causes undefined behaviour
    } //Power off all Button, if all button are not press
    if (fulloff == 13)   // <---- fulloff never goes above 11
    {

I fixed the first error and tested the second error to be sure it worked

    if (btn[on] == LOW)
    {
      setButton(&joyReport, on + 16);
      // Serial.println("botao ON");
      // Serial.println(on+16);
    } else {
      fulloff++;
    } //Power off all Button, if all button are not press
    if (fulloff == 11)
    {

After making these changes I could watch the individual buttons change as they were pressed and then they cleared when I let go.

It worked but I didn’t try to understand why fulloff wasn’t going above 11. Also, I noticed that a bit on button[3] always showed up when any button was pressed. I don’t know if you were seeing that on your setup so I just left it alone for now.

Thanks sooo much!

I tried the mods you suggested, but the fulloff == 11 didn't work at all. I made your suggested revision of fulloff++ instead of fulloff=fulloff++, then changed to 12 from 11 (i figured there are 12 inputs, so it made sense to me). Seems to work perfect now. Only limitations seem to be that the buttons capture each other. If I press 2 and let go of one, they all stay active until I let go... not the end of the world for my application.

Thanks again. You really helped me out here!

if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);
} else {
fulloff++;
}
if (fulloff == 12)
{

HOW i can burn own axis(analog input) NOT need more.
i need only max all analog what can add.
i read before have possiple add 16 analog to mega board ?
how made, i no understand how burn hex file, and how make description have full maximum analog input.
google i try read many but no have any step by step instruction how i can made own joystick.
i have flip program but what i connect this, what parts i need ?
i have usbasp programmer but i try many time install many different driver but newer no found port, ardunio ide no found programmer, flip software no found programmer, what i need can burn hex file ????
i need only max analog input my flight simulator FSX no more, who can made to me ?

I resume this old post to ask for help on the programming of Unojoy on arduino UNO R3 to control six axes (I do not care about the buttons but only the axes). I tried to use the sketch posted by mach1f90 but Unojoy only controls me two axes. Hello and thanks