appWindow.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # The code for changing pages was derived from: http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
  2. # License: http://creativecommons.org/licenses/by-sa/3.0/
  3. from database import Table
  4. from analogPressure.sdpArray import SdpArray
  5. from analogPressure.mcp3008 import MCP3008
  6. from digitalPressure.sdp610Array import Spd610Array
  7. from wirelessLoadCell.loadCells import LoadCells
  8. from motorController.pwmOutput import PWM
  9. from motorController.pidController import PID
  10. from ui import *
  11. import tkinter as tk
  12. import tk_tools
  13. from tkinter import filedialog
  14. import time
  15. import numpy as np
  16. import threading
  17. class Main(tk.Tk, Table):
  18. running = True
  19. def __init__(self, *args, **kwargs):
  20. print('initializing window...')
  21. tk.Tk.__init__(self, *args, **kwargs)
  22. tk.Tk.wm_title(self, "Windkanal-Tool")
  23. #early response to user
  24. self.update_idletasks()
  25. print('initializing sensors...')
  26. self.adc = MCP3008(0,0)
  27. self.pressureSensors = Spd610Array()
  28. self.forceSensors = LoadCells()
  29. self.forceSensors.start()
  30. self.motorController = PWM(32)
  31. self.pid = PID(100/22, 5, 1)
  32. self.pid.setWindup(1)
  33. print('initializing database...')
  34. Table.__init__(self,
  35. ["windspeed", "set_value", "motor_pwm"] +
  36. ["pressure_{}".format(i) for i in range(8)] +
  37. ["adc_{}".format(i) for i in range(1)] +
  38. ["force_X_sum", "force_Y_sum", "force_Z_sum"] +
  39. ["force_X_1", "force_Y_1", "force_Z_1"] +
  40. ["force_X_2", "force_Y_2", "force_Z_2"] +
  41. ["force_X_3", "force_Y_3", "force_Z_3"])
  42. print('initializing GUI...')
  43. self.menubar = tk.Menu(self)
  44. self.frameVar = tk.StringVar()
  45. self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_1', command=self.show_frame, label="Bedienelemente")
  46. self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_2', command=self.show_frame, label="Kräfte")
  47. self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_3', command=self.show_frame, label="Druck")
  48. self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_4', command=self.show_frame, label="Einstellungen")
  49. self.menubar.add_command(state=tk.DISABLED, label=" ")
  50. self.motorEnabled = tk.IntVar()
  51. self.menubar.add_checkbutton(indicatoron=0, variable=self.motorEnabled, background='#dd5252', label="Motor freischalten", command=lambda:
  52. self.menubar.entryconfigure("Motor freischalten", background='#dd5252' if self.motorEnabled.get() == 0 else 'green'))
  53. self.motorEnabled.set(0)
  54. self.menubar.add_command(state=tk.DISABLED, label=" ")
  55. self.menubar.add_command(label="Messwerte speichern", command = self.save_dialog)
  56. self.menubar.add_command(label='Messwerte löschen', command=self.reset)
  57. self.menubar.add_command(state=tk.DISABLED, label=" ")
  58. self.menubar.add_command(label="Beenden", foreground="red", command=self.stop)
  59. tk.Tk.config(self, menu=self.menubar)
  60. container = tk.Frame(self)
  61. container.pack(side="top", fill="both", expand = True)
  62. container.grid_rowconfigure(0, weight=1)
  63. container.grid_columnconfigure(0, weight=1)
  64. self.frames = {}
  65. for F in (Page_1, Page_2, Page_3, Page_4):
  66. frame = F(container, self)
  67. self.frames[F.__name__] = frame
  68. frame.grid(row=0, column=0, sticky="nsew")
  69. self.frameVar.set('Page_1')
  70. self.show_frame()
  71. print('program ready!')
  72. self.windspeed = 0
  73. self.adcValue = 0
  74. self.pwmValue = 0
  75. self.pidDelay = 100
  76. self.pidThread = threading.Thread(target=self.pidThreadFunction)
  77. self.pidThread.daemon = True
  78. self.pidThread.start()
  79. self.intervalDelay = 300 # ms
  80. self.interval()
  81. def show_frame(self):
  82. self.frames[self.frameVar.get()].tkraise()
  83. def popupmsg(self, msg=""):
  84. popup = tk.Toplevel(self.master)
  85. popup.wm_title("Error!")
  86. label = tk.Label(popup, text=msg, font=LARGE_FONT)
  87. label.pack(side="top", fill="x", pady=10)
  88. b1 = tk.Button(popup, text="Okay", command=popup.destroy)
  89. b1.pack()
  90. def save_dialog(self):
  91. f = filedialog.asksaveasfile(mode='w+', defaultextension=".csv")
  92. if f is None:
  93. return
  94. self.saveAsCsv(f)
  95. f.close()
  96. def pidThreadFunction(self):
  97. while self.running:
  98. start = time.time()
  99. self.adcValue = self.adc.getVoltage(0)
  100. self.windSpeed = self.adcValue * 5
  101. tmp = self.pid.update(self.windSpeed, start)
  102. if self.motorEnabled.get() == 0:
  103. self.pid.clear()
  104. self.pwmValue = 0
  105. elif tmp > 100:
  106. self.pwmValue = 100
  107. elif tmp < 0:
  108. self.pwmValue = 0
  109. else:
  110. self.pwmValue = tmp
  111. self.motorController.setDutyCycle(self.pwmValue)
  112. elapsed = time.time() - start
  113. time.sleep(max(0, self.pidDelay / 1000 - elapsed))
  114. def interval(self):
  115. self.after(self.intervalDelay, self.interval)
  116. start = time.time()
  117. setValue = self.frames['Page_1'].speedSlider.get()
  118. self.pid.setInput(setValue)
  119. i2cValues = self.pressureSensors.getValues()
  120. btValues = self.forceSensors.getForces()
  121. self.addRow(
  122. [self.windSpeed, setValue, self.pwmValue] +
  123. i2cValues +
  124. [self.adcValue] +
  125. list(np.sum(btValues, axis = 0, initial=0)) +
  126. list(btValues.flatten())
  127. )
  128. print("sensors: {:8.3f} ms".format((time.time() - start)*1000))
  129. start = time.time()
  130. for frame in self.frames:
  131. self.frames[frame].update(frame == self.frameVar.get())
  132. print("draw: {:8.3f} ms".format((time.time() - start)*1000))
  133. def stop(self):
  134. self.motorEnabled.set(0)
  135. self.running = False
  136. self.forceSensors.stop()
  137. self.pidThread.join()
  138. self.adc.close()
  139. self.motorController.stop()
  140. self.quit()