nut/drivers/adelsystem_cbi.h
2022-06-29 12:37:36 +02:00

531 lines
17 KiB
C

/* adelsystem_cbi.h - Driver for ADELSYSTEM CB/CBI DC-UPS
*
* Copyright (C)
* 2022 Dimitris Economou <dimitris.s.economou@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* code indentation with tabstop=4
*/
#ifndef ADELSYSTEM_CBI_H
#define ADELSYSTEM_CBI_H
#include <stdint.h>
/* UPS device details */
#define DEVICE_MFR "ADELSYSTEM"
#define DEVICE_TYPE "DC-UPS"
#define DEVICE_MODEL "CBI2801224A"
/* serial access parameters */
#define BAUD_RATE 9600
#define PARITY 'N'
#define DATA_BIT 8
#define STOP_BIT 1
/*
* modbus response and byte timeouts
* us: 1 - 999999
*/
#define MODRESP_TIMEOUT_s 0
#define MODRESP_TIMEOUT_us 200000
#define MODBYTE_TIMEOUT_s 0
#define MODBYTE_TIMEOUT_us 50000
/* modbus access parameters */
#define MODBUS_SLAVE_ID 5
/* number of modbus registers */
#define MODBUS_NUMOF_REGS 98
/* max HOLDING registers */
#define MAX_H_REGS 120
/* start HOLDING register index */
#define H_REG_STARTIDX 0
/* read all regs preprocessor flag */
#ifndef READALL_REGS
#define READALL_REGS 1
#endif
/* number of device models */
#define DEV_NUMOF_MODELS 10
/* shutdown repeat on error */
#define FSD_REPEAT_CNT 3
/* shutdown repeat interval in ms */
#define FSD_REPEAT_INTRV 1500
/* definition of register type */
enum regtype {
COIL = 0,
INPUT_B,
INPUT_R,
HOLDING
};
typedef enum regtype regtype_t;
/* product name info, "device.model" */
struct prodname {
uint16_t val;
char *name;
};
typedef struct prodname prodname_t;
static prodname_t prdnm_i[] = {
{1, "CBI1235A"},
{2, "CBI2420A"},
{3, "CBI4810A"},
{4, "CBI2801224"},
{7, "CBI480W"},
{8, "CB122410A"},
{9, "CB480W"},
{11, "CB12245AJ"},
{12, "CB1235A"},
{13, "CB2420A"},
{14, "CB4810A"}
};
/* charging status info, "battery.charger.status" */
static char *chrgs_i[] = {
"none",
"resting", /* recovering */
"charging", /* bulk */
"charging", /* absorb */
"floating" /* float */
};
struct chrgs {
int state;
char *info;
};
typedef struct chrgs chrgs_t;
/* power management info, "ups.status", "battery.charger.status" */
static char *pwrmng_i[] = {
"backup", /* "OB", "discharging" */
"charging", /* "OL" */
"boost",
"not charging"
};
struct pwrmng {
int state;
char *info;
};
typedef struct pwrmng pwrmng_t;
/* general modbus register value */
struct reg {
union val {
uint16_t ui16;
uint8_t ui8;
} val;
char *strval;
};
typedef struct reg reg_t;
/* general alarm struct */
struct alrm {
int actv; /* active flag */
char *descr; /* description field */
};
typedef struct alrm alrm_t;
/* general alarm array */
struct alrm_ar {
int alrm_c; /* alarm count */
alrm_t *alrm; /* alarm array */
};
typedef struct alrm_ar alrm_ar_t;
/*
* BIT MASKS and VALUES
*/
/* Charging status */
#define CHRG_NONE 0
#define CHRG_RECV 1
#define CHRG_BULK 2
#define CHRG_ABSR 3
#define CHRG_FLOAT 4
/* power management */
#define PMNG_BCKUP 0
#define PMNG_CHRGN 1
#define PMNG_BOOST 2
#define PMNG_NCHRG 3
/* product name */
#define PRDN_MAX 14
/* Mains alarm masks */
#define MAINS_AVAIL_M 0x0001 /* 0: available (OL) 1: not available (OB) */
#define SHUTD_REQST_M 0x0002 /* shutdown requested */
/* Mains alarm indices */
#define MAINS_AVAIL_I 0 /* 0: available (OL) 1: not available (OB) */
#define SHUTD_REQST_I 1 /* shutdown requested */
/* AC input voltage alarm masks */
#define VACA_HIALRM_M 0x0001 /* high alarm */
#define VACA_LOALRM_M 0x0002 /* low alarm */
/* AC input voltage alarm indices */
#define VACA_HIALRM_I 0 /* high alarm */
#define VACA_LOALRM_I 1 /* low alarm */
/* Onboard temperature alarm value */
#define OBTA_HIALRM_V 1 /* high alarm */
/* Onboard temperature alarm index */
#define OBTA_HIALRM_I 0 /* high alarm */
/* Device failure alarm masks */
#define DEVF_RCALRM_M 0x0001 /* rectifier failure */
#define DEVF_INALRM_M 0x0006 /* internal failure */
#define DEVF_LFNAVL_M 0x0008 /* lifetest not available */
/* Device failure alarm indices */
#define DEVF_RCALRM_I 0 /* rectifier failure */
#define DEVF_INALRM_I 1 /* internal failure */
#define DEVF_LFNAVL_I 2 /* lifetest not available */
/* Battery temp sensor failure alarm masks */
#define BTSF_FCND_M 0x0001 /* connection fault */
#define BTSF_NCND_M 0x0002 /* not connected */
/* Battery temp sensor failure alarm indices */
#define BTSF_FCND_I 0 /* connection fault */
#define BTSF_NCND_I 1 /* not connected */
/* Battery voltage alarm masks */
#define BVAL_HIALRM_M 0x0001 /* high voltage */
#define BVAL_LOALRM_M 0x0002 /* low voltage */
#define BVAL_BSTSFL_M 0x0004 /* battery start with battery flat */
/* Battery voltage alarm indices */
#define BVAL_HIALRM_I 0 /* high voltage */
#define BVAL_LOALRM_I 1 /* low voltage */
#define BVAL_BSTSFL_I 2 /* battery start with battery flat */
/* SoH and SoC alarm masks */
#define SHSC_HIRESI_M 0x0001 /* high internal resistance */
#define SHSC_LOCHEF_M 0x0002 /* low charge efficiency */
#define SHSC_LOEFCP_M 0x0004 /* low effective capacity */
#define SHSC_LOWSOC_M 0x0040 /* low state of charge */
/* SoH and SoC alarm indices */
#define SHSC_HIRESI_I 0 /* high internal resistance */
#define SHSC_LOCHEF_I 1 /* low charge efficiency */
#define SHSC_LOEFCP_I 2 /* low effective capacity */
#define SHSC_LOWSOC_I 3 /* low state of charge */
/* Battery status alarm masks */
#define BSTA_REVPOL_M 0x0001 /* reversed polarity */
#define BSTA_NOCNND_M 0x0002 /* not connected */
#define BSTA_CLSHCR_M 0x0004 /* cell short circuit */
#define BSTA_SULPHD_M 0x0008 /* sulphated */
#define BSTA_CHEMNS_M 0x0010 /* chemistry not supported */
#define BSTA_CNNFLT_M 0x0020 /* connection fault */
/* Battery status alarm indices */
#define BSTA_REVPOL_I 0 /* reversed polarity */
#define BSTA_NOCNND_I 1 /* not connected */
#define BSTA_CLSHCR_I 2 /* cell short circuit */
#define BSTA_SULPHD_I 3 /* sulphated */
#define BSTA_CHEMNS_I 4 /* chemistry not supported */
#define BSTA_CNNFLT_I 5 /* connection fault */
/* Allocate alarm arrays */
static inline
alrm_ar_t *alloc_alrm_ar(int as, size_t n)
{
alrm_ar_t *ret = xcalloc(sizeof(alrm_t) + n, 1);
if (ret) {
memcpy(ret,
&(alrm_ar_t const) {
.alrm_c = as
},
sizeof(alrm_ar_t)
);
}
return ret;
}
/* Initialize alarm arrays */
static inline
void alrm_ar_init(alrm_ar_t *ar_ptr, alrm_t *a_ptr, int as)
{
ar_ptr->alrm_c = as;
ar_ptr->alrm = a_ptr;
}
/* input mains and shutdown alarms */
static alrm_t mains_ar[] = {
{0, "input voltage not available"},
{0, "ups shutdown requested"}
};
static int mains_c = 2;
static alrm_ar_t *mains;
/* AC input voltage alarms */
static alrm_t vaca_ar[] = {
{0, "input voltage high alarm"},
{0, "input voltage low alarm"}
};
static int vaca_c = 2;
static alrm_ar_t *vaca;
/* device failure alarms */
static alrm_t devf_ar[] = {
{0, "UPS rectifier failure"},
{0, "UPS internal failure"},
{0, "UPS lifetest not available"}
};
static int devf_c = 3;
static alrm_ar_t *devf;
/* battery sensor failure alarms */
static alrm_t btsf_ar[] = {
{0, "battery temp sensor connection fault"},
{0, "battery temp sensor not connected"}
};
static int btsf_c = 2;
static alrm_ar_t *btsf;
/* battery voltage alarms */
static alrm_t bval_ar[] = {
{0, "battery high voltage"},
{0, "battery low voltage"},
{0, "battery start with battery flat"}
};
static int bval_c = 3;
static alrm_ar_t *bval;
/* battery SoH and SoC alarms */
static alrm_t shsc_ar[] = {
{0, "battery high internal resistance"},
{0, "battery low charge efficiency"},
{0, "battery low effective capacity"},
{0, "battery low state of charge"}
};
static int shsc_c = 4;
static alrm_ar_t *shsc;
/* battery status alarm */
static alrm_t bsta_ar[] = {
{0, "battery reversed polarity"},
{0, "battery not connected"},
{0, "battery cell short circuit"},
{0, "battery sulphated"},
{0, "battery chemistry not supported"},
{0, "battery connection fault"}
};
static int bsta_c = 4;
static alrm_ar_t *bsta;
/* onboard temperature alarm */
static alrm_t obta_ar[] = {
{0, "onboard temperature high"}
};
static int obta_c = 4;
static alrm_ar_t *obta;
/* UPS device reg enum */
enum devreg {
CHRG = 4, /* Charging status, "battery.charger.status" */
BATV = 7, /* Battery voltage, "battery.voltage" */
BCEF = 18, /* Battery charge efficiency factor (CEF) */
BSOH = 20, /* Battery state-of-health */
BSOC = 22, /* Battery state-of-charge, "battery.charge" */
BTMP = 25, /* Battery temperature in Kelvin units, "battery.temperature" */
PMNG = 5, /* Power management, "ups.status" */
OTMP = 28, /* Onboard temperature, "ups.temperature" */
PRDN = 67, /* Product name, "ups.model" */
VAC = 29, /* AC voltage, "input.voltage" */
LVDC = 10, /* Load voltage, "output.voltage" */
LCUR = 19, /* Load current, "output.current" */
BINH = 87, /* Backup inhibit */
FSD = 40, /* Force shutdown */
TBUF = 103, /* Time buffering, "battery.runtime" */
BSTA = 31, /* Battery status alarms */
SCSH, /* SoH and SoC alarms */
BVAL = 34, /* Battery voltage alarm */
BTSF = 43, /* Battery temp sensor failure */
DEVF = 42, /* Device failure */
OBTA = 46, /* On board temp alarm */
VACA = 44, /* VAC alarms */
MAIN /* Mains status */
};
typedef enum devreg devreg_t;
/* UPS register attributes */
struct regattr {
int num;
int saddr; /* register start address */
int xaddr; /* register hex address */
float scale; /* scale */
regtype_t type; /* register type */
};
typedef struct regattr regattr_t;
/* UPS device state info union */
union devstate {
prodname_t product; /* ups model name */
chrgs_t charge; /* charging status */
pwrmng_t power; /* ups status */
reg_t reg; /* state register*/
alrm_ar_t *alrm; /* alarm statuses */
};
typedef union devstate devstate_t;
/* device register memory image */
static uint16_t regs_data[MAX_H_REGS];
/* ADELSYSTEM CBI registers */
static regattr_t regs[] = {
{40001, 0, 0, 1, HOLDING}, /* Address of slave unit */
{40002, 0, 0, 1, HOLDING}, /* Baud rate for serial communication */
{40003, 0, 0, 1, HOLDING}, /* Parity bit for serial communication */
{40004, 0, 0, 1, HOLDING},
{40005, 0, 0, 1, HOLDING}, /* Charging status */
{40006, 0, 0, 1, HOLDING}, /* Power management
* 0:Backup 1:Charging 2:boost 3:Not charging
*/
{40007, 0, 0, 1, HOLDING}, /* Nominal output voltage */
{40008, 0, 0, 1, HOLDING}, /* Battery voltage */
{40009, 0, 0, 1, HOLDING}, /* Parameter map version ID */
{40010, 0, 0, 1, HOLDING}, /* Software ID */
{40011, 0, 0, 1, HOLDING}, /* Output load voltage */
{40012, 0, 0, 1, HOLDING},
{40013, 0, 0, 1, HOLDING},
{40014, 0, 0, 1, HOLDING}, /* Battery charge current */
{40015, 0, 0, 1, HOLDING},
{40016, 0, 0, .1, HOLDING}, /* Battery capacity consumed */
{40017, 0, 0, 1, HOLDING}, /* Battery discharge current */
{40018, 0, 0, .1, HOLDING}, /* Effective battery capacity */
{40019, 0, 0, 1, HOLDING}, /* Battery charge efficiency factor (CEF) */
{40020, 0, 0, 1, HOLDING}, /* Output load current */
{40021, 0, 0, 1, HOLDING}, /* Battery state-of-health */
{40022, 0, 0, 1, HOLDING}, /* Time remaining to 100% discharge */
{40023, 0, 0, .1, HOLDING}, /* Battery state-of-charge */
{40024, 0, 0, 1, HOLDING}, /* Battery type currently selected */
{40025, 0, 0, 1, HOLDING},
{40026, 0, 0, 1, HOLDING}, /* Battery temperature in Kelvin units */
{40027, 0, 0, 1, HOLDING}, /* Configuration mode */
{40028, 0, 0, .1, HOLDING}, /* Battery net internal resistance */
{40029, 0, 0, 1, HOLDING}, /* On-board temperature */
{40030, 0, 0, 1, HOLDING}, /* AC input voltage */
{40031, 0, 0, 1, HOLDING},
{40032, 0, 0, 1, HOLDING}, /* Battery status alarm */
{40033, 0, 0, 1, HOLDING}, /* Battery State of Charge and State of Health */
{40034, 0, 0, 1, HOLDING}, /* Load output off duration after PC shutdown */
{40035, 0, 0, 1, HOLDING}, /* Battery voltage alarm */
{40036, 0, 0, 1, HOLDING}, /* Low AC input voltage alarm threshold */
{40037, 0, 0, 1, HOLDING}, /* High AC input voltage alarm threshold */
{40038, 0, 0, 1, HOLDING}, /* Load alarm */
{40039, 0, 0, 1, HOLDING}, /* Device variant */
{40040, 0, 0, 1, HOLDING},
{40041, 0, 0, 1, HOLDING}, /* Force shutdown */
{40042, 0, 0, 1, HOLDING},
{40043, 0, 0, 1, HOLDING}, /* Device failure */
{40044, 0, 0, 1, HOLDING}, /* Battery temperature sensor failure */
{40045, 0, 0, 1, HOLDING}, /* AC input voltage alarm */
{40046, 0, 0, 1, HOLDING}, /* Mains status */
{40047, 0, 0, 1, HOLDING}, /* On board temperature alarm */
{40048, 0, 0, 1, HOLDING}, /* Number of charge cycles completed */
{40049, 0, 0, 1, HOLDING}, /* Charge cycles not completed */
{40050, 0, 0, .1, HOLDING}, /* Ah charged */
{40051, 0, 0, 1, HOLDING}, /* Total run time */
{40052, 0, 0, 1, HOLDING}, /* Number of low battery voltage events */
{40053, 0, 0, 1, HOLDING}, /* Number of high battery voltage events */
{40054, 0, 0, 1, HOLDING}, /* Number of low VAC events at mains input */
{40055, 0, 0, 1, HOLDING}, /* Number of High VAC events at mains input */
{40056, 0, 0, 1, HOLDING}, /* Number of over temperature inside events */
{40057, 0, 0, 1, HOLDING}, /* Number of mains-backup transitions */
{40058, 0, 0, 1, HOLDING}, /* Number power boost events */
{40059, 0, 0, 1, HOLDING}, /* Highest battery voltage */
{40060, 0, 0, 1, HOLDING}, /* Highest output load voltage */
{40061, 0, 0, .1, HOLDING}, /* Maximum depth of discharge */
{40062, 0, 0, 1, HOLDING}, /* Lowest battery voltage */
{40063, 0, 0, 1, HOLDING}, /* Lowest output load voltage */
{40064, 0, 0, .1, HOLDING}, /* Average depth of discharge */
{40065, 0, 0, 1, HOLDING}, /* History clear all */
{40066, 0, 0, 1, HOLDING}, /* Factory settings */
{40067, 0, 0, 1, HOLDING}, /* Product name */
{40068, 0, 0, 1, HOLDING},
{40069, 0, 0, 1, HOLDING}, /* Reset internal battery model */
{40070, 0, 0, 1, HOLDING},
{40071, 0, 0, 1, HOLDING}, /* Deep discharge battery prevention */
{40072, 0, 0, 1, HOLDING}, /* Maximum charge current */
{40073, 0, 0, 1, HOLDING}, /* Bulk voltage */
{40074, 0, 0, 1, HOLDING}, /* Max bulk timer */
{40075, 0, 0, 1, HOLDING}, /* Min bulk timer */
{40076, 0, 0, 1, HOLDING},
{40077, 0, 0, 1, HOLDING}, /* Absorption voltage */
{40078, 0, 0, 1, HOLDING}, /* Max absorption timer */
{40079, 0, 0, 1, HOLDING}, /* Min absorption timer */
{40080, 0, 0, 1, HOLDING}, /* Return Amperes to float */
{40081, 0, 0, 1, HOLDING}, /* Return amps timer */
{40082, 0, 0, 1, HOLDING}, /* Float voltage */
{40083, 0, 0, 1, HOLDING}, /* Force boost charge */
{40084, 0, 0, 1, HOLDING}, /* Return to bulk voltage from float */
{40085, 0, 0, 1, HOLDING}, /* Return to bulk delay */
{40086, 0, 0, 1, HOLDING},
{40087, 0, 0, 1, HOLDING}, /* Switchoff voltage without mains */
{40088, 0, 0, 1, HOLDING}, /* Backup Inhibit 0 = Backup allowed
* 1 = Backup not allowed
*/
{40089, 0, 0, 1, HOLDING}, /* Number of battery cells */
{40090, 0, 0, 1, HOLDING}, /* Temperature compensation coefficient */
{40091, 0, 0, 1, HOLDING},
{40092, 0, 0, 1, HOLDING}, /* Lifetest enable */
{40093, 0, 0, 1, HOLDING}, /* Max alarm temp */
{40094, 0, 0, 1, HOLDING}, /* Min alarm temp */
{40095, 0, 0, 1, HOLDING},
{40096, 0, 0, 1, HOLDING},
{40097, 0, 0, 1, HOLDING}, /* Low battery threshold */
{40098, 0, 0, 1, HOLDING}, /* SoC/SoH test period */
{40099, 0, 0, 1, HOLDING}, /* Manual SoC/SoH test request */
{40100, 0, 0, 1, HOLDING}, /* SoC/SoH test possible */
{40101, 0, 0, .1, HOLDING}, /* Nominal battery internal resistance */
{40102, 0, 0, .1, HOLDING}, /* Nominal battery cables resistance */
{40103, 0, 0, 1, HOLDING}, /* Firmware ID */
{40104, 0, 0, 1, HOLDING}, /* Time buffering */
{40105, 0, 0, .1, HOLDING}, /* Battery capacity C20 */
{40106, 0, 0, .1, HOLDING}, /* Battery Capacity C10 */
{40107, 0, 0, 1, HOLDING}, /* Device switchoff delay */
{40108, 0, 0, .1, HOLDING}, /* Battery Capacity C5 */
{40109, 0, 0, .1, HOLDING}, /* Battery Capacity C2 */
{40110, 0, 0, 1, HOLDING},
{40111, 0, 0, 1, HOLDING}, /* PC power supply removal delay */
{40112, 0, 0, .1, HOLDING}, /* Battery Capacity C1 */
{40113, 0, 0, .1, HOLDING}, /* Low state-of-charge */
{40114, 0, 0, 1, HOLDING},
{40115, 0, 0, 1, HOLDING},
{40116, 0, 0, 1, HOLDING},
{40117, 0, 0, 1, HOLDING},
{40118, 0, 0, 1, HOLDING},
{40119, 0, 0, 1, HOLDING},
{40120, 0, 0, 1, HOLDING} /* Zero-SoC reference */
};
#endif /* ADELSYSTEM_CBI_H */