zoom/pc/calibrate.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;
}