Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct voltage and battery capacity for Opti-UPS 230VAC and/or 24VDC models #2089

Merged
merged 7 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution.
- The `bestfortress` driver shutdown handling was fixed to use a non-trivial
default timeout [#1820]

- The `optiups` driver only gave accurate voltage information with 120VAC
models and assumed a 12V battery when calculating capacity. There is
a protocol command that gives a (fixed) voltage which correlates with
the voltage selection DIP switches on the back of the UPS, taking into
account whether it is a 120 or 240VAC model. Likewise, now the battery
capacity fix is applied globally, based on whether or not the battery
voltage is greater than 20V. [#2089]

- GPIO drivers [#1855]:
* Added a new category of drivers, using GPIO interface to locally connected
devices (currently limited to 2018+ Linux libgpiod, but its architecture
Expand Down
1 change: 1 addition & 0 deletions data/driver.list.in
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@
"Opti-UPS" "ups" "1" "PowerES" "420E" "optiups"
"Opti-UPS" "ups" "1" "VS 575C" "type=OPTI" "powercom"
"Opti-UPS" "ups" "1" "Power Series" "PS1500E" "blazer_usb"
"Opti-UPS" "ups" "1" "Power Series" "PS1440RM" "optiups"

"Orvaldi Power Protection" "ups" "2" "various" "not 400 or 600" "blazer_ser"
"Orvaldi Power Protection" "ups" "2" "750 / 900SP" "USB" "blazer_usb"
Expand Down
60 changes: 56 additions & 4 deletions drivers/optiups.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "nut_stdint.h"

#define DRIVER_NAME "Opti-UPS driver"
#define DRIVER_VERSION "1.03"
#define DRIVER_VERSION "1.04"

/* driver description structure */
upsdrv_info_t upsdrv_info = {
Expand Down Expand Up @@ -83,7 +83,8 @@ static char _buf[256];
static int optimodel = 0;
enum {
OPTIMODEL_DEFAULT = 0,
OPTIMODEL_ZINTO = 1
OPTIMODEL_ZINTO = 1,
OPTIMODEL_PS = 2
};


Expand Down Expand Up @@ -123,6 +124,19 @@ static ezfill_t _pollv_zinto[] = {
{ "BT", "ups.temperature", 0 },
};

/* When on a 220-2400V mains supply, the NV and OV commands return 115V values. FV
* returns a value that matches the DIP switch settings for 120/240V models, so
* it can be used to scale the valus from NV and OV.
*
* I suspect this will be the case for other Opti-UPS models, but as I can only
* test with a PS-1440RM at 230V the change is only applied to PowerSeries models.
*/
static ezfill_t _pollv_ps[] = {
{ "OL", "ups.load", 1.0 },
{ "FF", "input.frequency", 0.1 },
{ "BT", "ups.temperature", 0 },
};

/* model "IO" is parsed differently in upsdrv_initinfo() */
static ezfill_t _initv[] = {
{ "IM", "ups.mfr", 0 },
Expand Down Expand Up @@ -347,6 +361,13 @@ void upsdrv_initinfo(void)
optiquery( "ON" );
}

/* Autodetect an Opti-UPS PS series */
r = optiquery( "IO" );
if ( r > 0 && !strncasecmp(_buf, "PS-", 3) )
{
optimodel = OPTIMODEL_PS;
}

optifill( _initv, sizeof(_initv)/sizeof(_initv[0]) );

/* Parse out model into longer string -- is this really USEFUL??? */
Expand Down Expand Up @@ -463,6 +484,29 @@ void upsdrv_updateinfo(void)
/* read some easy settings */
if ( optimodel == OPTIMODEL_ZINTO )
optifill( _pollv_zinto, sizeof(_pollv_zinto)/sizeof(_pollv_zinto[0]) );
else if ( optimodel == OPTIMODEL_PS ) {
short inV, outV, fV;

optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) );

r = optiquery( "NV" );
str_to_short ( _buf, &inV, 10 );
r = optiquery( "OV" );
str_to_short ( _buf, &outV, 10 );

r = optiquery( "FV" );
if ( r >= 1 )
{
str_to_short ( _buf, &fV, 10 );
if ( fV > 180 )
{
inV = inV * 2;
outV = outV * 2;
}
}
dstate_setinfo( "input.voltage", "%d", inV );
dstate_setinfo( "output.voltage", "%d", outV );
}
else
optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) );

Expand All @@ -475,8 +519,16 @@ void upsdrv_updateinfo(void)
float p, v = strtol( _buf, NULL, 10 ) / 10.0;
dstate_setinfo("battery.voltage", "%.1f", v );

/* battery voltage range: 10.4 - 13.0 VDC */
p = ((v - 10.4) / 2.6) * 100.0;
if (v > 20)
{
/* battery voltage range: 20.8 - 26.0 VDC */
p = ((v - 20.8) / 5.2) * 100.0;
}
else
{
/* battery voltage range: 10.4 - 13.0 VDC */
p = ((v - 10.4) / 2.6) * 100.0;
}
if ( p > 100.0 )
p = 100.0;
dstate_setinfo("battery.charge", "%.1f", p );
Expand Down