Qwiic USB-PD - STUSB4500 - PDO Voltage Readback Issue

Hi, I had a question regarding the USB-PD board (STUSB4500) – I’ve been struggling for a while to get the voltage parameter to read properly. When running the supplied example code it outputs values which do not reflect the true values set (which are verified to be working by the expected PDO LED selected, and the output voltage being set properly).

A simple example, when running the SetParameters example sketch with the values:

  /* PDO1
   - Voltage fixed at 5V
   - Current value for PDO1 0-5A, if 0 used, FLEX_I value is used
   - Under Voltage Lock Out (setUnderVoltageLimit) fixed at 3.3V
   - Over Voltage Lock Out (setUpperVoltageLimit) 5-20%
  */
  usb.setCurrent(1,3.0);
  usb.setUpperVoltageLimit(1,20);

  /* PDO2
   - Voltage 5-20V
   - Current value for PDO2 0-5A, if 0 used, FLEX_I value is used
   - Under Voltage Lock Out (setUnderVoltageLimit) 5-20%
   - Over Voltage Lock Out (setUpperVoltageLimit) 5-20%
  */
  usb.setVoltage(2,12.0);
  usb.setCurrent(2,1.0);
  usb.setLowerVoltageLimit(2,20);
  usb.setUpperVoltageLimit(2,20);

  /* PDO3
   - Voltage 5-20V
   - Current value for PDO3 0-5A, if 0 used, FLEX_I value is used
   - Under Voltage Lock Out (setUnderVoltageLimit) 5-20%
   - Over Voltage Lock Out (setUpperVoltageLimit) 5-20%
  */
  usb.setVoltage(3,15.0);
  usb.setCurrent(3,1.0);
  usb.setLowerVoltageLimit(3,20);
  usb.setUpperVoltageLimit(3,20);

The output is:

Connected to STUSB4500!
New Parameters:

PDO Number: 3

Voltage1 (V): 49.80
Current1 (A): 3.00
Lower Voltage Tolerance1 (%): 0
Upper Voltage Tolerance1 (%): 20

Voltage2 (V): 50.40
Current2 (A): 1.00
Lower Voltage Tolerance2 (%): 20
Upper Voltage Tolerance2 (%): 20

Voltage3 (V): 50.20
Current3 (A): 1.00
Lower Voltage Tolerance3 (%): 20
Upper Voltage Tolerance3 (%): 20

Flex Current: 1.00
External Power: 0
USB Communication Capable: 0
Configuration OK GPIO: 2
GPIO Control: 1
Enable Power Only Above 5V: 0
Request Source Current: 0

To further investigate this I dumped the register values and found that only the first two bytes are returning as expected (based on the STUSB4500 programming guide). The first 20 bits should correspond to the current (bits 9-0) and voltage (bits 19-10), but only the lower 6 bits of the voltage are read back as expected, furthermore, bits 20 and 21 are reserved and shall be set to 0, however these are both set to 1’s – in fact the upper two bytes are all 1’s:

Current PDO 1
11111111	11111111	10010001	00101100

Current PDO 2
11111111	11111111	11000000	01100100

Current PDO 3
11111111	11111111	10110000	01100100

So this explains why the current is being read back properly but not the voltage. I’m wondering if anyone has any thoughts on why this might be?

For reference I’m using a Sparkfun Pro Micro (USB-C) connected via Qwiic to program the USB-PD board (the only modifications to the example made were changing ‘Serial’ to ‘SerialUSB’ and the write values – though even with the default values it still was off). Additionally I’m on Arduino v1.8.13, SparkFun AVR Boards v1.1.13, SparkFun STUSB4500 v1.1.0.

Thanks!

I’m getting the same issue, I think. Running the Example3-SetDefaults script unmodified it returns the following, which are seem to not be valid voltages. When I try usb.setVoltage then usb.getVoltage, I get a value in the 49-50 range instead of what I input, and the board seems to stay on 5 volt / PDO1.

Connected to STUSB4500!
Done writing default settings!

PDO Number: 3

Voltage1 (V): 49.80
Current1 (A): 1.50
Lower Voltage Tolerance1 (%): 0
Upper Voltage Tolerance1 (%): 15

Voltage2 (V): 50.40
Current2 (A): 0.00
Lower Voltage Tolerance2 (%): 20
Upper Voltage Tolerance2 (%): 10

Voltage3 (V): 50.20
Current3 (A): 0.50
Lower Voltage Tolerance3 (%): 20
Upper Voltage Tolerance3 (%): 20

Flex Current: 2.00
External Power: 0
USB Communication Capable: 0
Configuration OK GPIO: 2
GPIO Control: 1
Enable Power Only Above 5V: 0
Request Source Current: 0

