Wiznet makers

jaden

Published November 29, 2024 ©

72 UCC

17 WCC

49 VAR

0 Contests

0 Followers

0 Following

W55RP20-EVB-PICO PSE KIT!

W55RP20-EVB-PICO PSE KIT

COMPONENTS Hardware components

WIZnet - W55RP20-EVB-Pico

x 1


PROJECT DESCRIPTION

Power over Ethernet (PoE) PSE-KIT Project

PoE (Power over Ethernet) is a convenient feature that allows devices to receive power through Ethernet UTP cables.

That's why countless devices support PoE, and many makers have also created projects using PoE. However, most PoE-related projects made by makers are limited to Powered Devices (PDs).

Why is that...? Because PoE-PDs, which receive power, are simpler and have fewer considerations than Power Sourcing Equipment (PSEs) that supply power!

I thought that if we could monitor and control the voltage, current, temperature, and status of each port on a PSE—including the ability to turn them on/off—it would enable more efficient power management in smart systems. So, I decided to create a PSE-KIT.

 

System Block Diagram

The overall system block diagram is as follows.

Initially, I considered converting 220 VAC to 54 VDC, but after learning that PoE-specific 54 V adapters are widely available on the market, I changed the power input to 54 VDC. (The fact that I lack AC to DC design skills also played a part.)

DC 54V 2.6A SMPS,140W

Component Selection

 

Voltage Conversion

For converting 54 V to 3.3 V and 54 V to 5 V, I used Torex's XC9702A75CDR-G.

Reason for Selection: It has a maximum input voltage of 60 V, providing an input voltage margin, and I had previous experience using it in other projects.

 

Input Protection

  • Reverse Voltage Protection: An FET is used on the 54 V input.
  • Transient Voltage Suppression: A TVS diode is employed to maintain circuit stability against voltage transients.
Power protection circuitry

 

PSE Implementation

IP804AR - PSE IC

I used the IP804AR from ICplus as the PSE IC.

Features:

  • Supports 4 ports, each capable of supplying up to 30 W.
  • Uses internal FETs for switching PoE power, eliminating the need for additional external FETs.
  • Can directly use the 54 VDC from the PoE adapter as the IC supply voltage.

Limitation: The IP804AR only supports PoE-related operations and does not handle Ethernet data communication.

Internal FET
44~57V Power input

 

 

IP175G - Ethernet Switch IC

To enable Ethernet data communication, I also used the IP175G, a 5-port Ethernet switch IC from ICplus.

IP175G schematic image

 

PoE Configuration

  • Mode B Operation: Since I'm using PoE in Mode B, I used PoE-specific transformers and RJ45 connectors.
  • PoE+ Support: Aimed to support up to PoE+, so I selected components with higher specifications.
  • Cost Consideration: Cost was not a major concern as there are no plans for mass production.
RJ45
PoE Transformer

 

Integration with W55RP20-EVB-PICO

The key feature of the W55RP20-EVB-PICO PSE_KIT is that it can be used by connecting the W55RP20-EVB-PICO, as suggested by its name.

  • Port Allocation:
    • Out of the 5 ports on the IP175G, 4 ports are connected via RJ45 connectors for UTP cable connections.
    • The remaining 1 port is connected to the Ethernet interface of the W55RP20-EVB-PICO.

Connection Method

Initially, to connect the Ethernet port of the W55RP20-EVB-PICO to the IP175G, I considered using the method from the impressive project "Wiznet Rudge PoE Pico PLC" by Manuel Alejandro Iglesias Abbatemarco.

Wiznet Rudge PoE Pico PLC
  • Issue: This method required removing the RJ45 connector from the W55RP20-EVB-PICO, and once manually soldered, replacing the board would be difficult.
  • Solution: I opted to use pogo pins to connect the IP175G to the W55RP20-EVB-PICO.

Pogo Pin Details

  • Type Used: Cupped Head pogo pins from Adafruit.
  • Pin Arrangement: Positioned to contact pins 1, 2, 3, and 6 of the RJ45 connector on the W55RP20-EVB-PICO.
  • Outcome: When mounting the W55RP20-EVB-PICO, the pogo pins accurately made contact without needing precise alignment.

