A lightweight and experimental USB Power Delivery (PD) stack for the ESP32-C3. This project enables the ESP32-C3 to request voltages from a power supply, sniff and log PD communication, and inject commands for experimentation with Vendor Defined Messages (VDM).
Typical USB PD solutions require external ICs like the CH224K, which can be as large as the ESP32 itself. This implementation replaces such ICs with a minimalistic approach using MUN5233 NPN transistors with a monolithic bias resistor network (datasheet) for voltage level conversion.
- RX Path: Converts the 0-1.2V CC signal to 3.3V using a MUN5233 transistor and the IO in weak mode as a pull up.
- TX Path: Either directly drives with 3.3V (very hacky) or uses two outputs driving against each other, reducing voltage to approximately 1.7V - still outside protocol spec but works with all tested devices.
Just good enough for your casual DIY project, saving you another huge component on your design.
- USB PD Communication: Successfully requests user-defined voltage and maximum current from a USB PD power supply.
- Sniffing & Logging: Monitor and log USB PD communication on the CC line.
- Command Injection: Send messages to experiment with PD communication, including Vendor Defined Messages (VDM).
- Minimal Hardware Footprint: Removes the need for bulky PD controllers by leveraging simple transistor-based level shifting.
- Exploits the GPIOs capabilities by intentionally using them as weak outputs being driven to GND by the transistor or the CC-line. It's all still inside the specs, yet nothing one would really use for a reliable field design.
- Uses one GPIO for receiving and one GPIO (far beyond PD spec) or two GPIOs (closer to PD spec) for driving one CC line with 3.3V/1.7V, whilst both variants seem to work reliable.
The implementation is capable of successfully requesting a user-defined voltage and maximum current from a USB PD power supply. It operates using a hacky but functional method of voltage level shifting for communication. Although outside the official PD specifications, it has been tested and confirmed to work with multiple devices. It is outside the spec for the protocol encoding - but still a valid voltage on that line(!). In worst case scenario, the power supply will issue a PD protocol recovery over and over. Also the current state does only drive one CC-line. So in your design you have to combine the CC1/CC2 into one pin, which works not so reliable with all cables as raspberry users have noticed or simply rotate the plug if the device doesn't come up.
Alternatively use the second transistor in the MUN5233 to drive the same ESP32 RX pin low (unverified) and use a second TX pin, driving the second CC line as well. Needs another (or two) GPIOs. Something for next year or so :)
- Code cleanup: Currently, the caller must calculate checksums. The TX path should handle CRC. A separate logging task, as sending responses is time critical. A lot of small things that should get cleaned up.
- Retransmission Handling: Implement automatic retransmission when a GoodCRC is missing.
- Improved Packet Factory: Functions to construct different PD packets with proper encapsulation.
- ESP32-C3
- MUN5233 NPN Transistor I am using the MUN5233DW with two transistors (datasheet)
- 5.1kΩ pulldown on CC
- USB PD Power Supply
- CC Line Access for monitoring/sniffing
This project is an experimental, hacky implementation and does not fully comply with USB PD specifications. Use at your own risk! If you want to contribute, please do so. I will happily share access to the repository.
MIT License