#!/usr/bin/env python3 import sys import getopt import glob import serial import struct from tkinter import * import matplotlib.figure as figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from datetime import datetime def serial_ports(): """ Lists serial port names :raises EnvironmentError: On unsupported or unknown platforms :returns: A list of the serial ports available on the system """ if sys.platform.startswith('win'): ports = ['COM%s' % (i + 1) for i in range(256)] elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): # this excludes your current terminal "/dev/tty" ports = glob.glob('/dev/tty[A-Za-z]*') elif sys.platform.startswith('darwin'): ports = glob.glob('/dev/tty.*') else: raise EnvironmentError('Unsupported platform') result = [] for port in ports: try: s = serial.Serial(port) s.close() result.append(port) except (OSError, serial.SerialException): pass return result #print(serial_ports()) availableSerialPorts = serial_ports() print('choose a port:') counter = 0 for port in availableSerialPorts: print(' [' + str(counter) + '] ' + port) counter += 1 choosenPort = input('(type a number (0)) ') if choosenPort == '': choosenPortNumber = 0 else: choosenPortNumber = int(choosenPort) counter = 0 #serialPort = '/dev/pts/19' serialPort = '/dev/ttyACM0' serialPort = availableSerialPorts[choosenPortNumber] try: ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0) except: serialPort = '/dev/ttyACM1' ser = serial.Serial(serialPort, 19200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=0, writeTimeout=0) #ser = serial.Serial() #ser.port = "/dev/pts/19" #ser.baudrate = 9600 #ser.bytesize = serial.EIGHTBITS #ser.parity = serial.PARITY_NONE #ser.stopbits = serial.STOPBITS_ONE #ser.timeout = None #block read #ser.timeout = 1 #non-block read #ser.timeout = 2 #timeout block read #ser.xonxoff = False #disable software flow control #ser.rtscts = False #disable hardware (RTS/CTS) flow control #ser.dsrdtr = False #disable hardware (DSR/DTR) flow control #ser.writeTimeout = 2 #timeout for write #try: # ser.open() #except Exception as e: # print('error open serial port: ' + str(e)) # exit() #ser.open() #ser.write('hello world!') #values = bytearray([4, 9, 62, 144, 56, 30, 147, 3, 210, 89, 111, 78, 184, 151, 17, 129]) #ser.write(values) #while True: # print(ser.readline()) #from serial import * #from Tkinter import * #serialPort = "/dev/ttyACM0" #baudRate = 9600 #ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking logEnable = 0; #~ temps = [20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220] temps = [] tick = 0 #~ tickArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] tickArray = [] tActArray = [] tSetArray = [] errArray = [] errSumArray = [] outOrigArray = [] outArray = [] def functionLog(): global logEnable if logEnable == 1: sendSerial([0xa3]) app.after(1000, functionLog) def sendSerial(input): print('send ' + str(len(input)) + ' byte(s): ' + str([hex(x) for x in input])) data = bytearray([0xff, 0xf1]) data.append(len(input)) data.extend(bytearray(input)) ser.write(data) def processData(input): global logEnable global w global temps global tick global tickArray global tActArray global tSetArray global errArray global errSumArray global outOrigArray global outArray print(str([hex(x) for x in input])) if input[0] == 0xa0: if input[1] == 0x00: log.insert(END, '> temp sensor 0 status: ' + str.join(':', ('%02x' % x for x in input[2:])) + '\n') elif input[1] == 0x01: log.insert(END, '> temp sensor 1 status: ' + str.join(':', ('%02x' % x for x in input[2:])) + '\n') elif input[0] == 0x10: if input[1] == 0x00: log.insert(END, '> adc: wrong channel\n') elif input[1] == 0x01: log.insert(END, '> adc: start cartridge resistance measurement\n') elif input[1] == 0x02: log.insert(END, '> adc: start cartridge current measurement\n') elif input[1] == 0x03: log.insert(END, '> adc: start cartridge temperature measurement\n') elif input[1] == 0x04: log.insert(END, '> adc: start input voltage measurement\n') elif input[1] == 0xff: log.insert(END, '> adc: pending measurement\n') elif input[0] == 0x11: if input[1] == 0x01: log.insert(END, '> raw_adc_cartridge_resistance: ' + str(((input[2] * 256) + input[3])) + '\n') elif input[1] == 0x02: log.insert(END, '> raw_adc_cartridge_current: ' + str(((input[2] * 256) + input[3])) + '\n') elif input[1] == 0x03: log.insert(END, '> raw_adc_cartridge_temperature: ' + str(((input[2] * 256) + input[3])) + '\n') elif input[1] == 0x04: log.insert(END, '> raw_adc_v_in: ' + str(((input[2] * 256) + input[3])) + '\n') elif input[1] == 100: # log.insert(END, '> raw_adc_cartridge_temperature_cycle: ' + str(((input[2] * 256) + input[3])) + '\n') log.insert(END, '> raw_adc_cartridge_temperature_cycle: ' + str(round(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661)) + ' degC\n') #~ tick = tick + 1 #~ tickArray.append(tick) #~ temps.append(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661) #~ tickArray = tickArray[-200:] #~ temps = temps[-200:] #~ ax1.clear() #~ ax1.set_ylim(0, 400) #~ ax1.plot(tickArray, temps, linewidth=2, color='black') #~ fig.canvas.draw() elif input[0] == 0x20: if input[1] == 0x00: log.insert(END, '> cartridge resistance measure disabled\n') elif input[1] == 0x01: log.insert(END, '> cartridge resistance measure enabled\n') elif input[0] == 0x21: if input[1] == 0x00: log.insert(END, '> power-mosfet disabled\n') elif input[1] == 0x01: log.insert(END, '> power-mosfet enabled\n') elif input[0] == 0x8d: cartridge_temperature_adc_raw = ((input[1] * 256) + input[2]) tAct = struct.unpack('>f', input[3:7]) tSet = struct.unpack('>f', input[7:11]) err = struct.unpack('>f', input[11:15]) errSum = struct.unpack('>f', input[15:19]) outOrig = struct.unpack('>f', input[19:23]) out = input[23] * 256 + input[24] if out > 32767: out -= 65536 log.insert(END, 'tAct: ' + str(tAct) + 'tSet: ' + str(tSet) + 'err: ' + str(err) + 'errSum: ' + str(errSum) + 'outOrig: ' + str(outOrig) + 'out: ' + str(out) + '\n') #~ tActArray.append(tAct) #~ tActArray = tActArray[-200:] #~ ax1.clear() #~ ax1.plot(tickArray, tActArray, linewidth=2, color='black') #~ fig.canvas.draw() else: log.insert(END, '> ' + str.join(':', ('%02x' % x for x in input)) + '\n') log.see("end") def btnClearAction(): log.delete(1.0,END) log.insert(END, str(datetime.now()) + '\n') def btnGetRawAdcCartridgeResistanceAction(): sendSerial([0x10, 0x01]) def btnGetRawAdcCartridgeCurrentAction(): sendSerial([0x10, 0x02]) def btnGetRawAdcCartridgeTemperatureAction(): sendSerial([0x10, 0x03]) def btnGetRawAdcInputVoltageAction(): sendSerial([0x10, 0x04]) def btnSetCartridgeResistanceMosfetOnAction(): sendSerial([0x20, 0x01]) def btnSetCartridgeResistanceMosfetOffAction(): sendSerial([0x20, 0x00]) def btnSetPowerMosfetOnAction(): sendSerial([0x91, 0x01, 0x18]) def btnSetPowerMosfetOffAction(): sendSerial([0x91, 0x00, 0x00]) def btnGetTempSensor0DegCAction(): sendSerial([0xa2, 0x00]) def btnGetTempSensor1DegCAction(): sendSerial([0xa2, 0x01]) def btnGetTempSensorsDegCAction(): sendSerial([0xa3]) def btnStartLogAction(): global logEnable global w w = open('reflow_oven_temperature_log', 'w') logEnable = 1 w.write('time;seconds;status;temperature;tAct;tSet;err;errSum;outOrig;out\n') sendSerial([0xa5]) #functionLog() def btnStopLogAction(): global logEnable global w sendSerial([0xa4, 0x00]) logEnable = 0 w.close() def btnDisablePwmAction(): sendSerial([0xb0, 0x00, 0x00]) def btnSetTemperature0Action(): sendSerial([0xb1, 0x00]) def btnSetTemperature80Action(): sendSerial([0xb1, 0x50]) def btnSetTemperature150Action(): sendSerial([0xb1, 0x96]) def btnSetTemperature180Action(): sendSerial([0xb1, 0xb4]) def btnSetTemperature245Action(): sendSerial([0xb1, 0xf5]) #make a TkInter Window app = Tk() app.wm_title("attiny817_solderstation_app") # Create figure for plotting fig = figure.Figure(figsize=(12, 4)) #~ fig.subplots_adjust(left=0.1, right=0.8) ax1 = fig.add_subplot(1, 1, 1) ax1.set_ylim(0, 400) #~ ax1.set_xlim(0, 20) # Create a Tk Canvas widget out of our figure canvas = FigureCanvasTkAgg(fig, master=app) canvas_plot = canvas.get_tk_widget() # make a scrollbar scrollbar = Scrollbar(app) scrollbar.pack(side=RIGHT, fill=Y) # make a text box to put the serial output log = Text (app, width=250, height=20, takefocus=0) log.pack() # attach text box to scrollbar log.config(yscrollcommand=scrollbar.set) scrollbar.config(command=log.yview) btnClear = Button(app, text='clear', command=btnClearAction) btnGetRawAdcCartridgeResistance = Button(app, text='getRawAdcCartridgeResistance', command=btnGetRawAdcCartridgeResistanceAction) btnGetRawAdcCartridgeCurrent = Button(app, text='getRawAdcCartridgeCurrent', command=btnGetRawAdcCartridgeCurrentAction) btnGetRawAdcCartridgeTemperature = Button(app, text='getRawAdcCartridgeTemperature', command=btnGetRawAdcCartridgeTemperatureAction) btnGetRawAdcInputVoltage = Button(app, text='getRawAdcInputVoltage', command=btnGetRawAdcInputVoltageAction) btnSetCartridgeResistanceMosfetOn = Button(app, text='setCartridgeResistanceMosfetOn', command=btnSetCartridgeResistanceMosfetOnAction) btnSetCartridgeResistanceMosfetOff = Button(app, text='setCartridgeResistanceMosfetOff', command=btnSetCartridgeResistanceMosfetOffAction) btnSetPowerMosfetOn = Button(app, text='setPowerMosfetOn', command=btnSetPowerMosfetOnAction) btnSetPowerMosfetOff = Button(app, text='setPowerMosfetOff', command=btnSetPowerMosfetOffAction) btnGetTempSensor0DegC = Button(app, text='getTempSensor0DegC', command=btnGetTempSensor0DegCAction) btnGetTempSensor1DegC = Button(app, text='getTempSensor1DegC', command=btnGetTempSensor1DegCAction) btnGetTempSensorsDegC = Button(app, text='getTempSensorsDegC', command=btnGetTempSensorsDegCAction) btnStartLog = Button(app, text='startLog', command=btnStartLogAction) btnStopLog = Button(app, text='stopLog', command=btnStopLogAction) btnDisablePwm = Button(app, text='STOP', command=btnDisablePwmAction) btnSetTemperature0 = Button(app, text='setTemperature0', command=btnSetTemperature0Action) btnSetTemperature80 = Button(app, text='setTemperature80', command=btnSetTemperature80Action) btnSetTemperature150 = Button(app, text='setTemperature150', command=btnSetTemperature150Action) btnSetTemperature180 = Button(app, text='setTemperature180', command=btnSetTemperature180Action) btnSetTemperature245 = Button(app, text='setTemperature245', command=btnSetTemperature245Action) btnClear.pack() canvas_plot.pack() btnGetRawAdcCartridgeResistance.pack() btnGetRawAdcCartridgeCurrent.pack() btnGetRawAdcCartridgeTemperature.pack() btnGetRawAdcInputVoltage.pack() btnSetCartridgeResistanceMosfetOn.pack() btnSetCartridgeResistanceMosfetOff.pack() btnSetPowerMosfetOn.pack() btnSetPowerMosfetOff.pack() #make our own buffer #useful for parsing commands #Serial.readline seems unreliable at times too rxInputBuffer = bytearray() rxStatemachine = 0 def readSerial(): while True: c = ser.read() # attempt to read a character from Serial #was anything read? if len(c) == 0: break else: #print('DATA') #log.insert(END, ':' + c.hex()) global rxInputBuffer global rxStatemachine rxInputBuffer.append(c[0]) if rxStatemachine == 0: if rxInputBuffer[0] == 0xff: rxStatemachine = 1 rxInputBuffer = rxInputBuffer[1:] elif rxStatemachine == 1: if rxInputBuffer[0] == 0xf1: rxStatemachine = 2 else: rxStatemachine = 0 rxInputBuffer = rxInputBuffer[1:] elif rxStatemachine == 2: if len(rxInputBuffer) >= rxInputBuffer[0] + 1: processData(rxInputBuffer[1:rxInputBuffer[0] + 1]) rxInputBuffer = bytearray() rxStatemachine = 0 else: if len(rxInputBuffer) > 256: print('rxInputBuffer reset!') rxInputBuffer = bytearray() rxStatemachine = 0 app.after(1, readSerial) # check serial again soon # after initializing serial, an arduino may need a bit of time to reset app.after(100, readSerial) app.mainloop()