Arduino Forum

Forum 2005-2010 (read only) => General => Uno Punto Zero => Topic started by: ant.b on Oct 01, 2010, 09:53 pm

Title: Tutorial - How to change firmware on 8u2
Post by: ant.b on Oct 01, 2010, 09:53 pm
Hi
I've just received my arduino uno.
I try to upload a new firmware on the 8u2
I share here the steps I follow.
I use Windows.

Source
I use the following sources:
http://arduino.cc/en/Main/ArduinoBoardUno
http://arduino.cc/blog/2010/09/27/arduino-0020-released-for-windows-and-mac-supports-uno-and-mega-2560/
http://www.ladyada.net/library/arduino/unofaq.html
http://arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf

Software
I need those software:
After install, copy folder arduino-0020\hardware\arduino\firmwares\arduino-usbserial on LUFA_100807\Projects\

Hardware:
There are two modifications to do:
Solder 2 jumpers: one on the HWB line and one between pin 5 & 6 on ISP1 for RESET

(http://lh4.ggpht.com/_uwrqKMlmpEQ/TKZD5g0PENI/AAAAAAAAABA/Fo-v7oh6hAc/UNO%20DFU.JPG)

How to put the Uno on DFU mode:
     4. put the 8U2 into USB DFU mode:
     4.a. assert and hold the 8U2's RESET line
     4.b. assert and hold the 8U2's HWB line
     4.c. release the 8U2's RESET line
     4.d. release the 8U2's HWB line
     The device became USB DFU

Hardware, drivers installation:

Verify the board
Upload blink program on your uno to check that the board is working fine.

Compile firmware

Upload Arduino-usbserial.hex on the board

Test
Unplug the board and re-plug
The Name of the board should have changed : it becomes "ArduINo UNO"

Verify the board
Upload blink program on your uno to check that the board is still working fine.

That's all!
Title: Re: Tutorial - How to change firmware on 8u2
Post by: kraig on Oct 03, 2010, 06:22 am
good work. :D
Title: Re: Tutorial - How to change firmware on 8u2 / UPDATED
Post by: ant.b on Oct 07, 2010, 12:15 am
Hi,
This is the next step : how to make a joytick emulator with the arduino-uno.

First step
Be sure to be able to upload the initial firwmare arduino-serial: we need this firmware to upload the Atmega328.

How it works
The Atmega328 sends to 8u2 a byte on serial communication that represents the state of the joystick.

Point of attention
It's important to load first the atmega328 program and then the 8u2 firmware.
Once the firmware of 8u2 is upload with joystick program, atmega328 can't be loaded.
In order to modify atmega328 program, the original firmware of 8u2 need to be re-loaded.

Atmega328 program
Code: [Select]
/*
Program test for arduino uno
8u2 firmware-> Usb Joystick
ant.b
6 oct 2010
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1285962838
*/

void setup()
{
 Serial.begin(9600);
}

void loop()
{
send_byte(0,0,0,0,0,0);
send_byte(1,0,0,0,0,0);
send_byte(0,1,0,0,0,0);
send_byte(0,0,1,0,0,0);
send_byte(0,0,0,1,0,0);
send_byte(0,0,0,0,1,0);
send_byte(0,0,0,0,0,1);
}

void send_byte(boolean JOY_UP, boolean JOY_DOWN,
               boolean JOY_LEFT, boolean JOY_RIGHT,
               boolean JOY_PRESS, boolean BUTTONS_BUTTON1)
{
 byte byte_to_send;// use a 'byte' not a 'int'-> a int will send 3 bytes via serial
 byte_to_send= JOY_UP*32 + JOY_DOWN *16  +
               JOY_LEFT*8 + JOY_RIGHT*4 +
               JOY_PRESS*2 +  BUTTONS_BUTTON1*1;
 Serial.print(byte_to_send);  
 delay(1000);//delay 1s before send another byte
}


8u2 program


Changes to make
     In makefile
            Set TARGET = Joystick
     In Joystick.h
            Delete #include <LUFA/Drivers/Board/Joystick.h>
            Delete #include <LUFA/Drivers/Board/Buttons.h>
    In Joystick.c
            Add this on the begining:
Code: [Select]
#include <LUFA/Drivers/Peripheral/Serial.c>
uint8_t temp;
const uint8_t JOY_UP= 0b100000;
const uint8_t JOY_DOWN = 0b010000;
const uint8_t JOY_LEFT= 0b001000;
const uint8_t JOY_RIGHT= 0b000100;
const uint8_t JOY_PRESS= 0b000010;
const uint8_t BUTTONS_BUTTON1= 0b000001;

            Add this in void SetupHardware(void)
               
Code: [Select]
 Serial_Init(9600, false);

            I delete clock_prescale_set(clock_div_1); because this line can't compile. I don't know if it is usefull ??
            I also delete
              Joystick_Init();
                   Buttons_Init();

           I add this in  for( ;;; )
           
Code: [Select]
while (Serial_IsCharReceived())
               {
           temp=Serial_RxByte();
           Serial_TxByte(temp);// Sendback the same byte juste for information
           }


                And finally replace the content of CALLBACK_HID_Device_CreateHIDReport by that
Code: [Select]
USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;

uint8_t JoyStatus_LCL    =temp; //Joystick_GetStatus();

     if (JoyStatus_LCL & JOY_UP)
            JoystickReport->Y = -100;
       else if (JoyStatus_LCL & JOY_DOWN)
             JoystickReport->Y =  100;

      if (JoyStatus_LCL & JOY_LEFT)
             JoystickReport->X = -100;
      else if (JoyStatus_LCL & JOY_RIGHT)
             JoystickReport->X =  100;

      if (JoyStatus_LCL & JOY_PRESS)
             JoystickReport->Button  = (1 << 1);

      if (JoyStatus_LCL & BUTTONS_BUTTON1)
              JoystickReport->Button |= (1 << 0);

     *ReportSize = sizeof(USB_JoystickReport_Data_t);
       return false;


Then compile and upload this program on 8u2

Verify
You can verify that it is working by unplug and replug the usb connection.

The joystick is visible in configuration pannel / gamepad.

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?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: mellis on Oct 09, 2010, 04:02 pm
Thanks ant.b.  I was supposed to write a tutorial like this one but didn't get to it yet.  I linked here from the Arduino Uno page (under the programming section).
Title: Re: Tutorial - How to change firmware on 8u2
Post by: majolsurf on Oct 15, 2010, 12:52 pm
I had trouble with the arduino-0021 version of arduino-usbserial.  After building and programming it onto the 8U2 the Windows would ask to install drivers for the new device.  After pointing the installation to the arduino drivers directory windows would report a failure in driver installation.  The Arduino IDE would not recognize the UNO after that...  :-/  I compiled the 0020 version and my UNO is back in action...   8-)

