Do you guys have any suggestions how to optimize power consumption of a device while it's not connected (and thus not charging) from the USB bus?
I'm running out of IO ports, so I'm thinking 1M pullup on D+, and? how can I tell from inside the main poll loop if we're connected to the USB master and should never enter sleep states above 'idle' (otherwise interrupt wakeup will take more than 25 cycles ), and when we're on battery and should be going as low as power down?
Device: attiny84, external 16MHz oscillator.
Powersaving USB device
Re: Powersaving USB device
I have a low power USB design which uses the following tricks to reduce battery consumption:
(1) The design uses a 32 kHz crystal and synchronizes the RC oscillator to it.
(2) When USB is connected, the main clock frequency is synchronized to 12.8 MHz, without USB, we use 1 MHz.
(3) Every 1 s interval we poll for USB connectivity:
(4) The supply voltage is reduced to the battery voltage when possible. Otherwise we use a step-up converter.
The USB connectivity check works by sampling D-. Since the 1k5 pull-up is connected to USB supply, D- is low without USB connection. You must decouple the USB supply with a diode, though, so that the battery can't power the pull-up.
(1) The design uses a 32 kHz crystal and synchronizes the RC oscillator to it.
(2) When USB is connected, the main clock frequency is synchronized to 12.8 MHz, without USB, we use 1 MHz.
(3) Every 1 s interval we poll for USB connectivity:
Code: Select all
static void usbModeEnter(void)
{
static const prog_char usbText[16] = " USB "
" MODE ";
powerWasOn = powerIsOn;
if(!powerIsOn)
powerOn();
logSetRunning(0);
powerRegulatorOff(); // ensure that voltage regulator is not operated at 12 Mhz
usbDeviceDisconnect();
dispFillConst(usbText);
displaySendContent(displayRam[0]);
_delay_ms(200);
usbStoredOsccal = OSCCAL;
OSCCAL = usbOsccal;
clock_prescale_set(clock_div_1); // turbo boost...
usbInit();
isUsbMode = 1;
usbDeviceConnect();
}
static void usbModeLeave(void)
{
USB_INTR_ENABLE &= ~M1(USB_INTR_ENABLE_BIT);
clock_prescale_set(clock_div_8); // back to normal speed
usbOsccal = OSCCAL;
OSCCAL = usbStoredOsccal;
PORT_DDR_SET(PIN_USB_DMINUS);
PORT_DDR_SET(PIN_USB_DPLUS);
isUsbMode = 0;
needUpdate = 1;
powerRegulatorOn();
if(!powerWasOn)
powerOff();
fifoFlush();
}
static void pollUsbMode(void)
{
if(isUsbMode){
uchar i;
for(i = 0; i < 3; i++){
uchar x = PORT_IN(PIN_USB_DMINUS);
x &= M1(PORT_BIT(PIN_USB_DPLUS)) | M1(PORT_BIT(PIN_USB_DMINUS));
if(x == M1(PORT_BIT(PIN_USB_DMINUS))) // valid USB idle mode
return;
}
// if we did not detect valid USB idle status 3 times in a row, leave USB mode
usbModeLeave();
}else{
PORT_DDR_CLR(PIN_USB_DMINUS);
_delay_us(5);
if(PORT_PIN_VALUE(PIN_USB_DMINUS)){ // if we have a pull-up
usbModeEnter();
}else{
PORT_DDR_SET(PIN_USB_DMINUS);
}
}
}
(4) The supply voltage is reduced to the battery voltage when possible. Otherwise we use a step-up converter.
The USB connectivity check works by sampling D-. Since the 1k5 pull-up is connected to USB supply, D- is low without USB connection. You must decouple the USB supply with a diode, though, so that the battery can't power the pull-up.