PHY Connection

By connecting directly to the pins of the RJ45 connector (instead of through the RJ45 jack), the connection bypasses the internal LAN transformer.

  • Direct PHY-to-PHY Connection: To connect the PHYs without transformers, I used DC blocking capacitors between the IP175G and the W55RP20-EVB-PICO.
left side is IP175G and right side is POGO PIN(connected to W55RP20-EVB-PICO RJ45 pin)

 

Testing and Results

  • Power-Up and Link Confirmation: After supplying power and mounting the W55RP20-EVB-PICO, I confirmed that the LINK was established properly.
  • Port Verification: All 4 additional ports showed active links, confirmed by the LINK LEDs.
  • PoE Detection and Power Supply: Connected PoE PD devices to verify power delivery, confirmed by the PoE LEDs on each port.

 

Accessing IP804AR Registers via I2C

Referring to the IP804AR datasheet, I used the I2C interface of the W55RP20-EVB-PICO to read and analyze various registers of the IP804AR, outputting the data to the terminal.

Connection Setup

  • I2C Connection: Connected the I2C ports (previously brought out via header pins) to the I2C pins on the W55RP20-EVB-PICO using jumpers.
  • I2C Configuration:
    • The IP804AR divides the data line into SDAO and SDAI.
    • For standard 2-wire I2C communication, connected SDAO and SDAI together.

Pin Assignments

  • UART Output: Used GP0 and GP1 on the W55RP20-EVB-PICO for UART communication to the terminal.
  • I2C Interface: Assigned to GP4 and GP5.

 

Code Implementation

The code is as follows:

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"

#define IP804AR_I2C_ADDR 0x74  // Default I2C address for IP804AR
#define PICO_DEFAULT_I2C_SDA_PIN 4
#define PICO_DEFAULT_I2C_SCL_PIN 5

// Register definitions
#define REG_SYSTEM_CONFIG 0x01  // System Configuration Register
#define REG_PORT_POWER_CONTROL(port) (0x98 + (port))  // Power Control Register per port
#define REG_SUPPLY_VOLTAGE_MSB 0xE0
#define REG_PORT_VOLTAGE_MSB(port) (0xB0 + (port * 2))  // Port Voltage MSB
#define REG_PORT_CURRENT_MSB(port) (0xA0 + (port * 2))  // Port Current MSB
#define REG_PORT_TEMP_MSB(port) (0xC0 + (port * 2))     // Port Temperature MSB

#define REG_IVT_POLL 0xE3    // IVT Poll Register address
#define REG_DETECTED_PD_CLASS 0x88  // Detected PD Class Register address

void print_binary(uint8_t value) {
    for (int i = 7; i >= 0; i--) {
        printf("%c", (value & (1 << i)) ? '1' : '0');
    }
    printf("\n");
}

void switch_to_page(uint8_t page) {
    uint8_t device_register = 0x00;
    uint8_t value;

    // Read current page
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &device_register, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &value, 1, false) != 1) {
        printf("Failed to read current page.\n");
        return;
    }

    // Set page
    uint8_t new_value = (value & 0x3F) | (page << 6);  // Set page in the upper 2 bits
    uint8_t write_data[2] = {device_register, new_value};
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data, 2, false) != 2) {
        printf("Failed to switch to Page %d.\n", page);
        return;
    }
    printf("Page switched to %d.\n", page);
}



void enable_port_manual_mode(uint8_t port) {
    if (port > 3) {
        printf("Invalid port number. Must be 0-3.\n");
        return;
    }

    switch_to_page(1);  // Switch to page 1

    // Set Power Control register
    uint8_t power_control_register = REG_PORT_POWER_CONTROL(port);
    uint8_t power_control_data[2] = {power_control_register, 0x01};  // Activate Manual mode
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, power_control_data, 2, false) != 2) {
        printf("Failed to enable manual mode for Port %d.\n", port);
        return;
    }
    printf("Port %d enabled in Manual Mode.\n", port);
}

