Pages: 1 [2] 3   Go Down
Author Topic: Tutorial - How to change firmware on 8u2  (Read 103727 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks so much for this! Got an Uno for the purpose of making a funky arduino accelerometerfmouse and was fretting about the lack of info on how to go about the USB HID part til I found this post. Can't wait to get choppin with it!
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been lurking around in this thread for some time now.
I think I've wrapped my head around the general idea.
How hard would it be to add another 2 axes to the example joystick?
(axes A,B,C,D instead of only X-Y)

As far as I can see, it requires some tinkering in the Descriptors.c file.
Could any other "HID Usages" like Vx or Vbrx serve as my extra axes?
« Last Edit: December 03, 2010, 08:34:17 am by Blue_Boy » Logged

North Yorkshire, UK
Offline Offline
Faraday Member
**
Karma: 104
Posts: 5531
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How hard would it be to add another 2 axes to the example joystick?
Surely you only have X,Y and Z?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A Playstation Dualshock styled controller has 2 thumbsticks.
So four usable axes.
I would just like to pipe 4 different sensor values into Unity using no intermediate software whatsoever, so that's why.
Logged

North Yorkshire, UK
Offline Offline
Faraday Member
**
Karma: 104
Posts: 5531
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A Playstation Dualshock styled controller has 2 thumbsticks.
So four usable axes.
I would just like to pipe 4 different sensor values into Unity using no intermediate software whatsoever, so that's why.
Ahh I see.
Logged

France
Offline Offline
Newbie
*
Karma: 3
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PS2 has 2 more axes: Z and Rz
So Descriptors.c has to be modified:

Replace
Code:
     0x09, 0x30,          /*     Usage (X)                                      */
      0x09, 0x31,          /*     Usage (Y)                                      */
      0x15, 0x9c,          /*     Logical Minimum (-100)                         */
      0x25, 0x64,          /*     Logical Maximum (100)                          */
      0x75, 0x08,          /*     Report Size (8)                                */
      0x95, 0x02,          /*     Report Count (2)                               */

by

Code:
     0x09, 0x30,          /*     Usage (X)                                      */
      0x09, 0x31,          /*     Usage (Y)                                      */
      0x09, 0x32,          /*     Usage (Z)                                      */
      0x09, 0x35,          /*     Usage (Rz)                                      */
      0x15, 0x9c,          /*     Logical Minimum (-100)                         */
      0x25, 0x64,          /*     Logical Maximum (100)                          */
      0x75, 0x08,          /*     Report Size (8)                                */
      0x95, 0x04,          /*     Report Count (4)                               */

And change the data structure:
in Joystick.h

Replace

Code:
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 */
                  uint8_t Button; /**< Bit mask of the currently pressed joystick buttons */
            } USB_JoystickReport_Data_t;

by:

Code:
           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;

I think it's the only thing to modify to see the 8u2 as a 4 axes joystick.
The code that is used to manage serial communication between 8u2 and arduino has to be updated to.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Alright Ant!
Great work man, thanks!
Can you also direct me to the pages where you found this info?
The specific usage pages and hex values?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey,
I'm experimenting with this today.
I implemented your code. (Thanks!)
Now I have to figure out the encoding / decoding procedure.

My idea was this: send an "identification char" (a, b, c, d)
followed by the sensor data (0-255).

So in Arduino I do "Serial.println('a')" followed by "Serial.println(serialData)". That seems simple enough.

In the 82U I have this code.

Code:
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
                                         uint8_t* const ReportID,
                                         const uint8_t ReportType,
                                         void* ReportData,
                                         uint16_t* const ReportSize)
{
USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;

while (Serial_IsCharReceived())
      {
      temp=Serial_RxByte();
      if (temp == "a"){JoystickReport->X  =  Serial_RxByte();}
      if (temp == "b"){JoystickReport->Y  =  Serial_RxByte();}
      if (temp == "c"){JoystickReport->Z  =  Serial_RxByte();}
      if (temp == "d"){JoystickReport->Rz =  Serial_RxByte();}
      }

*ReportSize = sizeof(USB_JoystickReport_Data_t);
      return false;
}

But that don't work. Bummer.
Could somebody point me to why?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Comment : I have had some difficulties with Flip : I often had the error 'Address is out of range'. I don't really now why?? Does someone have an idea?

I think this might actually have to do with the size of the generated HEX file. Whenever I wrote too much code, I got over 4KB and I got this error too.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think CALLBACK_HID_Device_CreateHIDReport has to return quickly, you don't have enough time to wait for serial data inside CALLBACK_HID_Device_CreateHIDReport. Instead you should process serial data in main, and just copy it in the callback.

Also you are assuming that the two characters will come to the serial port together - they won't. There will be a delay between the identification character and the data. However because main does other tasks (the USBTask() calls) you can't just block it while waiting for serial characters. Instead you have to code it as a state machine.

You want to use Serial.print or Serial.write rather than println as you don't want the extra newline.

