dumpcurves.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #!/usr/bin/env python3
  2. #
  3. # Xytronic LF-1600
  4. # Debug interface tool
  5. #
  6. # Copyright (c) 2015-2016 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. #
  22. import sys
  23. import serial
  24. CURR_DIV = 10.0
  25. if len(sys.argv) != 3 or "-h" in sys.argv or "--help" in sys.argv:
  26. print("Usage: dumpcurves.py /dev/ttyUSB0 output.csv")
  27. print("")
  28. print("/dev/ttyUSB0 is the serial device where the data is read from.")
  29. print("output.csv is the output file.")
  30. sys.exit(1)
  31. inDev = sys.argv[1]
  32. outFile = sys.argv[2]
  33. s = serial.Serial(port = inDev, baudrate = 9600, bytesize = 8,
  34. parity = serial.PARITY_NONE, stopbits = 2)
  35. def writeOutFile(lines):
  36. outFd = open(outFile, "wb")
  37. outFd.write(b"time (ticks);"
  38. b"current controller real r (A);"
  39. b"current controller used r (A);"
  40. b"current controller r state;"
  41. b"current controller y (A);"
  42. b"temp controller r (*C);"
  43. b"temp controller y1 (*C);"
  44. b"temp controller y2 (A);"
  45. b"measured current (ADC);"
  46. b"filtered current (ADC);"
  47. b"measured temp (ADC);"
  48. b"boost mode\r\n")
  49. outFd.write("".join(lines).encode("utf-8"))
  50. outFd.close()
  51. def reset():
  52. global outLines
  53. global prevTimeStamp
  54. global val_currentRealR
  55. global val_currentUsedR
  56. global val_currentRState
  57. global val_currentY
  58. global val_tempR
  59. global val_tempY1
  60. global val_tempY2
  61. global val_measCurr
  62. global val_filtCurr
  63. global val_measTemp
  64. global val_boostMode;
  65. print("RESET")
  66. outLines = []
  67. writeOutFile(outLines)
  68. prevTimeStamp = None
  69. val_currentRealR = 0.0
  70. val_currentUsedR = 0.0
  71. val_currentRState = 0
  72. val_currentY = 0.0
  73. val_tempR = 0.0
  74. val_tempY1 = 0.0
  75. val_tempY2 = 0.0
  76. val_measCurr = 0
  77. val_filtCurr = 0
  78. val_measTemp = 0
  79. val_boostMode = 0
  80. def putLine(timeStamp):
  81. csvLine = "%d;%f;%f;%d;%f;%f;%f;%f;%d;%d;%d;%d\r\n" % (
  82. timeStamp,
  83. val_currentRealR,
  84. val_currentUsedR,
  85. val_currentRState,
  86. val_currentY,
  87. val_tempR,
  88. val_tempY1,
  89. val_tempY2,
  90. val_measCurr,
  91. val_filtCurr,
  92. val_measTemp,
  93. val_boostMode,
  94. )
  95. outLines.append(csvLine)
  96. writeOutFile(outLines)
  97. def parseInt(valStr, valIdent):
  98. try:
  99. val = int(valStr, 10)
  100. except ValueError:
  101. print("Invalid %s" % valIdent)
  102. return 0
  103. return val
  104. def parseFixpt(valStr, valIdent):
  105. val = parseInt(valStr, valIdent)
  106. val = float(val) / (1 << 6)
  107. return val
  108. reset()
  109. try:
  110. while 1:
  111. line = s.readline()
  112. line = line.decode("utf-8", "ignore").strip()
  113. if not line:
  114. continue
  115. if line == "st":
  116. reset()
  117. continue
  118. idx = line.find(':')
  119. if idx < 0:
  120. print("Time stamp not found")
  121. continue
  122. try:
  123. timeStamp = int(line[ : idx], 16)
  124. except ValueError:
  125. print("Invalid time stamp format")
  126. continue
  127. line = line[idx + 1 : ].strip()
  128. elems = line.split()
  129. if len(elems) != 2:
  130. print("Unknown format: %s" % line)
  131. continue
  132. if elems[0] == "cr1":
  133. val_currentRealR = parseFixpt(elems[1], "cr1") / CURR_DIV
  134. elif elems[0] == "cr2":
  135. val_currentUsedR = parseFixpt(elems[1], "cr2") / CURR_DIV
  136. elif elems[0] == "rs":
  137. val_currentRState = parseInt(elems[1], "rs")
  138. elif elems[0] == "cy":
  139. val_currentY = parseFixpt(elems[1], "cy") / CURR_DIV
  140. elif elems[0] == "tr":
  141. val_tempR = parseFixpt(elems[1], "tr")
  142. elif elems[0] == "ty1":
  143. val_tempY1 = parseFixpt(elems[1], "ty1")
  144. elif elems[0] == "ty2":
  145. val_tempY2 = parseFixpt(elems[1], "ty2") / CURR_DIV
  146. elif elems[0] == "tb":
  147. val_boostMode = parseInt(elems[1], "tb")
  148. elif elems[0] == "mc":
  149. val_measCurr = parseInt(elems[1], "mc")
  150. elif elems[0] == "fc":
  151. val_filtCurr = parseInt(elems[1], "fc")
  152. elif elems[0] == "mt":
  153. val_measTemp = parseInt(elems[1], "mt")
  154. else:
  155. print("Unknown elem: %s" % elems[0])
  156. continue
  157. # Fill the missing lines with copies of the previous.
  158. if 0:
  159. if prevTimeStamp is not None:
  160. t = (prevTimeStamp + 1) & 0xFFFF
  161. while t != timeStamp:
  162. putLine(t)
  163. t = (t + 1) & 0xFFFF
  164. prevTimeStamp = timeStamp
  165. # Put the current line into the CSV.
  166. putLine(timeStamp)
  167. print("temp-r: %.02f °C current-y: %.02f A current-r: %.02f A" % (
  168. val_tempR,
  169. val_currentY,
  170. val_currentUsedR,
  171. ))
  172. except KeyboardInterrupt as e:
  173. pass
  174. sys.exit(0)