Adjusting USB bMaxPower value w/ Arduino 1.0.1

A shrunk down Leonardo-compatible board, thumb drive sized with native USB support. [Product info]
Post Reply
adr1an
Posts: 21
Joined: Tue Nov 01, 2011 10:04 am

Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by adr1an » Wed May 30, 2012 1:42 pm

Ok, I've not needed this personally, But fractal pointed out in another thread that when plugging the new 1.0.1 sketches into a device that only allows LowPower devices to be attached, an annoying error message is generated in MaxOSX.

By default the sketches are set to negotiate to 500ma for the USB bMaxPower value - this value is part of the USB Standard and sets the maximum amount of current the device should draw. It is part of the spec, but isn't actually reflective of what current the device will draw (an important distinction I guess).

In order to write sketches that work without errors on the Host using the LeoStick w/ Arduino 1.0.1, then you can do the following to enable you to adjust the MaxPower values. Its ugly, and I have no idea what I'm doing, but it works, and compiles without error.

So this works, but no idea if its the best way..

Edit USBCore.cpp . Around line 47 or so, you'll see

Code: Select all

extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM;
Add the line

Code: Select all

int usbMaxPower = 500;
Edit USBCore.h. Edit the D_CONFIG define around line 284 to be:

Code: Select all

#define D_CONFIG(_totalLength,_interfaces) \
	{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(usbMaxPower) }
By default, it will now negotiate 500ma. However in your sketch, at the top, define

Code: Select all

extern int usbMaxPower
Then you can do in setup(), before calling any USB descriptors (i.e, one of the first things)

Code: Select all

usbMaxPower = 100; 
Voila! Script defineable usbMaxPower values... albeit very klunky and involving hacks to the USBCore.cpp/USBCore.h - which I was trying to avoid.

Incidentally - theres a bunch more VID/PID locations I should update I've found, as well as that ugly "Unknown IO" - so will post a fix to that in next day or so.

In the meantime - let me know if the above works - curious how transportable the hack is (it seems to have had almost negligible impact on sketch size too! about 6 bytes?)

adr1an
Posts: 21
Joined: Tue Nov 01, 2011 10:04 am

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by adr1an » Thu May 31, 2012 7:12 am

Oh btw Fractal - this is probably the most USB Spec Compliant way to attack this. The bMaxPower value is supposed to represent the Peak Load that the device will draw and should be measured in a 'worst case' scenario.

Technically, that is 500ma - but yes to use the LeoStick on a Keyboard/UnPowered Hub then it is better to be able to reduce the value. However as the Sketch can't possibly know with veracity what its max current draw is below 500ma, then its not something that can be 'negotiated' - rather its something that needs to be manually set with the full knowledge of its impact to the USB Spec.

Happy to be pointed to another train of thought, but I reckon given the above, this is the best way to handle it for now.

etx
Posts: 2
Joined: Fri Jun 01, 2012 2:19 am

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by etx » Fri Jun 01, 2012 2:22 am

Awesome! Just what I need!

But, I cannot seem to get it working. You're editing the files under hardware/arduino/cores/arduino/ correct?

adr1an
Posts: 21
Joined: Tue Nov 01, 2011 10:04 am

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by adr1an » Fri Jun 01, 2012 3:01 am

The above works only with Arduino 1.0.1 and running the new Bootloader, and depending on what you did around Board Profiles determines which files to edit. If you have replaced the arduino-sketches/hardware/leostick/core directory with the one from arduino 1.0.1 , you can then make sure you have the newer LeoStick Board Profile (see thread viewtopic.php?f=27&t=663 - if you download the updated leostick.zip the edits are now done in that archive) and edit the LeoStick core/ directory.

So updated LeoStick Profile as per other thread, edit \arduino-sketches\hardware\leostick\cores\arduino\USBCore.* and ensure you have Freetronics LeoStick as the Board Type

If you are using the Leonardo Board Profile, then edit the files in \arduino\hardware\arduino\cores\arduino\USBCore.* and ensure you select the Board Type as Leonardo

Attached is my two edited files
USBCore.h
(7.68 KiB) Downloaded 206 times
USBCore.cpp
(12.85 KiB) Downloaded 219 times
I then have this as the sketch I was using to test (I was running my updated LeoStick Profile). I used Keyboard test as I could open a Serial Monitor and hit a key to get a report on usbMaxPower (also because it happened to be the example I had open when I started hacking it :lol: )

Code: Select all

extern int usbMaxPower; // Import usbMaxPower from USBCore.cpp

void setup() {
  // Set USB MaxPower to be 150
  usbMaxPower = 150; 
  // open the serial port:
  Serial.begin(9600);
  // initialize control over the keyboard:
  Keyboard.begin();
  // Print usbMaxPower int to Serial to check during setup
  Serial.print("usbma ");
  Serial.println(usbMaxPower);
}

void loop() {
  // check for incoming serial data:
  if (Serial.available() > 0) {
    // read incoming serial data:
    char inChar = Serial.read();
    
    // Print usbMaxPower int to Serial to check
    Serial.print("usbma ");
    Serial.println(usbMaxPower);

    // Type the next ASCII value from what you received:
    Keyboard.write(inChar+1);
  }  
}
I then checked and confirmed the changing reported mA's via USBDeviceView on Windows
Hopefully I haven't confused you ! :D

Fractal
Posts: 12
Joined: Mon May 21, 2012 10:45 pm

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by Fractal » Fri Jun 01, 2012 5:33 pm

Hey, this looks great!
I didn't know you could modify variables through different libraries like that, but it's a very neat way of doing it, much cleaner than faffing around with eeprom, in retrospect.
I don't think it's too clunky, anyway, it should compile to roughly the same thing. It is a bit surprising that USB is not up and running by the time setup{ } has started, though!

Anway, I modified the USBCore files as per the first post, to yield the desired operation. Very handy!
N.B. You can probably get away with drawing 500ma even though you only request 100ma, though that would vary on a computer-computer basis. Nevertheless, for LEDs, and piezo, 100ma should be enough!

etx
Posts: 2
Joined: Fri Jun 01, 2012 2:19 am

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by etx » Fri Jun 01, 2012 5:44 pm

Ah! I'm yet to get the new bootloader on there. Hopefully this weekend I can give it a shot and try again.

Edit: Got the new caterina bootloader on there, your code works like a charm. Thanks a ton for posting this!

adr1an
Posts: 21
Joined: Tue Nov 01, 2011 10:04 am

Re: Adjusting USB bMaxPower value w/ Arduino 1.0.1

Post by adr1an » Mon Jun 04, 2012 2:15 am

etx wrote:Edit: Got the new caterina bootloader on there, your code works like a charm. Thanks a ton for posting this!
No worries - glad it helped out :)

Post Reply