3

I need help in writing some code that will allow for the ATMega32u4 to be aware of when it's plugged into a USB port. I'm not really familiar with the ATMega32 or with it's function in Arduino, so I'm lost in the dark on this one.

Update: So in my circuit, the uC will be powered by Lithium Ion Batteries. On my PCB, their is a battery charging circuit that is powered through a USB C cable. My goal is to implement some type of firmware that can differentiate when the board is plugged into a wall outlet and a USB port on a computer. The reason for this is because I don't want the batteries to charge when the USB C cable is plugged into a laptop.

Second Update: Added pictures of the ATMega32 along with the charging circuit mentioned. I'll be the 5V voltage from USBC to charge the batteries. I'll have the data lines on the USB C cable connected so I can program the microcontroller through a USB cable. My goal here is for the microcontroller to recognize when it's connected to a computer. When this happens, I'll talk to the battery charging IC and tell it to not charge. enter image description here

enter image description here

Jay
  • 135
  • 5
  • Updated my post, but the ATMega32 will be powered by Lithium Ion Batteries. They will be changed through a USB C connector that has the data pins connected. – Jay Aug 27 '21 at 01:41
  • 3
    you could try something like this ... `if(Serial) { ledon() } else { ledoff() }` ... see if the LED changes state when USB cable is plugged and unplugged – jsotola Aug 27 '21 at 03:30
  • Here is the documentation link to jsotolas comment: https://www.arduino.cc/reference/en/language/functions/communication/serial/ifserial/ – chrisl Aug 27 '21 at 06:46
  • I'm not sure you can get the best answer to this without details (schematic, etc) on the board itself. – timemage Aug 27 '21 at 11:45
  • @timemage Added schematic part of the mC and charging IC – Jay Aug 28 '21 at 00:31
  • You should get to know more about your charging IC (it is quite a powerful chip if not over-kill), read the datasheet, it has more than one pins that provide the indication on whether the power source is an USB or a charging port, it also has the capability to cut off the charging when the charging current is below the threshold, so in summary, once you understand it, what you are trying to do may not necessary. – hcheung Aug 28 '21 at 01:53
  • @hcheung The problem with that is I don't believe that the charging current input will always be 500mA. If connecting to a laptop with a USB C port, then that port has the potential to output up to 3A (which I don't want since I don't want the gloves to charge while connect to the laptop). I'm just trying to understand if the uC can tell when it is plugged into a USB port via the data lines. – Jay Aug 28 '21 at 02:35
  • did you try what jsotola suggested? – Juraj Sep 18 '21 at 13:23
  • @Juraj I did a test, and found that just checking to see if there is any activity on UDFNUML works for my application from Shreyas's answer. Having the MCU respond if there is activity is fine for my firmware – Jay Sep 18 '21 at 14:50
  • doesn't the bool operator on Serial do it better? – Juraj Sep 18 '21 at 14:51
  • https://github.com/arduino/ArduinoCore-avr/blob/8f8df161ebf3d8bc595d226c3d3a9125383042a5/cores/arduino/CDC.cpp#L245 – Juraj Sep 18 '21 at 14:57

1 Answers1

2

I imagine (haven't really tried it) this would work, with some minor adaptation to match your code structure.

//  VBUS or counting frames
//  Any frame counting?
u8 USBConnected()
{
    u8 f = UDFNUML;
    delay(3);
    return f != UDFNUML;
}

The method reads the UDFNUML - usb data frame number lower (byte) register, waits 3 milliseconds, which would be sufficient time get at least 1 more USB frame if the device was really connected to a USB host, reads the register again and checks if it some USB activity had happened.

Personally, I am not a big fan of busy wait delays like that because the CPU could be better utilized doing something useful in that period (3 milliseconds on a 16Mhz CPU = 48000 clocks ~= 48000 instructions) I'd probably use 1 millisecond timer to sample the register and keep track of the USB status

An alternative would be to use the bool USBDevice_::configured() method which is implemented like so

bool USBDevice_::configured()
{
    return _usbConfiguration;
}

//  Endpoint 0 interrupt
ISR(USB_COM_vect)
{
  //    ... snip ...
        else if (SET_CONFIGURATION == r)
        {
            if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
            {
                InitEndpoints();
                _usbConfiguration = setup.wValueL;
            } else
                ok = false;
  // ... snip ....
}

Hopefully one of the two approaches work for you...