The information on descriptors can be found here:
http://www.usb.org/developers/hidpage/
Unfortunately it is all very complicated and detailed. That's just the way it is.
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried to implement the state machine you suggested Stimmer.
However, I get the "adress out of range" error in Flip.
I assume this is because I ran out of program space.
My main loop now looks like this.

Code:
int main(void)
{
      SetupHardware();
      
      LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
      sei();
      
      for (;;)
      {
            HID_Device_USBTask(&Joystick_HID_Interface);
            USB_USBTask();
            
            if (Serial_IsCharReceived())
                  {
                  sensorIdentification =Serial_RxByte();
                  dataReceived = true;
                  }
            
            if (Serial_IsCharReceived() && dataReceived)
                  {
                  if             (sensorIdentification == "a") {sensorA =  Serial_RxByte();}
                  else if (sensorIdentification == "b") {sensorB =  Serial_RxByte();}
                  else if (sensorIdentification == "c") {sensorC =  Serial_RxByte();}
                  else if (sensorIdentification == "d") {sensorD =  Serial_RxByte();}
                  else    {Serial_RxByte();}
                  
                  dataReceived = false;
                  }

      }
}

The "create hid report" like this:

Code:
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
                                         uint8_t* const ReportID,
                                         const uint8_t ReportType,
                                         void* ReportData,
                                         uint16_t* const ReportSize)
{
USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;

JoystickReport->X  =  sensorA;
JoystickReport->Y  =  sensorB;
JoystickReport->Z  =  sensorC;
JoystickReport->Rz =  sensorD;


*ReportSize = sizeof(USB_JoystickReport_Data_t);
      return false;
}

As it stands right now, nonfunctional.
Even when I try to only transmit the data for sensor A with the X-axis, so I'm doing a few things wrong I think.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're on the right lines. The first if should be

if (Serial_IsCharReceived() && !dataReceived)

Serial_IsCharReceived and Serial_RxByte are inlines, so you can try to save space by only calling them once. Other ways to save space include removing the LED code, and shortening the product strings in Descriptors.c.



« Last Edit: December 07, 2010, 01:58:42 pm by stimmer » Logged


France
Offline Offline
Newbie
*
Karma: 3
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The memory is full as 98%. To get free space you can disable all the functions that use LEDs.

I'have emulated a joystick with uno:

I send 5 byte on serial to 8u2.

You can create this data:
uint8_t tampon;
uint8_t c;
uint8_t tempi[8];

And  modify the code:
Code:
for (;;)
      {
            HID_Device_USBTask(&Joystick_HID_Interface);
            USB_USBTask();

            if (c==8)
                  c=0;
            if (Serial_IsCharReceived())
        {
                  tampon=Serial_RxByte();
                  if (tampon==0xFF)
                        c=0;
                  tempi[c]=tampon;
                  c+=1;
            }      
            

And add that in the call back function

Code:
     JoystickReport->X=tempi[1];
      JoystickReport->Y=tempi[2];
      JoystickReport->Z=tempi[3];      
      JoystickReport->Rz=tempi[4];
      JoystickReport->Button1 =tempi[5];
      JoystickReport->Button2 =tempi[6];
      JoystickReport->Button3 =tempi[7];


The arduino has to send only bytes.
You have to use print function, not println that is sending others bytes after your data.
You can use a logic analyser to follow the data that are exchanged.

In this example, Uno has to send 0xFF as first byte (tempi[0]). However you can't send 0xFF as a data value or it will reset the c value.
« Last Edit: December 07, 2010, 02:13:10 pm by ant.b » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My code now looks like this:

Code:
for (;;)
      {
            HID_Device_USBTask(&Joystick_HID_Interface);
            USB_USBTask();
            
            if (Serial_IsCharReceived() && !dataReceived)
                  {
                  sensorIdentification =Serial_RxByte();
                  dataReceived = true;
                  }
            
            if (Serial_IsCharReceived() && dataReceived)
                  {
                  uint8_t data = Serial_RxByte();
                  
                  if             (sensorIdentification == "a") {sensorA =  data;}
                  else if (sensorIdentification == "b") {sensorB =  data;}
                  else if (sensorIdentification == "c") {sensorC =  data;}
                  else if (sensorIdentification == "d") {sensorD =  data;}
                  
                  dataReceived = false;
                  }

      }


In the callback

Code:
USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;

JoystickReport->X  =  sensorA;
JoystickReport->Y  =  sensorB;
JoystickReport->Z  =  sensorC;
JoystickReport->Rz =  sensorD;


*ReportSize = sizeof(USB_JoystickReport_Data_t);
      return false;
}

But the values don't update in any way.
When I run make, I get some warnings though.

Quote
warning: comparison with string literal results in unspecified behavior
warning: comparison between pointer and integer

Could this be the source of my problems?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to implement your code ant.
How do you send bytes out of the Arduino (atmega).

Code:
Serial.print(data, BYTE)
or just

Code:
Serial.print(data)
data ranging from 0-254?
« Last Edit: December 08, 2010, 07:09:33 am by Blue_Boy » Logged

Pages: 1 [2] 3   Go Up
Jump to: