Skip to content

Commit 3bf526e

Browse files
authored
Merge pull request #2089 from moonbuggy/master
Correct voltage and battery capacity for Opti-UPS 230VAC and/or 24VDC models
2 parents bfcee3f + 26bf63d commit 3bf526e

3 files changed

Lines changed: 65 additions & 4 deletions

File tree

NEWS.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution.
228228
- The `bestfortress` driver shutdown handling was fixed to use a non-trivial
229229
default timeout [#1820]
230230

231+
- The `optiups` driver only gave accurate voltage information with 120VAC
232+
models and assumed a 12V battery when calculating capacity. There is
233+
a protocol command that gives a (fixed) voltage which correlates with
234+
the voltage selection DIP switches on the back of the UPS, taking into
235+
account whether it is a 120 or 240VAC model. Likewise, now the battery
236+
capacity fix is applied globally, based on whether or not the battery
237+
voltage is greater than 20V. [#2089]
238+
231239
- GPIO drivers [#1855]:
232240
* Added a new category of drivers, using GPIO interface to locally connected
233241
devices (currently limited to 2018+ Linux libgpiod, but its architecture

data/driver.list.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,7 @@
925925
"Opti-UPS" "ups" "1" "PowerES" "420E" "optiups"
926926
"Opti-UPS" "ups" "1" "VS 575C" "type=OPTI" "powercom"
927927
"Opti-UPS" "ups" "1" "Power Series" "PS1500E" "blazer_usb"
928+
"Opti-UPS" "ups" "1" "Power Series" "PS1440RM" "optiups"
928929

929930
"Orvaldi Power Protection" "ups" "2" "various" "not 400 or 600" "blazer_ser"
930931
"Orvaldi Power Protection" "ups" "2" "750 / 900SP" "USB" "blazer_usb"

drivers/optiups.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include "nut_stdint.h"
2929

3030
#define DRIVER_NAME "Opti-UPS driver"
31-
#define DRIVER_VERSION "1.03"
31+
#define DRIVER_VERSION "1.04"
3232

3333
/* driver description structure */
3434
upsdrv_info_t upsdrv_info = {
@@ -83,7 +83,8 @@ static char _buf[256];
8383
static int optimodel = 0;
8484
enum {
8585
OPTIMODEL_DEFAULT = 0,
86-
OPTIMODEL_ZINTO = 1
86+
OPTIMODEL_ZINTO = 1,
87+
OPTIMODEL_PS = 2
8788
};
8889

8990

@@ -123,6 +124,19 @@ static ezfill_t _pollv_zinto[] = {
123124
{ "BT", "ups.temperature", 0 },
124125
};
125126

127+
/* When on a 220-2400V mains supply, the NV and OV commands return 115V values. FV
128+
* returns a value that matches the DIP switch settings for 120/240V models, so
129+
* it can be used to scale the valus from NV and OV.
130+
*
131+
* I suspect this will be the case for other Opti-UPS models, but as I can only
132+
* test with a PS-1440RM at 230V the change is only applied to PowerSeries models.
133+
*/
134+
static ezfill_t _pollv_ps[] = {
135+
{ "OL", "ups.load", 1.0 },
136+
{ "FF", "input.frequency", 0.1 },
137+
{ "BT", "ups.temperature", 0 },
138+
};
139+
126140
/* model "IO" is parsed differently in upsdrv_initinfo() */
127141
static ezfill_t _initv[] = {
128142
{ "IM", "ups.mfr", 0 },
@@ -347,6 +361,13 @@ void upsdrv_initinfo(void)
347361
optiquery( "ON" );
348362
}
349363

364+
/* Autodetect an Opti-UPS PS series */
365+
r = optiquery( "IO" );
366+
if ( r > 0 && !strncasecmp(_buf, "PS-", 3) )
367+
{
368+
optimodel = OPTIMODEL_PS;
369+
}
370+
350371
optifill( _initv, sizeof(_initv)/sizeof(_initv[0]) );
351372

352373
/* Parse out model into longer string -- is this really USEFUL??? */
@@ -463,6 +484,29 @@ void upsdrv_updateinfo(void)
463484
/* read some easy settings */
464485
if ( optimodel == OPTIMODEL_ZINTO )
465486
optifill( _pollv_zinto, sizeof(_pollv_zinto)/sizeof(_pollv_zinto[0]) );
487+
else if ( optimodel == OPTIMODEL_PS ) {
488+
short inV, outV, fV;
489+
490+
optifill( _pollv_ps, sizeof(_pollv_ps)/sizeof(_pollv_ps[0]) );
491+
492+
r = optiquery( "NV" );
493+
str_to_short ( _buf, &inV, 10 );
494+
r = optiquery( "OV" );
495+
str_to_short ( _buf, &outV, 10 );
496+
497+
r = optiquery( "FV" );
498+
if ( r >= 1 )
499+
{
500+
str_to_short ( _buf, &fV, 10 );
501+
if ( fV > 180 )
502+
{
503+
inV = inV * 2;
504+
outV = outV * 2;
505+
}
506+
}
507+
dstate_setinfo( "input.voltage", "%d", inV );
508+
dstate_setinfo( "output.voltage", "%d", outV );
509+
}
466510
else
467511
optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) );
468512

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

478-
/* battery voltage range: 10.4 - 13.0 VDC */
479-
p = ((v - 10.4) / 2.6) * 100.0;
522+
if (v > 20)
523+
{
524+
/* battery voltage range: 20.8 - 26.0 VDC */
525+
p = ((v - 20.8) / 5.2) * 100.0;
526+
}
527+
else
528+
{
529+
/* battery voltage range: 10.4 - 13.0 VDC */
530+
p = ((v - 10.4) / 2.6) * 100.0;
531+
}
480532
if ( p > 100.0 )
481533
p = 100.0;
482534
dstate_setinfo("battery.charge", "%.1f", p );

0 commit comments

Comments
 (0)