{
    "ok": true,
    "data": {
        "title": "EP-0245",
        "rev_id": 16196,
        "updated_at": "2026-01-09T03:06:00+00:00",
        "chunk_count": 64,
        "chunks": [
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "",
                "chunk_index": 0,
                "content": "# EP-0245",
                "char_count": 9,
                "token_estimate": 3
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "UPS Gen 6 power module compatible with Raspberry Pi 5\/4B",
                "chunk_index": 1,
                "content": "<figure>\n<img src=\"EP-0245-01.jpg\" title=\"EP-0245-01.jpg\" width=\"320\" alt=\"EP-0245-01.jpg\" \/>\n<figcaption aria-hidden=\"true\">EP-0245-01.jpg<\/figcaption>\n<\/figure>",
                "char_count": 162,
                "token_estimate": 41
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description",
                "chunk_index": 2,
                "content": "The UPS Gen 6 is the latest version of the UPS Plus series, designed for enhanced power management on Raspberry Pi or other SBCs. It supports up to 4 channels of 8.4V lithium battery packs in parallel and can be expanded with two 3.7V 18650 batteries in series. The device features intelligent power path management, prioritizing external power and switching to battery power during outages. It also supports real - time monitoring of battery status via I2C and custom firmware uploads through DFU. Additional features include programmable LEDs, a PikaPython interface for advanced monitoring, auto - restart on power recovery, safe shutdown countdown, and low - battery loop protection. UPS Gen 6 offers a versatile solution for your projects and will gain more features through future OTA firmware upgrades. NOTE: For convenience, the UPS Gen 6 motherboard will be referred to as \\*\\*upsv6\\*\\* in our subsequent code links.",
                "char_count": 925,
                "token_estimate": 232
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description > Key Features",
                "chunk_index": 3,
                "content": "-   Bumpless Transfer\n-   Hard Disk Power Supply Interface\n-   Cooling System\n-   OTA Expansion for Additional Functions\n-   I2C Communication Interface\n-   PikaPython Script Execution Capability\n-   Physical Power Button",
                "char_count": 221,
                "token_estimate": 56
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description > Specifications",
                "chunk_index": 4,
                "content": "-   <strong>Device Compatibility:<\/strong> Supports Raspberry Pi and Orange Pi series devices.\n-   <strong>Expansion Battery Pack Support:<\/strong>Supports 18650 battery packs with two batteries in series, providing a typical voltage of 7.4V and a maximum voltage of 8.4V, with up to four parallel battery packs supported.\n-   <strong>Power Management:<\/strong> Bumpless Transfer, Full UPS (Uninterruptible Power Supply) characteristics, supporting seamless failover to battery power.\n-   <strong>Communication Interface: <\/strong>I2C protocol for battery and device status monitoring and controlling.\n-   <strong>DIY Features: <\/strong>Programmable LED control via configuring i2c registers.\n-   <strong>PikaPython support:<\/strong>PikaPython script interpreter for Python script injection.\n-   <strong>Power Recovery Settings: <\/strong>Configurable voltage thresholds for auto-restart.\n-   <strong>Safe shutdown timer:<\/strong> Saft shutdown timer to prevent data loss.\n-   <strong>OTA Upgrade Features:<\/strong>Get more feature via OTA upgrade.",
                "char_count": 1047,
                "token_estimate": 262
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description > Compatibility Note",
                "chunk_index": 5,
                "content": "The screws, copper pillars, and other additional components of this product are primarily designed to fit the Raspberry Pi 5 and Raspberry Pi 4B. However, the product's functionality is compatible with other SBC (Single Board Computer) development boards on the market that are pin-compatible with the Raspberry Pi. If you need to install it smoothly, you may need to check whether the positioning hole locations match those of the Raspberry Pi 5 or Raspberry Pi 4B. Otherwise, it may not be physically compatible. This is hereby declared.",
                "char_count": 539,
                "token_estimate": 135
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description > UPS features Details",
                "chunk_index": 6,
                "content": "#### Feature 1: Auto Start Mode\n\n-   Register: auto_start_mode\n-   Function: Enables automatic power-on logic when written.\n-   Conditions for Auto Start: when Battery voltage \\> auto_start_voltage and Valid external power source present\n-   Protection Mechanism: Monitors battery voltage after auto-start; If voltage drops to battery_protection_voltage multiple times:\n\n<!-- -->\n\nAuto-start attempts will be abandoned\n\n-   Manual Shutdown by Button\n\n<!-- -->\n\nAuto clears auto_start_mode functionality\n\n#### Feature 2: Delayed Shutdown\n\n-   Register: shutdown_countdown\n\n<!-- -->\n\nInitiates shutdown after specified seconds when written.\n\n-   <strong> Important Notes<\/strong>\n\n<!-- -->\n\nCombined with active auto_start_mode: Functions as a reboot if conditions are met\n      For complete shutdown: Must clear auto_start_mode setting\n\n#### Feature 3: Runtime Tracking\n\n-   Register: runtime\n-   Unit: milliseconds (ms)\n-   Functionality: Tracks continuous operation time since last power-on\n\n#### Feature 4: Force OTA Mode\n\n-   Register: ota_request\n-   Write value: <strong>0xA5A5<\/strong>\n-   Behavior: Immediately forces device into OTA mode\n\n#### Feature 5: Physical Button Control",
                "char_count": 1186,
                "token_estimate": 297
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Description > UPS features Details",
                "chunk_index": 7,
                "content": "-   Current Implementation\n\nSingle button operation Toggles power state immediately\n\nNote: It should be emphasized that it is not recommended to use the button to force power off, as this can cause file system damage, which is equivalent to forcibly shutting down a computer by pressing the power button.\n\n---- <strong>Important Notice<\/strong>\n\\* Immediate shutdown risks: Potential data loss\n\n-   Recommended method: Use shutdown_countdown for safe shutdown\n\n#### Feature 6: L_FAST LED Indicators\n\n| LED State     | Meaning                 |\n|---------------|-------------------------|\n| Fast blinking | Bootloader mode         |\n| Solid on      | Fast charging available |\n| Slow blinking | UPS Fault               |\n| Off           | No input power          |",
                "char_count": 763,
                "token_estimate": 191
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Gallery",
                "chunk_index": 8,
                "content": "-   Product Outlook\n\n<img src=\"EP-0245-01.jpg\" title=\"EP-0245-01.jpg\" width=\"800\" alt=\"EP-0245-01.jpg\" \/>\n\\* Back face <img src=\"EP-0245-02.jpg\" title=\"EP-0245-02.jpg\" width=\"800\" alt=\"EP-0245-02.jpg\" \/>\n\\* Assembly status <img src=\"EP-0245-03.jpg\" title=\"EP-0245-03.jpg\" width=\"800\" alt=\"EP-0245-03.jpg\" \/>\n\\* Port definitions <img src=\"EP-0245-04.jpg\" title=\"EP-0245-04.jpg\" width=\"800\" alt=\"EP-0245-04.jpg\" \/>\n\n---- <strong>Please note: When the 12v HDD power port is needed for external power supply, an external PD power source and a battery need to be connected simultaneously. Otherwise, the 12v HDD power port will not be able to supply power properly.<\/strong>\n\n------------------------------------------------------------------------",
                "char_count": 743,
                "token_estimate": 186
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Gallery",
                "chunk_index": 9,
                "content": "\\* Easy to install <img src=\"EP-0245-05.jpg\" title=\"EP-0245-05.jpg\" width=\"800\" alt=\"EP-0245-05.jpg\" \/>\n\\* Heat dissipation effect <img src=\"EP-0245-06.jpg\" title=\"EP-0245-06.jpg\" width=\"800\" alt=\"EP-0245-06.jpg\" \/>\n\\* External Power supply <img src=\"EP-0245-07.jpg\" title=\"EP-0245-07.jpg\" width=\"800\" alt=\"EP-0245-07.jpg\" \/>\n<img src=\"EP-0245-08.jpg\" title=\"EP-0245-08.jpg\" width=\"800\" alt=\"EP-0245-08.jpg\" \/>\n\\* Standard Output for HDD (12V\/5V) <img src=\"EP-0245-09.jpg\" title=\"EP-0245-09.jpg\" width=\"800\" alt=\"EP-0245-09.jpg\" \/>\n\\* Mechanical Drawings Unit: mm\n\n-   Bottom view\n\n<img src=\"UPSGen6_MD01.png\" title=\"UPSGen6_MD01.png\" width=\"800\" alt=\"UPSGen6_MD01.png\" \/>\n\\* Front view <img src=\"UPSGen6_MD02.png\" title=\"UPSGen6_MD02.png\" width=\"800\" alt=\"UPSGen6_MD02.png\" \/>\n\\* Top view <img src=\"UPSGen6_MD03.png\" title=\"UPSGen6_MD03.png\" width=\"800\" alt=\"UPSGen6_MD03.png\" \/>",
                "char_count": 880,
                "token_estimate": 220
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Package List",
                "chunk_index": 10,
                "content": "-   1 x Aluminum Heatsink with Automatically controlled Fan.\n-   1 x UPS Gen 6 mainboard\n-   1 x A series connect battery case\n-   1 x 4CM Battery Connector wire\n-   1 x Acrylic battery base frame\n-   1 x Metal battery base frame\n-   1 x Copper pillar pack\n-   1 x Flat heat screws pack (M2.5)\n-   1 x UPS Gen 6 instructions\n\n<img src=\"EP-0245-PL.jpg\" title=\"EP-0245-PL.jpg\" width=\"800\" alt=\"EP-0245-PL.jpg\" \/>",
                "char_count": 410,
                "token_estimate": 103
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to assemble it?",
                "chunk_index": 11,
                "content": "-   For Raspberry Pi 4B\n\n<img src=\"EP-0245-IN-PI-4.jpg\" title=\"EP-0245-IN-PI-4.jpg\" width=\"800\" alt=\"EP-0245-IN-PI-4.jpg\" \/>\n\\* For Raspberry Pi 5 <img src=\"EP-0245-IN-PI-5.jpg\" title=\"EP-0245-IN-PI-5.jpg\" width=\"800\" alt=\"EP-0245-IN-PI-5.jpg\" \/>\n==YouTube Video==\n\n-   \\[ UPS Gen 6 power module compatible with Raspberry Pi 5\/4B \\| <https:\/\/youtu.be\/zbpnDJvAF1s>\\]",
                "char_count": 365,
                "token_estimate": 92
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual",
                "chunk_index": 12,
                "content": "-   　<strong>Please read the user manual carefully before proceeding.<\/strong>\n\n------------------------------------------------------------------------\n\n    This documentation assumes you are using a Raspberry Pi for testing. You can also use Orange Pi devices, but you will need to adjust the I2C controller address based on your specific setup. The default I2C device address for Raspberry Pi is \/dev\/i2c-1, while Orange Pi may use \/dev\/i2c-3. Adjust these settings according to your hardware.",
                "char_count": 496,
                "token_estimate": 124
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > The testing environment for this documentation includes:",
                "chunk_index": 13,
                "content": "-   Raspberry Pi 5\n-   4 battery packs, each consisting of two fully charged 18650 lithium batteries connected in series to provide 8.4V.\n-   A 100W USB-C PD protocol charger.\n-   Raspberry Pi OS 64-bit Bookworm, updated to the latest version.\n\nIf you are using a different operating system, refer to its specific environment configuration. Note that we currently provide configuration guidance only for Raspberry Pi OS. For other systems, please resolve compatibility issues independently.",
                "char_count": 490,
                "token_estimate": 123
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Register Summary Table",
                "chunk_index": 14,
                "content": "| Address | Name                       | Width | Access | Description                               | Default Value |\n|---------|----------------------------|-------|--------|-------------------------------------------|---------------|\n| 0x00    | WHO_AM_I                   | 8     | R　    | Device identification register            | 0xA6          |\n| 0x01    | version                    | 8     | R      | Version number                            | \\-            |\n| 0x02    | uuid0                      | 32    | R      | Unique ID (lower 32 bits)                 | \\-            |\n| 0x06    | uuid1                      | 32    | R      | Unique ID (middle 32 bits)                | \\-            |\n| 0x0A    | uuid2                      | 32    | R      | Unique ID (upper 32 bits)                 | \\-            |\n| 0x0E    | output_voltage             | 16    | R      | Output voltage (unit: mV, 5000mV output)  | \\-            |\n| 0x10    | input_voltage              | 16    | R      | Input voltage (unit: mV)                  | \\-            |\n| 0x12    | battery_voltage            | 16    | R      | Battery voltage (unit: mV)                | \\-            |",
                "char_count": 1178,
                "token_estimate": 295
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Register Summary Table",
                "chunk_index": 15,
                "content": "| 0x14    | mcu_voltage                | 16    | R      | MCU voltage (unit: mV)                    | \\-            |\n| 0x16    | output_current             | 16    | R      | Output current (unit: mA, 5V output)      | \\-            |\n| 0x18    | input_current              | 16    | R      | Input current (unit: mA)                  | \\-            |\n| 0x1A    | battery_current            | 16    | R      | Battery current (signed, unit: mA)        | \\-            |\n| 0x1C    | temperature                | 8     | R      | Temperature (two's complement, unit: °C)  | \\-            |\n| 0x1D    | CR1                        | 8     | R\/W    | Control Register 1                        | 0x01          |\n| 0x1E    | CR2                        | 8     | R\/W    | Control Register 2 (Reserved)             | 0x00          |\n| 0x1F    | SR1                        | 8     | R      | Status Register 1                         | \\-            |\n| 0x20    | SR2                        | 8     | R      | Status Register 2                         | \\-            |\n| 0x21    | battery_protection_voltage | 16    | R\/W    | Battery protection voltage (unit: mV)     | 7400          |",
                "char_count": 1179,
                "token_estimate": 295
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Register Summary Table",
                "chunk_index": 16,
                "content": "| 0x23    | shutdown_countdown         | 16    | R\/W    | Shutdown countdown (unit: seconds)        | \\-            |\n| 0x25    | auto_start_voltage         | 16    | R\/W    | Auto-start voltage threshold (unit: mV)   | 7400          |\n| 0x27    | rsv                        | 16    | R\/W    | Python output buffer content length       | \\-            |\n| 0x29    | ota_request                | 16    | W      | Writing to 0xA5A5 will request OTA mode.  | \\-            |\n| 0x2B    | runtime                    | 64    | R      | Cumulative runtime (unit: millisecond)    | \\-            |\n| 0x33    | charge_detect_interval_s   | 16    | R\/W    | Charge detection interval (unit: seconds) | \\-            |\n| 0x35    | led_ctl                    | 8     | R\/W    | LED control register                      | 0x01          |",
                "char_count": 825,
                "token_estimate": 207
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Control Register CR1 (Address: 0x1D)",
                "chunk_index": 17,
                "content": "| Bit  | Name            | Access | Description                             | Default Value |\n|------|-----------------|--------|-----------------------------------------|---------------|\n| BIT0 | auto_start_mode | R\/W    | Auto-start mode (0=disabled, 1=enabled) | 1             |",
                "char_count": 281,
                "token_estimate": 71
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Status Register SR1 (Address: 0x1F)",
                "chunk_index": 18,
                "content": "| Bit  | Name         | Access | Description                                                                   | Default Value |\n|------|--------------|--------|-------------------------------------------------------------------------------|---------------|\n| BIT0 | sw_status    | R      | 5V output status (0=off, 1=on)                                                | \\-            |\n| BIT1 | fast         | R      | Fast charging status (0=slow charging\/no external power, 1=12V fast charging) | \\-            |\n| BIT2 | charge       | R      | Charge\/discharge status (0=charging, 1=discharging)                           | \\-            |\n| BIT3 | input_low    | R      | Input voltage low (0=normal, 1=low)                                           | \\-            |\n| BIT4 | output_low   | R      | 5V output low (0=normal, 1=low)                                               | \\-            |\n| BIT5 | battery_low  | R      | Battery voltage low (0=normal, 1=low)                                         | \\-            |\n| BIT6 | adc_mismatch | R      | ADC mismatch (0=normal, 1=INA219 vs MCU sampling difference exceeded)         | \\-            |",
                "char_count": 1160,
                "token_estimate": 290
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Status Register SR1 (Address: 0x1F)",
                "chunk_index": 19,
                "content": "| BIT7 | battery_fail | R      | Battery failure (0=normal, 1=failure)                                         | \\-            |",
                "char_count": 128,
                "token_estimate": 32
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Status Register SR2 (Address: 0x20)",
                "chunk_index": 20,
                "content": "-   Not Avaliable right now.",
                "char_count": 28,
                "token_estimate": 7
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > LED Control Register （Address: 0x35)",
                "chunk_index": 21,
                "content": "| Bit  | Name          | Access | Description                       | Default Value |\n|------|---------------|--------|-----------------------------------|---------------|\n| BIT0 | i2c_ack       | R\/W    | LED on during I2C communication   | 1             |\n| BIT1 | bat_charge    | R\/W    | LED on during battery charging    | 0             |\n| BIT2 | bat_discharge | R\/W    | LED on during battery discharging | 0             |\n| BIT3 | fault_report  | R\/W    | LED on when fault detected        | 0             |\n| BIT4 | ok_report     | R\/W    | LED on during normal operation    | 0             |",
                "char_count": 601,
                "token_estimate": 151
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Special Notes",
                "chunk_index": 22,
                "content": "-   Data Format:\n\n<!-- -->\n\n      Voltage\/current values are unsigned integers\n      battery_current is signed (two's complement format)\n      temperature is signed 8-bit integer (two's complement), range: -40°C to +85°C\n\n-   Reserved Bits:\n\n<!-- -->\n\n      All reserved bits default to 0\n      Write operations to reserved bits are ignored (recommended to maintain default values)\n\n-   The register definitions in the bootloader state are not fully compatible.",
                "char_count": 461,
                "token_estimate": 116
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Getting Start",
                "chunk_index": 23,
                "content": "-   Assume that your Device Environment: Raspberry Pi 5, operating system: Raspberry Pi OS 64-bit (Bookworm).\n-   Assume that your Raspberry Pi 5 can access internet including GitHub.\n-   Assume that you have already assembled the UPS v6 with your Raspberry Pi 5 and booting up properly.\n-   Please refer to the following steps for operation:\n\n#### Install Dependencies package and libraries\n\n-   Open a terminal and typing:\n\n<!-- -->\n\n    sudo apt update\n    sudo apt upgrade -y\n    sudo apt -y install build-essential cmake libi2c-dev libssl-dev gcc-arm-none-eabi git wget vim virtualenv i2c-tools",
                "char_count": 599,
                "token_estimate": 150
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Download Demo codes repository",
                "chunk_index": 24,
                "content": "-   In order to use this module easily, I recommend you download the repository from GitHub, URL: \\[ <https:\/\/github.com\/geeekpi\/upsv6_pub.git> \\]\n-   Download to Raspberry Pi 5 locally, you need to open a terminal and typing following commands:\n\n<!-- -->\n\n    cd ~\/\n    git clone https:\/\/github.com\/geeekpi\/upsv6_pub.git\n\nor just open a browser and access this URL: \\[ <https:\/\/github.com\/geeekpi\/upsv6_pub.git> \\], click \\`code\\` -\\> click \\`Download ZIP\\` and then extract the contents to your Raspberry Pi 5 on desktop. <img src=\"Downloadrepo.png\" title=\"Downloadrepo.png\" width=\"800\" alt=\"Downloadrepo.png\" \/>",
                "char_count": 614,
                "token_estimate": 154
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Upload new firmware",
                "chunk_index": 25,
                "content": "-   Step 1. Enter into OTA mode\n-   Step 2. Upload new firmware_encrypted.bin file\n\n<!-- -->\n\n    python enable_ota.py\n\nCheck if the UPS v6 has been entered into OTA mode:\n\n    i2cdetect -y 1\n\nIf the i2c device address is changed from 0x17 to 0x18 means UPS Gen 6 is already in OTA mode.\n\n    .\/user_write_tool firmware_encrypted.bin\n\nUntil you see following figure: <img src=\"Flash_complete.png\" title=\"Flash_complete.png\" width=\"800\" alt=\"Flash_complete.png\" \/>",
                "char_count": 463,
                "token_estimate": 116
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "User Manual > Push button status",
                "chunk_index": 26,
                "content": "-   Push button will keep the status after last operation.",
                "char_count": 58,
                "token_estimate": 15
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to read UPS status",
                "chunk_index": 27,
                "content": "-   Step 1. Download repository by using git command, open a terminal and typing following command:\n\n<!-- -->\n\n    cd ~\n    git clone https:\/\/github.com\/geeekpi\/upsv6_pub.git\n    cd upsv6_pub\/\n\n-   Step 2. Enable I2C function by using raspi-config command:\n\n<!-- -->\n\n    sudo raspi-config\n\nNavigate to 3 Interface Options -\\> I2C -\\> YES -\\> OK -\\> Finished\n\n-   Step 3. Execute Python script\n\n<!-- -->\n\n    python script\/tools\/python_demo\/read_device_basic_demo.py",
                "char_count": 466,
                "token_estimate": 117
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 28,
                "content": "To calculate the input and output power using the values read from the registers, you need to follow these steps:\n\n-   Read the voltage and current values from the respective registers.\n-   Convert the voltage from millivolts (mV) to volts (V) by dividing by 1000.\n-   Convert the current from milliamperes (mA) to amperes (A) by dividing by 1000.\n-   Calculate the power using the formula:\n\n<!-- -->\n\nPower (W)=Voltage (V)×Current (A)\n\nHere is the modified Python code that includes the calculation of input and output power:\n\nfrom smbus2 import SMBus\n    import time\n\n# Device address\n\nDEVICE_ADDRESS = 0x17\n\n# init SMBus\n\nbus = SMBus(1)  # 1 means I2C no.1 bus\n\n# Define registers address\n\n# WHO_AM_I_REG = 0x00 \/\/ will always be 0xA6\n\nVERSION_REG = 0x01\n    UID0_REG = 0x02\n    UID1_REG = 0x06\n    UID2_REG = 0x0A\n    OUTPUT_VOLTAGE_REG = 0x0E\n    INPUT_VOLTAGE_REG = 0x10\n    BATTERY_VOLTAGE_REG = 0x12\n    MCU_VOLTAGE_REG = 0x14\n    OUTPUT_CURRENT_REG = 0x16\n    INPUT_CURRENT_REG = 0x18\n    BATTERY_CURRENT_REG = 0x1A\n    TEMPERATURE_REG = 0x1C\n\n# Define ANSI color\n\nRED = '\\033[95m'\n    GREEN = '\\033[92m'\n    END_COLOR = '\\033[0m'\n\n# read 8bit register",
                "char_count": 1161,
                "token_estimate": 291
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 29,
                "content": "def read_byte_register(register_address):\n        value = bus.read_byte_data(DEVICE_ADDRESS, register_address)\n        if value > 127:\n            value -= 256\n        return value\n\n# read 16bit register\n\ndef read_word_register(register_address):\n        value = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        if value > 32767:\n            value -= 65536\n        return value\n\n# read 32bit register\n\ndef read_dword_register(register_address):\n        low = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        high = bus.read_word_data(DEVICE_ADDRESS, register_address + 2)\n        return (high << 16) | low\n\n# read all registers data",
                "char_count": 656,
                "token_estimate": 164
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 30,
                "content": "def read_all_registers():\n        registers = {\n            \"WHO_AM_I\": \"0xA6\",\n            \"VERSION\": read_byte_register(VERSION_REG),\n            \"UID0\": read_dword_register(UID0_REG),\n            \"UID1\": read_dword_register(UID1_REG),\n            \"UID2\": read_dword_register(UID2_REG),\n            \"OUTPUT_VOLTAGE\": read_word_register(OUTPUT_VOLTAGE_REG),\n            \"INPUT_VOLTAGE\": read_word_register(INPUT_VOLTAGE_REG),\n            \"BATTERY_VOLTAGE\": read_word_register(BATTERY_VOLTAGE_REG),\n            \"MCU_VOLTAGE\": read_word_register(MCU_VOLTAGE_REG),\n            \"OUTPUT_CURRENT\": read_word_register(OUTPUT_CURRENT_REG),\n            \"INPUT_CURRENT\": read_word_register(INPUT_CURRENT_REG),\n            \"BATTERY_CURRENT\": read_word_register(BATTERY_CURRENT_REG),\n            \"TEMPERATURE\": read_byte_register(TEMPERATURE_REG)\n        }\n        return registers\n\n# Calculate power\n\ndef calculate_power(voltage_mv, current_ma):\n        # Convert mV to V and mA to A\n\nvoltage_v = voltage_mv \/ 1000.0\n        current_a = current_ma \/ 1000.0\n        # Calculate power in watts\n\npower_w = voltage_v * current_a\n        return power_w\n\n# read and print out all registers data.",
                "char_count": 1179,
                "token_estimate": 295
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 31,
                "content": "try:\n        while True:\n            print(f\"{RED}=== 52Pi UPS V6 Raw Data Output ==={END_COLOR}\")\n            registers = read_all_registers()\n\n# Extract voltage and current values\n\ninput_voltage_mv = registers[\"INPUT_VOLTAGE\"]\n            input_current_ma = registers[\"INPUT_CURRENT\"]\n            output_voltage_mv = registers[\"OUTPUT_VOLTAGE\"]\n            output_current_ma = registers[\"OUTPUT_CURRENT\"]\n\n# Calculate input and output power\n\ninput_power_w = calculate_power(input_voltage_mv, input_current_ma)\n            output_power_w = calculate_power(output_voltage_mv, output_current_ma)\n\n# Print all register values\n\nfor key, value in registers.items():\n                if \"VOLTAGE\" in key:\n                    print(f\"* {key}: {GREEN}{value}mV{END_COLOR} \")\n                elif \"CURRENT\" in key:\n                    print(f\"* {key}: {RED}{value}mA{END_COLOR} \")\n                elif \"TEMPERATURE\" in key:\n                    print(f\"* {key}: {GREEN}{value}C{END_COLOR} \")\n                elif \"WHO_AM_I\" in key:\n                    print(f\"* {key}: {value}\")\n                else:\n                    print(f\"* {key}: {value}\")\n\n# Print calculated power values",
                "char_count": 1170,
                "token_estimate": 293
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 32,
                "content": "print(f\"* INPUT_POWER: {GREEN}{input_power_w:.2f}W{END_COLOR}\")\n            print(f\"* OUTPUT_POWER: {RED}{output_power_w:.2f}W{END_COLOR}\")\n\nprint(\"-\"*80)\n            print(\" \"*80)\n            time.sleep(2)  # flush interval in 2 seconds\n\nexcept KeyboardInterrupt:\n        # Shutdown SMBus\n\nbus.close()\n        print(\"Quit Demo\")\n\nSave it and execute it by using :\n\npython calculate_power.py\n\nYou will see the result on ternimal: <img src=\"Calculate_power.jpg\" title=\"Calculate_power.jpg\" width=\"800\" alt=\"Calculate_power.jpg\" \/>\n===Explanation of Power Calculation===\n\n-   Reading Voltage and Current:\n\nThe voltage and current values are read from the respective registers in millivolts (mV) and milliamperes (mA).\n\n-   Unit Conversion:\n\nThe voltage is converted from millivolts to volts by dividing by 1000.\nThe current is converted from milliamperes to amperes by dividing by 1000.\n\n-   Power Calculation:\n\nThe power is calculated using the formula:\n\nPower (W)=Voltage (V)×Current (A)\n\nThis ensures that the power is correctly calculated in watts.\n\n-   Output:",
                "char_count": 1063,
                "token_estimate": 266
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to calculate input and output power?",
                "chunk_index": 33,
                "content": "The calculated input and output power values are printed in watts, formatted to two decimal places. This code will continuously read the register values, calculate the input and output power, and print the results every 2 seconds.",
                "char_count": 230,
                "token_estimate": 58
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Modify the configuration on Home assistant",
                "chunk_index": 34,
                "content": "-   Please find the home assistant configuration.yaml file and adding following lines, In my case, I have use a docker container for my home assistant application.\n\n<!-- -->\n\nsudo vim \/opt\/homeassistant\/configuration.yaml\n\nadding:\n\n# Loads default set of integrations. Do not remove.\n\ndefault_config:\n\n# Load frontend themes from the themes folder\n\nfrontend:\n      themes: !include_dir_merge_named themes\n\nautomation: !include automations.yaml\n    script: !include scripts.yaml\n    scene: !include scenes.yaml\n\nmqtt:\n      sensor:\n        - name: \"OUTPUT_VOLTAGE\"\n          state_topic: \"ups_status\/OUTPUT_VOLTAGE\"\n          unit_of_measurement: \"mV\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"OUTPUT_CURRENT\"\n          state_topic: \"ups_status\/OUTPUT_CURRENT\"\n          unit_of_measurement: \"mA\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"INPUT_VOLTAGE\"\n          state_topic: \"ups_status\/INPUT_VOLTAGE\"\n          unit_of_measurement: \"mV\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"BATTERY_VOLTAGE\"\n          state_topic: \"ups_status\/BATTERY_VOLTAGE\"\n          unit_of_measurement: \"mV\"\n          value_template: \"{{ value | int }}\"",
                "char_count": 1173,
                "token_estimate": 294
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Modify the configuration on Home assistant",
                "chunk_index": 35,
                "content": "- name: \"MCU_VOLTAGE\"\n          state_topic: \"ups_status\/MCU_VOLTAGE\"\n          unit_of_measurement: \"mV\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"INPUT_CURRENT\"\n          state_topic: \"ups_status\/INPUT_CURRENT\"\n          unit_of_measurement: \"mA\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"BATTERY_CURRENT\"\n          state_topic: \"ups_status\/BATTERY_CURRENT\"\n          unit_of_measurement: \"mA\"\n          value_template: \"{{ value | int }}\"\n\n- name: \"TEMPERATURE\"\n          state_topic: \"ups_status\/TEMPERATURE\"\n          unit_of_measurement: \"C\"\n          value_template: \"{{ value | int }}\"\n\n-   Restart Home assistant docker\n\n<!-- -->\n\nsudo docker restart $(sudo docker ps -qa)",
                "char_count": 709,
                "token_estimate": 178
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Create a python script on Raspberry Pi",
                "chunk_index": 36,
                "content": "-   filename: send_data_to_mqtt.py， please install paho library first.\n\n<!-- -->\n\nsudo apt -y install python3-paho-mqtt\n\nand then create a python script file and name it 'send_data_to_mqtt.py' with following:\n\nfrom smbus2 import SMBus\n    import time\n    import paho.mqtt.client as mqtt\n\n# MQTT server configure\n\nMQTT_BROKER = \"192.168.3.218\"   # Replace this IP address to your Raspberry Pi's IP address\n\nMQTT_PORT = 1883\n    MQTT_USERNAME = \"jacky\"         # Replace it to your MQTT user's name\n\nMQTT_PASSWORD = \"mypassword\"    # Replace it to your MQTT user's password\n\nMQTT_TOPIC = \"ups_status\"       # define a MQTT topic\n\n# Device address\n\nDEVICE_ADDRESS = 0x17\n\n# init SMBus\n\nbus = SMBus(1)  # 1 means I2C no.1 bus\n\n# init mqtt client\n\nmqtt_client = mqtt.Client()\n    mqtt_client.username_pw_set(MQTT_USERNAME, password=MQTT_PASSWORD)\n\n# connect to mqtt server\n\ndef connect_mqtt():\n        try:\n            mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)\n            print(f\"{GREEN}Connected to MQTT Broker at {MQTT_BROKER}:{MQTT_PORT}{END_COLOR}\")\n        except Exception as e:\n            print(f\"{RED}Failed to connect to MQTT Broker: {e}{END_COLOR}\")\n            exit(1)",
                "char_count": 1182,
                "token_estimate": 296
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Create a python script on Raspberry Pi",
                "chunk_index": 37,
                "content": "# Define registers address\n\n# WHO_AM_I_REG = 0x00 \/\/ will always be 0xA6\n\nVERSION_REG = 0x01\n    UID0_REG = 0x02\n    UID1_REG = 0x06\n    UID2_REG = 0x0A\n    OUTPUT_VOLTAGE_REG = 0x0E\n    INPUT_VOLTAGE_REG = 0x10\n    BATTERY_VOLTAGE_REG = 0x12\n    MCU_VOLTAGE_REG = 0x14\n    OUTPUT_CURRENT_REG = 0x16\n    INPUT_CURRENT_REG = 0x18\n    BATTERY_CURRENT_REG = 0x1A\n    TEMPERATURE_REG = 0x1C\n\n# Define ANSI color\n\nRED = '\\033[95m'\n    GREEN = '\\033[92m'\n    END_COLOR = '\\033[0m'\n\n# read 8bit register\n\ndef read_byte_register(register_address):\n        value = bus.read_byte_data(DEVICE_ADDRESS, register_address)\n        if value > 127:\n            value -= 256\n        return value\n\n# read 16bit register\n\ndef read_word_register(register_address):\n        value = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        if value > 32767:\n            value -= 65536\n        return value\n\n# read 32bit register\n\ndef read_dword_register(register_address):\n        low = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        high = bus.read_word_data(DEVICE_ADDRESS, register_address + 2)\n        return (high << 16) | low\n\n# read all registers data",
                "char_count": 1154,
                "token_estimate": 289
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Create a python script on Raspberry Pi",
                "chunk_index": 38,
                "content": "def read_all_registers():\n        registers = {\n            \"WHO_AM_I\": \"0xA6\",\n            \"VERSION\": read_byte_register(VERSION_REG),\n            \"UID0\": read_dword_register(UID0_REG),\n            \"UID1\": read_dword_register(UID1_REG),\n            \"UID2\": read_dword_register(UID2_REG),\n            \"OUTPUT_VOLTAGE\": read_word_register(OUTPUT_VOLTAGE_REG),\n            \"INPUT_VOLTAGE\": read_word_register(INPUT_VOLTAGE_REG),\n            \"BATTERY_VOLTAGE\": read_word_register(BATTERY_VOLTAGE_REG),\n            \"MCU_VOLTAGE\": read_word_register(MCU_VOLTAGE_REG),\n            \"OUTPUT_CURRENT\": read_word_register(OUTPUT_CURRENT_REG),\n            \"INPUT_CURRENT\": read_word_register(INPUT_CURRENT_REG),\n            \"BATTERY_CURRENT\": read_word_register(BATTERY_CURRENT_REG),\n            \"TEMPERATURE\": read_byte_register(TEMPERATURE_REG)\n        }\n        return registers\n\n# send data to MQTT server",
                "char_count": 898,
                "token_estimate": 225
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Create a python script on Raspberry Pi",
                "chunk_index": 39,
                "content": "def send_data_to_mqtt(data):\n        try:\n            for key, value in data.items():\n                if key in [\"OUTPUT_VOLTAGE\", \"INPUT_VOLTAGE\", \"BATTERY_VOLTAGE\", \"MCU_VOLTAGE\"]:\n                    mqtt_client.publish(f\"{MQTT_TOPIC}\/{key}\", value)\n                elif key in [\"OUTPUT_CURRENT\", \"INPUT_CURRENT\", \"BATTERY_CURRENT\"]:\n                    mqtt_client.publish(f\"{MQTT_TOPIC}\/{key}\", value)\n                elif key == \"TEMPERATURE\":\n                    mqtt_client.publish(f\"{MQTT_TOPIC}\/{key}\", value)\n            print(f\"{GREEN}Data sent to MQTT topic {MQTT_TOPIC}:{data}{END_COLOR}\")\n        except Exception as e:\n            print(f\"{RED}Failed to send data to MQTT broker:{e}{END_COLOR}\")\n\n# main loop\n\ndef main():\n        connect_mqtt()\n        mqtt_client.loop_start()  # start mqtt loop",
                "char_count": 812,
                "token_estimate": 203
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to send the UPS Gen 6's data to Home assistant > Create a python script on Raspberry Pi",
                "chunk_index": 40,
                "content": "try:\n            while True:\n                print(f\"{RED}===52Pi UPS v6 Raw data output ==={END_COLOR}\")\n                registers = read_all_registers()\n                send_data_to_mqtt(registers)\n                time.sleep(2)\n        except KeyboardInterrupt:\n            bus.close()\n            mqtt_client.loop_stop()\n            mqtt_client.disconnect()\n            print(\"Quit Demo\")\n\nif  == \"\":\n        main()\n\nand then execute the python script:\n\npython send_data_to_mqtt.py\n\n<img src=\"Send_data_to_mqtt.jpg\" title=\"Send_data_to_mqtt.jpg\" width=\"800\" alt=\"Send_data_to_mqtt.jpg\" \/>\n\n-   Adding Card in Home assistant\n\n<img src=\"Adding_card_to_HA.jpg\" title=\"Adding_card_to_HA.jpg\" width=\"800\" alt=\"Adding_card_to_HA.jpg\" \/>\n\n-   Finally result\n\n<img src=\"Result_of_ha.jpg\" title=\"Result_of_ha.jpg\" width=\"800\" alt=\"Result_of_ha.jpg\" \/>",
                "char_count": 845,
                "token_estimate": 212
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown",
                "chunk_index": 41,
                "content": "Here is the modified code, rewritten as a systemd service to monitor only the battery voltage and current. When the battery voltage drops below 7400mV, it triggers a shutdown operation. The monitoring interval is set to check every 2 minutes.\n\n-   Python Code (demo)\n\n<!-- -->\n\n#!\/usr\/bin\/env python3\n    \"\"\"\n    This script monitors the battery voltage and current of a 52Pi UPS V6 device.\n    If the battery voltage drops below 7400mV, it triggers a shutdown process.\n    \"\"\"\n\nfrom smbus2 import SMBus\n    import time\n    import subprocess\n    import logging\n\n#define log file path\n    LOG_FILE = \"\/var\/log\/battery_monitor.log\"\n\n# configure logging settings\n\nlogging.basicConfig(filename=LOG_FILE, level=logging.INFO, format='%(asctime)s - %(message)s')\n\n# Device address\n\nDEVICE_ADDRESS = 0x17\n\n# Define registers address\n\nBATTERY_VOLTAGE_REG = 0x12\n    BATTERY_CURRENT_REG = 0x1A\n\n# Threshold for battery voltage\n\nBATTERY_VOLTAGE_THRESHOLD = 7400  # in mV\n\n# Shutdown command\n\nSHUTDOWN_COMMAND = \"sudo sync ; sudo init 0\"\n\n# Initialize SMBus\n\nbus = SMBus(1)  # 1 means I2C no.1 bus\n\n# Read 16-bit register",
                "char_count": 1109,
                "token_estimate": 278
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown",
                "chunk_index": 42,
                "content": "def read_word_register(register_address):\n        \"\"\"\n        Read a 16-bit register from the device.\n        \"\"\"\n        value = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        if value > 32767:\n            value -= 65536\n        return value\n\n# Read battery voltage and current\n\ndef read_battery_status():\n        \"\"\"\n        Read the battery voltage and current from the device.\n        \"\"\"\n        battery_voltage = read_word_register(BATTERY_VOLTAGE_REG)\n        battery_current = read_word_register(BATTERY_CURRENT_REG)\n        return battery_voltage, battery_current\n\n# Check battery status and trigger shutdown if necessary\n\ndef check_battery_status():\n        \"\"\"\n        Check the battery status and trigger shutdown if the voltage is below the threshold.\n        \"\"\"\n        battery_voltage, battery_current = read_battery_status()\n        logging.info(f\"Battery Voltage: {battery_voltage}mV, Current: {battery_current}mA.\")",
                "char_count": 948,
                "token_estimate": 237
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown",
                "chunk_index": 43,
                "content": "if battery_voltage < BATTERY_VOLTAGE_THRESHOLD:\n            logging.info(f\"Battery voltage is below {BATTERY_VOLTAGE_THRESHOLD}mV. Initiating shutdown.\")\n            logging.info(f\"Battery voltage is below {BATTERY_VOLTAGE_THRESHOLD}mV. Initiating shutdown.\")\n            subprocess.run(SHUTDOWN_COMMAND, shell=True)\n\n# Main loop\n\ndef main():\n        \"\"\"\n        Main loop to periodically check the battery status.\n        \"\"\"\n        try:\n            while True:\n                check_battery_status()\n                time.sleep(120)  # Check every 2 minutes\n\nexcept KeyboardInterrupt:\n            print(\"Exiting battery monitor script.\")\n        finally:\n            bus.close()\n\nif  == \"\":\n        main()\n\nPlease save it and name it as 'battery_monitory.py' and put it to your own location. in this case, the file location is \\`\/home\/pi\/upsv6_pub\/script\/tools\/python_demo\/battery_monitor.py\\`.",
                "char_count": 896,
                "token_estimate": 224
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Code Explanation",
                "chunk_index": 44,
                "content": "-   Optimization:\n\n``   - Removed unnecessary `read_byte_register` and `read_dword_register` functions, as only the battery voltage and current are monitored, both of which are 16-bit registers. ``\n``   - Removed the redundant `read_all_registers` function and directly read the battery voltage and current in `check_battery_status`. ``\n`  - Removed excess print statements, retaining only those for battery voltage and current.`\n\n-   Monitoring Logic:\n\n`  - Checks the battery voltage and current every 2 minutes.`\n``   - If the battery voltage falls below 7400mV, it calls `subprocess.run` to execute the shutdown command. ``\n\n-   Comments:\n\n`  - Added detailed English comments to explain the purpose of each function and the main logic.`",
                "char_count": 741,
                "token_estimate": 186
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Creating a systemd Service",
                "chunk_index": 45,
                "content": "To run this script as a systemd service, you need to create a systemd service file.\n\n-   Create the Service File:\n\n``   Create a service file in the `\/etc\/systemd\/system\/` directory, for example, `battery_monitor.service`. ``\n\n       sudo nano \/etc\/systemd\/system\/battery_monitor.service\n\n-   Edit the Service File:\n\n`  Add the following content to the file:`\n\n       [Unit]\n       Description=Battery Monitor Service\n       After=network.target\n\n       [Service]\n       ExecStart=\/usr\/bin\/python3 \/path\/to\/your\/script\/battery_monitor.py   # Do remember replace this path to your own battery_monitor.py file's location.\n\n       Restart=always\n       User=pi\n\n       [Install]\n       WantedBy=multi-user.target\n\n``   - `ExecStart` specifies the path to the script. ``\n``   - `Restart=always` ensures the service restarts automatically if it fails. ``\n``   - `User=pi` specifies that the script runs as the `pi` user. ``",
                "char_count": 918,
                "token_estimate": 230
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Create log file and grant permissions",
                "chunk_index": 46,
                "content": "sudo touch \/var\/log\/battery_monitor.log\n    sudo chown pi:pi \/var\/log\/battery_monitor.log\n    sudo chmod 664 \/var\/log\/battery_monitor.log",
                "char_count": 137,
                "token_estimate": 35
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Start the Service",
                "chunk_index": 47,
                "content": "`  After saving the file, run the following commands to start the service and enable it to start on boot:`\n\n       sudo systemctl daemon-reload\n       sudo systemctl enable battery_monitor.service\n       sudo systemctl start battery_monitor.service",
                "char_count": 248,
                "token_estimate": 62
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Check Service Status",
                "chunk_index": 48,
                "content": "`  Use the following command to check the service status:`\n\n       sudo systemctl status battery_monitor.service\n\nWith this setup, the script will run as a systemd service, checking the battery voltage and current every 2 minutes and triggering a shutdown operation when the voltage falls below 7400mV.",
                "char_count": 302,
                "token_estimate": 76
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot the power status by using matplotlib",
                "chunk_index": 49,
                "content": "Here is the detailed step-by-step guide and code example in English to create a real-time dynamic plot using matplotlib to display input and output power.\n\n-   Step 1: Install Necessary Libraries\n\nEnsure you have the smbus2 and matplotlib libraries installed. If not, you can install them using the following command:\n\nsudo apt update\n    sudo apt -y install python3-smbus2 python3-matplotlib python3-numpy\n\n-   Step 2: Write the Code\n\nHere is the complete code example that reads input and output power in real-time and uses matplotlib to dynamically display these values.\n\nfrom smbus2 import SMBus\n    import time\n    import matplotlib.pyplot as plt\n    import matplotlib.animation as animation\n    import numpy as np\n\n# Device address\n\nDEVICE_ADDRESS = 0x17\n\n# Define registers address\n\nVERSION_REG = 0x01\n    OUTPUT_VOLTAGE_REG = 0x0E\n    INPUT_VOLTAGE_REG = 0x10\n    OUTPUT_CURRENT_REG = 0x16\n    INPUT_CURRENT_REG = 0x18\n\n# Initialize SMBus\n\nbus = SMBus(1)  # 1 means I2C no.1 bus\n\n# Read 16-bit register\n\ndef read_word_register(register_address):\n        value = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        if value > 32767:\n            value -= 65536\n        return value",
                "char_count": 1196,
                "token_estimate": 299
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot the power status by using matplotlib",
                "chunk_index": 50,
                "content": "# Calculate power\n\ndef calculate_power(voltage_mv, current_ma):\n        voltage_v = voltage_mv \/ 1000.0\n        current_a = current_ma \/ 1000.0\n        return voltage_v * current_a  # Result in watts\n\n# Initialize lists to store data\n\ninput_power_data = []\n    output_power_data = []\n    time_data = []\n\n# Initialize time\n\nstart_time = time.time()\n\n# Function to update the plot\n\ndef update(frame):\n        global start_time\n\n# Read voltage and current values\n\ninput_voltage_mv = read_word_register(INPUT_VOLTAGE_REG)\n        input_current_ma = read_word_register(INPUT_CURRENT_REG)\n        output_voltage_mv = read_word_register(OUTPUT_VOLTAGE_REG)\n        output_current_ma = read_word_register(OUTPUT_CURRENT_REG)\n\n# Calculate input and output power\n\ninput_power_w = calculate_power(input_voltage_mv, input_current_ma)\n        output_power_w = calculate_power(output_voltage_mv, output_current_ma)\n\n# Append data\n\ncurrent_time = time.time() - start_time\n        time_data.append(current_time)\n        input_power_data.append(input_power_w)\n        output_power_data.append(output_power_w)\n\n# Limit the data to the last 100 points",
                "char_count": 1132,
                "token_estimate": 283
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot the power status by using matplotlib",
                "chunk_index": 51,
                "content": "if len(time_data) > 100:\n            time_data.pop(0)\n            input_power_data.pop(0)\n            output_power_data.pop(0)\n\n# Clear the previous plot\n\nax.clear()\n\n# Plot input power\n\nax.plot(time_data, input_power_data, label='Input Power (W)', color='blue')\n        ax.set_ylabel('Power (W)')\n        ax.set_xlabel('Time (s)')\n        ax.legend(loc='upper left')\n\n# Plot output power\n\nax.plot(time_data, output_power_data, label='Output Power (W)', color='red')\n        ax.legend(loc='upper left')\n\n# Set title\n\nax.set_title('Real-time Input and Output Power')\n\n# Create a figure and axis\n\nfig, ax = plt.subplots()\n\n# Create the animation\n\nani = animation.FuncAnimation(fig, update, interval=2000)  # Update every 2 seconds\n\n# Show the plot\n\nplt.show()\n\nSave it as \\`plot_power.py\\`, or just find it in the repository of \\`upsv6_pub\\` on GitHub.\n\n-   Execute it:\n\n<!-- -->\n\npython plot_power.py\n\nIt will plot the input and output power status in animation. <img src=\"Plot_power.jpg\" title=\"Plot_power.jpg\" width=\"800\" alt=\"Plot_power.jpg\" \/>",
                "char_count": 1046,
                "token_estimate": 262
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Explanation of the Code",
                "chunk_index": 52,
                "content": "-   Initialize SMBus and Register Addresses:\n\nThe smbus2 library is used to initialize the I2C bus, and the register addresses for reading voltage and current values are defined.\n\n-   Read Register Values:\n\nThe read_word_register function reads 16-bit values from the specified registers.\n\n-   Calculate Power:\n\nThe calculate_power function converts millivolts (mV) to volts (V) and milliamperes (mA) to amperes (A), then calculates the power in watts.\n\n-   Store Data:\n\nLists input_power_data, output_power_data, and time_data are used to store the power values and corresponding time stamps.\n\n-   Dynamic Plot Update:\n\nThe matplotlib.animation.FuncAnimation function is used to create a dynamic plot that updates every 2 seconds. The update function reads the latest power values, appends them to the data lists, and updates the plot.\n\n-   Limit Data Points:\n\nTo prevent performance issues with too much data, the lists are limited to the last 100 data points.\n\n-   Display the Plot:\n\nThe plot is displayed using plt.show(), showing real-time updates of input and output power.\n\n-   Running the Code",
                "char_count": 1101,
                "token_estimate": 276
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Explanation of the Code",
                "chunk_index": 53,
                "content": "When you run the code, you will see a dynamic plot that updates every 2 seconds, showing the real-time changes in input and output power. The plot will display the last 100 data points for both input and output power.\n\n-   If external power is failed, you will see some picture like this:\n\n<img src=\"Plot_power01.jpg\" title=\"Plot_power01.jpg\" width=\"800\" alt=\"Plot_power01.jpg\" \/>",
                "char_count": 380,
                "token_estimate": 95
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot input and output power by using pygame",
                "chunk_index": 54,
                "content": "-   Create a python file named: \\`plot_power_pygame.py\\`\n\n<!-- -->\n\nvim plot_power_pygame.py\n\n-   Copy and paste following demo code:\n\n<!-- -->\n\nimport pygame\n    import sys\n    from smbus2 import SMBus\n    import math\n    import time\n\n# Device address\n\nDEVICE_ADDRESS = 0x17\n\n# Define registers address\n\nVERSION_REG = 0x01\n    OUTPUT_VOLTAGE_REG = 0x0E\n    INPUT_VOLTAGE_REG = 0x10\n    OUTPUT_CURRENT_REG = 0x16\n    INPUT_CURRENT_REG = 0x18\n\n# Initialize SMBus\n\nbus = SMBus(1)  # 1 means I2C no.1 bus\n\n# Read 16-bit register\n\ndef read_word_register(register_address):\n        value = bus.read_word_data(DEVICE_ADDRESS, register_address)\n        if value > 32767:\n            value -= 65536\n        return value\n\n# Calculate power\n\ndef calculate_power(voltage_mv, current_ma):\n        voltage_v = voltage_mv \/ 1000.0\n        current_a = current_ma \/ 1000.0\n        return voltage_v * current_a  # Result in watts\n\n# Initialize Pygame\n\npygame.init()\n\n# Set up the display\n\nscreen = pygame.display.set_mode((800, 400))\n    pygame.display.set_caption(\"Power Gauges\")\n\n# Define colors\n\nBLACK = (0, 0, 0)\n    CYAN = (0, 255, 255)\n    RED = (255, 0, 0)\n\n# Draw the gauge background",
                "char_count": 1175,
                "token_estimate": 294
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot input and output power by using pygame",
                "chunk_index": 55,
                "content": "def draw_gauge_background(x_offset, title):\n        pygame.draw.circle(screen, CYAN, (200 + x_offset, 200), 130, 2)\n        max_power = 30  # Maximum power is 30W for the gauge\n\nnum_ticks = int(max_power \/ 0.5)  # Number of ticks\n\nfor i in range(num_ticks + 1):\n            angle = math.radians(270 - (i \/ num_ticks * 180))  # 0 point at the bottom\n\nx1 = 200 + 120 * math.cos(angle) + x_offset\n            y1 = 200 + 120 * math.sin(angle)\n            x2 = 200 + 124 * math.cos(angle) + x_offset\n            y2 = 200 + 124 * math.sin(angle)\n            pygame.draw.line(screen, CYAN, (x1, y1), (x2, y2), 1)\n            if i % 5 == 0:  # Only display every 5th tick\n\nfont = pygame.font.SysFont(None, 16)\n                img = font.render(f\"{i * 0.5:.1f}\", True, CYAN)\n                text_width, text_height = font.size(f\"{i * 0.5:.1f}\")\n                text_x = 200 + (135 + 3) * math.cos(angle) + x_offset - text_width \/ 2\n                text_y = 200 + (135 + 3) * math.sin(angle) - text_height \/ 2\n                screen.blit(img, (text_x, text_y))\n\n# Draw title",
                "char_count": 1064,
                "token_estimate": 266
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot input and output power by using pygame",
                "chunk_index": 56,
                "content": "font = pygame.font.SysFont(None, 24)\n        img = font.render(title, True, CYAN)\n        screen.blit(img, (200 + x_offset - img.get_width() \/ 2, 10))\n\n# Draw the needle\n\ndef draw_needle(x_offset, power):\n        max_power = 30  # Maximum power is 100W for the gauge\n\nangle = 270 - (power \/ max_power * 180)  # 0 point at the bottom\n\nangle_rad = math.radians(angle)\n        x = 200 + 120 * math.cos(angle_rad) + x_offset\n        y = 200 + 120 * math.sin(angle_rad)\n        pygame.draw.line(screen, RED, (200 + x_offset, 200), (x, y), 2)\n\n# Main loop\n\ndef main():\n        clock = pygame.time.Clock()\n        while True:\n            for event in pygame.event.get():\n                if event.type == pygame.QUIT:\n                    pygame.quit()\n                    sys.exit()\n\n# Read power values\n\ninput_voltage_mv = read_word_register(INPUT_VOLTAGE_REG)\n            input_current_ma = read_word_register(INPUT_CURRENT_REG)\n            input_power_w = calculate_power(input_voltage_mv, input_current_ma)",
                "char_count": 1002,
                "token_estimate": 251
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > How to plot input and output power by using pygame",
                "chunk_index": 57,
                "content": "output_voltage_mv = read_word_register(OUTPUT_VOLTAGE_REG)\n            output_current_ma = read_word_register(OUTPUT_CURRENT_REG)\n            output_power_w = calculate_power(output_voltage_mv, output_current_ma)\n\n# Update the gauges\n\nscreen.fill(BLACK)\n            draw_gauge_background(0, \"INPUT\")\n            draw_gauge_background(400, \"OUTPUT\")\n            draw_needle(0, input_power_w)\n            draw_needle(400, output_power_w)\n            pygame.display.flip()\n            clock.tick(0.5)  # Update every 2 seconds\n\nif  == \"\":\n        main()\n\n-   Save it and execute it.\n\n<!-- -->\n\npython plot_power_pygame.py",
                "char_count": 618,
                "token_estimate": 155
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Demostration",
                "chunk_index": 58,
                "content": "-   Gaugue Figure\n\n<img src=\"Plot_power_pygame.jpg\" title=\"Plot_power_pygame.jpg\" width=\"800\" alt=\"Plot_power_pygame.jpg\" \/>\n===Explaination of demo code===\n\n-   Implementation Explanation\n\nThis code is designed to create a graphical user interface (GUI) using Pygame to display power gauges for input and output power readings from a device connected via I2C. The gauges are represented as circular meters with needles that move based on the power values read from the device. The code also includes titles for each gauge (\"INPUT\" and \"OUTPUT\") and evenly spaced tick marks with numerical labels.\n\n#### Key Components and Logic",
                "char_count": 628,
                "token_estimate": 157
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Demostration",
                "chunk_index": 59,
                "content": "-   I2C Communication: The code uses the smbus2 library to communicate with an I2C device at address 0x17. Functions like read_word_register are used to read 16-bit values from specific registers on the device, which correspond to input and output voltage and current readings.\n-   Power Calculation: The calculate_power function converts the raw voltage and current readings from millivolts and milliamps to volts and amps, respectively, and then calculates the power in watts.\n-   Pygame Initialization: Pygame is initialized to create a window with a size of 800x400 pixels. Colors for the background, tick marks, and needle are defined.\n-   Gauge Background Drawing:\n\nThe draw_gauge_background function draws the circular gauge, including:\n\n1. A circle representing the gauge outline.\n    2. Tick marks spaced evenly around the gauge. The tick marks are spaced based on a maximum power value of 30W, with each tick representing 0.5W.\n    3. Numerical labels for every 5th tick mark, positioned slightly outside the gauge to avoid overlap.\n    4. A title (\"INPUT\" or \"OUTPUT\") displayed above each gauge.",
                "char_count": 1107,
                "token_estimate": 277
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Demostration",
                "chunk_index": 60,
                "content": "-   Needle Drawing: The draw_needle function calculates the angle of the needle based on the power value and draws it on the gauge. The angle is adjusted so that 0W corresponds to the bottom of the gauge.\n-   Main Loop: The main function contains the main loop of the program:\n\n<!-- -->\n\n1. It reads the power values from the I2C device.\n    2. It updates the gauges by clearing the screen, redrawing the gauge backgrounds, and drawing the needles based on the current power values.\n    3. It updates the display and limits the refresh rate to once every 2 seconds.",
                "char_count": 565,
                "token_estimate": 142
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "How to monitor battery and safe shutdown > Features and Enhancements",
                "chunk_index": 61,
                "content": "-   Tick Marks and Labels: The tick marks are evenly spaced around the gauge, and labels are added to indicate power values in watts. The labels are positioned slightly outside the gauge to ensure they are readable.\n-   Titles: Each gauge has a title (\"INPUT\" and \"OUTPUT\") to distinguish between the two power readings.\n-   Needle Positioning: The needle's position is calculated based on the power value, with 0W starting at the bottom of the gauge and increasing clockwise.\n-   This implementation provides a clear and visually intuitive way to monitor input and output power readings from an I2C device in real-time.",
                "char_count": 620,
                "token_estimate": 155
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Model and Structure file download",
                "chunk_index": 62,
                "content": "-   STEP File: [File:UPS Gen6 STEP file.zip](File:UPS_Gen6_STEP_file.zip \"wikilink\")\n-   STP structure File: [File:UPS Gen6 STP StructureFile.zip](File:UPS_Gen6_STP_StructureFile.zip \"wikilink\")",
                "char_count": 194,
                "token_estimate": 49
            },
            {
                "title": "EP-0245",
                "rev_id": 16196,
                "heading_path": "Model and Structure file download > More information",
                "chunk_index": 63,
                "content": "-   Please visit: \\[ <https:\/\/github.com\/geeekpi\/upsv6_pub\/> \\]",
                "char_count": 63,
                "token_estimate": 16
            }
        ]
    }
}