452 lines
9.5 KiB
C
452 lines
9.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <syslog.h>
|
|
#include <err.h>
|
|
#include <linux/serial.h>
|
|
#include <sys/signal.h>
|
|
#include "serial-util.h"
|
|
#include "gpib.h"
|
|
#include "zoom.h"
|
|
#include "math.h"
|
|
|
|
void zero(int zoom);
|
|
void write_dac(int zoom, int dac);
|
|
void single_sweep(int zoom);
|
|
void calibrate(int zoom, int gpib);
|
|
void sweep_ota(int zoom, int gpib, int ota_sweep_count);
|
|
void hold_ota(int zoom, int gpib, int ota_cmd);
|
|
|
|
#define info(x...) fprintf(stderr,x)
|
|
|
|
int g_quit = 0;
|
|
void handle_sig(int sig) { g_quit = 1; }
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *zoomdev=strdup("/dev/serial/by-id/usb-FTDI_FT232R_"
|
|
"USB_UART_A6007wc5-if00-port0");
|
|
char *gpibdev=strdup("/dev/serial/by-id/usb-Prologix_Prologix_"
|
|
"GPIB-USB_Controller_PXQQY20G-if00-port0");
|
|
int getopt_index;
|
|
int zoom, gpib;
|
|
int do_write = 0;
|
|
int do_zero = 0;
|
|
int write_cmd = 32768;
|
|
int do_single_sweep = 0;
|
|
int ota_opt = 0;
|
|
int ota_sweep_count = 64;
|
|
int ota_cmd = 32768;
|
|
char *end;
|
|
|
|
static struct option long_opts[] = {
|
|
{ "zoom-device", required_argument, NULL, 'Z' },
|
|
{ "gpib-device", required_argument, NULL, 'G' },
|
|
{ "write-dac", required_argument, NULL, 'w' },
|
|
{ "zero", no_argument, NULL, 'z' },
|
|
{ "single-sweep", no_argument, NULL, 's' },
|
|
{ "ota-sweep", required_argument, NULL, 'o' },
|
|
{ "ota-hold", required_argument, NULL, 'l' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ 0, 0, 0, 0}
|
|
};
|
|
int help=0;
|
|
char c;
|
|
|
|
while ((c = getopt_long(argc, argv, "Z:G:szw:o:l:h?",
|
|
long_opts, &getopt_index)) != -1) {
|
|
switch(c)
|
|
{
|
|
case 'Z':
|
|
free(zoomdev);
|
|
zoomdev = strdup(optarg);
|
|
break;
|
|
case 'G':
|
|
free(gpibdev);
|
|
gpibdev = strdup(optarg);
|
|
break;
|
|
case 'w':
|
|
do_write = 1;
|
|
write_cmd = strtoul(optarg, &end, 0);
|
|
if (*end) {
|
|
fprintf(stderr, "bad number %s\n", optarg);
|
|
help = 1;
|
|
}
|
|
break;
|
|
case 's':
|
|
do_single_sweep = 1;
|
|
break;
|
|
case 'z':
|
|
do_zero = 1;
|
|
break;
|
|
case 'o':
|
|
ota_opt = 1;
|
|
ota_sweep_count = strtoul(optarg, &end, 0);
|
|
if (*end) {
|
|
fprintf(stderr, "bad number %s\n", optarg);
|
|
help = 1;
|
|
}
|
|
break;
|
|
case 'l':
|
|
ota_opt = 2;
|
|
ota_cmd = strtoul(optarg, &end, 0);
|
|
if (*end) {
|
|
fprintf(stderr, "bad number %s\n", optarg);
|
|
help = 1;
|
|
}
|
|
break;
|
|
case 'h':
|
|
|
|
case '?':
|
|
default:
|
|
help = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (help) {
|
|
fprintf(stderr, "Zoom Nilm Calibration Tool\n");
|
|
fprintf(stderr, "usage: %s [options]\n\n", *argv);
|
|
fprintf(stderr, " -Z, --zoom-device %-14s "
|
|
"zoom NILM serial port\n", "/dev/xxx" /*zoomdev*/);
|
|
fprintf(stderr, " -G, --gpib-device %-14s "
|
|
"GPIB serial port\n", "/dev/xxx" /*gpibdev*/);
|
|
fprintf(stderr, " -w, --write-dac %-14d "
|
|
"write one value to the DAC constantly\n", write_cmd);
|
|
fprintf(stderr, " -s, --single-sweep "
|
|
"do a single sweep on the PIC\n");
|
|
fprintf(stderr, " -z, --zero "
|
|
"set DAC value such that ADC input is centered\n");
|
|
fprintf(stderr, " -o, --ota-sweep %-14d "
|
|
"sweep OTA\n", ota_sweep_count);
|
|
fprintf(stderr, " -l, --ota-hold %-14d "
|
|
"hold OTA constant\n", ota_cmd);
|
|
fprintf(stderr, " -h, --help "
|
|
"this help\n");
|
|
return 1;
|
|
}
|
|
|
|
signal(SIGINT, handle_sig);
|
|
|
|
if ((zoom = serial_open(zoomdev, 115200)) == -1)
|
|
err(1, "failed to open zoom device %s", zoomdev);
|
|
|
|
if (do_write) {
|
|
write_dac(zoom, write_cmd);
|
|
close(zoom);
|
|
return 0;
|
|
}
|
|
|
|
if (do_zero) {
|
|
zero(zoom);
|
|
close(zoom);
|
|
return 0;
|
|
}
|
|
|
|
if (do_single_sweep) {
|
|
single_sweep(zoom);
|
|
close(zoom);
|
|
return 0;
|
|
}
|
|
|
|
if ((gpib = serial_open(gpibdev, 9600)) == -1)
|
|
err(1, "failed to open gpib device %s", gpibdev);
|
|
|
|
switch (ota_opt) {
|
|
case 1:
|
|
sweep_ota(zoom, gpib, ota_sweep_count);
|
|
break;
|
|
case 2:
|
|
hold_ota(zoom, gpib, ota_cmd);
|
|
break;
|
|
default:
|
|
calibrate(zoom, gpib);
|
|
break;
|
|
}
|
|
|
|
close(zoom);
|
|
close(gpib);
|
|
return 0;
|
|
}
|
|
|
|
void calibrate(int zoom, int gpib)
|
|
{
|
|
double idesired, iactual;
|
|
int i;
|
|
int zero;
|
|
int r = 0;
|
|
int dac[ZOOM_SWEEP_COUNT];
|
|
int adc[ZOOM_SWEEP_COUNT];
|
|
|
|
info("Initializing Zoom NILM\n");
|
|
if (zoom_init(zoom) < 0) goto fail;
|
|
|
|
info("Zeroing\n");
|
|
if (zoom_zero_start(zoom) < 0) goto fail;
|
|
|
|
info("Initializing GPIB\n");
|
|
if (gpib_init(gpib) < 0) goto fail;
|
|
|
|
info("Initializing Keithley\n");
|
|
if (gpib_addr(gpib, 24) < 0) goto fail;
|
|
if (keithley_init(gpib) < 0) goto fail;
|
|
if (keithley_current(gpib, 0) < 0) goto fail;
|
|
if (isnan(keithley_read(gpib))) goto fail;
|
|
|
|
info("Stop zeroing\n");
|
|
if (zoom_zero_stop(zoom) < 0) goto fail;
|
|
|
|
info("Sweeping\n");
|
|
for (idesired = -1.0; idesired <= 1.0 && !g_quit; idesired += 0.10) {
|
|
// for (idesired = -0.2; idesired <= 0.2 && !g_quit; idesired += 0.02) {
|
|
info("Zeroing\n");
|
|
if (zoom_zero_start(zoom) < 0) goto fail;
|
|
|
|
info("Setting current: %.8f\n", idesired);
|
|
keithley_current(gpib, idesired);
|
|
usleep(100000);
|
|
iactual = keithley_read(gpib);
|
|
info("Actual current: %.8f\n", iactual);
|
|
|
|
info("Stop zeroing\n");
|
|
if ((zero = zoom_zero_stop(zoom)) < 0) goto fail;
|
|
info("DAC zero point = %d\n", zero);
|
|
|
|
info("Sweeping...\n");
|
|
if ((r = zoom_sweep(zoom, dac, adc)) < 0) goto fail;
|
|
|
|
info("Done\n");
|
|
for (i = 0; i < ZOOM_SWEEP_COUNT; i++) {
|
|
printf("%.8f %d %d\n", iactual, dac[i], adc[i]);
|
|
}
|
|
}
|
|
|
|
safecleanup:
|
|
zoom_zero_start(zoom);
|
|
keithley_off(gpib);
|
|
usleep(50000);
|
|
zoom_zero_stop(zoom);
|
|
return;
|
|
|
|
fail:
|
|
info("Failed (code %d)\n", r);
|
|
goto safecleanup;
|
|
}
|
|
|
|
void write_dac(int zoom, int dac)
|
|
{
|
|
char buf[128];
|
|
|
|
if (zoom_init(zoom) < 0)
|
|
errx(1, "init failed");
|
|
|
|
if (dac < 0)
|
|
dac = 0;
|
|
if (dac > 65535)
|
|
dac = 65535;
|
|
while (!g_quit) {
|
|
sprintf(buf, "v%04x", dac);
|
|
if (safewrite(zoom, buf, 5) != 5)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
chomp(buf);
|
|
printf("%s\n", buf);
|
|
}
|
|
}
|
|
|
|
void single_sweep(int zoom)
|
|
{
|
|
int i, r;
|
|
int dac[ZOOM_SWEEP_COUNT];
|
|
int adc[ZOOM_SWEEP_COUNT];
|
|
|
|
info("Initializing Zoom NILM\n");
|
|
if (zoom_init_nozero(zoom) < 0) goto fail;
|
|
|
|
info("Sweeping\n");
|
|
if ((r = zoom_sweep(zoom, dac, adc)) < 0) goto fail;
|
|
|
|
info("Done\n");
|
|
for (i = 0; i < ZOOM_SWEEP_COUNT; i++) {
|
|
printf("%d %d\n", dac[i], adc[i]);
|
|
}
|
|
|
|
return;
|
|
|
|
fail:
|
|
info("Failed (code %d)\n", r);
|
|
return;
|
|
}
|
|
|
|
void zero(int zoom)
|
|
{
|
|
int r = 0;
|
|
int dac;
|
|
|
|
info("Initializing Zoom NILM\n");
|
|
if (zoom_init(zoom) < 0) goto fail;
|
|
|
|
info("Starting zeroing, ^C to stop\n");
|
|
if (zoom_zero_start(zoom) < 0) goto fail;
|
|
|
|
while (!g_quit)
|
|
usleep(100000);
|
|
|
|
info("Stop zeroing\n");
|
|
if ((dac = zoom_zero_stop(zoom)) < 0) goto fail;
|
|
info("DAC zero point = 0x%04x %d\n", dac, dac);
|
|
|
|
info("Done\n");
|
|
return;
|
|
|
|
fail:
|
|
info("Failed (code %d)\n", r);
|
|
return;
|
|
}
|
|
|
|
void sweep_ota(int zoom, int gpib, int ota_sweep_count)
|
|
{
|
|
double iactual;
|
|
int i,j;
|
|
int r = 0;
|
|
char buf[128];
|
|
char zcmd[128];
|
|
int mycmd = 0;
|
|
int cmd_inc = 4096;
|
|
|
|
info("Initializing Zoom NILM\n");
|
|
if (zoom_init(zoom) < 0) goto fail;
|
|
|
|
info("Initializing GPIB\n");
|
|
if (gpib_init(gpib) < 0) goto fail;
|
|
|
|
info("Initializing Keithley 2002 Multimeter\n");
|
|
if (gpib_addr(gpib, 23) < 0) goto fail;
|
|
if (keithley2002_init(gpib) < 0) goto fail;
|
|
if (isnan(keithley2002_read(gpib))) goto fail;
|
|
|
|
buf[0] = '0';
|
|
if (safewrite(zoom, buf, 1) != 1)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
drain(zoom);
|
|
|
|
|
|
|
|
info("Sweeping OTA\n");
|
|
for (i = 0; i <= 16 && !g_quit; i++){
|
|
|
|
for(j = -2; j <= 2; j++){
|
|
if(mycmd+j > 65535 || mycmd+j < 0)
|
|
continue;
|
|
|
|
if(sprintf(zcmd,"v%.4x",(mycmd +j)) < 5)
|
|
errx(1, "fail hex conversion");
|
|
|
|
if (safewrite(zoom, zcmd, 5) != 5)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
|
|
usleep(100);
|
|
|
|
iactual = keithley2002_read(gpib);
|
|
|
|
printf("%d %.8f\n",(int)(mycmd + j), iactual);
|
|
}
|
|
|
|
mycmd += cmd_inc;
|
|
|
|
}
|
|
|
|
// return to zero
|
|
buf[0] = '0';
|
|
if (safewrite(zoom, buf, 1) != 1)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
|
|
|
|
|
|
safecleanup:
|
|
return;
|
|
|
|
fail:
|
|
info("Failed (code %d)\n", r);
|
|
goto safecleanup;
|
|
}
|
|
|
|
|
|
void hold_ota(int zoom, int gpib, int ota_cmd)
|
|
{
|
|
double iactual;
|
|
double tx;
|
|
int i;
|
|
int r = 0;
|
|
char buf[128];
|
|
char zcmd[128];
|
|
|
|
info("Initializing Zoom NILM\n");
|
|
if (zoom_init(zoom) < 0) goto fail;
|
|
|
|
info("Initializing GPIB\n");
|
|
if (gpib_init(gpib) < 0) goto fail;
|
|
|
|
info("Initializing Keithley 2002 Multimeter\n");
|
|
if (gpib_addr(gpib, 23) < 0) goto fail;
|
|
if (keithley2002_init2(gpib) < 0) goto fail;
|
|
if (isnan(keithley2002_read(gpib))) goto fail;
|
|
|
|
buf[0] = '0';
|
|
if (safewrite(zoom, buf, 1) != 1)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
drain(zoom);
|
|
|
|
if(ota_cmd > 65535 || ota_cmd < 0)
|
|
errx(1, "ota command out-of-range");
|
|
|
|
if(sprintf(zcmd,"v%.4x",(ota_cmd)) < 5)
|
|
errx(1, "fail hex conversion");
|
|
|
|
if (safewrite(zoom, zcmd, 5) != 5)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
|
|
usleep(100);
|
|
|
|
info("Holding OTA\n");
|
|
for (i = 0; i <= 500 && !g_quit; i++){
|
|
|
|
iactual = keithley2002_read2(gpib, &tx);
|
|
|
|
printf("%.12f %.12f\n", tx, iactual);
|
|
|
|
}
|
|
|
|
// return to zero
|
|
buf[0] = '0';
|
|
if (safewrite(zoom, buf, 1) != 1)
|
|
errx(1, "write failed");
|
|
if (fdgets(buf, 128, zoom, 1000) == NULL)
|
|
errx(1, "read timeout");
|
|
|
|
|
|
|
|
safecleanup:
|
|
return;
|
|
|
|
fail:
|
|
info("Failed (code %d)\n", r);
|
|
goto safecleanup;
|
|
}
|