#include #include #include #include #include #include #include #include struct scale { float read; float result; }; const struct scale *current_scale = NULL; const struct scale *voltage_scale = NULL; float current_r = 0; const struct scale current_scale_1 = {3851, 0.5367}; const float current_r_1 = 0.2; const struct scale current_scale_2 = {3651, 0.9761}; const float current_r_2 = 0.1; // const float current_r_3 = 0.05; const struct scale voltage_scale_1 = {4041.5, 5.996}; const struct scale voltage_scale_2 = {4063.5, 13.547}; const struct scale voltage_scale_3 = {4038, 23.672}; volatile int quit; const char *prog; static void set_quit(int s) { quit = 1; } static void usage() { errx(1, "usage: %s -c [1|2] -v [1|2|3] ", prog); } int main(int argc, char * const argv[]) { int d; int bytes; int nfds; char buf[256]; int i; fd_set rfds; char gpio[2], current[4], tension[4]; char *endp; int currenti, tensioni; float current_a, tension_v; int val; extern char *optarg; extern int optind; int ch; enum { INIT, GPIO, CURRENT, TENSION, MARK } state; struct termios t, ot; prog = argv[0]; state = INIT; currenti = tensioni = 0; while ((ch = getopt(argc, argv, "c:v:")) != -1) { switch (ch) { case 'c': val = atoi(optarg); if (val == 1) { current_scale = ¤t_scale_1; current_r = current_r_1; } else if (val == 2) { current_scale = ¤t_scale_2; current_r = current_r_2; } break; case 'v': val = atoi(optarg); if (val == 1) { voltage_scale = &voltage_scale_1; } else if (val == 2) { voltage_scale = &voltage_scale_2; } else if (val == 3) { voltage_scale = &voltage_scale_3; } break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1 || current_scale == NULL || voltage_scale == NULL) usage(); d = open(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK, 0); if (d < 0) { err(1, "open %s", argv[0]); } fprintf(stderr, "o\n"); if (tcgetattr(d, &ot) < 0) { err(1, "tcgetattr"); } fprintf(stderr, "tg\n"); quit = 0; if (signal(SIGINT, set_quit) == SIG_ERR) { err(1, "signal(SIGINT)"); } if (signal(SIGQUIT, set_quit) == SIG_ERR) { err(1, "signal(SIGQUIT)"); } if (signal(SIGPIPE, set_quit) == SIG_ERR) { err(1, "signal(SIGPIPE)"); } if (signal(SIGTERM, set_quit) == SIG_ERR) { err(1, "signal(SIGTERM)"); } t = ot; cfmakeraw(&t); t.c_cflag |= CLOCAL; t.c_cflag &= ~CRTSCTS; cfsetspeed(&t, B921600); if (tcsetattr(d, TCSANOW | TCSAFLUSH, &t) < 0) { err(1, "tcsetattr"); } fprintf(stderr, "tty ready\n"); FD_ZERO(&rfds); while (quit == 0) { FD_SET(d, &rfds); nfds = select(d+1, &rfds, NULL, NULL, NULL); if (nfds > 0 && FD_ISSET(d, &rfds)) { bytes = read(d, buf, sizeof(buf)); if (bytes < 0 && errno != EAGAIN) { warn("read"); } for (i = 0; i < bytes; i++) { switch(state) { case INIT: /* look for an X mark */ if (buf[i] == 'X') state = GPIO; break; case GPIO: gpio[0] = buf[i]; gpio[1] = '\0'; val = strtol(gpio, &endp, 16); if (*endp != '\0') { fprintf(stderr, "gpio error: %c\n", *endp); state = INIT; } else { state = TENSION; tensioni = 0; printf("%2d ", val); } break; case CURRENT: current[currenti] = buf[i]; currenti++; if (currenti < 3) break; current[currenti] = '\0'; val = strtol(current, &endp, 16); if (*endp != '\0') { fprintf(stderr, "current error: %c\n", *endp); state = INIT; } else { if (val == 4095) { fprintf(stderr, "current saturation\n" ); } state = MARK; current_a = val / current_scale->read * current_scale->result; printf("%8f ", current_a); /* correct for in our resistor */ tension_v -= current_a * current_r; printf("%8f ", tension_v); printf("%8f\n", current_a * tension_v); } break; case TENSION: tension[tensioni] = buf[i]; tensioni++; if (tensioni < 3) break; tension[tensioni] = '\0'; val = strtol(tension, &endp, 16); if (*endp != '\0') { fprintf(stderr, "tension error: %c\n", *endp); state = INIT; } else { if (val == 4095) { fprintf(stderr, "tension saturation\n" ); } state = CURRENT; currenti = 0; tension_v = val / voltage_scale->read * voltage_scale->result; } break; case MARK: if (buf[i] != 'X') { fprintf(stderr, "mark error: %c\n", buf[i]); state = INIT; } else { state = GPIO; } break; } } } else if (nfds < 0) { warn("select"); } } if (tcsetattr(d, TCSANOW, &ot) < 0) { err(1, "restore tcsetattr"); } exit(0); }