void read_ivt(uint8_t port) {
    uint8_t msb, lsb;

    // **Switch to page 0**
    switch_to_page(0);

    // **Read supply voltage (Supply Voltage)**
    uint8_t supply_voltage_reg = REG_SUPPLY_VOLTAGE_MSB;
    uint8_t supply_voltage_data[2];
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &supply_voltage_reg, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, supply_voltage_data, 2, false) != 2) {
        printf("Failed to read supply voltage.\n");
        return;
    }
    uint8_t supply_voltage_integer = ((supply_voltage_data[0] & 0x0F) << 4) | (supply_voltage_data[1] >> 4);
    uint8_t supply_voltage_fractional = supply_voltage_data[1] & 0x0F;
    float supply_voltage = supply_voltage_integer + (supply_voltage_fractional * 0.0625);

    printf("Supply Voltage: %.2f V\n", supply_voltage);

    // **Read port voltage (Port Voltage)**
    uint8_t voltage_reg = REG_PORT_VOLTAGE_MSB(port);
    uint8_t voltage_data[2];
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &voltage_reg, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, voltage_data, 2, false) != 2) {
        printf("Failed to read voltage for Port %d.\n", port);
        return;
    }

    // **Print port voltage MSB and LSB**
    printf("Port %d Voltage MSB (Binary): ", port);
    print_binary(voltage_data[0]);  // Print MSB
    printf("Port %d Voltage LSB (Binary): ", port);
    print_binary(voltage_data[1]);  // Print LSB

    // **Calculate port voltage**
    uint8_t port_voltage_integer = ((voltage_data[0] & 0x0F) << 4) | (voltage_data[1] >> 4);  // MSB lower 4 bits + LSB upper 4 bits
    uint8_t port_voltage_fractional = voltage_data[1] & 0x0F;  // LSB lower 4 bits
    float port_voltage = port_voltage_integer + (port_voltage_fractional * 0.0625);

    // **Calculate true voltage: Supply Voltage - Port Voltage**
    float true_port_voltage = supply_voltage - port_voltage;

    printf("Port %d Voltage: %.2f V (True Port Voltage: %.2f V)\n", port, port_voltage, true_port_voltage);

    // **Read current**
    uint8_t current_reg = REG_PORT_CURRENT_MSB(port);
    uint8_t current_data[2];
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &current_reg, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, current_data, 2, false) != 2) {
        printf("Failed to read current for Port %d.\n", port);
        return;
    }

    // **Print current MSB and LSB**
    printf("Port %d Current MSB (Binary): ", port);
    print_binary(current_data[0]);  // Print MSB
    printf("Port %d Current LSB (Binary): ", port);
    print_binary(current_data[1]);  // Print LSB

    // **Calculate current**
    uint8_t current_integer = ((current_data[0] & 0x0F) << 6) | (current_data[1] >> 2);  // MSB lower 4 bits + LSB upper 6 bits
    uint8_t current_fractional = current_data[1] & 0x03;  // LSB lower 2 bits
    float current = current_integer + (current_fractional * 0.25);  // Calculate fractional part (2 bits = * 0.25)

    printf("Port %d Current: %.2f mA\n", port, current);

    // **Read temperature**
    uint8_t temp_reg = REG_PORT_TEMP_MSB(port);
    uint8_t temp_data[2];
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &temp_reg, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, temp_data, 2, false) != 2) {
        printf("Failed to read temperature for Port %d.\n", port);
        return;
    }

    // **Print temperature MSB and LSB**
    printf("Port %d Temperature MSB (Binary): ", port);
    print_binary(temp_data[0]);  // Print MSB
    printf("Port %d Temperature LSB (Binary): ", port);
    print_binary(temp_data[1]);  // Print LSB

    // **Calculate temperature**
    uint8_t integer_part = ((temp_data[0] & 0x1F) << 4) | (temp_data[1] >> 4);  // MSB lower 5 bits + LSB upper 4 bits
    uint8_t fractional_raw = temp_data[1] & 0x0F;  // LSB lower 4 bits
    float fractional_part = fractional_raw * 0.0625;  // Calculate fractional part
    float temperature = integer_part + fractional_part;

    printf("Port %d Temperature: %.2f °C\n", port, temperature);
}

