Monitor status of DC1018P DC UPS

Hi, I recently purchased the DC UPS (some OEM with model: DC1018P) for my wifi router.
I would like to monitor this DC UPS with home assistant and ESP32
Interestingly, I found there are 2 ports on the DC UPS PCB for external interfacing.
1 port with SWD label which I believe it is for debugging purpose?
another port with 9 pin port without label. (it has marking from pin 1 to 9 in sequence start with R, G, 100, C75, W50, D25, KEY, 3V3, GND)

Does anyone could suggest any possible to monitor this DC UPS with serial communication to ESP32?

Photo as below.

1 Like

Might be possible, but unlikely worth of time needed to find serial connection and reverse engineer communication protocol. What you need to monitor?

Hi Karosm, I would like to monitor the battery voltage, current and UPS power status

Ok, further to the invetigation, found that the 9 pin port is actually for external communication with the UPS.

It will be useful for others as belwo references.

R= main power supply unavailable to UPS. (signal is active low)
G= main power supply available to UPS. (signal is active low)
100= steady: battery is 100% and discharging, bliking: battery is charging and reach between 76%-99%. (signal is active low)
C75= steady: battery is 75% and discharging, blinking: battery is charging and reach between 51%-75%. (signal is active low)
W50= steady: battery is 50% and discharging, blinking: battery is charging and reach between 26%-50%. (signal is active low)
D25= steady: battery is 25% and discharging, blinking: battery is charging and reach between 0%-25%. (signal is active low)
KEY= Has pull up resistor to source (4.8V while UPS ON, 7V while UPS OFF). Make connection between KEY pin and GND pin for more than 3 sec for power ON or OFF the UPS.
3V3= it is actually 5V DC supply!! for external controller.
GND= ground

1 Like

Nice job! And no serial needed.

Hey @westwoon did you integrate this UPS to the Home Assistant? I spent a few days trying to read the device status via wemos d1 mini gpio’s, but no luck still…

Sorry, I yet had time to integrate to HA. Plan to do it sometime in next week.

Hi @busha , I found out the 3V3 pin is actually with 5V supply!! (the 3V3 marking is so misleading). All signal from the 9 pin port are with 5V. So we need 6 channel logic level shifter for R,G, 100, C75, W50, D25.
Further checking on the KEY pin, it is actually with pull up resistor to the source. However, the voltage measured is 4.8V while UPS ON, and 7V while UPS OFF.

wire jumper the KEY pin and GND pin for more than 3 sec to power ON or OFF the UPS.

Hey @westwoon ! It seems so that voltage may differ from UPS to UPS :slight_smile:
I already finished integrating it to the HA, as well, and can confirm that on my device logic is 3.3v as marked on the PCB.

Overall code is pretty simple:

binary_sensor:
  - platform: gpio
    pin: GPIO16 
    name: "UPS External Power"
    device_class: power
    id: external_power
    filters:
      - delayed_on: 500ms
      - delayed_off: 500ms
    on_press:
      then:
        - logger.log: "External power connected"
        - homeassistant.event:
            event: esphome.ups_power_restored
            data:
              source: ups_monitor
    on_release:
      then:
        - logger.log: "External power disconnected"
        - homeassistant.event:
            event: esphome.ups_power_lost
            data:
              source: ups_monitor

  - platform: gpio
    pin: GPIO14
    name: "UPS Battery 25%"
    id: battery_25
    filters:
      - delayed_on: 2s
      - delayed_off: 2s
    on_press:
      then:
        - logger.log: "Battery 25 activated"
    on_release:
      then:
        - logger.log: "Battery 25 deactivated"

text_sensor:
  - platform: template
    name: "UPS Status Text"
    icon: "mdi:ups"
    update_interval: 10s
    lambda: |-
      if (id(external_power).state) {
        return {"On external power"};
      } else {
        char buffer[32];
        sprintf(buffer, "On battery");
        return {buffer};
      }
2 Likes

Finally, I have integrated it into HA as well.

My overall code as below. I’m new in ESPhome, so I got reference from @busha code above.
Sensor

sensor:
### Battery level check ###
#Battery-100 input
  - platform: duty_cycle
    id: battery_100
    pin: 
      number: GPIO40
      mode: INPUT_PULLUP
      inverted: true
    internal: true
    update_interval: 2s

#Battery-75 input
  - platform: duty_cycle
    id: battery_75
    pin: 
      number: GPIO38
      mode: INPUT_PULLUP
      inverted: true
    internal: true
    update_interval: 2s

#Battery-50 input
  - platform: duty_cycle
    id: battery_50
    pin: 
      number: GPIO21
      mode: INPUT_PULLUP
      inverted: true
    internal: true
    update_interval: 2s

#Battery-25 input
  - platform: duty_cycle
    id: battery_25
    pin: 
      number: GPIO17
      mode: INPUT_PULLUP
      inverted: true
    internal: true
    update_interval: 2s

### Battery level status ###
  - platform: template
    name: "Battery"
    filters:
      - debounce: 0.5s
    lambda: |-
      if (id(battery_100).state > 75) {
        return 100.0;
      } else if ((id(battery_100).state < 25) && (id(battery_75).state > 75)) {
        return 75.0;
      } else if ((id(battery_75).state < 25) && (id(battery_50).state > 75)) {
        return 50.0;
      } else if ((id(battery_50).state < 25) && (id(battery_25).state > 75)) {
        return 25.0;
      } else if ((id(battery_100).state > 25) && (id(battery_100).state < 75))  {
        return 75.0;
      } else if ((id(battery_75).state > 25) && (id(battery_75).state < 75))  {
        return 50.0;
      } else if ((id(battery_50).state > 25) && (id(battery_50).state < 75))  {
        return 25.0;
      } else if ((id(battery_25).state > 25) && (id(battery_25).state < 75))  {
        return 5.0;
      } else {
        return NAN;
      }    
    update_interval: 1.5s
    unit_of_measurement: "%"
    device_class: "battery"
    state_class: "measurement"
    accuracy_decimals: 0


### UPS power supply check input ###
binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO36
      mode: INPUT_PULLUP
      inverted: true
    name: "Power source"
    device_class: power
    id: Power_power
    filters:
      - delayed_on: 0.5s
      - delayed_off: 0.5s
    on_press:
      then:
        - logger.log: "External power disconnected"
        - homeassistant.event:
            event: esphome.ups_power_lost
            data:
              source: ups_monitor
    on_release:
      then:
        - logger.log: "External power connected"
        - homeassistant.event:
            event: esphome.ups_power_restored
            data:
              source: ups_monitor

### Charging status ###
text_sensor:
  - platform: template
    name: "Battery state"
    icon: "mdi:generator-stationary"
    lambda: |-
      if ((id(battery_100).state > 75) && (id(Power_power).state))  {
        return {"Standby"};
      } else if (id(Power_power).state)  {
        return {"Charging"};
      } else if ((id(battery_100).state > 75) && !(id(Power_power).state))  {
        return {"Discharging"};
      } else if ((id(battery_75).state > 75) && !(id(Power_power).state))  {
        return {"Discharging"};
      } else if ((id(battery_50).state > 75) && !(id(Power_power).state))  {
        return {"Discharging"};
      } else if ((id(battery_25).state > 75) && !(id(Power_power).state))  {
        return {"Discharging"};
      } else {
        return {"Standby"};
      }        
    update_interval: 0.5s