Here’s Example3-SetDefaults for posterity.

/*
  Resetting the STUSB4500 Power Delivery Board to Factory Settings
  By: Alex Wende
  SparkFun Electronics
  Date: February 6th, 2020
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
  Feel like supporting our work? Buy a board from SparkFun!
  https://www.sparkfun.com/products/15801
  
  This example will reset the NVM settings to default factory settings.
  
  Quick-start:
  - Use a SparkFun RedBoard Qwiic -or- attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
  - Upload example sketch
  - Plug the Power Delivery Board onto the RedBoard/shield
  - Open the serial monitor and set the baud rate to 115200
  - The RedBoard will connect to the Power Delivery Board over I2C and print out all of the settings saved.
*/
// Include the SparkFun STUSB4500 library.
// Click here to get the library: http://librarymanager/All#SparkFun_STUSB4500

#include <Wire.h>
#include <SparkFun_STUSB4500.h>

STUSB4500 usb;

void setup() 
{
  Serial.begin(115200);
  Wire.begin(); //Join I2C bus
  
  delay(500);
  
  /* The Power Delivery board uses the default settings with address 0x28 using Wire.
  
     Opionally, if the address jumpers are modified, or using a different I2C bus,
     these parameters can be changed here. E.g. usb.begin(0x29,Wire1)
  
     It will return true on success or false on failure to communicate. */
  if(!usb.begin())
  {
    Serial.println("Cannot connect to STUSB4500.");
    Serial.println("Is the board connected? Is the device ID correct?");
    while(1);
  }
  
  Serial.println("Connected to STUSB4500!");
  delay(100);

  usb.write(DEFAULT);
  Serial.println("Done writing default settings!\n");
  
  /* Read the NVM settings to verify the new settings are correct */
  usb.read();

  /* Read the Power Data Objects (PDO) highest priority */
  Serial.print("PDO Number: ");
  Serial.println(usb.getPdoNumber());

  /* Read settings for PDO1 */
  Serial.println();
  Serial.print("Voltage1 (V): ");
  Serial.println(usb.getVoltage(1));
  Serial.print("Current1 (A): ");
  Serial.println(usb.getCurrent(1));
  Serial.print("Lower Voltage Tolerance1 (%): ");
  Serial.println(usb.getLowerVoltageLimit(1));
  Serial.print("Upper Voltage Tolerance1 (%): ");
  Serial.println(usb.getUpperVoltageLimit(1));
  Serial.println();

  /* Read settings for PDO2 */
  Serial.print("Voltage2 (V): ");
  Serial.println(usb.getVoltage(2));
  Serial.print("Current2 (A): ");
  Serial.println(usb.getCurrent(2));
  Serial.print("Lower Voltage Tolerance2 (%): ");
  Serial.println(usb.getLowerVoltageLimit(2));
  Serial.print("Upper Voltage Tolerance2 (%): ");
  Serial.println(usb.getUpperVoltageLimit(2));
  Serial.println();

  /* Read settings for PDO3 */
  Serial.print("Voltage3 (V): ");
  Serial.println(usb.getVoltage(3));
  Serial.print("Current3 (A): ");
  Serial.println(usb.getCurrent(3));
  Serial.print("Lower Voltage Tolerance3 (%): ");
  Serial.println(usb.getLowerVoltageLimit(3));
  Serial.print("Upper Voltage Tolerance3 (%): ");
  Serial.println(usb.getUpperVoltageLimit(3));
  Serial.println();

  /* Read the flex current value */
  Serial.print("Flex Current: ");
  Serial.println(usb.getFlexCurrent());

  /* Read the External Power capable bit */
  Serial.print("External Power: ");
  Serial.println(usb.getExternalPower());

  /* Read the USB Communication capable bit */
  Serial.print("USB Communication Capable: ");
  Serial.println(usb.getUsbCommCapable());

  /* Read the POWER_OK pins configuration */
  Serial.print("Configuration OK GPIO: ");
  Serial.println(usb.getConfigOkGpio());

  /* Read the GPIO pin configuration */
  Serial.print("GPIO Control: ");
  Serial.println(usb.getGpioCtrl());

  /* Read the bit that enables VBUS_EN_SNK pin only when power is greater than 5V */
  Serial.print("Enable Power Only Above 5V: ");
  Serial.println(usb.getPowerAbove5vOnly());
  
  /* Read bit that controls if the Source or Sink device's 
     operating current is used in the RDO message */
  Serial.print("Request Source Current: ");
  Serial.println(usb.getReqSrcCurrent());
}

void loop()
{
}