Andrew built a simple power supply so he could get some hands-on experience with the capabilities of the relatively new USB Power Delivery (USB-PD) technology. USB-PD allows for voltages up to 20V at currents up to 5A to be delivered across the interface. He shares the details of his design that gives insight into the workings of USB-PD.
The simple power supply described here offers modest specifications, but was designed primarily so I could get some hands-on experience with the capabilities of the relatively new USB Power Delivery (USB-PD) technology . Unlike previous generations of USB that are limited to 5V at a couple of amps, USB-PD allows voltages up to 20V at currents up to 5A to be delivered across the interface. To make this work, the power source and the sink (and in some circumstances, even the cable) need to negotiate and agree on the voltage and current to be supplied.
I should note here that USB-C is the standard that describes the connector and its specific capabilities. USB-PD describes the power delivery protocol which operates across this interface.
A device at the end of a USB-PD connection can be a source that provides power, a sink that consumes power, or a dual role device that can both source and sink power (but not at the same time). A USB-C port on a laptop is a good example of a dual-role power port— it can be a sink when the laptop is being charged, or a source when a peripheral such as a USB memory stick is being powered.
A USB-C connection includes a configuration channel (CC) that is used to determine when a device is attached, the orientation of the cable, and to establish a power delivery “contract” passively or actively between the source and the sink (and the cable in some circumstances, as we shall see).
THE CONFIGURATION CHANNEL
Figure 1 shows the pin configuration of the USB-C receptacle, and the two possible plug orientations. The VBUS, ground and classic data pins D+ and D- are symmetrical and will be correctly connected whichever way the plug is inserted. The two super-speed duplex channels and the sideband use channels will be swapped when the plug is flipped, so they need to be sorted out in hardware if they are used. Therefore, we need to be able to tell if the plug is flipped or not.
The USB-C cable contains only one CC line, which will be connected to either the CC1 or CC2 pin, depending on the plug orientation. The other CC pin is connected to VCON to power an active cable, if one is used.
At power-on, the source pulls both CC pins up via resistors Rp, and the sink pulls them down via Rd, as shown in Figure 2. To detect attach and cable orientation, the source detects which of its CC pins is pulled low by Rd, and the sink detects which of its CC pins is pulled high by Rp. The sink can detect the source capability by reading the value of Rp presented by the source—or more accurately by measuring the current sourced. Table 1 shows the various possibilities.
In the case of an electrically marked cable, the cable pulls the other CC pin down via a resistor Ra of between 800Ω and 1.2kΩ. The source must detect this, and then switch in a 5V VCONN supply on the appropriate CC pin to power the electronics in the cable.
NEGOTIATING A CONTRACT
On attach, a USB-PD source is configured to provide 5V at a level of current indicated by the value of Rp, for compatibility with legacy USB devices. If this is all the sink needs, then nothing else needs to happen, and an implicit contract is said to exist. If a different voltage or current is required, the sink and the source must negotiate an explicit contract.
The source and sink communicate across the configuration channel at 300kbaud using 32-bit packets with bi-phase mark (BMC) encoding and CRC protection. All messages begin with a “Start of Packet” (SOP) packet, which indicates the intended destination of the message, and end with a CRC and an “End of Packet” (EOP) packet. The receiver must check the CRC and respond to the sender to acknowledge successful reception.
Messages can be sent to one of three possible destinations; messages starting with an SOP packet are intended for the source or sink, those starting with an SOP’ packet are intended for the chip in the connector at the source end of an electrically marked cable, and those starting with a SOP” packet are intended for the chip in the sink end of an electrically marked cable.
Figure 3 shows a capture of the communication between a typical source and sink. Initially, the source advertises its capabilities by transmitting Source_Capability messages at the highlighted line and the one below, until the sink acknowledges with a Good_CRC response. The structure of the Source_Capability message is shown in Figure 4. This source is a 45W wall wart capable of supplying five different voltages. It can supply 5V, 9V, 12V, or 15V at up to 3A, and 20V at up to 2.25A. The message includes five capability objects with indices 0 to 4—one for each source option.
To request the source switch to one of these capabilities, the sink issues a Request message containing the index of one of the advertised capability objects. The source responds with a Good_CRC message if it received the request, and an Accept message if it agrees to the request. If the sink replies with a Good_CRC message, the source begins to switch its output to the desired level. Once this is done, the source issues a PS_Ready message, which the sink acknowledges, and the transaction is complete. You can see from Figure 3 that this whole transaction takes about 400ms.
USB-C cables are usually rated for only 3A, so 60W is the maximum power that can be negotiated over a passive cable (20V @ 3A). To use the full 100W capability of USB-C, an electrically marked cable capable of 5A must be used. Figure 5 shows the capture of a negotiation involving an electrically marked cable. Before advertising its capabilities, the source queries the cable with a DiscIdentity message. The cable responds with a DiscIdentity message shown in Figure 6. Here you can see that the cable advertises a VBUS current capacity of 5A. The source will then advertise currents up to 5A if it is capable of supplying them.
A PRACTICAL EXAMPLE
I wanted to build a simple project to familiarize myself with USB Type C Power Delivery hardware and software. I chose a simple power supply, since it occurred to me that I could use the USB-PD ability to switch the input voltage as a crude pre-regulator, thus limiting the power dissipation in the series-pass element. My specifications were modest. I chose to build a supply that could be used to power simple microcontroller projects, so a maximum of 10V and 1.0A would be sufficient. I wanted to be able to measure the voltage and current with 10mV and 1mA resolution, respectively. The supply should have true current limiting, and therefore must be able to regulate the output voltage right down to zero.
The block diagram in Figure 7 shows the concept. A USB-PD sink control chip manages the configuration channel interface, including the encoding and decoding of messages, generation of the CRC, and detection of attachment. This is followed by a simple linear voltage and current regulator, and a measurement circuit to read voltage and current. Everything is controlled by a low-cost microcontroller and a simple user interface based on an off-the-shelf LCD touchscreen display.
USB-PD SINK CONTROLLER
I chose the STMicroelectronics STUSB4500 controller for my design. This can be used in stand-alone mode or with a microcontroller, and is capable doing everything necessary to detect attachment, establish communication with the source, and negotiate a power delivery contract. The analog schematic (Figure 8) shows how I have connected it. The CC1 and CC2 pins on the USB-C receptacle are connected directly to the STUSB4500 CC1 and CC2 pins, respectively. A TVS diode pair (Z102) protects these lines from transients.
The STUSB4500 is connected to the microcontroller via an I2C bus and an interrupt line. Resistors R101 and R102 allow the controller to discharge the bus in situations when the voltage is switching from higher to lower levels in the absence of a load. Capacitors C102 and C103 provide filtering for the chip’s internal voltage regulators.
The regulator is based on the venerable LT3080 (Analog Devices). This is a 1.1A regulator that can regulate down to 0V. It has a drop-out voltage of about 1.2V. The SET pin sources 10µA, and the output follows the voltage at this pin exactly. The 2.2MΩ resistor, R107, means that the output will be at its maximum in the absence of regulation provided by the op-amps U3A and U4A.
Voltage regulation is achieved through the error amplifier U4A, where output voltage feedback on the inverting input is compared with a setpoint voltage on the non-inverting input. The feedback is obtained via op-amp buffer U6A and the divider formed by R112 and R113. This divider means the 10V full-scale output will appear as 2.5V at the op-amp. The setpoint voltage is obtained via a two-stage RC filter (R114, R115, C111, C112) from a PWM output from the microcontroller. The duty cycle of the PWM is varied to change the setpoint.
Current regulation is similarly achieved through error amplifier U3A, where the current feedback signal is compared with a setpoint signal. The current signal is obtained via the instrumentation amplifier U5 from a 50mΩ shunt resistor. The instrumentation amp has a fixed gain of 50, so that a full-scale current of 1A will translate to 2.5V at the op-amp. The current setpoint is derived from a filtered PWM signal in the same way as for the voltage setpoint.
The current and voltage control loops are connected to the LT3080 set pin via diodes. While the current is below the set point D102 will be reverse biased and the voltage loop will control the output.
As soon as the current limit is reached, the current loop will take over and reduce the output voltage to limit the current to the set level. Q104 can override both loops and force the supply output to zero, under the control of the microcontroller.
VOLTAGE AND CURRENT MEASUREMENT
Voltage and current measurement are handled by U7. This is an INA233 ADC (Texas Instruments), specifically designed for voltage and current measurement in power supplies. It includes a 16-bit ADC and measures bus voltage with a resolution of 1.25mV, and a shunt voltage with a resolution of 2.5µV. The latter corresponds to 50µA current resolution with our setup.
U6 is required to buffer the output voltage measurement, since the combined load of U5, U7 and R113 plus R112 would cause a current error of almost 300µA. It does introduce some error, but has an offset voltage of up to 4µV that we can take care of in software, and an offset voltage drift of 0.015µV/˚C, which is OK for our purposes.
The only other point of note in the analog part of this circuit is the network consisting of Q101, Q102 and Q103. This forms a Wilson current mirror to provide a minimum load of about 1mA on the LT3080. This load is required to keep the regulator working, because the LT3080 does not otherwise have a path to ground for the current it requires to operate. The current mirror is referenced to a -2.5V rail, so that it can continue to provide 1mA even if the regulator output is zero.
MICROCONTROLLER & POWER SUPPLY
The schematic for the digital portion of the design, shown in Figure 9, is likewise very simple. An STM32F091 microcontroller (STMicroelectronics) manages everything, including an I2C bus for communicating with the STUSB4500 controller and the INA233. A separate I2C bus is used to communicate with a non-volatile FRAM, which stores device state, such as previous set points and calibration constants. This could have been hooked onto the other I2C bus, but I had one to spare, so why not?
The user interface is a low-cost off-the-shelf module with a 480 × 320 TFT LCD and a touchscreen. I bought mine for just a few dollars from one of the well-known Chinese vendors. The display module interfaces with the microcontroller via two SPI ports, one for the display, and one for the touchscreen controller. Again, one microcontroller SPI port would have worked for both, but since I had two available, it made sense to use them.
I also added a beeper to indicate a switch to current-limit mode audibly.
The power supply requirements are a little bit unusual, in that we require regulated 5V, 3.3V and -2.5V rails, while the input voltage can range between 5V and 20V. I chose a TPS5506 buck-boost converter (Texas Instruments), which can provide a regulated 5V output with any input voltage between 1.5V and 40V.
The 3.3V is derived from the 5V rail via a linear regulator U9. The -2.5V is created from the 5V supply by a regulated switched capacitor voltage inverter, the LTC1261L from Analog Devices (it was a Linear Technology part originally).
Given that this project was a proof of concept, there is no case. The project consists of a small two-layer PCB with all the components mounted on one side
(Figure 10). The LT3080 is mounted on a heatsink made from a small length of 25mm × 12mm × 1.2mm aluminium angle. The display is mounted above the main board, as shown in Figure 11 and Figure 12.
The software is implemented in C and C++ using the FreeRTOS real-time operating system. There are three threads—one to manage the USB-PD control tasks, one to manage the user interface, and one to handle the overall power supply control. For simplicity, the threads share a single data set, with access governed by a mutex, so that conflicts are avoided.
The USB-PD thread first checks that it can communicate with the STUSB4500 by reading one of its ID registers. The thread then goes sleep, waiting for an alert event that signals that the STUSB4500 has received a message from the source. It processes any such message and then returns to sleep until the next one occurs.
The UI thread initializes the LCD and touchscreen and initiates a read of the source’s capabilities. This is done by requesting the STUSB4500 to initiate an explicit 5V contract. The USB-PD thread monitors the sequence of messages and captures the source capability data, which is then displayed on the screen. This data is used to determine the maximum output voltage the power supply can provide, since the output is limited to the lesser of 1.5V less than the maximum the source can supply or 10V.
The UI thread then checks the UI every 50ms, to determine if the screen has been pressed and to update the display if that is needed.
There is a bit of complexity in the UI; however, the basic idea is simple. Events (either screen touches or timer ticks) are passed to each widget (button, label, display and so forth) on the current screen for processing. If the event is relevant to the widget, the widget state is updated.
Most widgets have optional call-back functions that are used to implement the application-specific code. Once all the widgets have processed the event, the widgets that have changed state are redrawn. In this way only areas of the screen that need to change are redrawn. This is important with a slow interface like SPI.
Finally, the controller task starts. This initializes the rest of the peripherals and reads the configuration data from the FRAM. It then enters a loop that repeats every 500ms. The control loop is very simple. The output voltage and current and the USB bus voltage are read, and the appropriate calibration factors applied. The software then checks if the bus voltage needs to be changed to maintain a minimum of 1.5V headroom between the output voltage and the bus voltage. It also determines whether the supply is in constant voltage or current mode, by comparing the voltage setpoint and the measured value. Finally, the setpoints are updated.
On power-up, the device checks the power delivery of the USB-C source and lists them. From these, it determines the maximum voltage and current it can supply (up to 10V and 1A). The source must be able to supply at least 12V for 10V output. If the source cannot supply this, the output voltage is limited to 1.5V less than the maximum the source can supply. Figure 11 shows a shot of this screen when the unit is powered from an 18W USB-C wall wart. Pressing the start button switches to the main screen.
Figure 12 shows how this screen is organized. At the top is a display of the output voltage and setpoint, along with a couple of buttons to adjust the setpoint. Below this is the same arrangement for the current. At the bottom there is a display of the measured USB bus voltage, an indicator of whether the supply is in constant voltage or current mode, and an output on/off button.
That’s really all there is to it. As a power supply, it is average at best; however, this project achieved its purpose in that I have learned a lot about USB-C Power Delivery. One of the biggest challenges in getting this process to work was the lack of documentation on the internal registers in the STUSB4500 and their functions. I had to piece a lot of this information together by reverse engineering the code they provide online. That said, I have learned a lot now and I feel ready to tackle any USB-C Power Delivery project. CC
Additional materials from the author are available at:
References  as marked in the article can be found there.
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • MAY 2022 #382 – Get a PDF of the issueSponsor this Article
Andrew Levido (firstname.lastname@example.org) earned a bachelor’s degree in Electrical Engineering in Sydney, Australia, in 1986. He worked for many years in R&D for power electronics and telecommunication companies, before moving into management roles. Andrew has maintained a hands-on interest in electronics, particularly embedded systems, power electronics and analog design. Over the years, he has written articles for various electronics publications, and provides consulting services as time allows.