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.

444 lines
17 KiB

  1. #!/usr/bin/env python3
  2. import sys
  3. import getopt
  4. import glob
  5. import serial
  6. import struct
  7. import tkinter
  8. from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
  9. # Implement the default Matplotlib key bindings.
  10. from matplotlib.backend_bases import key_press_handler
  11. from matplotlib.figure import Figure
  12. import numpy as np
  13. tempe = 0
  14. tSetGlobal = 0.0
  15. controllerDebugWindowOpen = 0
  16. tick = 0
  17. tickArray = []
  18. tActArray = []
  19. tSetArray = []
  20. tickDebug = 0
  21. tickDebugArray = []
  22. tActDebugArray = []
  23. tSetDebugArray = []
  24. errDebugArray = []
  25. errSumDebugArray = []
  26. outOrigDebugArray = []
  27. outDebugArray = []
  28. outAvgDebugArray = []
  29. sleepCounterDebugArray = []
  30. rxInputBuffer = bytearray()
  31. rxStatemachine = 0
  32. def serial_ports():
  33. """ Lists serial port names
  34. :raises EnvironmentError:
  35. On unsupported or unknown platforms
  36. :returns:
  37. A list of the serial ports available on the system
  38. """
  39. if sys.platform.startswith('win'):
  40. ports = ['COM%s' % (i + 1) for i in range(256)]
  41. elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
  42. # this excludes your current terminal "/dev/tty"
  43. ports = glob.glob('/dev/tty[A-Za-z]*')
  44. elif sys.platform.startswith('darwin'):
  45. ports = glob.glob('/dev/tty.*')
  46. else:
  47. raise EnvironmentError('Unsupported platform')
  48. result = []
  49. for port in ports:
  50. try:
  51. s = serial.Serial(port)
  52. s.close()
  53. result.append(port)
  54. except (OSError, serial.SerialException):
  55. pass
  56. return result
  57. #print(serial_ports())
  58. availableSerialPorts = serial_ports()
  59. print('choose a port:')
  60. counter = 0
  61. for port in availableSerialPorts:
  62. print(' [' + str(counter) + '] ' + port)
  63. counter += 1
  64. choosenPort = input('(type a number (0)) ')
  65. if choosenPort == '':
  66. choosenPortNumber = 0
  67. else:
  68. choosenPortNumber = int(choosenPort)
  69. counter = 0
  70. #serialPort = '/dev/pts/19'
  71. serialPort = '/dev/ttyACM0'
  72. serialPort = availableSerialPorts[choosenPortNumber]
  73. try:
  74. ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0)
  75. except:
  76. serialPort = '/dev/ttyACM1'
  77. ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0)
  78. def readSerial():
  79. while True:
  80. c = ser.read() # attempt to read a character from Serial
  81. #was anything read?
  82. if len(c) == 0:
  83. break
  84. else:
  85. #print('DATA')
  86. #log.insert(END, ':' + c.hex())
  87. global rxInputBuffer
  88. global rxStatemachine
  89. rxInputBuffer.append(c[0])
  90. if rxStatemachine == 0:
  91. if rxInputBuffer[0] == 0xff:
  92. rxStatemachine = 1
  93. rxInputBuffer = rxInputBuffer[1:]
  94. elif rxStatemachine == 1:
  95. if rxInputBuffer[0] == 0xf1:
  96. rxStatemachine = 2
  97. else:
  98. rxStatemachine = 0
  99. rxInputBuffer = rxInputBuffer[1:]
  100. elif rxStatemachine == 2:
  101. if len(rxInputBuffer) >= rxInputBuffer[0] + 1:
  102. processData(rxInputBuffer[1:rxInputBuffer[0] + 1])
  103. rxInputBuffer = bytearray()
  104. rxStatemachine = 0
  105. else:
  106. if len(rxInputBuffer) > 256:
  107. print('rxInputBuffer reset!')
  108. rxInputBuffer = bytearray()
  109. rxStatemachine = 0
  110. root.after(10, readSerial) # check serial again soon
  111. def processData(input):
  112. global tSetGlobal
  113. print([ "0x%02x" % b for b in input ])
  114. # ~ print(str([hex(x) for x in input]))
  115. # ~ if input[0] == 0x11:
  116. # ~ if input[1] == 100:
  117. # ~ temperatureString.set(str(round(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661)) + "degC")
  118. # ~ processControllerDebugData(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661, 20, 10, 0, -10, -20)
  119. if input[0] == 0x33:
  120. print("debugDataEnabled")
  121. tickDebugArray.clear()
  122. tActDebugArray.clear()
  123. tSetDebugArray.clear()
  124. errDebugArray.clear()
  125. errSumDebugArray.clear()
  126. outOrigDebugArray.clear()
  127. outDebugArray.clear()
  128. outAvgDebugArray.clear()
  129. sleepCounterDebugArray.clear()
  130. elif input[0] == 0x34:
  131. print("debugDataDisabled")
  132. elif input[0] == 0x8d:
  133. cartridge_temperature_adc_raw = ((input[1] * 256) + input[2])
  134. tAct = struct.unpack('>f', input[3:7])[0]
  135. tSet = struct.unpack('>f', input[7:11])[0]
  136. err = struct.unpack('>f', input[11:15])[0]
  137. errSum = struct.unpack('>f', input[15:19])[0]
  138. outOrig = struct.unpack('>f', input[19:23])[0]
  139. out = input[23] * 256 + input[24]
  140. outAvg = input[25] * 256 + input[26]
  141. sleepCounter = input[27] * 256 + input[28]
  142. if out > 32767:
  143. out -= 65536
  144. tActString.set(str(round(tAct)) + "degC")
  145. tSetString.set("(" + str(round(tSet)) + "degC)")
  146. tSetGlobal = tSet
  147. processTemperatureData(tAct, tSet)
  148. processControllerDebugData(tAct, tSet, err, errSum, outOrig, out, outAvg, sleepCounter)
  149. elif input[0] == 0x8c:
  150. tAct = struct.unpack('>f', input[1:5])[0]
  151. tSet = struct.unpack('>f', input[5:9])[0]
  152. tActString.set(str(round(tAct)) + "degC")
  153. tSetString.set("(" + str(round(tSet)) + "degC)")
  154. tSetGlobal = tSet
  155. processTemperatureData(tAct, tSetGlobal)
  156. # ~ elif input[0] == 0x91:
  157. # ~ tSet = struct.unpack('>f', input[1:5])[0]
  158. # ~ tSetString.set("(" + str(round(tSet)) + "degC)")
  159. # ~ elif input[0] == 0x92:
  160. # ~ controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0]))
  161. # ~ elif input[0] == 0x93:
  162. # ~ controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0]))
  163. # ~ elif input[0] == 0x94:
  164. # ~ controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0]))
  165. # ~ elif input[0] == 0x95:
  166. # ~ controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0]))
  167. # ~ elif input[0] == 0x96:
  168. # ~ controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0]))
  169. # ~ elif input[0] == 0x97:
  170. # ~ controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0]))
  171. # ~ elif input[0] == 0x98:
  172. # ~ controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0]))
  173. # ~ elif input[0] == 0x99:
  174. # ~ controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0]))
  175. elif input[0] == 0xa0:
  176. controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0]))
  177. elif input[0] == 0xa1:
  178. controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0]))
  179. elif input[0] == 0xa2:
  180. controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0]))
  181. elif input[0] == 0xa3:
  182. controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0]))
  183. elif input[0] == 0xf0:
  184. tSet = struct.unpack('>f', input[1:5])[0]
  185. controllerKp = struct.unpack('>f', input[5:9])[0]
  186. controllerKi = struct.unpack('>f', input[9:13])[0]
  187. controllerKd = struct.unpack('>f', input[13:17])[0]
  188. controllerKit = struct.unpack('>f', input[17:21])[0]
  189. tSetString.set("(" + str(round(tSet)) + "degC)")
  190. tSetGlobal = tSet
  191. controllerValueKpString.set("Kp: " + str(controllerKp))
  192. controllerValueKiString.set("Ki: " + str(controllerKi))
  193. controllerValueKdString.set("Kd: " + str(controllerKd))
  194. controllerValueKitString.set("Kit: " + str(controllerKit))
  195. def sendSerial(payloadType, payload):
  196. # ~ print('send ' + str(len(input)) + ' byte(s): ' + str([hex(x) for x in input]))
  197. data = bytearray([0xff, 0xf1])
  198. data.append(1 + len(payload))
  199. data.append(payloadType)
  200. data.extend(bytearray(payload))
  201. print("send " + str([ "0x%02x" % b for b in data ]))
  202. ser.write(data)
  203. def createNewWindow():
  204. global controllerDebugWindowOpen
  205. newWindow = tkinter.Toplevel(root)
  206. newWindow.protocol("WM_DELETE_WINDOW", lambda: closeWindow(newWindow))
  207. # ~ labelExample = tkinter.Label(master=newWindow, text="new window")
  208. # ~ labelExample.pack()
  209. canvas2 = FigureCanvasTkAgg(controllerDebugFigure, master=newWindow) # A tk.DrawingArea.
  210. canvas2.draw()
  211. canvas2.get_tk_widget().pack()
  212. controllerDebugWindowOpen = 1
  213. def closeWindow(myVar):
  214. print("closeWindow " + str(myVar))
  215. controllerDebugWindowOpen = 0
  216. myVar.destroy()
  217. def increaseTemperature():
  218. global tempe, temperatureString
  219. tempe = tempe + 10
  220. temperatureString.set(str(tempe) + "degC")
  221. def processTemperatureData(tAct, tSet):
  222. global tick, tickArray, tActArray, tSetArray
  223. tickArray.append(tick)
  224. tickArray = tickArray[-30:]
  225. tick = tick + 1
  226. tActArray.append(tAct)
  227. tActArray = tActArray[-30:]
  228. tSetArray.append(tSet)
  229. tSetArray = tSetArray[-30:]
  230. yMin = tSet - 10
  231. yMax = tSet + 10
  232. if min(tActArray) < yMin:
  233. yMin = min(tActArray) - 2
  234. if max(tActArray) > yMax:
  235. yMax = max(tActArray) + 2
  236. temperatureFigureAxis1.clear()
  237. temperatureFigureAxis1.plot(tickArray, tActArray, linewidth=1, color="black")
  238. temperatureFigureAxis1.plot(tickArray, tSetArray, linewidth=1, color="green")
  239. temperatureFigureAxis1.set_ylim(yMin, yMax)
  240. # ~ temperatureFigure.tight_layout()
  241. temperatureFigure.canvas.draw()
  242. def processControllerDebugData(tAct, tSet, err, errSum, outOrig, out, outAvg, sleepCounter):
  243. # ~ print("processControllerDebugData")
  244. global tickDebug, tickDebugArray, tActDebugArray, tSetDebugArray, errDebugArray, errSumDebugArray, outOrigDebugArray, outDebugArray, outAvgDebugArray, sleepCounterDebugArray
  245. global controllerDebugWindowOpen
  246. tickDebugArray.append(tickDebug)
  247. tickDebugArray = tickDebugArray[-1000:]
  248. tickDebug = tickDebug + 1
  249. tActDebugArray.append(tAct)
  250. tActDebugArray = tActDebugArray[-1000:]
  251. tSetDebugArray.append(tSet)
  252. tSetDebugArray = tSetDebugArray[-1000:]
  253. errDebugArray.append(err)
  254. errDebugArray = errDebugArray[-1000:]
  255. errSumDebugArray.append(errSum)
  256. errSumDebugArray = errSumDebugArray[-1000:]
  257. outOrigDebugArray.append(outOrig)
  258. outOrigDebugArray = outOrigDebugArray[-1000:]
  259. outDebugArray.append(out)
  260. outDebugArray = outDebugArray[-1000:]
  261. outAvgDebugArray.append(outAvg)
  262. outAvgDebugArray = outAvgDebugArray[-1000:]
  263. sleepCounterDebugArray.append(sleepCounter)
  264. sleepCounterDebugArray = sleepCounterDebugArray[-1000:]
  265. if controllerDebugWindowOpen == 1:
  266. # ~ ax1.clear()
  267. # ~ ax1.plot(tickArray, tActArray, linewidth=2, color='black')
  268. # ~ fig.canvas.draw()
  269. controllerDebugFigureAxis1.clear()
  270. controllerDebugFigureAxis1.plot(tickDebugArray, tActDebugArray, linewidth=1, color="black", label="tAct")
  271. controllerDebugFigureAxis1.plot(tickDebugArray, tSetDebugArray, linewidth=1, color="green", label="tSet")
  272. controllerDebugFigureAxis1.plot(tickDebugArray, errDebugArray, linewidth=1, color="red", label="err")
  273. controllerDebugFigureAxis1.plot(tickDebugArray, errSumDebugArray, linewidth=1, color="orange", label="errSum")
  274. controllerDebugFigureAxis1.plot(tickDebugArray, outOrigDebugArray, linewidth=1, color="royalblue", label="outOrig")
  275. controllerDebugFigureAxis1.plot(tickDebugArray, outDebugArray, linewidth=1, color="blueviolet", label="out")
  276. controllerDebugFigureAxis1.plot(tickDebugArray, outAvgDebugArray, linewidth=1, color="blue", label="outAvg")
  277. controllerDebugFigureAxis1.plot(tickDebugArray, sleepCounterDebugArray, linewidth=1, color="grey", label="sleepCounter")
  278. controllerDebugFigureAxis1.legend(loc="lower left")
  279. controllerDebugFigureAxis1.set_ylim(-100, 1000)
  280. # ~ controllerDebugFigure.tight_layout()
  281. controllerDebugFigure.canvas.draw()
  282. root = tkinter.Tk()
  283. root.wm_title("Embedding in Tk")
  284. root.geometry("320x850")
  285. # ~ root.protocol("WM_DELETE_WINDOW", lambda: closeWindow(root))
  286. # ~ fig = Figure(figsize=(5, 4), dpi=100)
  287. # ~ fig2 = Figure(figsize=(5, 4), dpi=100)
  288. # ~ t = np.arange(0, 3, .01)
  289. # ~ fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
  290. # ~ fig2.add_subplot(111).plot(t, 2 * np.cos(2 * np.pi * t))
  291. temperatureFigure = Figure(figsize=(3, 2))
  292. temperatureFigureAxis1 = temperatureFigure.add_subplot(1, 1, 1)
  293. temperatureFigureAxis1.yaxis.set_label_position("right")
  294. temperatureFigureAxis1.yaxis.tick_right()
  295. temperatureFigure.tight_layout()
  296. controllerDebugFigure = Figure(figsize=(15, 9))
  297. controllerDebugFigureAxis1 = controllerDebugFigure.add_subplot(1, 1, 1)
  298. controllerDebugFigureAxis1.yaxis.set_label_position("right")
  299. controllerDebugFigureAxis1.yaxis.tick_right()
  300. controllerDebugFigureAxis1.set_ylim(-200, 500)
  301. controllerDebugFigure.tight_layout()
  302. # ~ canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
  303. # ~ canvas.draw()
  304. # pack_toolbar=False will make it easier to use a layout manager later on.
  305. # ~ toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
  306. # ~ toolbar.update()
  307. # ~ canvas.mpl_connect("key_press_event", lambda event: print(f"you pressed {event.key}"))
  308. # ~ canvas.mpl_connect("key_press_event", key_press_handler)
  309. # ~ btn = tk.Button(root, text="Press", command=lambda: myFunction("See this worked!"))
  310. # ~ button = tkinter.Button(master=root, text="Quit", command=root.quit)
  311. buttonNewWindow = tkinter.Button(master=root, text="open controller debug window", command=createNewWindow)
  312. # Packing order is important. Widgets are processed sequentially and if there
  313. # is no space left, because the window is too small, they are not displayed.
  314. # The canvas is rather flexible in its size, so we pack it last which makes
  315. # sure the UI controls are displayed as long as possible.
  316. # ~ button.pack(side=tkinter.BOTTOM)
  317. buttonNewWindow.pack(side=tkinter.BOTTOM)
  318. # ~ toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
  319. # ~ canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
  320. tkinter.Button(master=root, text="set 330degC", command=lambda: sendSerial(0x91, [0x01, 0x4a])).pack()
  321. tkinter.Button(master=root, text="set 200degC", command=lambda: sendSerial(0x91, [0x00, 0xc8])).pack()
  322. tkinter.Button(master=root, text="set 0degC", command=lambda: sendSerial(0x91, [0x00, 0x00])).pack()
  323. tActString = tkinter.StringVar()
  324. tActString.set("0degC")
  325. tSetString = tkinter.StringVar()
  326. tSetString.set("(0degC)")
  327. controllerValueKpString = tkinter.StringVar()
  328. controllerValueKpString.set("Kp: 0")
  329. controllerValueKiString = tkinter.StringVar()
  330. controllerValueKiString.set("Ki: 0")
  331. controllerValueKdString = tkinter.StringVar()
  332. controllerValueKdString.set("Kd: 0")
  333. controllerValueKitString = tkinter.StringVar()
  334. controllerValueKitString.set("Kit: 0")
  335. tkinter.Label(master=root, textvariable=tActString, font=("Free Mono", 40)).pack()
  336. tkinter.Label(master=root, textvariable=tSetString, font=("Free Mono", 20)).pack()
  337. canvas = FigureCanvasTkAgg(temperatureFigure, master=root) # A tk.DrawingArea.
  338. canvas.draw()
  339. canvas.get_tk_widget().pack()
  340. # ~ tkinter.Button(master=root, text="Kp +1", command=lambda: sendSerial(0x92, [])).pack()
  341. tkinter.Label(master=root, textvariable=controllerValueKpString, font=("Free Mono", 20)).pack()
  342. textValueKp = tkinter.Text(master=root, height=1, width=20)
  343. textValueKp.pack()
  344. tkinter.Button(master=root, text="set Kp", command=lambda: sendSerial(0xa0, convertStringToFloatBytearray(textValueKp.get("1.0", "end-1c")))).pack()
  345. # ~ tkinter.Button(master=root, text="Kp -1", command=lambda: sendSerial(0x93, [])).pack()
  346. # ~ tkinter.Button(master=root, text="Ki +1", command=lambda: sendSerial(0x94, [])).pack()
  347. tkinter.Label(master=root, textvariable=controllerValueKiString, font=("Free Mono", 20)).pack()
  348. textValueKi = tkinter.Text(master=root, height=1, width=20)
  349. textValueKi.pack()
  350. tkinter.Button(master=root, text="set Ki", command=lambda: sendSerial(0xa1, convertStringToFloatBytearray(textValueKi.get("1.0", "end-1c")))).pack()
  351. # ~ tkinter.Button(master=root, text="Ki -1", command=lambda: sendSerial(0x95, [])).pack()
  352. # ~ tkinter.Button(master=root, text="Kd +1", command=lambda: sendSerial(0x96, [])).pack()
  353. tkinter.Label(master=root, textvariable=controllerValueKdString, font=("Free Mono", 20)).pack()
  354. textValueKd = tkinter.Text(master=root, height=1, width=20)
  355. textValueKd.pack()
  356. tkinter.Button(master=root, text="set Kd", command=lambda: sendSerial(0xa2, convertStringToFloatBytearray(textValueKd.get("1.0", "end-1c")))).pack()
  357. # ~ tkinter.Button(master=root, text="Kd -1", command=lambda: sendSerial(0x97, [])).pack()
  358. # ~ tkinter.Button(master=root, text="Kit +1", command=lambda: sendSerial(0x98, [])).pack()
  359. tkinter.Label(master=root, textvariable=controllerValueKitString, font=("Free Mono", 20)).pack()
  360. textValueKit = tkinter.Text(master=root, height=1, width=20)
  361. textValueKit.pack()
  362. tkinter.Button(master=root, text="set Kit", command=lambda: sendSerial(0xa3, convertStringToFloatBytearray(textValueKit.get("1.0", "end-1c")))).pack()
  363. # ~ tkinter.Button(master=root, text="Kit -1", command=lambda: sendSerial(0x99, [])).pack()
  364. tkinter.Button(master=root, text="enable debug data", command=lambda: sendSerial(0x33, [])).pack()
  365. tkinter.Button(master=root, text="disable debug data", command=lambda: sendSerial(0x34, [])).pack()
  366. # ~ tkinter.Button(master=root, text="init", command=lambda: sendSerial(0xf0, [])).pack()
  367. def convertStringToFloatBytearray(inputString):
  368. try:
  369. floatValue = float(inputString)
  370. byteArrayValue = bytearray(struct.pack('>f', floatValue))
  371. # ~ print(str(floatValue))
  372. # ~ print([ "0x%02x" % b for b in byteArrayValue ])
  373. return byteArrayValue
  374. except:
  375. print("can not convert [" + inputString + "] to float!")
  376. return []
  377. root.after(100, readSerial)
  378. sendSerial(0xf0, [])
  379. tkinter.mainloop()