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

scpi-pps: Add support for Elektro-Automatik PS 20xx #254

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
203 changes: 203 additions & 0 deletions src/hardware/scpi-pps/profiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,197 @@ static int chroma_62000p_probe_channels(struct sr_dev_inst *sdi,
return SR_OK;
}

/* Elektro Automatik PS 20xx series */
static const uint32_t ea_ps_20xx_devopts[] = {
SR_CONF_CONTINUOUS,
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
};

static const uint32_t ea_ps_20xx_devopts_cg[] = {
SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_VOLTAGE | SR_CONF_GET,
SR_CONF_VOLTAGE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_CURRENT | SR_CONF_GET,
SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
};

static const struct channel_group_spec ea_ps_20xx_cg[] = {
{ "1", CH_IDX(0), PPS_OVP | PPS_OCP, SR_MQFLAG_DC },
};

static int ea_ps_20xx_probe_channels(struct sr_dev_inst *sdi,
struct sr_scpi_hw_info *hw_info,
struct channel_spec **channels, unsigned int *num_channels,
struct channel_group_spec **channel_groups,
unsigned int *num_channel_groups)
{
struct sr_scpi_dev_inst *scpi;
int ret;
float nom_volt, nom_curr, nom_pow;
char *response;

scpi = sdi->conn;
/* Get nominal voltage */
ret = sr_scpi_get_string(scpi, ":SYST:NOM:VOLT?", &response);
if (ret != SR_OK && !response) {
sr_err("Failed to get nominal voltage.");
return ret;
}
/* Remove unit */
response[ret] = 0;
if (sr_atof_ascii(response, &nom_volt) != SR_OK) {
sr_err("Failed to convert nominal voltage from: '%s'", response);
return SR_ERR_DATA;
}
if (nom_volt < 0) {
sr_err("Suspicious nominal voltage %f, ignoring.", nom_volt);
return SR_ERR_DATA;
}

/* Get nominal current */
ret = sr_scpi_get_string(scpi, ":SYST:NOM:CURR?", &response);
if (ret != SR_OK && !response) {
sr_err("Failed to get nominal current.");
return ret;
}
/* Remove unit */
response[ret] = 0;
if (sr_atof_ascii(response, &nom_curr) != SR_OK) {
sr_err("Failed to convert nominal current from: '%s'", response);
return SR_ERR_DATA;
}
if (nom_curr < 0) {
sr_err("Suspicious nominal current %f, ignoring.", nom_volt);
return SR_ERR_DATA;
}

/* Get nominal power */
ret = sr_scpi_get_string(scpi, ":SYST:NOM:POW?", &response);
if (ret != SR_OK && !response) {
sr_err("Failed to get nominal power.");
return ret;
}
/* Remove unit */
response[ret] = 0;
if (sr_atof_ascii(response, &nom_pow) != SR_OK) {
sr_err("Failed to convert nominal power from: '%s'", response);
return SR_ERR_DATA;
}
if (nom_pow < 0) {
sr_err("Suspicious nominal power %f, ignoring.", nom_volt);
return SR_ERR_DATA;
}

*channels = g_malloc0(sizeof(struct channel_spec));
*channel_groups = g_malloc0(sizeof(struct channel_group_spec));
**channel_groups = ea_ps_20xx_cg[0];
*num_channel_groups = 1;

(*channels)[0].name = "1";

(*channels)[0].current[0] = 0.0;
(*channels)[0].current[1] = nom_curr;
(*channels)[0].current[2] = 0.01; /* Programming resolution. */
(*channels)[0].current[3] = 2; /* Spec digits. */
(*channels)[0].current[4] = 2; /* Encoding digits. */

(*channels)[0].voltage[0] = 0.0;
(*channels)[0].voltage[1] = nom_volt;
(*channels)[0].voltage[2] = 0.01; /* Programming resolution. */
(*channels)[0].voltage[3] = 2; /* Spec digits. */
(*channels)[0].voltage[4] = 2; /* Encoding digits. */

(*channels)[0].power[0] = 0.0;
(*channels)[0].power[1] = nom_pow;
(*channels)[0].power[2] = 0; /* Programming resolution. */
(*channels)[0].power[3] = 2; /* Spec digits. */
(*channels)[0].power[4] = 2; /* Encoding digits. */
*num_channels = 1;

return SR_OK;
}

