You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

215 lines
4.3 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <errno.h>
  5. #include <unistd.h>
  6. #include <getopt.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include <syslog.h>
  10. #include <err.h>
  11. #include <linux/serial.h>
  12. #include "serial-util.h"
  13. int hex = 0;
  14. int dec = 0;
  15. int screen = 0;
  16. int unprocessed = 0;
  17. int total = 0;
  18. int process(const uint8_t *buf, int len);
  19. int main(int argc, char *argv[])
  20. {
  21. char *device=strdup("/dev/ttyUSB0");
  22. int rate=500000;
  23. int fd;
  24. int getopt_index;
  25. char buf[1024];
  26. int len;
  27. static struct option long_opts[] = {
  28. { "device", required_argument, NULL, 'd' },
  29. { "rate", required_argument, NULL, 'r' },
  30. { "hex", no_argument, NULL, 'x' },
  31. { "dec", no_argument, NULL, 'D' },
  32. { "total", no_argument, NULL, 't' },
  33. { "raw", no_argument, NULL, 'R' },
  34. { "unprocessed", no_argument, NULL, 'u' },
  35. { "screen", no_argument, NULL, 's' },
  36. { "help", no_argument, NULL, 'h' },
  37. { 0, 0, 0, 0 }
  38. };
  39. int help=0;
  40. char c;
  41. while ((c = getopt_long(argc, argv, "d:r:xDutsh?",
  42. long_opts, &getopt_index)) != -1) {
  43. switch(c)
  44. {
  45. case 'd':
  46. free(device);
  47. device = strdup(optarg);
  48. break;
  49. case 'r':
  50. rate = atoi(optarg);
  51. if(rate == 0)
  52. errx(1, "invalid rate: %s",optarg);
  53. break;
  54. case 'x':
  55. hex = 1;
  56. break;
  57. case 'D':
  58. dec = 1;
  59. break;
  60. case 't':
  61. total = 1;
  62. break;
  63. case 'u':
  64. unprocessed = 1;
  65. break;
  66. case 's':
  67. screen = 1;
  68. break;
  69. case 'h':
  70. case '?':
  71. default:
  72. help = 1;
  73. break;
  74. }
  75. }
  76. if (help) {
  77. fprintf(stderr, "Zoom Nilm Client\n");
  78. fprintf(stderr, "usage: %s [options]\n\n", *argv);
  79. fprintf(stderr, " -d, --device %-14s serial port\n", device);
  80. fprintf(stderr, " -r, --rate %-16d baud rate\n", rate);
  81. fprintf(stderr, " -x, --hex hex out\n");
  82. fprintf(stderr, " -u, --unprocessed dump raw unprocessed data\n");
  83. fprintf(stderr, " -s, --screen send \\r instead of \\n\n");
  84. fprintf(stderr, " -t, --total just display total amps\n");
  85. fprintf(stderr, " -h, --help this cruft\n");
  86. return 1;
  87. }
  88. if ((fd = serial_open(device, rate)) == -1)
  89. errx(1, "serial_open failed");
  90. len = 0;
  91. while (1) {
  92. int processed, n;
  93. n = read(fd, buf + len, sizeof(buf) - len);
  94. if (n <= 0)
  95. err(1, "read");
  96. len += n;
  97. processed = process((uint8_t *) buf, len);
  98. memmove(buf, buf + processed, len - processed);
  99. len -= processed;
  100. }
  101. return 1;
  102. }
  103. uint16_t current_to_dac(float amps)
  104. {
  105. float tmp;
  106. uint16_t dacc;
  107. tmp = 536.0 / 1.0 * amps + 32524;
  108. if (tmp < 0)
  109. tmp = 0;
  110. if (tmp > 65535)
  111. tmp = 65535;
  112. dacc = (uint16_t)(tmp + 0.5);
  113. return dacc;
  114. }
  115. /* Convert the DAC output value to an effective current in the measuring loop */
  116. float dac_to_current(uint16_t dacv)
  117. {
  118. float amps;
  119. amps = ((float)dacv - 32524.0) * 1.0 / 536.0;
  120. return amps;
  121. }
  122. float adc12_to_current(int16_t picv)
  123. {
  124. float amps;
  125. if (picv < 0)
  126. picv = 0;
  127. if (picv > 2047)
  128. picv = 2047;
  129. amps = (picv - 1024.0) / 404.0;
  130. return amps;
  131. }
  132. int process(const uint8_t *buf, int len)
  133. {
  134. int n = 0;
  135. uint16_t dac, tmp;
  136. int16_t adc;
  137. float idac = dac_to_current(dac);
  138. float iadc = adc12_to_current(adc);
  139. if (unprocessed) {
  140. n = write(fileno(stdout), buf, len);
  141. if (n >= 0)
  142. return n;
  143. return 0;
  144. }
  145. /* Process blocks */
  146. retry:
  147. for (; (n + 4) <= len; buf += 4, n += 4) {
  148. if ((!buf[0] & 0x80) ||
  149. (buf[1] & 0x80) ||
  150. (buf[2] & 0x80) ||
  151. (buf[3] & 0x80)) {
  152. /* badly formed data, eat one byte and retry */
  153. buf++;
  154. n++;
  155. goto retry;
  156. }
  157. tmp = ((buf[0] & 0x7f) << 5) |
  158. ((buf[1] & 0x7c) >> 2);
  159. dac = ((buf[1] & 0x03) << 14) |
  160. (buf[2] << 7) | buf[3];
  161. /* sign-extend ADC value */
  162. if (tmp & 0x0800)
  163. tmp |= 0xF000;
  164. else
  165. tmp &= ~0xF000;
  166. adc = (int16_t)tmp;
  167. /* compute floating-point currents */
  168. idac = dac_to_current(dac);
  169. iadc = adc12_to_current(adc);
  170. /* send it out */
  171. if (hex) {
  172. printf("%04x %03x", dac, adc & 0x0FFF);
  173. } else if (dec) {
  174. printf("%d %d", dac, adc & 0x0FFF);
  175. } else if (total) {
  176. printf("%.6f", idac - iadc);
  177. } else {
  178. printf("DAC: %5d (% f) ADC: % 5d (% f) Total: % 10.6f amps",
  179. dac, idac, (int16_t)adc, iadc, idac - iadc);
  180. if (adc < 0 || adc >= 2047)
  181. printf(" **** adc limit");
  182. }
  183. if (screen)
  184. printf("\033[K\r");
  185. else
  186. printf("\n");
  187. }
  188. return n;
  189. }