Loading...
Searching...
No Matches
UsbPdPower.ino

Prints the board's USB-PD power profiles, the charger's contract and the measured VBUS once a second. Send 5, 9, 12, 15 or 20 over Serial to ask a USB-PD charger for up to that many volts, with stusb4500::boardProfiles() and stusb4500::setProfiles().

Wiring
A USB-PD charger on the USB-C port for anything above 5 V; a PC port gives 5 V and no contract (offer 0). With a charger on the port, use Serial1 (D1 TX, D0 RX, 115200) through a USB-serial adapter or a second board running a serial bridge: the sketch writes to, and reads from, both.
Output
Serial Monitor at 115200 baud, for example:
Asking for up to 12 V
profiles: 5.0V/2.00A 9.0V/1.00A 12.0V/0.83A contract: offer 3, 830 mA VBUS: 12.04 V
Warning
VBUS also feeds the VIN pin, so VIN follows the contract. Disconnect anything on VIN that can't take the voltage asked for. The request lasts until power-down; then Tools > USB-PD Power applies again.
// USB-PD power: prints the board's power profiles, the charger's contract and
// the measured VBUS once a second. Send 5, 9, 12, 15 or 20 to ask a USB-PD
// charger for up to that many volts and watch VBUS change.
// A charger takes the USB-C port, so output also goes to Serial1 (D1 TX,
// D0 RX, 115200) and commands are read from it: watch from a USB-serial
// adapter, or a second board running a serial bridge.
// VBUS also feeds the VIN pin, so VIN follows the contract: disconnect
// anything on VIN that can't take the voltage you ask for.
// The request lasts until the board loses power; at the next start-up the
// Tools > USB-PD Power setting applies again.
#include <stusb4500.h>
// Writes to USB Serial and Serial1. USB Serial drops data when no PC is listening.
class BothSerials : public Print {
public:
size_t write(uint8_t c) override {
Serial.write(c);
Serial1.write(c);
return 1;
}
};
static BothSerials out;
static void askForVolts(long volts) {
if (volts != 5 && volts != 9 && volts != 12 && volts != 15 && volts != 20) {
out.println("Send 5, 9, 12, 15 or 20.");
return;
}
// The board's profiles up to that voltage, limited to 10 W.
const uint8_t count = stusb4500::boardProfiles(volts * 1000, profiles);
out.print("Asking for up to ");
out.print(volts);
out.println(stusb4500::setProfiles(profiles, count) ? " V" : " V: failed");
}
static void printStatus() {
const uint8_t count = stusb4500::getProfiles(profiles);
out.print("profiles:");
for (uint8_t i = 0; i < count; i++) {
out.print(' ');
out.print(profiles[i].millivolts / 1000.0, 1);
out.print("V/");
out.print(profiles[i].milliamps / 1000.0, 2);
out.print('A');
}
// Offer 0 means no PD contract: plain 5 V USB, or a PC port.
out.print(" contract: offer ");
out.print(", ");
out.print(" mA VBUS: ");
out.print(stusb4500::vbusMillivolts() / 1000.0, 2);
out.println(" V");
}
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
const unsigned long start = millis();
while (!Serial && millis() - start < 5000) {} // no PC on a charger: go on after 5 s
if (!stusb4500::begin()) {
out.println("USB-PD controller not answering");
while (true) {}
}
out.println("Send 5, 9, 12, 15 or 20 to set the highest voltage.");
}
void loop() {
// parseInt() returns 0 for a lone line ending, so 0 is ignored.
if (Serial.available()) {
const long volts = Serial.parseInt();
if (volts != 0) askForVolts(volts);
}
if (Serial1.available()) {
const long volts = Serial1.parseInt();
if (volts != 0) askForVolts(volts);
}
printStatus();
delay(1000);
}
SerialUARTClass Serial1
UART0 on D1 (TX) and D0 (RX).
SerialUSBClass Serial
USB serial port, the one the Serial Monitor uses.
void loop(void)
Written by the sketch: runs over and over after setup(), on core 0.
void setup(void)
Written by the sketch: runs once after reset, on core 0.
unsigned long millis(void)
Milliseconds since the board started.
void delay(unsigned long)
Waits a number of milliseconds.
bool begin()
Sets up I2C1 and the control pins.
uint8_t getProfiles(Profile *out)
Reads the active profiles.
uint8_t contractPosition()
Which charger offer is in use.
uint16_t contractMilliamps()
Operating current agreed in the current contract.
constexpr uint8_t kMaxProfiles
Number of profiles the chip holds.
Definition stusb4500.h:44
uint8_t boardProfiles(uint16_t max_millivolts, Profile *out)
The board's profiles for Tools > USB-PD Power.
bool setProfiles(const Profile *profiles, uint8_t count)
Loads 1-3 profiles and renegotiates if they differ from the current ones.
uint32_t vbusMillivolts()
VBUS measured by the on-board ADC (MAX11635 channel 3).
One sink profile (PDO): a voltage the board accepts and the current it draws.
Definition stusb4500.h:38
Driver for the on-board STUSB4500 USB Power Delivery sink controller (U6).