]> sigrok.org Git - libsigrok.git/commitdiff
scpi-pps: Add support for Elektro-Automatik PS 20xx
authorNicolas Labriet <redacted>
Fri, 8 Nov 2024 15:35:20 +0000 (16:35 +0100)
committerSoeren Apel <redacted>
Sun, 9 Nov 2025 22:36:30 +0000 (23:36 +0100)
Signed-off-by: Nicolas Labriet <redacted>
src/hardware/scpi-pps/profiles.c

index 577aa41e90ae0fa482150107c41c97ddc7c6b3a4..c2bb3e6e4edbc48ceca1c5649badb0ad2e3527f3 100644 (file)
@@ -275,6 +275,198 @@ 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,
@@ -1570,6 +1762,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