Skip to content
Get started

FUSB302B USB-C Power Delivery

The fusb302b component supports the onsemi FUSB302B USB Type-C and Power Delivery (PD) controller. It acts as a PD sink: when a USB-C power source is attached, it negotiates a power contract for a fixed supply voltage of up to 20 V.

The FUSB302B communicates over I²C, so an I²C bus must be configured. The component is only supported on ESP32.

# Example configuration entry
fusb302b:
interrupt_pin: GPIOXX
request_voltage: 20
  • interrupt_pin (Required, Pin): The GPIO pin connected to the INT_N output of the FUSB302B. INT_N is an open-drain output; the internal pull-up of the pin is enabled by default.
  • request_voltage (Required, int): The voltage in volts to request from the source, from 5 to 20. See Power Negotiation.
  • id (Optional, ID): Manually specify the ID used for code generation.
  • address (Optional, int): The I²C address of the FUSB302B. Defaults to 0x22, the address of the FUSB302BMPX. The FUSB302B01MPX, FUSB302B10MPX and FUSB302B11MPX use 0x23, 0x24 and 0x25.
  • i2c_id (Optional, ID): The ID of the I²C bus the FUSB302B is connected to. Required when more than one I²C bus is configured.
  • on_connect (Optional, Automation): An automation to perform when a source is attached. See on_connect Trigger.
  • on_disconnect (Optional, Automation): An automation to perform when the source is removed. See on_disconnect Trigger.
  • on_power_ready (Optional, Automation): An automation to perform when power negotiation is finished. See on_power_ready Trigger.
  • on_request_failed (Optional, Automation): An automation to perform when a voltage request ends without a new contract. See on_request_failed Trigger.
  • on_error (Optional, Automation): An automation to perform when communication with the FUSB302B fails. See on_error Trigger.

USB PD sources offer a list of fixed supply voltages, chosen from 5, 9, 12, 15 and 20 V. The component requests the highest one that does not exceed request_voltage, at the maximum current the source offers for it. For example, with request_voltage: 12 and a source offering 5, 9, 15 and 20 V, the component requests 9 V.

The component stays at 5 V Type-C default power when:

  • The source does not support Power Delivery, or does not send its capabilities after the component asks for them and sends a soft reset.
  • The source rejects the request, does not answer it in time, or does not report the new supply as ready in time.

The negotiation runs in a dedicated FreeRTOS task, so replies to the source meet the PD timing requirements even while the main loop is busy. The first measurement of the CC lines is made 2 seconds after boot, to give the source time to settle.

WARNING

The requested voltage appears on VBUS. Make sure that everything connected to VBUS, such as the voltage regulator that powers the ESP32, is rated for the highest voltage that request_voltage allows.

The power contract is exposed through a sensor platform and a text_sensor platform. They are updated each time the power contract changes:

  • At 5 V Type-C default power, before negotiation or when it fails, they report 5 V and 0.5 A (0.50A @ 5V).
  • After a successful negotiation, they report the voltage and maximum current of the new contract.
  • When the source is removed or communication with the FUSB302B fails, voltage and current report 0 and contract reports Detached.
sensor:
- platform: fusb302b
voltage:
name: "PD Voltage"
current:
name: "PD Current"
text_sensor:
- platform: fusb302b
contract:
name: "PD Contract"
  • voltage (Optional): A sensor that reports the voltage of the current power contract in volts. All options from Sensor.
  • current (Optional): A sensor that reports the maximum current of the current power contract in amperes. All options from Sensor.
  • fusb302b_id (Optional, ID): The ID of the FUSB302B component. Required when more than one fusb302b is configured.
  • contract (Optional): A text sensor that reports the current power contract, for example 3.00A @ 20V, or Detached when no source is attached. All options from Text Sensor.
  • fusb302b_id (Optional, ID): The ID of the FUSB302B component. Required when more than one fusb302b is configured.

The triggers run in the main loop. Changes in the connection state are queued, so the triggers run in the order the changes happened, even when the main loop was busy at the time.

This automation is triggered when a source is attached to the USB-C port, before power negotiation starts. It is also triggered when a source is detected again after communication with the FUSB302B is restored.

fusb302b:
# ...
on_connect:
- logger.log: "USB-C source attached"

This automation is triggered when the source is removed, or when communication with the FUSB302B fails while a source is attached.

This automation is triggered each time power negotiation is finished:

  • The source reported the newly requested supply as ready, so the requested voltage is now on VBUS.
  • Negotiation failed or the source does not support Power Delivery, so VBUS stays at 5 V.

The voltage sensor is updated before the automation runs, so use it to check which of the two applies. When a fusb302b.request_voltage request fails while a contract is already in place, that contract stays valid and only on_request_failed is triggered.

sensor:
- platform: fusb302b
voltage:
id: pd_voltage
fusb302b:
# ...
on_power_ready:
- if:
condition:
sensor.in_range:
id: pd_voltage
above: 19.0
then:
- switch.turn_on: load_power

This automation is triggered when a voltage request ends without a new contract:

  • The source rejects the request.
  • The source keeps answering that it is busy, until the component stops retrying.
  • The source does not answer the request in time.
  • The request cannot be sent, including a fusb302b.request_voltage action that runs after the component failed at boot.
  • After the first negotiation, for example after a fusb302b.request_voltage action, the source does not send its capabilities when the component asks for them, even after a soft reset.

A contract that is already in place stays valid. When the first request after attach fails, the component stays at 5 V and on_power_ready is triggered as well. It is not triggered when the source does not support Power Delivery, or when a request is cut short because communication with the FUSB302B fails: that triggers on_error instead.

fusb302b:
# ...
on_request_failed:
- logger.log: "Voltage request failed"

This automation is triggered when communication with the FUSB302B over I²C fails after boot. The component keeps trying to initialize the chip and triggers on_connect once a source is detected again.

It is not triggered when the chip cannot be reached at boot, for example because it is missing or wired incorrectly. The component is then marked as failed, which is shown in the logs.

This action changes the voltage to request from the source. When a source is attached, the component negotiates a new power contract right away, following the same rules as request_voltage in the configuration (see Power Negotiation). When no source is attached, the new voltage is used at the next attach.

A voltage outside 5 to 20, for example from a lambda, is clamped to that range and a warning is logged. The new voltage is not saved: after a reboot, the component requests the voltage set in the configuration again.

on_...:
- fusb302b.request_voltage: 9
# Or with a lambda
- fusb302b.request_voltage:
voltage: !lambda "return 12;"
  • voltage (Required, int, templatable): The voltage in volts to request, from 5 to 20.
  • id (Optional, ID): The ID of the FUSB302B component. Required when more than one fusb302b is configured.

WARNING

The same applies as for request_voltage in the configuration: make sure that everything connected to VBUS is rated for the voltage this action can request.

This condition checks whether a source is attached to the USB-C port.

on_...:
- if:
condition:
fusb302b.is_connected:
then:
- logger.log: "USB-C source attached"
  • id (Optional, ID): The ID of the FUSB302B component. Required when more than one fusb302b is configured.

The lambda equivalent is id(pd).is_connected(), where pd is the id of the fusb302b component.