@ -0,0 +1,399 @@ | |||
#!/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() |
@ -0,0 +1,444 @@ | |||
#!/usr/bin/env python3 | |||
import sys | |||
import getopt | |||
import glob | |||
import serial | |||
import struct | |||
import tkinter | |||
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk) | |||
# Implement the default Matplotlib key bindings. | |||
from matplotlib.backend_bases import key_press_handler | |||
from matplotlib.figure import Figure | |||
import numpy as np | |||
tempe = 0 | |||
tSetGlobal = 0.0 | |||
controllerDebugWindowOpen = 0 | |||
tick = 0 | |||
tickArray = [] | |||
tActArray = [] | |||
tSetArray = [] | |||
tickDebug = 0 | |||
tickDebugArray = [] | |||
tActDebugArray = [] | |||
tSetDebugArray = [] | |||
errDebugArray = [] | |||
errSumDebugArray = [] | |||
outOrigDebugArray = [] | |||
outDebugArray = [] | |||
outAvgDebugArray = [] | |||
sleepCounterDebugArray = [] | |||
rxInputBuffer = bytearray() | |||
rxStatemachine = 0 | |||
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) | |||
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 | |||
root.after(10, readSerial) # check serial again soon | |||
def processData(input): | |||
global tSetGlobal | |||
print([ "0x%02x" % b for b in input ]) | |||
# ~ print(str([hex(x) for x in input])) | |||
# ~ if input[0] == 0x11: | |||
# ~ if input[1] == 100: | |||
# ~ temperatureString.set(str(round(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661)) + "degC") | |||
# ~ processControllerDebugData(((input[2] * 256) + input[3]) * 0.4833149757 + 35.1689715661, 20, 10, 0, -10, -20) | |||
if input[0] == 0x33: | |||
print("debugDataEnabled") | |||
tickDebugArray.clear() | |||
tActDebugArray.clear() | |||
tSetDebugArray.clear() | |||
errDebugArray.clear() | |||
errSumDebugArray.clear() | |||
outOrigDebugArray.clear() | |||
outDebugArray.clear() | |||
outAvgDebugArray.clear() | |||
sleepCounterDebugArray.clear() | |||
elif input[0] == 0x34: | |||
print("debugDataDisabled") | |||
elif input[0] == 0x8d: | |||
cartridge_temperature_adc_raw = ((input[1] * 256) + input[2]) | |||
tAct = struct.unpack('>f', input[3:7])[0] | |||
tSet = struct.unpack('>f', input[7:11])[0] | |||
err = struct.unpack('>f', input[11:15])[0] | |||
errSum = struct.unpack('>f', input[15:19])[0] | |||
outOrig = struct.unpack('>f', input[19:23])[0] | |||
out = input[23] * 256 + input[24] | |||
outAvg = input[25] * 256 + input[26] | |||
sleepCounter = input[27] * 256 + input[28] | |||
if out > 32767: | |||
out -= 65536 | |||
tActString.set(str(round(tAct)) + "degC") | |||
tSetString.set("(" + str(round(tSet)) + "degC)") | |||
tSetGlobal = tSet | |||
processTemperatureData(tAct, tSet) | |||
processControllerDebugData(tAct, tSet, err, errSum, outOrig, out, outAvg, sleepCounter) | |||
elif input[0] == 0x8c: | |||
tAct = struct.unpack('>f', input[1:5])[0] | |||
tSet = struct.unpack('>f', input[5:9])[0] | |||
tActString.set(str(round(tAct)) + "degC") | |||
tSetString.set("(" + str(round(tSet)) + "degC)") | |||
tSetGlobal = tSet | |||
processTemperatureData(tAct, tSetGlobal) | |||
# ~ elif input[0] == 0x91: | |||
# ~ tSet = struct.unpack('>f', input[1:5])[0] | |||
# ~ tSetString.set("(" + str(round(tSet)) + "degC)") | |||
# ~ elif input[0] == 0x92: | |||
# ~ controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x93: | |||
# ~ controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x94: | |||
# ~ controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x95: | |||
# ~ controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x96: | |||
# ~ controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x97: | |||
# ~ controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x98: | |||
# ~ controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0])) | |||
# ~ elif input[0] == 0x99: | |||
# ~ controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0])) | |||
elif input[0] == 0xa0: | |||
controllerValueKpString.set("Kp: " + str(struct.unpack('>f', input[1:5])[0])) | |||
elif input[0] == 0xa1: | |||
controllerValueKiString.set("Ki: " + str(struct.unpack('>f', input[1:5])[0])) | |||
elif input[0] == 0xa2: | |||
controllerValueKdString.set("Kd: " + str(struct.unpack('>f', input[1:5])[0])) | |||
elif input[0] == 0xa3: | |||
controllerValueKitString.set("Kit: " + str(struct.unpack('>f', input[1:5])[0])) | |||
elif input[0] == 0xf0: | |||
tSet = struct.unpack('>f', input[1:5])[0] | |||
controllerKp = struct.unpack('>f', input[5:9])[0] | |||
controllerKi = struct.unpack('>f', input[9:13])[0] | |||
controllerKd = struct.unpack('>f', input[13:17])[0] | |||
controllerKit = struct.unpack('>f', input[17:21])[0] | |||
tSetString.set("(" + str(round(tSet)) + "degC)") | |||
tSetGlobal = tSet | |||
controllerValueKpString.set("Kp: " + str(controllerKp)) | |||
controllerValueKiString.set("Ki: " + str(controllerKi)) | |||
controllerValueKdString.set("Kd: " + str(controllerKd)) | |||
controllerValueKitString.set("Kit: " + str(controllerKit)) | |||
def sendSerial(payloadType, payload): | |||
# ~ print('send ' + str(len(input)) + ' byte(s): ' + str([hex(x) for x in input])) | |||
data = bytearray([0xff, 0xf1]) | |||
data.append(1 + len(payload)) | |||
data.append(payloadType) | |||
data.extend(bytearray(payload)) | |||
print("send " + str([ "0x%02x" % b for b in data ])) | |||
ser.write(data) | |||
def createNewWindow(): | |||
global controllerDebugWindowOpen | |||
newWindow = tkinter.Toplevel(root) | |||
newWindow.protocol("WM_DELETE_WINDOW", lambda: closeWindow(newWindow)) | |||
# ~ labelExample = tkinter.Label(master=newWindow, text="new window") | |||
# ~ labelExample.pack() | |||
canvas2 = FigureCanvasTkAgg(controllerDebugFigure, master=newWindow) # A tk.DrawingArea. | |||
canvas2.draw() | |||
canvas2.get_tk_widget().pack() | |||
controllerDebugWindowOpen = 1 | |||
def closeWindow(myVar): | |||
print("closeWindow " + str(myVar)) | |||
controllerDebugWindowOpen = 0 | |||
myVar.destroy() | |||
def increaseTemperature(): | |||
global tempe, temperatureString | |||
tempe = tempe + 10 | |||
temperatureString.set(str(tempe) + "degC") | |||
def processTemperatureData(tAct, tSet): | |||
global tick, tickArray, tActArray, tSetArray | |||
tickArray.append(tick) | |||
tickArray = tickArray[-30:] | |||
tick = tick + 1 | |||
tActArray.append(tAct) | |||
tActArray = tActArray[-30:] | |||
tSetArray.append(tSet) | |||
tSetArray = tSetArray[-30:] | |||
yMin = tSet - 10 | |||
yMax = tSet + 10 | |||
if min(tActArray) < yMin: | |||
yMin = min(tActArray) - 2 | |||
if max(tActArray) > yMax: | |||
yMax = max(tActArray) + 2 | |||
temperatureFigureAxis1.clear() | |||
temperatureFigureAxis1.plot(tickArray, tActArray, linewidth=1, color="black") | |||
temperatureFigureAxis1.plot(tickArray, tSetArray, linewidth=1, color="green") | |||
temperatureFigureAxis1.set_ylim(yMin, yMax) | |||
# ~ temperatureFigure.tight_layout() | |||
temperatureFigure.canvas.draw() | |||
def processControllerDebugData(tAct, tSet, err, errSum, outOrig, out, outAvg, sleepCounter): | |||
# ~ print("processControllerDebugData") | |||
global tickDebug, tickDebugArray, tActDebugArray, tSetDebugArray, errDebugArray, errSumDebugArray, outOrigDebugArray, outDebugArray, outAvgDebugArray, sleepCounterDebugArray | |||
global controllerDebugWindowOpen | |||
tickDebugArray.append(tickDebug) | |||
tickDebugArray = tickDebugArray[-1000:] | |||
tickDebug = tickDebug + 1 | |||
tActDebugArray.append(tAct) | |||
tActDebugArray = tActDebugArray[-1000:] | |||
tSetDebugArray.append(tSet) | |||
tSetDebugArray = tSetDebugArray[-1000:] | |||
errDebugArray.append(err) | |||
errDebugArray = errDebugArray[-1000:] | |||
errSumDebugArray.append(errSum) | |||
errSumDebugArray = errSumDebugArray[-1000:] | |||
outOrigDebugArray.append(outOrig) | |||
outOrigDebugArray = outOrigDebugArray[-1000:] | |||
outDebugArray.append(out) | |||
outDebugArray = outDebugArray[-1000:] | |||
outAvgDebugArray.append(outAvg) | |||
outAvgDebugArray = outAvgDebugArray[-1000:] | |||
sleepCounterDebugArray.append(sleepCounter) | |||
sleepCounterDebugArray = sleepCounterDebugArray[-1000:] | |||
if controllerDebugWindowOpen == 1: | |||
# ~ ax1.clear() | |||
# ~ ax1.plot(tickArray, tActArray, linewidth=2, color='black') | |||
# ~ fig.canvas.draw() | |||
controllerDebugFigureAxis1.clear() | |||
controllerDebugFigureAxis1.plot(tickDebugArray, tActDebugArray, linewidth=1, color="black", label="tAct") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, tSetDebugArray, linewidth=1, color="green", label="tSet") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, errDebugArray, linewidth=1, color="red", label="err") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, errSumDebugArray, linewidth=1, color="orange", label="errSum") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, outOrigDebugArray, linewidth=1, color="royalblue", label="outOrig") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, outDebugArray, linewidth=1, color="blueviolet", label="out") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, outAvgDebugArray, linewidth=1, color="blue", label="outAvg") | |||
controllerDebugFigureAxis1.plot(tickDebugArray, sleepCounterDebugArray, linewidth=1, color="grey", label="sleepCounter") | |||
controllerDebugFigureAxis1.legend(loc="lower left") | |||
controllerDebugFigureAxis1.set_ylim(-100, 1000) | |||
# ~ controllerDebugFigure.tight_layout() | |||
controllerDebugFigure.canvas.draw() | |||
root = tkinter.Tk() | |||
root.wm_title("Embedding in Tk") | |||
root.geometry("320x850") | |||
# ~ root.protocol("WM_DELETE_WINDOW", lambda: closeWindow(root)) | |||
# ~ fig = Figure(figsize=(5, 4), dpi=100) | |||
# ~ fig2 = Figure(figsize=(5, 4), dpi=100) | |||
# ~ t = np.arange(0, 3, .01) | |||
# ~ fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) | |||
# ~ fig2.add_subplot(111).plot(t, 2 * np.cos(2 * np.pi * t)) | |||
temperatureFigure = Figure(figsize=(3, 2)) | |||
temperatureFigureAxis1 = temperatureFigure.add_subplot(1, 1, 1) | |||
temperatureFigureAxis1.yaxis.set_label_position("right") | |||
temperatureFigureAxis1.yaxis.tick_right() | |||
temperatureFigure.tight_layout() | |||
controllerDebugFigure = Figure(figsize=(15, 9)) | |||
controllerDebugFigureAxis1 = controllerDebugFigure.add_subplot(1, 1, 1) | |||
controllerDebugFigureAxis1.yaxis.set_label_position("right") | |||
controllerDebugFigureAxis1.yaxis.tick_right() | |||
controllerDebugFigureAxis1.set_ylim(-200, 500) | |||
controllerDebugFigure.tight_layout() | |||
# ~ canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea. | |||
# ~ canvas.draw() | |||
# pack_toolbar=False will make it easier to use a layout manager later on. | |||
# ~ toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False) | |||
# ~ toolbar.update() | |||
# ~ canvas.mpl_connect("key_press_event", lambda event: print(f"you pressed {event.key}")) | |||
# ~ canvas.mpl_connect("key_press_event", key_press_handler) | |||
# ~ btn = tk.Button(root, text="Press", command=lambda: myFunction("See this worked!")) | |||
# ~ button = tkinter.Button(master=root, text="Quit", command=root.quit) | |||
buttonNewWindow = tkinter.Button(master=root, text="open controller debug window", command=createNewWindow) | |||
# Packing order is important. Widgets are processed sequentially and if there | |||
# is no space left, because the window is too small, they are not displayed. | |||
# The canvas is rather flexible in its size, so we pack it last which makes | |||
# sure the UI controls are displayed as long as possible. | |||
# ~ button.pack(side=tkinter.BOTTOM) | |||
buttonNewWindow.pack(side=tkinter.BOTTOM) | |||
# ~ toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X) | |||
# ~ canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1) | |||
tkinter.Button(master=root, text="set 330degC", command=lambda: sendSerial(0x91, [0x01, 0x4a])).pack() | |||
tkinter.Button(master=root, text="set 200degC", command=lambda: sendSerial(0x91, [0x00, 0xc8])).pack() | |||
tkinter.Button(master=root, text="set 0degC", command=lambda: sendSerial(0x91, [0x00, 0x00])).pack() | |||
tActString = tkinter.StringVar() | |||
tActString.set("0degC") | |||
tSetString = tkinter.StringVar() | |||
tSetString.set("(0degC)") | |||
controllerValueKpString = tkinter.StringVar() | |||
controllerValueKpString.set("Kp: 0") | |||
controllerValueKiString = tkinter.StringVar() | |||
controllerValueKiString.set("Ki: 0") | |||
controllerValueKdString = tkinter.StringVar() | |||
controllerValueKdString.set("Kd: 0") | |||
controllerValueKitString = tkinter.StringVar() | |||
controllerValueKitString.set("Kit: 0") | |||
tkinter.Label(master=root, textvariable=tActString, font=("Free Mono", 40)).pack() | |||
tkinter.Label(master=root, textvariable=tSetString, font=("Free Mono", 20)).pack() | |||
canvas = FigureCanvasTkAgg(temperatureFigure, master=root) # A tk.DrawingArea. | |||
canvas.draw() | |||
canvas.get_tk_widget().pack() | |||
# ~ tkinter.Button(master=root, text="Kp +1", command=lambda: sendSerial(0x92, [])).pack() | |||
tkinter.Label(master=root, textvariable=controllerValueKpString, font=("Free Mono", 20)).pack() | |||
textValueKp = tkinter.Text(master=root, height=1, width=20) | |||
textValueKp.pack() | |||
tkinter.Button(master=root, text="set Kp", command=lambda: sendSerial(0xa0, convertStringToFloatBytearray(textValueKp.get("1.0", "end-1c")))).pack() | |||
# ~ tkinter.Button(master=root, text="Kp -1", command=lambda: sendSerial(0x93, [])).pack() | |||
# ~ tkinter.Button(master=root, text="Ki +1", command=lambda: sendSerial(0x94, [])).pack() | |||
tkinter.Label(master=root, textvariable=controllerValueKiString, font=("Free Mono", 20)).pack() | |||
textValueKi = tkinter.Text(master=root, height=1, width=20) | |||
textValueKi.pack() | |||
tkinter.Button(master=root, text="set Ki", command=lambda: sendSerial(0xa1, convertStringToFloatBytearray(textValueKi.get("1.0", "end-1c")))).pack() | |||
# ~ tkinter.Button(master=root, text="Ki -1", command=lambda: sendSerial(0x95, [])).pack() | |||
# ~ tkinter.Button(master=root, text="Kd +1", command=lambda: sendSerial(0x96, [])).pack() | |||
tkinter.Label(master=root, textvariable=controllerValueKdString, font=("Free Mono", 20)).pack() | |||
textValueKd = tkinter.Text(master=root, height=1, width=20) | |||
textValueKd.pack() | |||
tkinter.Button(master=root, text="set Kd", command=lambda: sendSerial(0xa2, convertStringToFloatBytearray(textValueKd.get("1.0", "end-1c")))).pack() | |||
# ~ tkinter.Button(master=root, text="Kd -1", command=lambda: sendSerial(0x97, [])).pack() | |||
# ~ tkinter.Button(master=root, text="Kit +1", command=lambda: sendSerial(0x98, [])).pack() | |||
tkinter.Label(master=root, textvariable=controllerValueKitString, font=("Free Mono", 20)).pack() | |||
textValueKit = tkinter.Text(master=root, height=1, width=20) | |||
textValueKit.pack() | |||
tkinter.Button(master=root, text="set Kit", command=lambda: sendSerial(0xa3, convertStringToFloatBytearray(textValueKit.get("1.0", "end-1c")))).pack() | |||
# ~ tkinter.Button(master=root, text="Kit -1", command=lambda: sendSerial(0x99, [])).pack() | |||
tkinter.Button(master=root, text="enable debug data", command=lambda: sendSerial(0x33, [])).pack() | |||
tkinter.Button(master=root, text="disable debug data", command=lambda: sendSerial(0x34, [])).pack() | |||
# ~ tkinter.Button(master=root, text="init", command=lambda: sendSerial(0xf0, [])).pack() | |||
def convertStringToFloatBytearray(inputString): | |||
try: | |||
floatValue = float(inputString) | |||
byteArrayValue = bytearray(struct.pack('>f', floatValue)) | |||
# ~ print(str(floatValue)) | |||
# ~ print([ "0x%02x" % b for b in byteArrayValue ]) | |||
return byteArrayValue | |||
except: | |||
print("can not convert [" + inputString + "] to float!") | |||
return [] | |||
root.after(100, readSerial) | |||
sendSerial(0xf0, []) | |||
tkinter.mainloop() |
@ -0,0 +1,933 @@ | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include <util/delay.h> | |||
#include "main.h" | |||
#define DEF_F_BAUD 19200 | |||
#define DEF_BAUD 64 * F_CPU / 16 / DEF_F_BAUD | |||
#define ADC_MUXPOS_CARTRIDGE_RESISTANCE ADC_MUXPOS_AIN4_gc | |||
#define ADC_MUXPOS_CARTRIDGE_CURRENT ADC_MUXPOS_AIN7_gc | |||
#define ADC_MUXPOS_CARTRIDGE_TEMPERATURE ADC_MUXPOS_AIN8_gc | |||
#define ADC_MUXPOS_V_IN ADC_MUXPOS_AIN9_gc | |||
#define BUFFER_SIZE (64) | |||
volatile uint8_t debugRxStateMachine = 0x00; | |||
volatile uint8_t debugRxBuffer[BUFFER_SIZE]; | |||
volatile uint8_t debugRxBufferIndex = 0; | |||
volatile uint8_t debugRxFrameLength = 0; | |||
volatile uint8_t debugTxStateMachine = 0x00; | |||
volatile uint8_t debugTxBuffer[BUFFER_SIZE]; | |||
volatile uint8_t debugTxBufferIndex = 0; | |||
volatile uint8_t debugTxFrameLength = 0; | |||
volatile uint8_t adc_channel = 0; | |||
volatile uint8_t adc_counter = 0; | |||
volatile uint16_t cartridge_temperature_data[8]; | |||
volatile uint8_t cartridge_temperature_data_pointer = 0; | |||
//~ volatile uint8_t out_data[32]; | |||
//~ volatile uint8_t out_data_pointer = 0; | |||
volatile uint16_t sleep_kp_value = 0; | |||
volatile uint16_t sleep_counter = 0; | |||
volatile uint8_t sleep_state = 1; | |||
volatile uint16_t out_avg = 0; | |||
volatile int8_t out_avg_counter = 0; | |||
#define Kp 30 | |||
#define Kd 0 | |||
#define Ki 0.5 | |||
#define Kit 400 | |||
#define errSumMax 1 / Ki * Kit | |||
volatile float controllerKp = 0; | |||
volatile float controllerKpBuff = Kp; | |||
volatile uint8_t controllerKpBuffFlag = 1; | |||
volatile float controllerKd = 0; | |||
volatile float controllerKdBuff = Kd; | |||
volatile uint8_t controllerKdBuffFlag = 1; | |||
volatile float controllerKi = 0; | |||
volatile float controllerKiBuff = Ki; | |||
volatile uint8_t controllerKiBuffFlag = 1; | |||
volatile float controllerKit = 0; | |||
volatile float controllerKitBuff = Kit; | |||
volatile uint8_t controllerKitBuffFlag = 1; | |||
volatile float controllerErrSumMax = 0; | |||
volatile float tSet = 0; | |||
volatile float tSetBuff = 200; | |||
volatile uint8_t tSetBuffFlag = 1; | |||
#define OUT_MAX 800 | |||
volatile float tAct = 0; | |||
volatile float err = 0; | |||
volatile float errAlt = 0; | |||
volatile float errSum = 0; | |||
volatile float outOrig = 0; | |||
volatile uint16_t out = 0; | |||
volatile uint16_t outOld = 0; | |||
volatile uint8_t outSettlingCounter = 0; | |||
volatile uint8_t outSettlingState = 0; | |||
volatile uint8_t debugDataEnable = 0; | |||
void DebugAppendData(uint8_t data) | |||
{ | |||
if (debugTxStateMachine == 0x00) | |||
{ | |||
if (debugTxFrameLength < BUFFER_SIZE) | |||
{ | |||
debugTxBuffer[debugTxFrameLength] = data; | |||
debugTxFrameLength++; | |||
} | |||
} | |||
} | |||
void DebugSendData(void) | |||
{ | |||
if (debugTxStateMachine == 0x00) | |||
{ | |||
debugTxStateMachine = 0x01; | |||
while ((USART0.STATUS & 0b00100000) == 0) {} | |||
USART0.CTRLA |= 0b00100000; | |||
USART0.TXDATAL = 0xff; | |||
} | |||
} | |||
ISR(USART0_RXC_vect) | |||
{ | |||
uint8_t data = USART0.RXDATAL; | |||
switch (debugRxStateMachine) | |||
{ | |||
case 0x00: | |||
if (data == 0xff) | |||
{ | |||
debugRxStateMachine = 0x01; | |||
} | |||
break; | |||
case 0x01: | |||
if (data == 0xf1) | |||
{ | |||
debugRxStateMachine = 0x02; | |||
} | |||
else | |||
{ | |||
debugRxStateMachine = 0x00; | |||
} | |||
break; | |||
case 0x02: | |||
debugRxFrameLength = data; | |||
if (debugRxFrameLength <= BUFFER_SIZE) | |||
{ | |||
debugRxStateMachine = 0x03; | |||
} | |||
else | |||
{ | |||
debugRxStateMachine = 0xff; | |||
} | |||
break; | |||
case 0x03: | |||
if (debugRxBufferIndex < BUFFER_SIZE) | |||
{ | |||
debugRxBuffer[debugRxBufferIndex] = data; | |||
debugRxBufferIndex++; | |||
if (debugRxBufferIndex >= debugRxFrameLength) | |||
{ | |||
debugRxBufferIndex = 0; | |||
debugRxStateMachine = 0x04; | |||
} | |||
} | |||
else | |||
{ | |||
debugRxStateMachine = 0xff; | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
ISR(USART0_DRE_vect) | |||
{ | |||
switch (debugTxStateMachine) | |||
{ | |||
case 0x01: | |||
debugTxStateMachine = 0x02; | |||
USART0.TXDATAL = 0xf1; | |||
break; | |||
case 0x02: | |||
debugTxStateMachine = 0x03; | |||
debugTxBufferIndex = 0; | |||
USART0.TXDATAL = debugTxFrameLength; | |||
break; | |||
case 0x03: | |||
if (debugTxBufferIndex == debugTxFrameLength - 1) | |||
{ | |||
debugTxStateMachine = 0x04; | |||
} | |||
USART0.TXDATAL = debugTxBuffer[debugTxBufferIndex]; | |||
debugTxBufferIndex++; | |||
break; | |||
case 0x04: | |||
USART0.CTRLA &= 0b11011111; | |||
debugTxFrameLength = 0; | |||
debugTxStateMachine = 0; | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
ISR(ADC0_RESRDY_vect) | |||
{ | |||
//~ uint16_t adc_value = ADC0.RES >> 5; | |||
uint16_t adc_value = ADC0.RES; | |||
switch (adc_channel) | |||
{ | |||
case 100: | |||
cartridge_temperature_data[cartridge_temperature_data_pointer] = adc_value; | |||
cartridge_temperature_data_pointer++; | |||
cartridge_temperature_data_pointer &= 7; | |||
uint16_t cartridge_temperature = 0; | |||
for (uint8_t i = 0; i < 8; i++) | |||
{ | |||
cartridge_temperature += cartridge_temperature_data[i]; | |||
} | |||
cartridge_temperature >>= 3; | |||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |||
if (tSetBuffFlag > 0) | |||
{ | |||
tSet = tSetBuff; | |||
tSetBuffFlag = 0; | |||
if (tSet > 250) | |||
{ | |||
sleep_state = 0; | |||
sleep_counter = 0; | |||
} | |||
else | |||
{ | |||
sleep_state++; | |||
} | |||
} | |||
if (controllerKpBuffFlag > 0) | |||
{ | |||
controllerKp = controllerKpBuff; | |||
controllerKpBuffFlag = 0; | |||
sleep_kp_value = (uint16_t) (controllerKp * 2.0); | |||
} | |||
if (controllerKdBuffFlag > 0) | |||
{ | |||
controllerKd = controllerKdBuff; | |||
controllerKdBuffFlag = 0; | |||
} | |||
if (controllerKiBuffFlag > 0) | |||
{ | |||
if (controllerKiBuff == 0) | |||
{ | |||
controllerKiBuff = 1; | |||
} | |||
controllerKi = controllerKiBuff; | |||
controllerErrSumMax = 1 / controllerKi * controllerKit; | |||
controllerKiBuffFlag = 0; | |||
} | |||
if (controllerKitBuffFlag > 0) | |||
{ | |||
controllerKit = controllerKitBuff; | |||
controllerErrSumMax = 1 / controllerKi * controllerKit; | |||
controllerKitBuffFlag = 0; | |||
} | |||
float m = 0.4833149757, b = 35.1689715661; | |||
tAct = ((float) cartridge_temperature) * m + b; | |||
err = tSet - tAct; | |||
errSum = errSum + err; | |||
if (errSum < -controllerErrSumMax) | |||
{ | |||
errSum = -controllerErrSumMax; | |||
} | |||
if (errSum > controllerErrSumMax) | |||
{ | |||
errSum = controllerErrSumMax; | |||
} | |||
outOrig = controllerKp * err + controllerKi * errSum + controllerKd * (err - errAlt); | |||
errAlt = err; | |||
outOld = out; | |||
if (outOrig < 0) | |||
{ | |||
out = 0; | |||
} | |||
else if (outOrig > OUT_MAX) | |||
{ | |||
out = OUT_MAX; | |||
} | |||
else | |||
{ | |||
out = (uint16_t) outOrig; | |||
} | |||
TCA0.SINGLE.CMP0BUF = out; | |||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |||
if (out == 0 || out == OUT_MAX) | |||
{ | |||
outSettlingState = 0; | |||
outSettlingCounter = 0; | |||
} | |||
else | |||
{ | |||
if (outSettlingState == 0) | |||
{ | |||
outSettlingCounter++; | |||
int16_t outDiff = (int16_t) (out - outOld); | |||
if (outDiff > 25) | |||
{ | |||
outSettlingCounter = 0; | |||
} | |||
if (outDiff < -25) | |||
{ | |||
outSettlingCounter = 0; | |||
} | |||
if (outSettlingCounter > 180) | |||
{ | |||
outSettlingState = 1; | |||
} | |||
} | |||
} | |||
if (outSettlingState == 0) | |||
{ | |||
out_avg = out; | |||
} | |||
else | |||
{ | |||
if (out > out_avg) | |||
{ | |||
if (out < out_avg + sleep_kp_value) | |||
{ | |||
out_avg_counter++; | |||
} | |||
//~ out_avg_counter++; | |||
} | |||
else if (out < out_avg) | |||
{ | |||
out_avg_counter--; | |||
} | |||
if (out_avg_counter > 10) | |||
{ | |||
if (out_avg < 800) | |||
{ | |||
out_avg++; | |||
} | |||
out_avg_counter = 0; | |||
} | |||
else if (out_avg_counter < -3) | |||
{ | |||
if (out_avg > 0) | |||
{ | |||
out_avg--; | |||
} | |||
out_avg_counter = 0; | |||
} | |||
if (sleep_state == 0) | |||
{ | |||
sleep_counter++; | |||
} | |||
if (out > out_avg + sleep_kp_value) | |||
{ | |||
sleep_counter = 0; | |||
if (sleep_state > 0) | |||
{ | |||
tSetBuff = 330; | |||
tSetBuffFlag++; | |||
sleep_state = 0; | |||
} | |||
} | |||
if (sleep_counter > 2350) | |||
{ | |||
tSetBuff = 200; | |||
tSetBuffFlag++; | |||
sleep_counter = 0; | |||
sleep_state++; | |||
} | |||
} | |||
//~ if (adc_counter > 4) | |||
//~ { | |||
//~ out_data[out_data_pointer] = (uint8_t) (out >> 2); | |||
//~ out_data_pointer++; | |||
//~ out_data_pointer &= 31; | |||
//~ out_avg = 0; | |||
//~ for (uint8_t i = 0; i < 32; i++) | |||
//~ { | |||
//~ out_avg += out_data[i]; | |||
//~ } | |||
//~ out_avg >>= 3; | |||
//~ } | |||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |||
if (adc_counter > 8) | |||
{ | |||
adc_counter = 0; | |||
if (debugDataEnable > 0) | |||
{ | |||
DebugAppendData(0x8d); | |||
DebugAppendData((uint8_t) (cartridge_temperature >> 8)); | |||
DebugAppendData((uint8_t) (cartridge_temperature)); | |||
uint32_t value = *(uint32_t*) &tAct; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &tSet; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &err; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &errSum; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &outOrig; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
DebugAppendData((uint8_t) ((out & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (out & 0x00FF)); | |||
DebugAppendData((uint8_t) ((out_avg & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (out_avg & 0x00FF)); | |||
DebugAppendData((uint8_t) ((sleep_counter & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (sleep_counter & 0x00FF)); | |||
DebugSendData(); | |||
} | |||
else | |||
{ | |||
DebugAppendData(0x8c); | |||
uint32_t value = *(uint32_t*) &tAct; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &tSet; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
DebugSendData(); | |||
} | |||
} | |||
else | |||
{ | |||
adc_counter++; | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
//~ if (adc_channel < 100) | |||
//~ { | |||
//~ DebugAppendData(0x11); | |||
//~ DebugAppendData(adc_channel); | |||
//~ DebugAppendData((uint8_t) (adc_value >> 8)); | |||
//~ DebugAppendData((uint8_t) (adc_value)); | |||
//~ DebugSendData(); | |||
//~ } | |||
//~ else | |||
//~ { | |||
//~ } | |||
adc_channel = 0; | |||
} | |||
ISR(TCA0_CMP1_vect) | |||
{ | |||
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_CMP1_bm; | |||
VREF.CTRLA = VREF_ADC0REFSEL_1V5_gc | VREF_DAC0REFSEL_0V55_gc; | |||
ADC0.MUXPOS = ADC_MUXPOS_CARTRIDGE_TEMPERATURE; | |||
_delay_us(10); | |||
ADC0.COMMAND = ADC_STCONV_bm; | |||
adc_channel = 100; | |||
} | |||
int main(void) | |||
{ | |||
CPU_CCP = CCP_IOREG_gc; | |||
//~ CLKCTRL.MCLKCTRLB = CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm; | |||
CLKCTRL.MCLKCTRLB = 0; | |||
/* | |||
* PA2: power_mosfet | |||
* PA4: cartridge_resistance_measure (AIN4) | |||
* PA7: cartridge_current_measure (AIN7) | |||
*/ | |||
PORTA.DIR = 0b00000100; | |||
PORTA.OUT = 0b00000000; | |||
//~ PORTA.INTFLAGS = ; | |||
//~ PORTA.PIN0CTRL = ; | |||
//~ PORTA.PIN1CTRL = ; | |||
//~ PORTA.PIN2CTRL = ; | |||
//~ PORTA.PIN3CTRL = ; | |||
PORTA.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc; | |||
//~ PORTA.PIN5CTRL = ; | |||
//~ PORTA.PIN6CTRL = ; | |||
PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc; | |||
/* | |||
* PB2: TxD | |||
* PB3: RxD | |||
* PB4: v_in_measure (AIN9) | |||
* PB5: cartridge_temperature_measure (AIN8) | |||
*/ | |||
PORTB.DIR = 0b00000100; | |||
PORTB.OUT = 0b00001000; | |||
//~ PORTB.INTFLAGS = ; | |||
//~ PORTB.PIN0CTRL = ; | |||
//~ PORTB.PIN1CTRL = ; | |||
//~ PORTB.PIN2CTRL = ; | |||
//~ PORTB.PIN3CTRL = ; | |||
PORTB.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc; | |||
PORTB.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc; | |||
//~ PORTB.PIN6CTRL = ; | |||
//~ PORTB.PIN7CTRL = ; | |||
/* | |||
* PC0: measure_mosfet | |||
*/ | |||
PORTC.DIR = 0b00000001; | |||
PORTC.OUT = 0b00000000; | |||
//~ PORTC.INTFLAGS = ; | |||
//~ PORTC.PIN0CTRL = ; | |||
//~ PORTC.PIN1CTRL = ; | |||
//~ PORTC.PIN2CTRL = ; | |||
//~ PORTC.PIN3CTRL = ; | |||
//~ PORTC.PIN4CTRL = ; | |||
//~ PORTC.PIN5CTRL = ; | |||
// configure USART | |||
USART0.BAUD = DEF_BAUD; | |||
USART0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_SBMODE_1BIT_gc | USART_CHSIZE_8BIT_gc; | |||
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm | USART_RXMODE_NORMAL_gc; | |||
USART0.CTRLA = USART_RXCIE_bm | USART_RS485_OFF_gc; | |||
//~ while (RTC.STATUS > 0) {} // Wait for all register to be synchronized | |||
//~ RTC.CLKSEL = 0b00000000; | |||
//~ //RTC.CNTL = 0; | |||
//~ //RTC.CNTH = 0; | |||
//~ //RTC.CMPL = 10; | |||
//~ //RTC.CMPH = 0; | |||
//~ RTC.PERL = 0; | |||
//~ RTC.PERH = 134; | |||
//~ RTC.INTCTRL = 0b00000010; | |||
//~ RTC.CTRLA = 0b10000001; | |||
// configure VREF | |||
VREF.CTRLA = VREF_ADC0REFSEL_0V55_gc | VREF_DAC0REFSEL_0V55_gc; | |||
VREF.CTRLB = VREF_ADC0REFEN_bm | VREF_DAC0REFEN_bm; | |||
// configure ADC | |||
ADC0.CTRLB = ADC_SAMPNUM_ACC1_gc; | |||
ADC0.CTRLC = ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV256_gc; | |||
ADC0.CTRLD = ADC_INITDLY_DLY0_gc; | |||
ADC0.CTRLE = ADC_WINCM_NONE_gc; | |||
ADC0.MUXPOS = ADC_MUXPOS_CARTRIDGE_RESISTANCE; | |||
ADC0.INTCTRL = ADC_RESRDY_bm; | |||
ADC0.CTRLA = ADC_ENABLE_bm; | |||
// configure DAC | |||
DAC0.DATA = 112; | |||
DAC0.CTRLA = DAC_RUNSTDBY_bm |DAC_ENABLE_bm; | |||
// configure AC0 | |||
AC0.MUXCTRLA = AC_MUXPOS_PIN0_gc | AC_MUXNEG_DAC_gc; | |||
AC0.CTRLA = AC_RUNSTDBY_bm | AC_ENABLE_bm; | |||
//~ AC0.CTRLA = AC_RUNSTDBY_bm | AC_OUTEN_bm | AC_LPMODE_bm | AC_ENABLE_bm; | |||
// configure TCA0 | |||
TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; | |||
TCA0.SINGLE.INTCTRL = TCA_SINGLE_CMP1EN_bm; | |||
TCA0.SINGLE.CNT = 0; | |||
TCA0.SINGLE.PER = 976; | |||
TCA0.SINGLE.CMP0BUF = 0; | |||
TCA0.SINGLE.CMP1BUF = 900; | |||
// configure TCB0 | |||
TCB0.CTRLB = TCB_ASYNC_bm | TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc; | |||
TCB0.EVCTRL = TCB_CAPTEI_bm; | |||
TCB0.CCMP = 50; | |||
TCB0.CNT = 0; | |||
// configure CCL | |||
CCL.SEQCTRL0 = CCL_SEQSEL_RS_gc; | |||
//~ CCL.LUT0CTRLB = CCL_INSEL1_AC0_gc | CCL_INSEL0_TCA0_gc; | |||
//~ CCL.TRUTH0 = 0b00001010; | |||
//~ CCL.LUT0CTRLB = CCL_INSEL1_TCB0_gc; | |||
//~ CCL.LUT0CTRLB = CCL_INSEL0_TCA0_gc; | |||
CCL.LUT0CTRLB = CCL_INSEL1_TCB0_gc | CCL_INSEL0_TCA0_gc; | |||
CCL.LUT0CTRLC = CCL_INSEL2_FEEDBACK_gc; | |||
CCL.TRUTH0 = 0b00000010; | |||
CCL.LUT0CTRLA = CCL_EDGEDET_bm | CCL_ENABLE_bm; | |||
//~ CCL.LUT1CTRLB = CCL_INSEL1_AC0_gc | CCL_INSEL0_TCA0_gc; | |||
//~ CCL.TRUTH1 = 0b00001101; | |||
CCL.LUT1CTRLB = CCL_INSEL1_AC0_gc | CCL_INSEL0_TCA0_gc; | |||
CCL.TRUTH1 = 0b00001101; | |||
//~ CCL.LUT1CTRLA = CCL_EDGEDET_bm | CCL_FILTSEL_SYNCH_gc | CCL_ENABLE_bm; | |||
CCL.LUT1CTRLA = CCL_ENABLE_bm; | |||
CCL.CTRLA = CCL_ENABLE_bm; | |||
// configure EVSYS | |||
EVSYS.ASYNCCH0 = EVSYS_ASYNCCH0_CCL_LUT0_gc; | |||
EVSYS.ASYNCCH1 = EVSYS_ASYNCCH1_AC0_OUT_gc; | |||
EVSYS.ASYNCUSER_EVOUT0 = EVSYS_ASYNCUSER_ASYNCCH0_gc; | |||
EVSYS.ASYNCUSER_TCB0 = EVSYS_ASYNCUSER_ASYNCCH1_gc; | |||
//~ EVSYS.ASYNCUSER_CCL_LUT0EV0 = EVSYS_ASYNCUSER_ASYNCCH2_gc; | |||
PORTMUX.CTRLA = PORTMUX_EVOUT0_bm; | |||
sei(); | |||
TCB0.CTRLA = TCB_ENABLE_bm; | |||
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc | TCA_SINGLE_ENABLE_bm; | |||
//~ _delay_ms(2000); | |||
//~ DebugAppendData(0xab); | |||
//~ DebugAppendData(0xcd); | |||
//~ DebugAppendData(0xef); | |||
//~ DebugSendData(); | |||
uint32_t value; | |||
while(1) | |||
{ | |||
/* | |||
* debug protocol: 0xff, 0xf1, [length_of_data], [data] | |||
*/ | |||
if (debugRxStateMachine == 0x04) | |||
{ | |||
switch (debugRxBuffer[0]) | |||
{ | |||
//~ case 0x10: | |||
//~ DebugAppendData(debugRxBuffer[0]); | |||
//~ if (adc_channel == 0) | |||
//~ { | |||
//~ switch (debugRxBuffer[1]) | |||
//~ { | |||
//~ case 1: | |||
//~ VREF.CTRLA = VREF_ADC0REFSEL_0V55_gc | VREF_DAC0REFSEL_0V55_gc; | |||
//~ ADC0.MUXPOS = ADC_MUXPOS_CARTRIDGE_RESISTANCE; | |||
//~ _delay_us(10); | |||
//~ ADC0.COMMAND = ADC_STCONV_bm; | |||
//~ adc_channel = 1; | |||
//~ break; | |||
//~ case 2: | |||
//~ VREF.CTRLA = VREF_ADC0REFSEL_0V55_gc | VREF_DAC0REFSEL_0V55_gc; | |||
//~ ADC0.MUXPOS = ADC_MUXPOS_CARTRIDGE_CURRENT; | |||
//~ _delay_us(10); | |||
//~ ADC0.COMMAND = ADC_STCONV_bm; | |||
//~ adc_channel = 2; | |||
//~ break; | |||
//~ case 3: | |||
//~ VREF.CTRLA = VREF_ADC0REFSEL_0V55_gc | VREF_DAC0REFSEL_0V55_gc; | |||
//~ ADC0.MUXPOS = ADC_MUXPOS_CARTRIDGE_TEMPERATURE; | |||
//~ _delay_us(10); | |||
//~ ADC0.COMMAND = ADC_STCONV_bm; | |||
//~ adc_channel = 3; | |||
//~ break; | |||
//~ case 4: | |||
//~ VREF.CTRLA = VREF_ADC0REFSEL_4V34_gc | VREF_DAC0REFSEL_0V55_gc; | |||
//~ ADC0.MUXPOS = ADC_MUXPOS_V_IN; | |||
//~ _delay_us(10); | |||
//~ ADC0.COMMAND = ADC_STCONV_bm; | |||
//~ adc_channel = 4; | |||
//~ break; | |||
//~ default: | |||
//~ break; | |||
//~ } | |||
//~ DebugAppendData(adc_channel); | |||
//~ } | |||
//~ else | |||
//~ { | |||
//~ DebugAppendData(255); | |||
//~ } | |||
//~ break; | |||
//~ case 0x20: | |||
//~ DebugAppendData(debugRxBuffer[0]); | |||
//~ if (debugRxBuffer[1] > 0) | |||
//~ { | |||
//~ PORTC.OUTSET = 0b00000001; | |||
//~ DebugAppendData(1); | |||
//~ } | |||
//~ else | |||
//~ { | |||
//~ PORTC.OUTCLR = 0b00000001; | |||
//~ DebugAppendData(0); | |||
//~ } | |||
//~ break; | |||
case 0x33: | |||
DebugAppendData(debugRxBuffer[0]); | |||
debugDataEnable = 1; | |||
break; | |||
case 0x34: | |||
DebugAppendData(debugRxBuffer[0]); | |||
debugDataEnable = 0; | |||
break; | |||
case 0x91: | |||
DebugAppendData(debugRxBuffer[0]); | |||
uint16_t receivedTemperatureSet = (uint16_t) (debugRxBuffer[1] * 256 + debugRxBuffer[2]); | |||
if (receivedTemperatureSet > 400) | |||
{ | |||
receivedTemperatureSet = 400; | |||
} | |||
tSetBuff = (float) receivedTemperatureSet; | |||
tSetBuffFlag++; | |||
value = *(uint32_t*) &tSetBuff; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
case 0xa0: | |||
DebugAppendData(debugRxBuffer[0]); | |||
value = ((uint32_t) debugRxBuffer[1]) << 24 | ((uint32_t) debugRxBuffer[2]) << 16 | ((uint32_t) debugRxBuffer[3]) << 8 | ((uint32_t) debugRxBuffer[4]); | |||
controllerKpBuff = *(float*) &value; | |||
controllerKpBuffFlag++; | |||
value = *(uint32_t*) &controllerKpBuff; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
case 0xa1: | |||
DebugAppendData(debugRxBuffer[0]); | |||
value = ((uint32_t) debugRxBuffer[1]) << 24 | ((uint32_t) debugRxBuffer[2]) << 16 | ((uint32_t) debugRxBuffer[3]) << 8 | ((uint32_t) debugRxBuffer[4]); | |||
controllerKiBuff = *(float*) &value; | |||
controllerKiBuffFlag++; | |||
value = *(uint32_t*) &controllerKiBuff; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
case 0xa2: | |||
DebugAppendData(debugRxBuffer[0]); | |||
value = ((uint32_t) debugRxBuffer[1]) << 24 | ((uint32_t) debugRxBuffer[2]) << 16 | ((uint32_t) debugRxBuffer[3]) << 8 | ((uint32_t) debugRxBuffer[4]); | |||
controllerKdBuff = *(float*) &value; | |||
controllerKdBuffFlag++; | |||
value = *(uint32_t*) &controllerKdBuff; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
case 0xa3: | |||
DebugAppendData(debugRxBuffer[0]); | |||
value = ((uint32_t) debugRxBuffer[1]) << 24 | ((uint32_t) debugRxBuffer[2]) << 16 | ((uint32_t) debugRxBuffer[3]) << 8 | ((uint32_t) debugRxBuffer[4]); | |||
controllerKitBuff = *(float*) &value; | |||
controllerKitBuffFlag++; | |||
value = *(uint32_t*) &controllerKitBuff; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
case 0xf0: | |||
DebugAppendData(debugRxBuffer[0]); | |||
value = *(uint32_t*) &tSet; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &controllerKp; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &controllerKi; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &controllerKd; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
value = *(uint32_t*) &controllerKit; | |||
DebugAppendData((uint8_t) ((value & 0xFF000000) >> 24)); | |||
DebugAppendData((uint8_t) ((value & 0xFF0000) >> 16)); | |||
DebugAppendData((uint8_t) ((value & 0xFF00) >> 8)); | |||
DebugAppendData((uint8_t) (value & 0x00FF)); | |||
break; | |||
default: | |||
DebugAppendData(0xff); | |||
DebugAppendData(0xde); | |||
DebugAppendData(0xad); | |||
DebugAppendData(0xbe); | |||
DebugAppendData(0xef); | |||
break; | |||
} | |||
DebugSendData(); | |||
debugRxFrameLength = 0; | |||
debugRxStateMachine = 0x00; | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
#ifndef _AVR_ATTINY817_H_INCLUDED | |||
# error "<avr/iotn817.h> must be included before this file." | |||
#endif | |||
/* | |||
-------------------------------------------------------------------------- | |||
EVSYS - Event System | |||
-------------------------------------------------------------------------- | |||
*/ | |||
#define ASYNCUSER_TCB0 ASYNCUSER0 | |||
#define ASYNCUSER_ADC0 ASYNCUSER1 | |||
#define ASYNCUSER_CCL_LUT0EV0 ASYNCUSER2 | |||
#define ASYNCUSER_CCL_LUT1EV0 ASYNCUSER3 | |||
#define ASYNCUSER_CCL_LUT0EV1 ASYNCUSER4 | |||
#define ASYNCUSER_CCL_LUT1EV1 ASYNCUSER5 | |||
#define ASYNCUSER_TCD0_EV0 ASYNCUSER6 | |||
#define ASYNCUSER_TCD0_EV1 ASYNCUSER7 | |||
#define ASYNCUSER_EVOUT0 ASYNCUSER8 | |||
#define ASYNCUSER_EVOUT1 ASYNCUSER9 | |||
#define ASYNCUSER_EVOUT2 ASYNCUSER10 | |||
#define SYNCUSER_TCA0 SYNCUSER0 | |||
#define SYNCUSER_USART0 SYNCUSER1 | |||
/* Asynchronous User Ch x Input Selection */ | |||
typedef enum EVSYS_ASYNCUSER_enum | |||
{ | |||
EVSYS_ASYNCUSER_OFF_gc = (0x00<<0), /* Off */ | |||
EVSYS_ASYNCUSER_SYNCCH0_gc = (0x01<<0), /* Synchronous Event Channel 0 */ | |||
EVSYS_ASYNCUSER_SYNCCH1_gc = (0x02<<0), /* Synchronous Event Channel 1 */ | |||
EVSYS_ASYNCUSER_ASYNCCH0_gc = (0x03<<0), /* Asynchronous Event Channel 0 */ | |||
EVSYS_ASYNCUSER_ASYNCCH1_gc = (0x04<<0), /* Asynchronous Event Channel 1 */ | |||
EVSYS_ASYNCUSER_ASYNCCH2_gc = (0x05<<0), /* Asynchronous Event Channel 2 */ | |||
EVSYS_ASYNCUSER_ASYNCCH3_gc = (0x06<<0), /* Asynchronous Event Channel 3 */ | |||
} EVSYS_ASYNCUSER_t; | |||
/* Synchronous User Ch x Input Selection */ | |||
typedef enum EVSYS_SYNCUSER_enum | |||
{ | |||
EVSYS_SYNCUSER_OFF_gc = (0x00<<0), /* Off */ | |||
EVSYS_SYNCUSER_SYNCCH0_gc = (0x01<<0), /* Synchronous Event Channel 0 */ | |||
EVSYS_SYNCUSER_SYNCCH1_gc = (0x02<<0), /* Synchronous Event Channel 1 */ | |||
} EVSYS_SYNCUSER_t; |
@ -0,0 +1,481 @@ | |||
# Hey Emacs, this is a -*- makefile -*- | |||
# | |||
# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al. | |||
# Released to the Public Domain | |||
# Please read the make user manual! | |||
# | |||
# Additional material for this makefile was submitted by: | |||
# Tim Henigan | |||
# Peter Fleury | |||
# Reiner Patommel | |||
# Sander Pool | |||
# Frederik Rouleau | |||
# Markus Pfaff | |||
# | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB). | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio | |||
# 4.07 or greater). | |||
# | |||
# make program = Download the hex file to the device, using avrdude. Please | |||
# customize the avrdude settings below first! | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
# | |||
# mth 2004/09 | |||
# Differences from WinAVR 20040720 sample: | |||
# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum) | |||
# - F_OSC Define in CFLAGS and AFLAGS | |||
# MCU name | |||
MCU = attiny817 | |||
# Main Oscillator Frequency | |||
# This is only used to define F_OSC in all assembler and c-sources. | |||
F_CPU = 20000000 | |||
# Output format. (can be srec, ihex, binary) | |||
FORMAT = ihex | |||
# Target file name (without extension). | |||
TARGET = main | |||
# List C source files here. (C dependencies are automatically generated.) | |||
SRC = $(TARGET).c | |||
# List Assembler source files here. | |||
# Make them always end in a capital .S. Files ending in a lowercase .s | |||
# will not be considered source files but generated files (assembler | |||
# output from the compiler), and will be deleted upon "make clean"! | |||
# Even though the DOS/Win* filesystem matches both .s and .S the same, | |||
# it will preserve the spelling of the filenames, and gcc itself does | |||
# care about how the name is spelled on its command-line. | |||
ASRC = | |||
# Optimization level, can be [0, 1, 2, 3, s]. | |||
# 0 = turn off optimization. s = optimize for size. | |||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) | |||
OPT = s | |||
# Debugging format. | |||
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. | |||
# AVR (extended) COFF requires stabs, plus an avr-objcopy run. | |||
#DEBUG = stabs | |||
DEBUG = dwarf-2 | |||
# List any extra directories to look for include files here. | |||
# Each directory must be seperated by a space. | |||
EXTRAINCDIRS = | |||
# Compiler flag to set the C Standard level. | |||
# c89 - "ANSI" C | |||
# gnu89 - c89 plus GCC extensions | |||
# c99 - ISO C99 standard (not yet fully implemented) | |||
# gnu99 - c99 plus GCC extensions | |||
CSTANDARD = -std=gnu99 | |||
# Place -D or -U options here | |||
CDEFS = | |||
# Place -I options here | |||
CINCS = | |||
# Compiler flags. | |||
# -g*: generate debugging information | |||
# -O*: optimization level | |||
# -f...: tuning, see GCC manual and avr-libc documentation | |||
# -Wall...: warning level | |||
# -Wa,...: tell GCC to pass this to the assembler. | |||
# -adhlns...: create assembler listing | |||
CFLAGS = -g$(DEBUG) | |||
CFLAGS += $(CDEFS) $(CINCS) | |||
CFLAGS += -O$(OPT) | |||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums | |||
CFLAGS += -Wall -Wstrict-prototypes | |||
CFLAGS += -Wa,-adhlns=$(<:.c=.lst) | |||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||
CFLAGS += $(CSTANDARD) | |||
CFLAGS += -DF_CPU=$(F_CPU) | |||
#CFLAGS += -B /home/bucde/__avr_gcc/ATtiny_DFP/1.3.172/gcc/dev/attiny817/ | |||
#CFLAGS += -I /home/bucde/__avr_gcc/ATtiny_DFP/1.3.172/include/ | |||
# Assembler flags. | |||
# -Wa,...: tell GCC to pass this to the assembler. | |||
# -ahlms: create listing | |||
# -gstabs: have the assembler create line number information; note that | |||
# for use in COFF files, additional information about filenames | |||
# and function names needs to be present in the assembler source | |||
# files -- see avr-libc docs [FIXME: not yet described there] | |||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs | |||
ASFLAGS += -DF_OSC=$(F_OSC) | |||
#Additional libraries. | |||
# Minimalistic printf version | |||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min | |||
# Floating point printf version (requires MATH_LIB = -lm below) | |||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt | |||
PRINTF_LIB = | |||
# Minimalistic scanf version | |||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min | |||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below) | |||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt | |||
SCANF_LIB = | |||
MATH_LIB = -lm | |||
# External memory options | |||
# 64 KB of external RAM, starting after internal RAM (ATmega128!), | |||
# used for variables (.data/.bss) and heap (malloc()). | |||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff | |||
# 64 KB of external RAM, starting after internal RAM (ATmega128!), | |||
# only used for heap (malloc()). | |||
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff | |||
EXTMEMOPTS = | |||
# Linker flags. | |||
# -Wl,...: tell GCC to pass this to linker. | |||
# -Map: create map file | |||
# --cref: add cross reference to map file | |||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref | |||
LDFLAGS += $(EXTMEMOPTS) | |||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) | |||
LDFLAGS += -Ttext=0x0000 | |||
# Programming support using avrdude. Settings and variables. | |||
# Programming hardware: alf avr910 avrisp bascom bsd | |||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 | |||
# | |||
# Type: avrdude -c ? | |||
# to get a full listing. | |||
# | |||
AVRDUDE_PROGRAMMER = xplainedmini_updi | |||
# com1 = serial port. Use lpt1 to connect to parallel port. | |||
AVRDUDE_PORT = usb | |||
# programmer connected to serial device | |||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex | |||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep | |||
# Uncomment the following if you want avrdude's erase cycle counter. | |||
# Note that this counter needs to be initialized first using -Yn, | |||
# see avrdude manual. | |||
#AVRDUDE_ERASE_COUNTER = -y | |||
# Uncomment the following if you do /not/ wish a verification to be | |||
# performed after programming the device. | |||
#AVRDUDE_NO_VERIFY = -V | |||
# Increase verbosity level. Please use this when submitting bug | |||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> | |||
# to submit bug reports. | |||
#AVRDUDE_VERBOSE = -v -v | |||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) | |||
#AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) | |||
#AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) | |||
#AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) | |||
#read fuses | |||
#./avrdude -p atmega4808 -P usb -c xplainedmini_updi -U fuse0:r:fuse_wdtcfg:h -U fuse1:r:fuse_bodcfg:h -U fuse2:r:fuse_osccfg:h -U fuse5:r:fuse_syscfg0:h -U fuse6:r:fuse_syscfg1:h -U fuse7:r:fuse_append:h -U fuse8:r:fuse_bootend:h | |||
AVRDUDE_FUSE0_WDTCFG = 0x00 | |||
AVRDUDE_FUSE1_BODCFG = 0x00 | |||
AVRDUDE_FUSE2_OSCCFG = 0x02 | |||
AVRDUDE_FUSE5_SYSCFG0 = 0b11101101 | |||
#AVRDUDE_FUSE5_SYSCFG0[2] must be set to 1 | |||
#AVRDUDE_FUSE5_SYSCFG0[5] must be set to 1 | |||
AVRDUDE_FUSE6_SYSCFG1 = 0x00 | |||
AVRDUDE_FUSE7_APPEND = 0x00 | |||
AVRDUDE_FUSE8_BOOTEND = 0x00 | |||
AVRDUDE_WRITE_FUSES = -U fuse0:w:$(AVRDUDE_FUSE0_WDTCFG):m | |||
AVRDUDE_WRITE_FUSES += -U fuse1:w:$(AVRDUDE_FUSE1_BODCFG):m | |||
AVRDUDE_WRITE_FUSES += -U fuse2:w:$(AVRDUDE_FUSE2_OSCCFG):m | |||
AVRDUDE_WRITE_FUSES += -U fuse5:w:$(AVRDUDE_FUSE5_SYSCFG0):m | |||
AVRDUDE_WRITE_FUSES += -U fuse6:w:$(AVRDUDE_FUSE6_SYSCFG1):m | |||
AVRDUDE_WRITE_FUSES += -U fuse7:w:$(AVRDUDE_FUSE7_APPEND):m | |||
AVRDUDE_WRITE_FUSES += -U fuse8:w:$(AVRDUDE_FUSE8_BOOTEND):m | |||
AVRDUDE_READ_FUSES = -U fuse0:r:fuse0_wdtcfg:h | |||
AVRDUDE_READ_FUSES += -U fuse1:r:fuse1_bodcfg:h | |||
AVRDUDE_READ_FUSES += -U fuse2:r:fuse2_osccfg:h | |||
AVRDUDE_READ_FUSES += -U fuse5:r:fuse5_syscfg0:h | |||
AVRDUDE_READ_FUSES += -U fuse6:r:fuse6_syscfg1:h | |||
AVRDUDE_READ_FUSES += -U fuse7:r:fuse7_append:h | |||
AVRDUDE_READ_FUSES += -U fuse8:r:fuse8_bootend:h | |||
# --------------------------------------------------------------------------- | |||
# Define directories, if needed. | |||
#DIRAVR = /home/bucde/local/avr | |||
DIRAVR = /home/bucde/documents/hobby/repos/avrgcc | |||
#DIRAVR = ${AVRGCC} | |||
DIRAVRBIN = $(DIRAVR)/bin | |||
#DIRAVRUTILS = $(DIRAVR)/utils/bin | |||
#DIRINC = . | |||
#DIRLIB = $(DIRAVR)/avr/lib | |||
# Define programs and commands. | |||
SHELL = sh | |||
CC = $(DIRAVRBIN)/avr-gcc | |||
OBJCOPY = $(DIRAVRBIN)/avr-objcopy | |||
OBJDUMP = $(DIRAVRBIN)/avr-objdump | |||
SIZE = $(DIRAVRBIN)/avr-size | |||
NM = $(DIRAVRBIN)/avr-nm | |||
AVRDUDE = $(DIRAVRBIN)/avrdude | |||
REMOVE = rm -f | |||
COPY = cp | |||
# Define Messages | |||
# English | |||
MSG_ERRORS_NONE = Errors: none | |||
MSG_INFO = -------- info -------- | |||
MSG_BEGIN = -------- begin -------- | |||
MSG_END = -------- end -------- | |||
MSG_SIZE_BEFORE = Size before: | |||
MSG_SIZE_AFTER = Size after: | |||
MSG_COFF = Converting to AVR COFF: | |||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF: | |||
MSG_FLASH = Creating load file for Flash: | |||
MSG_EEPROM = Creating load file for EEPROM: | |||
MSG_EXTENDED_LISTING = Creating Extended Listing: | |||
MSG_SYMBOL_TABLE = Creating Symbol Table: | |||
MSG_LINKING = Linking: | |||
MSG_COMPILING = Compiling: | |||
MSG_ASSEMBLING = Assembling: | |||
MSG_CLEANING = Cleaning project: | |||
# Define all object files. | |||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) | |||
# Define all listing files. | |||
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst) | |||
# Compiler flags to generate dependency files. | |||
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d | |||
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d | |||
# Combine all necessary flags and optional flags. | |||
# Add target processor to flags. | |||
#ALL_CFLAGS = -mmcu=$(MCU) -B /home/bucde/local/packs/Atmel.ATtiny_DFP.1.3.172.atpack_FILES/gcc/dev/attiny817 -I. $(CFLAGS) $(GENDEPFLAGS) | |||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) | |||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) | |||
# Default target. | |||
all: info begin gccversion sizebefore build sizeafter finished end | |||
build: elf hex eep lss sym | |||
elf: $(TARGET).elf | |||
hex: $(TARGET).hex | |||
eep: $(TARGET).eep | |||
lss: $(TARGET).lss | |||
sym: $(TARGET).sym | |||
# Eye candy. | |||
# AVR Studio 3.x does not check make's exit code but relies on | |||
# the following magic strings to be generated by the compile job. | |||
begin: | |||
@echo | |||
@echo $(MSG_BEGIN) | |||
finished: | |||
@echo $(MSG_ERRORS_NONE) | |||
end: | |||
@echo $(MSG_END) | |||
@echo | |||
# Display size of file. | |||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex | |||
ELFSIZE = $(SIZE) -A $(TARGET).elf | |||
sizebefore: | |||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi | |||
sizeafter: | |||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi | |||
info: | |||
@echo | |||
@echo $(MSG_INFO) | |||
@echo MCU: $(MCU) | |||
@echo F_CPU: $(F_CPU) | |||
# Display compiler version information. | |||
gccversion : | |||
@$(CC) --version | |||
# Program the device. | |||
program: $(TARGET).hex $(TARGET).eep | |||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) | |||
flashfuses : | |||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FUSES) | |||
readfuses : | |||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_READ_FUSES) | |||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. | |||
COFFCONVERT=$(OBJCOPY) --debugging \ | |||
--change-section-address .data-0x800000 \ | |||
--change-section-address .bss-0x800000 \ | |||
--change-section-address .noinit-0x800000 \ | |||
--change-section-address .eeprom-0x810000 | |||
coff: $(TARGET).elf | |||
@echo | |||
@echo $(MSG_COFF) $(TARGET).cof | |||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof | |||
extcoff: $(TARGET).elf | |||
@echo | |||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof | |||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof | |||
# Create final output files (.hex, .eep) from ELF output file. | |||
%.hex: %.elf | |||
@echo | |||
@echo $(MSG_FLASH) $@ | |||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ | |||
%.eep: %.elf | |||
@echo | |||
@echo $(MSG_EEPROM) $@ | |||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ | |||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@ | |||
# Create extended listing file from ELF output file. | |||
%.lss: %.elf | |||
@echo | |||
@echo $(MSG_EXTENDED_LISTING) $@ | |||
$(OBJDUMP) -h -S $< > $@ | |||
# Create a symbol table from ELF output file. | |||
%.sym: %.elf | |||
@echo | |||
@echo $(MSG_SYMBOL_TABLE) $@ | |||
$(NM) -n $< > $@ | |||
# Link: create ELF output file from object files. | |||
.SECONDARY : $(TARGET).elf | |||
.PRECIOUS : $(OBJ) | |||
%.elf: $(OBJ) | |||
@echo | |||
@echo $(MSG_LINKING) $@ | |||
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) | |||
# Compile: create object files from C source files. | |||
%.o : %.c | |||
@echo | |||
@echo $(MSG_COMPILING) $< | |||
$(CC) -c $(ALL_CFLAGS) $< -o $@ | |||
# Compile: create assembler files from C source files. | |||
%.s : %.c | |||
$(CC) -S $(ALL_CFLAGS) $< -o $@ | |||
# Assemble: create object files from assembler source files. | |||
%.o : %.S | |||
@echo | |||
@echo $(MSG_ASSEMBLING) $< | |||
$(CC) -c $(ALL_ASFLAGS) $< -o $@ | |||
# Target: clean project. | |||
clean: begin clean_list finished end | |||
clean_list : | |||
@echo | |||
@echo $(MSG_CLEANING) | |||
$(REMOVE) $(TARGET).hex | |||
$(REMOVE) $(TARGET).eep | |||
$(REMOVE) $(TARGET).obj | |||
$(REMOVE) $(TARGET).cof | |||
$(REMOVE) $(TARGET).elf | |||
$(REMOVE) $(TARGET).map | |||
$(REMOVE) $(TARGET).obj | |||
$(REMOVE) $(TARGET).a90 | |||
$(REMOVE) $(TARGET).sym | |||
$(REMOVE) $(TARGET).lnk | |||
$(REMOVE) $(TARGET).lss | |||
$(REMOVE) $(OBJ) | |||
$(REMOVE) $(LST) | |||
$(REMOVE) $(SRC:.c=.s) | |||
$(REMOVE) $(SRC:.c=.d) | |||
$(REMOVE) .dep/* | |||
# Include the dependency files. | |||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) | |||
# Listing of phony targets. | |||
.PHONY : all begin finish end sizebefore sizeafter gccversion \ | |||
build elf hex eep lss sym coff extcoff \ | |||
clean clean_list program |