void read_and_print_voltage_binary(uint8_t reg) {
    uint8_t device_register = 0x00;  // I2C Device Address Register
    uint8_t value;

    // **Set page to 0**
    i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &device_register, 1, true);
    i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &value, 1, false);
    uint8_t new_value_page0 = value & 0x3F;  // Set upper 2 bits to 00
    uint8_t write_data_page0[2] = {device_register, new_value_page0};
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data_page0, 2, false) != 2) {
        printf("Failed to switch to Page 0\n");
        return;
    }
    printf("Page switched to 0 for register 0x%02X.\n", reg);

    uint8_t data[2];  // 2-byte array for Burst Read

    // **Perform Burst Read**
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &reg, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, data, 2, false) != 2) {
        printf("Failed to read from register 0x%02X\n", reg);
        return;
    }

    // **Print MSB and LSB in binary**
    printf("Register 0x%02X MSB (Binary): ", reg);
    print_binary(data[0]);
    printf("Register 0x%02X LSB (Binary): ", reg + 1);
    print_binary(data[1]);

    // **Calculate voltage value**
    uint16_t integer_raw = ((data[0] & 0x0F) << 4) | (data[1] >> 4);  // Combine lower 4 bits of MSB and upper 4 bits of LSB
    uint8_t fractional_raw = data[1] & 0x0F;  // Lower 4 bits of LSB (fractional part)
    float fractional_part = fractional_raw * 0.0625;  // Convert to decimal (4-bit value * 0.0625)
    float voltage = integer_raw + fractional_part;

    // **Print voltage value**
    printf("Voltage: %u.%02u V\n", integer_raw, (uint8_t)(fractional_part * 100));
}

void read_system_config() {
    uint8_t device_register = 0x00;  // I2C Device Address Register address
    uint8_t system_config;
    uint8_t system_config_register = REG_SYSTEM_CONFIG;

    // **Set page to 1**
    i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &device_register, 1, true);
    i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &system_config, 1, false);
    uint8_t new_value_page1 = (system_config & 0x3F) | (1 << 6);
    uint8_t write_data_page1[2] = {device_register, new_value_page1};
    i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data_page1, 2, false);
    printf("Page switched to 1\n");

    // **Read System Configuration Register**
    i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &system_config_register, 1, true);
    if (i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &system_config, 1, false) != 1) {
        printf("Failed to read System Configuration Register\n");
        return;
    }

    // **Print System Configuration status**
    printf("System Configuration Register (0x01): 0b");
    for (int i = 7; i >= 0; i--) {
        printf("%c", (system_config & (1 << i)) ? '1' : '0');
    }
    printf("\n");

    // **Check Operation Mode**
    uint8_t operation_mode = (system_config >> 6) & 0x03;
    printf("Operation Mode: ");
    switch (operation_mode) {
        case 0b00: printf("Auto Mode\n"); break;
        case 0b01: printf("Manual Mode\n"); break;
        case 0b10: printf("Diagnostic Mode\n"); break;
        case 0b11: printf("Scan Mode\n"); break;
        default: printf("Unknown Mode\n"); break;
    }

    // **Check Suspend Classification**
    if (system_config & (1 << 2)) {
        printf("Suspend Classification: Enabled\n");
    } else {
        printf("Suspend Classification: Disabled\n");
    }

    // **Check Suspend Power Up**
    if (system_config & (1 << 1)) {
        printf("Suspend Power Up: Enabled\n");
    } else {
        printf("Suspend Power Up: Disabled\n");
    }

    // **Check I2C Checksum**
    if (system_config & (1 << 0)) {
        printf("I2C Checksum: Enabled\n");
    } else {
        printf("I2C Checksum: Disabled\n");
    }
}

