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.

399 lines
12 KiB

  1. #!/usr/bin/env python3
  2. import sys
  3. import getopt
  4. import glob
  5. import serial
  6. import struct
  7. from tkinter import *
  8. import matplotlib.figure as figure
  9. from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
  10. from datetime import datetime
  11. def serial_ports():
  12. """ Lists serial port names
  13. :raises EnvironmentError:
  14. On unsupported or unknown platforms
  15. :returns:
  16. A list of the serial ports available on the system
  17. """
  18. if sys.platform.startswith('win'):
  19. ports = ['COM%s' % (i + 1) for i in range(256)]
  20. elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
  21. # this excludes your current terminal "/dev/tty"
  22. ports = glob.glob('/dev/tty[A-Za-z]*')
  23. elif sys.platform.startswith('darwin'):
  24. ports = glob.glob('/dev/tty.*')
  25. else:
  26. raise EnvironmentError('Unsupported platform')
  27. result = []
  28. for port in ports:
  29. try:
  30. s = serial.Serial(port)
  31. s.close()
  32. result.append(port)
  33. except (OSError, serial.SerialException):
  34. pass
  35. return result
  36. #print(serial_ports())
  37. availableSerialPorts = serial_ports()
  38. print('choose a port:')
  39. counter = 0
  40. for port in availableSerialPorts:
  41. print(' [' + str(counter) + '] ' + port)
  42. counter += 1
  43. choosenPort = input('(type a number (0)) ')
  44. if choosenPort == '':
  45. choosenPortNumber = 0
  46. else:
  47. choosenPortNumber = int(choosenPort)
  48. counter = 0
  49. #serialPort = '/dev/pts/19'
  50. serialPort = '/dev/ttyACM0'
  51. serialPort = availableSerialPorts[choosenPortNumber]
  52. try:
  53. ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0)
  54. except:
  55. serialPort = '/dev/ttyACM1'
  56. ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0)
  57. #ser = serial.Serial()
  58. #ser.port = "/dev/pts/19"
  59. #ser.baudrate = 9600
  60. #ser.bytesize = serial.EIGHTBITS
  61. #ser.parity = serial.PARITY_NONE
  62. #ser.stopbits = serial.STOPBITS_ONE
  63. #ser.timeout = None #block read
  64. #ser.timeout = 1 #non-block read
  65. #ser.timeout = 2 #timeout block read
  66. #ser.xonxoff = False #disable software flow control
  67. #ser.rtscts = False #disable hardware (RTS/CTS) flow control
  68. #ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
  69. #ser.writeTimeout = 2 #timeout for write
  70. #try:
  71. # ser.open()
  72. #except Exception as e:
  73. # print('error open serial port: ' + str(e))
  74. # exit()
  75. #ser.open()
  76. #ser.write('hello world!')
  77. #values = bytearray([4, 9, 62, 144, 56, 30, 147, 3, 210, 89, 111, 78, 184, 151, 17, 129])
  78. #ser.write(values)
  79. #while True:
  80. # print(ser.readline())
  81. #from serial import *
  82. #from Tkinter import *
  83. #serialPort = "/dev/ttyACM0"
  84. #baudRate = 9600
  85. #ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking
  86. logEnable = 0;
  87. #~ temps = [20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220]
  88. temps = []
  89. tick = 0
  90. #~ tickArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  91. tickArray = []
  92. tActArray = []
  93. tSetArray = []
  94. errArray = []
  95. errSumArray = []
  96. outOrigArray = []
  97. outArray = []
  98. def functionLog():
  99. global logEnable
  100. if logEnable == 1:
  101. sendSerial([0xa3])
  102. app.after(1000, functionLog)
  103. def sendSerial(input):
  104. print('send ' + str(len(input)) + ' byte(s): ' + str([hex(x) for x in input]))
  105. data = bytearray([0xff, 0xf1])
  106. data.append(len(input))
  107. data.extend(bytearray(input))
  108. ser.write(data)
  109. def processData(input):
  110. global logEnable
  111. global w
  112. global temps
  113. global tick
  114. global tickArray
  115. global tActArray
  116. global tSetArray
  117. global errArray
  118. global errSumArray
  119. global outOrigArray
  120. global outArray
  121. print(str([hex(x) for x in input]))
  122. if input[0] == 0xa0:
  123. if input[1] == 0x00:
  124. log.insert(END, '> temp sensor 0 status: ' + str.join(':', ('%02x' % x for x in input[2:])) + '\n')
  125. elif input[1] == 0x01:
  126. log.insert(END, '> temp sensor 1 status: ' + str.join(':', ('%02x' % x for x in input[2:])) + '\n')
  127. elif input[0] == 0x10:
  128. if input[1] == 0x00:
  129. log.insert(END, '> adc: wrong channel\n')
  130. elif input[1] == 0x01:
  131. log.insert(END, '> adc: start cartridge resistance measurement\n')
  132. elif input[1] == 0x02:
  133. log.insert(END, '> adc: start cartridge current measurement\n')
  134. elif input[1] == 0x03:
  135. log.insert(END, '> adc: start cartridge temperature measurement\n')
  136. elif input[1] == 0x04:
  137. log.insert(END, '> adc: start input voltage measurement\n')
  138. elif input[1] == 0xff:
  139. log.insert(END, '> adc: pending measurement\n')
  140. elif input[0] == 0x11:
  141. if input[1] == 0x01:
  142. log.insert(END, '> raw_adc_cartridge_resistance: ' + str(((input[2] * 256) + input[3])) + '\n')
  143. elif input[1] == 0x02:
  144. log.insert(END, '> raw_adc_cartridge_current: ' + str(((input[2] * 256) + input[3])) + '\n')
  145. elif input[1] == 0x03:
  146. log.insert(END, '> raw_adc_cartridge_temperature: ' + str(((input[2] * 256) + input[3])) + '\n')
  147. elif input[1] == 0x04:
  148. log.insert(END, '> raw_adc_v_in: ' + str(((input[2] * 256) + input[3])) + '\n')
  149. elif input[1] == 100:
  150. # log.insert(END, '> raw_adc_cartridge_temperature_cycle: ' + str(((input[2] * 256) + input[3])) + '\n')
  151. log.insert(END, '> raw_adc_cartridge_temperature_cycle: ' + str(round(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661)) + ' degC\n')
  152. #~ tick = tick + 1
  153. #~ tickArray.append(tick)
  154. #~ temps.append(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661)
  155. #~ tickArray = tickArray[-200:]
  156. #~ temps = temps[-200:]
  157. #~ ax1.clear()
  158. #~ ax1.set_ylim(0, 400)
  159. #~ ax1.plot(tickArray, temps, linewidth=2, color='black')
  160. #~ fig.canvas.draw()
  161. elif input[0] == 0x20:
  162. if input[1] == 0x00:
  163. log.insert(END, '> cartridge resistance measure disabled\n')
  164. elif input[1] == 0x01:
  165. log.insert(END, '> cartridge resistance measure enabled\n')
  166. elif input[0] == 0x21:
  167. if input[1] == 0x00:
  168. log.insert(END, '> power-mosfet disabled\n')
  169. elif input[1] == 0x01:
  170. log.insert(END, '> power-mosfet enabled\n')
  171. elif input[0] == 0x8d:
  172. cartridge_temperature_adc_raw = ((input[1] * 256) + input[2])
  173. tAct = struct.unpack('>f', input[3:7])
  174. tSet = struct.unpack('>f', input[7:11])
  175. err = struct.unpack('>f', input[11:15])
  176. errSum = struct.unpack('>f', input[15:19])
  177. outOrig = struct.unpack('>f', input[19:23])
  178. out = input[23] * 256 + input[24]
  179. if out > 32767:
  180. out -= 65536
  181. log.insert(END, 'tAct: ' + str(tAct) + 'tSet: ' + str(tSet) + 'err: ' + str(err) + 'errSum: ' + str(errSum) + 'outOrig: ' + str(outOrig) + 'out: ' + str(out) + '\n')
  182. #~ tActArray.append(tAct)
  183. #~ tActArray = tActArray[-200:]
  184. #~ ax1.clear()
  185. #~ ax1.plot(tickArray, tActArray, linewidth=2, color='black')
  186. #~ fig.canvas.draw()
  187. else:
  188. log.insert(END, '> ' + str.join(':', ('%02x' % x for x in input)) + '\n')
  189. log.see("end")
  190. def btnClearAction():
  191. log.delete(1.0,END)
  192. log.insert(END, str(datetime.now()) + '\n')
  193. def btnGetRawAdcCartridgeResistanceAction():
  194. sendSerial([0x10, 0x01])
  195. def btnGetRawAdcCartridgeCurrentAction():
  196. sendSerial([0x10, 0x02])
  197. def btnGetRawAdcCartridgeTemperatureAction():
  198. sendSerial([0x10, 0x03])
  199. def btnGetRawAdcInputVoltageAction():
  200. sendSerial([0x10, 0x04])
  201. def btnSetCartridgeResistanceMosfetOnAction():
  202. sendSerial([0x20, 0x01])
  203. def btnSetCartridgeResistanceMosfetOffAction():
  204. sendSerial([0x20, 0x00])
  205. def btnSetPowerMosfetOnAction():
  206. sendSerial([0x91, 0x01, 0x18])
  207. def btnSetPowerMosfetOffAction():
  208. sendSerial([0x91, 0x00, 0x00])
  209. def btnGetTempSensor0DegCAction():
  210. sendSerial([0xa2, 0x00])
  211. def btnGetTempSensor1DegCAction():
  212. sendSerial([0xa2, 0x01])
  213. def btnGetTempSensorsDegCAction():
  214. sendSerial([0xa3])
  215. def btnStartLogAction():
  216. global logEnable
  217. global w
  218. w = open('reflow_oven_temperature_log', 'w')
  219. logEnable = 1
  220. w.write('time;seconds;status;temperature;tAct;tSet;err;errSum;outOrig;out\n')
  221. sendSerial([0xa5])
  222. #functionLog()
  223. def btnStopLogAction():
  224. global logEnable
  225. global w
  226. sendSerial([0xa4, 0x00])
  227. logEnable = 0
  228. w.close()
  229. def btnDisablePwmAction():
  230. sendSerial([0xb0, 0x00, 0x00])
  231. def btnSetTemperature0Action():
  232. sendSerial([0xb1, 0x00])
  233. def btnSetTemperature80Action():
  234. sendSerial([0xb1, 0x50])
  235. def btnSetTemperature150Action():
  236. sendSerial([0xb1, 0x96])
  237. def btnSetTemperature180Action():
  238. sendSerial([0xb1, 0xb4])
  239. def btnSetTemperature245Action():
  240. sendSerial([0xb1, 0xf5])
  241. #make a TkInter Window
  242. app = Tk()
  243. app.wm_title("attiny817_solderstation_app")
  244. # Create figure for plotting
  245. fig = figure.Figure(figsize=(12, 4))
  246. #~ fig.subplots_adjust(left=0.1, right=0.8)
  247. ax1 = fig.add_subplot(1, 1, 1)
  248. ax1.set_ylim(0, 400)
  249. #~ ax1.set_xlim(0, 20)
  250. # Create a Tk Canvas widget out of our figure
  251. canvas = FigureCanvasTkAgg(fig, master=app)
  252. canvas_plot = canvas.get_tk_widget()
  253. # make a scrollbar
  254. scrollbar = Scrollbar(app)
  255. scrollbar.pack(side=RIGHT, fill=Y)
  256. # make a text box to put the serial output
  257. log = Text (app, width=250, height=20, takefocus=0)
  258. log.pack()
  259. # attach text box to scrollbar
  260. log.config(yscrollcommand=scrollbar.set)
  261. scrollbar.config(command=log.yview)
  262. btnClear = Button(app, text='clear', command=btnClearAction)
  263. btnGetRawAdcCartridgeResistance = Button(app, text='getRawAdcCartridgeResistance', command=btnGetRawAdcCartridgeResistanceAction)
  264. btnGetRawAdcCartridgeCurrent = Button(app, text='getRawAdcCartridgeCurrent', command=btnGetRawAdcCartridgeCurrentAction)
  265. btnGetRawAdcCartridgeTemperature = Button(app, text='getRawAdcCartridgeTemperature', command=btnGetRawAdcCartridgeTemperatureAction)
  266. btnGetRawAdcInputVoltage = Button(app, text='getRawAdcInputVoltage', command=btnGetRawAdcInputVoltageAction)
  267. btnSetCartridgeResistanceMosfetOn = Button(app, text='setCartridgeResistanceMosfetOn', command=btnSetCartridgeResistanceMosfetOnAction)
  268. btnSetCartridgeResistanceMosfetOff = Button(app, text='setCartridgeResistanceMosfetOff', command=btnSetCartridgeResistanceMosfetOffAction)
  269. btnSetPowerMosfetOn = Button(app, text='setPowerMosfetOn', command=btnSetPowerMosfetOnAction)
  270. btnSetPowerMosfetOff = Button(app, text='setPowerMosfetOff', command=btnSetPowerMosfetOffAction)
  271. btnGetTempSensor0DegC = Button(app, text='getTempSensor0DegC', command=btnGetTempSensor0DegCAction)
  272. btnGetTempSensor1DegC = Button(app, text='getTempSensor1DegC', command=btnGetTempSensor1DegCAction)
  273. btnGetTempSensorsDegC = Button(app, text='getTempSensorsDegC', command=btnGetTempSensorsDegCAction)
  274. btnStartLog = Button(app, text='startLog', command=btnStartLogAction)
  275. btnStopLog = Button(app, text='stopLog', command=btnStopLogAction)
  276. btnDisablePwm = Button(app, text='STOP', command=btnDisablePwmAction)
  277. btnSetTemperature0 = Button(app, text='setTemperature0', command=btnSetTemperature0Action)
  278. btnSetTemperature80 = Button(app, text='setTemperature80', command=btnSetTemperature80Action)
  279. btnSetTemperature150 = Button(app, text='setTemperature150', command=btnSetTemperature150Action)
  280. btnSetTemperature180 = Button(app, text='setTemperature180', command=btnSetTemperature180Action)
  281. btnSetTemperature245 = Button(app, text='setTemperature245', command=btnSetTemperature245Action)
  282. btnClear.pack()
  283. canvas_plot.pack()
  284. btnGetRawAdcCartridgeResistance.pack()
  285. btnGetRawAdcCartridgeCurrent.pack()
  286. btnGetRawAdcCartridgeTemperature.pack()
  287. btnGetRawAdcInputVoltage.pack()
  288. btnSetCartridgeResistanceMosfetOn.pack()
  289. btnSetCartridgeResistanceMosfetOff.pack()
  290. btnSetPowerMosfetOn.pack()
  291. btnSetPowerMosfetOff.pack()
  292. #make our own buffer
  293. #useful for parsing commands
  294. #Serial.readline seems unreliable at times too
  295. rxInputBuffer = bytearray()
  296. rxStatemachine = 0
  297. def readSerial():
  298. while True:
  299. c = ser.read() # attempt to read a character from Serial
  300. #was anything read?
  301. if len(c) == 0:
  302. break
  303. else:
  304. #print('DATA')
  305. #log.insert(END, ':' + c.hex())
  306. global rxInputBuffer
  307. global rxStatemachine
  308. rxInputBuffer.append(c[0])
  309. if rxStatemachine == 0:
  310. if rxInputBuffer[0] == 0xff:
  311. rxStatemachine = 1
  312. rxInputBuffer = rxInputBuffer[1:]
  313. elif rxStatemachine == 1:
  314. if rxInputBuffer[0] == 0xf1:
  315. rxStatemachine = 2
  316. else:
  317. rxStatemachine = 0
  318. rxInputBuffer = rxInputBuffer[1:]
  319. elif rxStatemachine == 2:
  320. if len(rxInputBuffer) >= rxInputBuffer[0] + 1:
  321. processData(rxInputBuffer[1:rxInputBuffer[0] + 1])
  322. rxInputBuffer = bytearray()
  323. rxStatemachine = 0
  324. else:
  325. if len(rxInputBuffer) > 256:
  326. print('rxInputBuffer reset!')
  327. rxInputBuffer = bytearray()
  328. rxStatemachine = 0
  329. app.after(1, readSerial) # check serial again soon
  330. # after initializing serial, an arduino may need a bit of time to reset
  331. app.after(100, readSerial)
  332. app.mainloop()