static const struct scpi_command ea_ps_20xx_cmd[] = {
{ SCPI_CMD_REMOTE, "SYST:LOCK 1" },
{ SCPI_CMD_LOCAL, "SYST:LOCK 0" },
{ SCPI_CMD_GET_MEAS_VOLTAGE, ":MEAS:VOLT?" },
{ SCPI_CMD_GET_MEAS_CURRENT, ":MEAS:CURR?" },
{ SCPI_CMD_GET_MEAS_POWER, ":MEAS:POW?" },
{ SCPI_CMD_GET_VOLTAGE_TARGET, ":VOLT?" },
{ SCPI_CMD_SET_VOLTAGE_TARGET, ":VOLT %.2f" },
{ SCPI_CMD_GET_CURRENT_LIMIT, ":CURR?" },
{ SCPI_CMD_SET_CURRENT_LIMIT, ":CURR %.2f" },
{ SCPI_CMD_GET_OUTPUT_ENABLED, ":OUTP?" },
{ SCPI_CMD_SET_OUTPUT_ENABLE, ":OUTP 1" },
{ SCPI_CMD_SET_OUTPUT_DISABLE, ":OUTP 0" },
{ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, ":VOLT:PROT %.2f" },
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":CURR:PROT %.2f" },
ALL_ZERO
};

static int ea_ps_20xx_update_status(const struct sr_dev_inst *sdi)
{
struct sr_scpi_dev_inst *scpi;
int ret;
int response;
gboolean cv, cc;
gboolean regulation_changed;
char *regulation;

scpi = sdi->conn;

ret = sr_scpi_get_int(scpi, "STAT:QUES?", &response);
if (ret != SR_OK)
return ret;

/* OVP */
if (response & (1 << 0))
sr_session_send_meta(sdi, SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE,
g_variant_new_boolean(response & (1 << 0)));

/* OCP */
if (response & (1 << 1))
sr_session_send_meta(sdi, SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE,
g_variant_new_boolean(response & (1 << 1)));

/* OTP */
if (response & (1 << 3))
sr_session_send_meta(sdi, SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE,
g_variant_new_boolean(response & (1 << 3)));

ret = sr_scpi_get_int(scpi, "STAT:OPER?", &response);
if (ret != SR_OK)
return ret;

/* CV */
cv = (response & (1 << 8));
regulation_changed = (response & (1 << 8));
/* CC */
cc = (response & (1 << 9));
regulation_changed = (response & (1 << 9)) | regulation_changed;

if (regulation_changed) {
if (cv && !cc)
regulation = "CV";
else if (cc && !cv)
regulation = "CC";
else if (!cv && !cc)
regulation = "";
else {
sr_dbg("Undefined regulation for EA PS 20xx "
"(CV=%i, CC=%i).", cv, cc);
return FALSE;
}
sr_session_send_meta(sdi, SR_CONF_REGULATION,
g_variant_new_string(regulation));
}

return SR_OK;
}

/* Envox EEZ PSU Series */
static const uint32_t eez_psu_devopts[] = {
SR_CONF_CONTINUOUS,
Expand Down Expand Up @@ -1570,6 +1761,18 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
.update_status = NULL,
},

/* Elektro Automatik PS 20xx series*/
{ "EA Elektro-Automatik GmbH & Co. KG", "PS 20(42|84)-", SCPI_DIALECT_UNKNOWN, 0,
ARRAY_AND_SIZE(ea_ps_20xx_devopts),
ARRAY_AND_SIZE(ea_ps_20xx_devopts_cg),
NULL, 0,
NULL, 0,
ea_ps_20xx_cmd,
.probe_channels = ea_ps_20xx_probe_channels,
.init_acquisition = NULL,
.update_status = ea_ps_20xx_update_status,
},

/*
* Envox EEZ PSU Series
* The documented identification strings disagree with the behavior
Expand Down