void enable_auto_polling() {
    uint8_t device_register = 0x00;  // I2C Device Address Register
    uint8_t value;

    // **Set page to 0**
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &device_register, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &value, 1, false) != 1) {
        printf("Failed to read current page from I2C Device Address Register\n");
        return;
    }

    uint8_t new_value_page0 = value & 0x3F;  // Set upper 2 bits to 00
    uint8_t write_data_page0[2] = {device_register, new_value_page0};
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data_page0, 2, false) != 2) {
        printf("Failed to switch to Page 0\n");
        return;
    }
    printf("Page switched to 0 for enabling Auto Polling.\n");

    uint8_t ivt_poll_register = REG_IVT_POLL;  // IVT Poll Register address
    uint8_t ivt_poll_status;

    // Read IVT Poll Register
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &ivt_poll_register, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &ivt_poll_status, 1, false) != 1) {
        printf("Failed to read IVT Poll Register (0xE3)\n");
        return;
    }

    // Enable Auto Polling (Set Bit 5)
    ivt_poll_status |= (1 << 5);  // Set Bit 5 to 1
    uint8_t write_data[2] = {ivt_poll_register, ivt_poll_status};
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data, 2, false) != 2) {
        printf("Failed to write to IVT Poll Register (0xE3)\n");
        return;
    }
    printf("Auto Polling enabled.\n");
}

void read_ivt_poll_register() {
    uint8_t device_register = 0x00;  // I2C Device Address Register
    uint8_t value;

    // **Set page to 0**
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &device_register, 1, true) != 1 ||
        i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &value, 1, false) != 1) {
        printf("Failed to read current page from I2C Device Address Register\n");
        return;
    }

    uint8_t new_value_page0 = value & 0x3F;  // Set upper 2 bits to 00
    uint8_t write_data_page0[2] = {device_register, new_value_page0};
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, write_data_page0, 2, false) != 2) {
        printf("Failed to switch to Page 0\n");
        return;
    }
    printf("Page switched to 0 for IVT Poll Register (0xE3).\n");

    uint8_t ivt_poll_register = REG_IVT_POLL;  // IVT Poll Register address
    uint8_t ivt_poll_status;

    // Read IVT Poll Register
    if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &ivt_poll_register, 1, true) != 1) {
        printf("Failed to write to IVT Poll Register (0xE3)\n");
        return;
    }

    if (i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, &ivt_poll_status, 1, false) != 1) {
        printf("Failed to read IVT Poll Register (0xE3)\n");
        return;
    }

    // Print IVT Poll Register status
    printf("IVT Poll Register (0xE3): 0b");
    for (int i = 7; i >= 0; i--) {
        printf("%c", (ivt_poll_status & (1 << i)) ? '1' : '0');
    }
    printf("\n");

    // Interpret status
    if (ivt_poll_status & (1 << 7)) {
        printf("Polling is currently in progress.\n");
    } else {
        printf("No polling is in progress.\n");
    }

    if (ivt_poll_status & (1 << 5)) {
        printf("Auto Polling is enabled.\n");
    } else {
        printf("Auto Polling is disabled.\n");
    }

    uint8_t poll_interval = ivt_poll_status & 0x0F;
    printf("Poll Interval: %d (units of 0.25ms)\n", poll_interval);
}

