From 65b128ab01e58751a0f2db32e69f6889005abe4c Mon Sep 17 00:00:00 2001 From: bucde Date: Sun, 28 Feb 2021 14:14:43 +0100 Subject: [PATCH] ADD copied local files to repo --- app.py | 399 ++++++++++++++++++++++++ app2.py | 444 ++++++++++++++++++++++++++ main.c | 933 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.h | 43 +++ makefile | 481 ++++++++++++++++++++++++++++ 5 files changed, 2300 insertions(+) create mode 100755 app.py create mode 100755 app2.py create mode 100644 main.c create mode 100644 main.h create mode 100644 makefile diff --git a/app.py b/app.py new file mode 100755 index 0000000..55c6409 --- /dev/null +++ b/app.py @@ -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() diff --git a/app2.py b/app2.py new file mode 100755 index 0000000..3117da7 --- /dev/null +++ b/app2.py @@ -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() diff --git a/main.c b/main.c new file mode 100644 index 0000000..0eb6e71 --- /dev/null +++ b/main.c @@ -0,0 +1,933 @@ +#include +#include +#include + +#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; + } + } +} diff --git a/main.h b/main.h new file mode 100644 index 0000000..77945e8 --- /dev/null +++ b/main.h @@ -0,0 +1,43 @@ +#ifndef _AVR_ATTINY817_H_INCLUDED +# error " 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; diff --git a/makefile b/makefile new file mode 100644 index 0000000..e1d3ef3 --- /dev/null +++ b/makefile @@ -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 +# 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