I noticed in the 0021 release mentioned tweaks to PID/VID values... wondering if that has something to do with it.  I don't have time to look at it tonight it's 12:50am   :P

Great tutorial ant.b!  Can't wait to try the joystick version tomorrow.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: majolsurf on Oct 16, 2010, 02:01 am
Update:  In the arduino-0021 version of arduino-usbserial the Descriptor.c file is using VID = 0x03EB (Atmel) and PID = 0x204B (LUFA USBtoSerial demo).    The Arduino UNO.inf is looking for VID=0x2341 and PID=0x0001 which is reflected in arduino-0020...  

I see in the 0021 release notes indicate "Modifying VID / PID combination in 8U2 firmwares" but was this the intent?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: mellis on Oct 16, 2010, 08:47 pm
According to the USB folks, we're not really allowed to share our VID / PIDs with other organizations.  So the firmware was modified to use other ones.  Probably we should create a different version of the .inf file that uses the other VID/PID pair.  The intent is that any VID/PID pair should work with the IDE, but that the Arduino ones should only be used with the official Arduino hardware.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: tjhowse on Oct 27, 2010, 07:50 am
Awesome work! I wasn't looking forward to working out all this stuff on my own.

The only problem I've encountered is loading the DFU drivers in windows 7. It seems they aren't signed so win7 refuses to allow access to the device via Flip. I had to install it on an XP machine before I could write my newly compiled .hex to the 8U2.

There are ways of making win7 load unsigned drivers in test mode, but this is cumbersome.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: mellis on Oct 28, 2010, 05:25 pm
You can also use an ISP to update the 8U2 firmware, if you have one.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: anv on Oct 29, 2010, 04:14 pm
It would be great if the software on the ATmega8u2 had various usb "personalities" included, selectable by software on the 328.

You could send some special string to 328 to swithch it from usb-serial mode to usb-keyboard mode or usb-joystick mode.

Then, there will be no need to upload new software to the 8u2.

When power off it could return to the default usb-serial mode.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: stimmer on Nov 04, 2010, 02:53 am
Here's a way to get the Uno into DFU mode without any soldering. Put two wires into GND pins on either side of the board. Then put the other ends of the wires on the board as follows:

