|
#!/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()
|