Pinoccio / hardware-pinoccio

The schematics, board layout, and datasheets for the Pinoccio board
Other
55 stars 26 forks source link

16u2 wastes power when USB disconnected #4

Open matthijskooijman opened 9 years ago

matthijskooijman commented 9 years ago

When USB is disconnected (as-in, no USB power applied, not talking about opening/closing the USB serial port here), the 16u2 is powered down. In this mode, it seems it does not put its outputs in high-impedance mode, but instead they offer a (medium impedance) path to ground.

This is particularly observed in the TX0 pin. The 256rfr2 keeps the pin at idle (high) level, which causes about 1mA of current to flow into the 16u2, which is power wasted. There is also no guarantee about the signal level on the RX0 pin and in fact, any data sent out on TX0 while the 16u2 is powered down seems to cause garbage to appear on RX0 right now.

There is also a "PROG" pin, which seems to be intended to switch the charge controller on and off. Weirdly enough, this pin is put into high impedance mode when the 16u2 powers up, so perhaps it contains an internal pullup or something. However, when the 16u2 is powered down, there is not really the guarentee that pulls the PROG pin down (or wherever it should go), so it seems that this might be relying on undefined behaviour currently.

Possible fixes include:

amcjen commented 9 years ago

Interesting. To experiment while measuring current draw on some environmental backpacks yesterday, I confirmed the 1mA issue during sleep. Here are my findings:

The 16U2 was set up using the "always power chip from 5V USB, but make sure logic levels are at 3.3V" mode, as outlined in the 16U2 datasheet. So in order to have the 16U2 absolutely off and not leaking when not powered, I think just pullups/pulldowns should be able to do it, no?

I suppose we could figure out a way for the 256RFR2 to detect when the 16U2 is powered off via a load switch or something. We have extra pins on the 16U2 that we could change the bootloader to make high upon startup, that would enable a load switch gate that's connected to a spare pin on the 256RFR2, perhaps one of those on Port G that aren't being used.

amcjen commented 9 years ago

Also, is it safe to say that putting Serial.end() here: https://github.com/Pinoccio/library-pinoccio/blob/master/src/Scout.cpp#L620 solves the TX0 high issue, but a separate 1MΩ resistor between RX0 and GND will solve the RX0 issue?

matthijskooijman commented 9 years ago

I think that the power savings from connecting RX0 and ground are mostly due to this code https://github.com/Pinoccio/library-pinoccio/blob/master/src/SleepHandler.cpp#L172-L173

Since that code is essentially a hack that I'd like to get rid of in a future version, I don't think putting a pulldown on RX0 really helps. Putting a pulldown on TX0 won't help either, that just creates an additional path to ground, leaking more current.

Having an explicit USB power detection is probably a good way to do things. Not sure if that should be a pin on the 16u2 (since that goes floating or becomes otherwise undefined when the 16u2 is off, which might be fixable with a pulldown, not sure). Perhaps sampling the 5V line directly (through a resistor divider or transistor or something could help, though that also wastes some power).

Putting the Serial.end there would solve the TX0 issue during sleep, but it would still drain 1mA of unneeded power during active mode.

amcjen commented 9 years ago

Agreed on the hack. For the v1.0 boards, the 1MΩ resistor is pretty critical to getting sleep currents down to µA levels unfortunately. Are you saying that if that code you linked to is removed, that we wouldn't need the pulldown? If so, that sounds good.

For next revision, the load switch seems to be the best move--then it's super clear if there is USB power or not.

matthijskooijman commented 9 years ago

Are you saying that if that code you linked to is removed, that we wouldn't need the pulldown?

No, I'm saying that if the code is removed, the pulldown will no longer have any efffect and it will always leak 1mA. The pulldown helps to detect (guess, rather) when the 16u2 is powered down. But that's really a different discussion - this ticket is about fixing this properly for the next hardware revision (I mostly created it to prevent losing track of it).

What do you mean with a load switch exactly? Does that allow the 256rfr2 to detect USB power through an extra pin? If so, that would be ok for a new scout revision, but for e.g. the mini, things would be different. It would be a waste if we had to sacrifice one of the pins on the mini just for this? In that case it might be better to actually put a switching transistor in the TX (and perhaps also RX?) line, so the 16u2 is really disconnected when the USB power is off?

matthijskooijman commented 9 years ago

Or perhaps keeping the 16u2 powered from the battery, put keep it in reset mode? Not sure what the power usage is then, probably more than we'd like...

amcjen commented 9 years ago

I gotcha. Yes, the mini will have less pins, b/c of the use of the 2564RFR2 version instead of the 256RFR2 one. So not using a pin would be more helpful for a mini-fied Scout.

A switching transistor on TX/RX makes more sense. I'd still prefer not to power up the 16U2 unless USB is plugged in, since it's wasteful. Cool!

amcjen commented 9 years ago

@matthijskooijman Can we revisit this quickly?

I'm willing to try to get a simple change, like a 1MΩ pulldown onto RX0 in order to change the sleep current draw from 1.1mA to ~70µA. Adding more specific hardware components to detect USB power is less desirable (because large-scale changes to the board design increase risk of multiple board runs, and timing is very critical.)

Agree that this will get us closer?

matthijskooijman commented 9 years ago

Did you test this? I'd be surprised if adding an additional path to ground would reduce current. Then again, I'm not exactly sure what happens inside the powered down 16u2 either to cause the current draw.