(http://img87.imageshack.us/img87/4207/arduinodfu.jpg)

The sequence is, hold the first wire on the top left 8u2 ICSP pad, then touch the second wire against the left side of the capacitor below the RX LED. Then remove both wires. It's slightly different to the sequence in the instructions but it seems to work.

Be careful with the second wire as the capacitor is quite near a 5v track. You can try using a low-value resistor instead of a wire if you are worried about blowing up your board.

To get back to normal mode, hold wire 1 in place as above, press the reset button, then remove wire 1. Or just unplug the USB cable and plug it back in.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Ranking on Nov 15, 2010, 04:33 pm
I doesen'T have an Arduino Uno only a nano does someone know how I can use this code on an Arduino nano 3.0

it would be realy great if anyone has an answer for me ;D
Title: Re: Tutorial - How to change firmware on 8u2
Post by: PaulS on Nov 15, 2010, 05:01 pm
Quote
does someone know how I can use this code on an Arduino nano 3.0

Can you post a picture of your nano with a ATMega8U2 chip on it?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: tjhowse on Nov 17, 2010, 09:36 am
Found a solution to my problem:

http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=3842&showinfo=1

These drivers were signed by some generous avrfreak, and work with the Uno under Win7 64b. Happy days!
Title: Re: Tutorial - How to change firmware on 8u2
Post by: AustralianRobotics on Nov 22, 2010, 10:05 pm
Great! I want to try this now.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: hughperman on Nov 30, 2010, 06:33 pm
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!
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 03, 2010, 02:11 pm
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?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: mowcius on Dec 03, 2010, 02:32 pm
Quote
How hard would it be to add another 2 axes to the example joystick?

Surely you only have X,Y and Z?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 03, 2010, 02:36 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: mowcius on Dec 03, 2010, 02:51 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: ant.b on Dec 03, 2010, 05:46 pm
PS2 has 2 more axes: Z and Rz
So Descriptors.c has to be modified:

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


by:

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;


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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 07, 2010, 10:50 am
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?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 07, 2010, 04:30 pm
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: [Select]
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?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 07, 2010, 05:19 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: stimmer on Dec 07, 2010, 05:25 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 07, 2010, 07:25 pm
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: [Select]
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: [Select]
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: stimmer on Dec 07, 2010, 07:57 pm
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.



Title: Re: Tutorial - How to change firmware on 8u2
Post by: ant.b on Dec 07, 2010, 08:11 pm
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: [Select]
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: [Select]
     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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 08, 2010, 12:32 pm
My code now looks like this:

Code: [Select]
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: [Select]
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?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 08, 2010, 01:09 pm
I'm trying to implement your code ant.
How do you send bytes out of the Arduino (atmega).

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

Code: [Select]
Serial.print(data)
data ranging from 0-254?
Title: Re: Tutorial - How to change firmware on 8u2
Post by: stimmer on Dec 08, 2010, 01:32 pm
sensorIdentification == "a" is wrong, it should be sensorIdentification == 'a' (single quotes instead of double) and the same for b,c and d.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 08, 2010, 01:47 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: ant.b on Dec 08, 2010, 02:25 pm
In uno's code I define something like that:

Code: [Select]
byte start_b;
byte b1;
....

start_b=0xFF;
b1= ...
...

Serial.print(start_b);
Serial.print(b1);
....


Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 08, 2010, 03:35 pm
Alright!
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: ant.b on Dec 08, 2010, 04:10 pm
Maybe it's because you data has to be between -100 and 100.

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


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

by:

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

     
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 08, 2010, 04:27 pm
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)
{
     SetupHardware();
     
     //LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
     
     sei();
     
     for (;;)
     {
           HID_Device_USBTask(&Joystick_HID_Interface);
           USB_USBTask();
           
           if (counter==5){counter=0;}
           if (Serial_IsCharReceived())
       {
                 dataIn = Serial_RxByte();
                 if (dataIn == 0xFF){counter=0;}
                 data[counter]=dataIn;
                 counter+=1;
           }


     }
}


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:
 Serial.begin(9600);
 }

void loop() {
 // Send start byte to 8u2
 Serial.print(dataStart);
 
 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:        
   Serial.print(sensorValue);
   }
 delay(40);    
}


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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: ant.b on Dec 08, 2010, 11:52 pm
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
Title: Re: Tutorial - How to change firmware on 8u2
Post by: PaulS on Dec 09, 2010, 12:50 am
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: Blue_Boy on Dec 20, 2010, 11:47 am
Hey Guys,
You were right.
It was indeed the analogRead() value being pushed in a byte.
Thanks!
Title: Re: Tutorial - How to change firmware on 8u2
Post by: fkeel on Jan 07, 2011, 06:55 pm

thanks for this tutorial. gives me some hope to be able to build my custom mouse one day :-)
Title: Re: Tutorial - How to change firmware on 8u2
Post by: blacksanta_69 on Jan 16, 2011, 08:35 am
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! :)
Title: Re: Tutorial - How to change firmware on 8u2
Post by: bneedhamia on Jan 19, 2011, 09:15 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: stimmer on Jan 19, 2011, 10:21 pm
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.
Title: Re: Tutorial - How to change firmware on 8u2
Post by: bneedhamia on Jan 21, 2011, 10:20 pm
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.