void read_ivt_all_ports() {
    for (uint8_t port = 0; port < 4; port++) {  // Repeat for ports 0 to 3
        printf("\nReading data for Port %d\n", port);

        uint8_t msb, lsb;

        // **Switch to page 0**
        switch_to_page(0);

        // **Read supply voltage (Supply Voltage)**
        uint8_t supply_voltage_reg = REG_SUPPLY_VOLTAGE_MSB;
        uint8_t supply_voltage_data[2];
        if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &supply_voltage_reg, 1, true) != 1 ||
            i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, supply_voltage_data, 2, false) != 2) {
            printf("Failed to read supply voltage.\n");
            return;
        }
        uint8_t supply_voltage_integer = ((supply_voltage_data[0] & 0x0F) << 4) | (supply_voltage_data[1] >> 4);
        uint8_t supply_voltage_fractional = supply_voltage_data[1] & 0x0F;
        float supply_voltage = supply_voltage_integer + (supply_voltage_fractional * 0.0625);

        printf("Supply Voltage: %.2f V\n", supply_voltage);

        // **Read port voltage (Port Voltage)**
        uint8_t voltage_reg = REG_PORT_VOLTAGE_MSB(port);
        uint8_t voltage_data[2];
        if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &voltage_reg, 1, true) != 1 ||
            i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, voltage_data, 2, false) != 2) {
            printf("Failed to read voltage for Port %d.\n", port);
            continue;  // Move to next port
        }

        // **Calculate port voltage**
        uint8_t port_voltage_integer = ((voltage_data[0] & 0x0F) << 4) | (voltage_data[1] >> 4);
        uint8_t port_voltage_fractional = voltage_data[1] & 0x0F;
        float port_voltage = port_voltage_integer + (port_voltage_fractional * 0.0625);
        float true_port_voltage = supply_voltage - port_voltage;

        printf("Port %d Voltage: %.2f V\n", port, true_port_voltage);

        // **Read current**
        uint8_t current_reg = REG_PORT_CURRENT_MSB(port);
        uint8_t current_data[2];
        if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &current_reg, 1, true) != 1 ||
            i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, current_data, 2, false) != 2) {
            printf("Failed to read current for Port %d.\n", port);
            continue;  // Move to next port
        }

        // **Calculate current**
        uint8_t current_integer = ((current_data[0] & 0x0F) << 6) | (current_data[1] >> 2);
        uint8_t current_fractional = current_data[1] & 0x03;
        float current = current_integer + (current_fractional * 0.25);

        printf("Port %d Current: %.2f mA\n", port, current);

        // **Read temperature**
        uint8_t temp_reg = REG_PORT_TEMP_MSB(port);
        uint8_t temp_data[2];
        if (i2c_write_blocking(i2c_default, IP804AR_I2C_ADDR, &temp_reg, 1, true) != 1 ||
            i2c_read_blocking(i2c_default, IP804AR_I2C_ADDR, temp_data, 2, false) != 2) {
            printf("Failed to read temperature for Port %d.\n", port);
            continue;  // Move to next port
        }

        // **Calculate temperature**
        uint8_t integer_part = ((temp_data[0] & 0x1F) << 4) | (temp_data[1] >> 4);
        uint8_t fractional_raw = temp_data[1] & 0x0F;
        float fractional_part = fractional_raw * 0.0625;
        float temperature = integer_part + fractional_part;

        printf("Port %d Temperature: %.2f °C\n", port, temperature);
    }
}


int main() {
    // Initialize UART
    stdio_init_all();

    // Initialize I2C
    i2c_init(i2c_default, 100 * 1000);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

//    printf("Reading IVT Poll Register\n");
//    read_ivt_poll_register();
//    printf("----------------------------------------\n");
//    printf("Enable Auto poll\n");
//    enable_auto_polling();
//    printf("----------------------------------------\n");
    printf("Reading IVT Poll Register\n");
    read_ivt_poll_register();
    printf("----------------------------------------\n");
    printf("Reading System Configuration Register\n");
    read_system_config();
    printf("----------------------------------------\n");
    // Activate Manual Mode on Port 0
    //enable_port_manual_mode(0);

    while (1) {
        read_and_print_voltage_binary(REG_SUPPLY_VOLTAGE_MSB);
        printf("\nMonitoring Port 0~3 IVT...\n");
        read_ivt_all_ports();
        printf("\n\n\n");
        sleep_ms(10000);  // Wait for 1 second
    }

    return 0;
}

Note: The code is a bit messy due to quick testing. Please excuse any inconsistencies.

 

The CMakeLists.txt was written as follows:

 

set(TARGET_NAME pse)

add_executable(${TARGET_NAME}
       ${TARGET_NAME}.c
       )

target_link_libraries(${TARGET_NAME}
       pico_stdlib
       hardware_i2c
       )


pico_enable_stdio_usb(${TARGET_NAME} 0)
pico_enable_stdio_uart(${TARGET_NAME} 1)

pico_add_extra_outputs(${TARGET_NAME})
 

Terminal Output

Upon checking the terminal output, the data appeared as follows:

Observation: Since I was testing with a PoE PD device connected to Port 0, its temperature was slightly higher compared to the other ports.

 

"In the attached schematic, pin 13 of the IP175G is marked as NC (Not Connected), which was my mistake. I discovered this later and fixed it with a jumper wire. Please take note."

 

Next Steps

In the next project, I plan to utilize this W55RP20-EVB-PICO PSE_KIT to add functionality that allows monitoring and controlling the PSE's status via a web server.

Thank you for your interest!

 

Documents
  • W55RP20-EVB-PICO_PSE_KIT

Comments Write