Go Down

Topic: Tutorial - How to change firmware on 8u2 (Read 271849 times) previous topic - next topic


sensorIdentification == "a" is wrong, it should be sensorIdentification == 'a' (single quotes instead of double) and the same for b,c and d.


I'm implementing (at least trying to) ant's code.
Now I'm finally getting some movement on the axes in windows again.
So at least something is getting through.
But nothing useful. I suspect it has something to do with the 0xFF start byte.


In uno's code I define something like that:

Code: [Select]
byte start_b;
byte b1;

b1= ...



It worked.
My problem so far was that I sent out my "sensorData" as int-s instead of bytes. So now it Works.

But now, In windows, I get another problem.
The values that I put into JoystickReport->X range from 0-254.
It seems the values wrap around.
I'm testing with a potentiometer, and the values roll over from 0-63 in the windows testing screen quite a few times.

I'm not quite sure where to pinpoint this problem.


Maybe it's because you data has to be between -100 and 100.

If your range is 0-255 you should change the descriptor:

Code: [Select]
     0x15, 0x9c,          /*     Logical Minimum (-100)                         */
     0x25, 0x64,          /*     Logical Maximum (100)                          */


Code: [Select]
     0x15, 0x00,          /*     Logical Minimum (0)                         */
     0x26, 0xff, 0x00,    /*     Logical Maximum (255)                          */



Dec 08, 2010, 04:27 pm Last Edit: Dec 08, 2010, 07:28 pm by Blue_Boy Reason: 1
I thought of this too.
Didn't make a difference.
Why did you add the extra 0x00 after 0xff by the way?
My Code, as it stands now.

Hid Descriptor
Code: [Select]
USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] =
     0x05, 0x01,          /* Usage Page (Generic Desktop)                       */
     0x09, 0x04,          /* Usage (Joystick)                                   */
     0xa1, 0x01,          /* Collection (Application)                           */
     0x09, 0x01,          /*   Usage (Pointer)                                  */
     0xa1, 0x00,          /*   Collection (Physical)                            */
     0x05, 0x01,          /*     Usage Page (Generic Desktop)                   */
     0x09, 0x30,          /*     Usage (X)                                      */
     0x09, 0x31,          /*     Usage (Y)                                      */
     0x09, 0x32,          /*     Usage (Z)                                      */
     0x09, 0x35,          /*     Usage (Rz)                                     */
     0x15, 0x00,          /*     Logical Minimum (0)                         */
     0x26, 0xff, 0x00,    /*     Logical Maximum (255)                          */
     0x75, 0x08,          /*     Report Size (8)                                */
     0x95, 0x04,          /*     Report Count (4)                               */
     0x81, 0x82,          /*     Input (Data, Variable, Absolute, Volatile)     */
     0xc0,                /*   End Collection                                   */
     0x05, 0x09,          /*   Usage Page (Button)                              */
     0x09, 0x02,          /*   Usage (Button 2)                                 */
     0x09, 0x01,          /*   Usage (Button 1)                                 */
     0x15, 0x00,          /*   Logical Minimum (0)                              */
     0x25, 0x01,          /*   Logical Maximum (1)                              */
     0x75, 0x01,          /*   Report Size (1)                                  */
     0x95, 0x02,          /*   Report Count (2)                                 */
     0x81, 0x02,          /*   Input (Data, Variable, Absolute)                 */
     0x75, 0x06,          /*   Report Size (6)                                  */
     0x95, 0x01,          /*   Report Count (1)                                 */
     0x81, 0x01,          /*   Input (Constant)                                 */
     0xc0                 /* End Collection                                     */

Code: [Select]
typedef struct
                 int8_t  X; /**< Current absolute joystick X position, as a signed 8-bit integer */
                 int8_t  Y; /**< Current absolute joystick Y position, as a signed 8-bit integer */
                 int8_t  Z; /**< Current absolute joystick Z position, as a signed 8-bit integer */
                 int8_t  Rz; /**< Current absolute joystick Rz position, as a signed 8-bit integer */
                 uint8_t Button; /**< Bit mask of the currently pressed joystick buttons */
           } USB_JoystickReport_Data_t;

Data Holders

Code: [Select]
uint8_t dataIn;
uint8_t data[5];
uint8_t counter;

Main loop

Code: [Select]
int main(void)
     for (;;)
           if (counter==5){counter=0;}
           if (Serial_IsCharReceived())
                 dataIn = Serial_RxByte();
                 if (dataIn == 0xFF){counter=0;}


Code: [Select]
USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;

JoystickReport->X  =  data[1];
JoystickReport->Y  =  data[2];
JoystickReport->Z  =  data[3];
JoystickReport->Rz =  data[4];

JoystickReport->Button = 0;

*ReportSize = sizeof(USB_JoystickReport_Data_t);
     return false;

And Arduino code:

Code: [Select]
int sensorBottom[] = {0, 0, 0, 0};
int sensorTop[] = {1024, 1024, 1024, 1024};

byte dataStart = 0xFF;
byte sensorValue;

void setup()
 // initialize serial communications at 9600 bps:

void loop() {
 // Send start byte to 8u2
 for (int i = 0; i < 4; i++)
   sensorValue = analogRead(i);            

   sensorValue = map(sensorValue, sensorBottom[i], sensorTop[i], 0, 255);
   sensorValue = constrain(sensorValue, 0, 255);
   // print the results to the serial monitor:        

Problem: the values "wrap" around.
In the Windows 7 calibrate dialog I see the values ranging from 0 to 63 and then wrap around, a total of 4 time. (This makes sense in a way, it equals 256. I'm still not sure why though...)
Also, no matter what range (I tried 64 steps instead of 265), the values still "roll around" 4 times in a row.


Dec 08, 2010, 11:52 pm Last Edit: Dec 09, 2010, 12:17 am by ant.b Reason: 1
The problem seems to be with
Code: [Select]
sensorValue = analogRead(i);
sensorValue is a byte so its range is 0-255

then you map:
Code: [Select]
sensorValue = map(sensorValue, 0, 1024, 0, 255);
 so sensorValue=255*255/1024=63  

I hope this can help you


Code: [Select]
sensorValue = map(sensorValue, 0, 1024, 0, 255);
Please don't do this.
sensorValue = analogRead(i)/4;
produces the same result, in much less time.


Hey Guys,
You were right.
It was indeed the analogRead() value being pushed in a byte.


thanks for this tutorial. gives me some hope to be able to build my custom mouse one day :-)


ant.b - this worked great. I have a few things to figure out, but with a little modification, my uno thinks and looks like a joystick. Thank you so much for posting your tut! :)


Clarification for reply #10.  According to the datasheet, the chip looks at the HWB pin state as reset is released (on the rising edge of /Reset).  So you should take the wire off the reset pin before taking the wire off the HWB pin.  If you take both wires off at once, it's a matter of luck whether the HWB pin is still grounded when you release the reset pin.

So to save frustration, I recommend following the datasheet, and remove the Reset wire before you remove the HWB wire.


There's a certain amount of capacitance in the Uno circuit though (you are touching the wire against a capacitor, charging it). That's why, if you take off both wires together, it should still be low at the reset. On my board it holds enough charge to stay low for at least half a second.


Ah, that's a nice feature: being able to yank both wires at once and the cap takes care of enforcing the HWB state requirement.  Thanks for that detail.

Go Up