For one-off projects, adding a few integrated circuits to a PCB is not too big of a deal. The price of transistors is extremely low thanks to Moore and his laws, so we’re fairly free to throw chips around like peanuts. But for extremely space-constrained projects, huge production runs, or for engineering challenges, every bit of PCB real estate counts. [g3gg0] falls into the latter group, and this project aims to remove the dedicated USB-PD module from a lighting project and instead bit-bang the protocol with the ESP32 already on the board.
The modern USB power delivery (PD) protocol isn’t quite as simple as older USB ports that simply present a 5V source to whatever plugs itself into the port. But with the added complexity we get a lot more capability including different voltages and greater power handling capabilities. The first step with the PD protocol is to communicate with a power source, which requires a 1.2V 600kHz signal. Just generating the signal is challenging enough, but the data encoding for USB requires level changes to encode bits rather than voltage levels directly. With that handled, the program can then move on to encoding packets and sending them out over the bus.
After everything is said and done, [g3gg0] has a piece of software that lets the ESP32 request voltages from a power supply, sniff and log PD communication, and inject commands with vendor defined messages (VDM), all without needing to use something like a CH224K chip which would normally offload the USB-PD tasks. For anyone looking to save PCB space for whatever reason, this could be a valuable starting point. To see some more capabilities of the protocol, check out this USB-PD power supply that can deliver 2 kW.
This comment is intended to start a discussion rather than to criticize anyone, and especially not the project’s author, who, on the contrary, deserves praise for doing so much diligent research, and then blogging about it for our benefit! With that caveat, here goes…
IMHO, bit-banging communication protocols is fraught, especially in the face of jitter introduced when processor-interrupts are enabled. It can take considerable validation efforts to make sure a bit-banged transmitter is actually adhering to the spec under all circumstances. To be fair, bi-phase encoded data is not rocket science, but 600kHz is still kind-of fast to bit-bang reliably. It is often impossible to cycle-count on modern RISC processors, so you have to use timers. (But then, is that really “bit-banging” in the traditional sense?) And can you get into the timer interrupt routine in a deterministic number of clock cycles?
A decade back, when bit-banging low-speed USB protocols was popular, the best that could be said was that these implementations were not future-proofed. They’d work okay until one day they wouldn’t (like when USB3 arrived on the scene).
An embedded software wizard friend once tried to productize a communication protocol he developed in an academic setting. What seemed reliable in the lab was not reliable enough for a product. Fortunately, since it was his private protocol, he had the luxury of slowing it way down. That worked!
Hi,
No offense as well and I fully understand your point :)
Maybe you were a bit quick without reading the blog post, while the HaD title was picking up the term “bitbang” which did not not exactly pinpoint what I did.
I did not exactly bitbang it, while this was my initial question in the blog post:
“why not bitbang PD-protocol with the ESP32 and save precious PCB space? Is this even possible?
Or can we use a peripheral for this task?”
and later:
“or we can use the wonderful RMT peripheral, which gives us a sequence of levels and their duration”
Now we could discuss if “getting high/low durations from a peripheral” is considered bitbanging.
I’d say no, but its neither bitbang nor native, and thus getting a meta-discussion here.
It is still a bit timing critical as I use the CPU to switch IO directions before/after transmission.
(To clarify it for further readers, I added a “Instead of bitbanging” when selecting the peripheral)
sorry, should have been a reply to Tim McNerney’s comment.
Driving the CC lines with 1.7V or even 3.3V seems a bit brutish to me when 1.2V is specified.
How about using two 74AUP1G125 (or ‘126) to drive the two CC lines instead? That would allow to properly drive them with a low-impedance CMOS signal of 1.2V high, 0V low or high-impedance when the other side is sending. The 74AUP1G series gates inputs can be driven with up to 3.6V, so they have no problem with a 3.3V input signal from the ESP32.
You can get them in SOT363-5 for like 5 cents per piece from LCSC, or even go down to DFN1010 if that should be too large.
You’d need a small 1.2V voltage regulator too of course.