title: Communication Loop with a GUI
body: <p>I am making a GUI in Python for a machine. My python program runs on a Raspberry Pi 3 and it is communicating by serial with an Arduino UNO.</p>
  
  <p>I've made a protocol; the arduino sends a "1". The raspberry knows the "1" stands for Run/Stop, and gives back the value of the RunStop variable (which is either 0 or 1). After that the arduino sends a "2". The raspberry knows it stands for the Speed value, and sends back the Speed variable (Which is between 1 and 4).</p>
  
  <p>I've made the 2 following programs that work, but I don't know how to implement it in the GUI. Because when I add it before the <strong>root.mainloop()</strong> , the GUI won't start. And when I put it after, the while loop never starts.</p>
  
  <p>Arduino Code:</p>
  
  <pre><code>int RunStop, Speed = 0;
  
  void setup() {
  
    Serial.begin(9600);
    pinMode(13, OUTPUT);
    pinMode(12, OUTPUT);
  }
  
  
  void loop() {
    Serial.write(1);
    delay(2000);
    RunStop = Serial.read(); 
    if (RunStop == 1) {
      digitalWrite(13, HIGH);
    } else {
      digitalWrite(13, LOW);
    }
    delay(2000);
  
  
    Serial.write(2);
    delay(2000);
    Speed = Serial.read(); 
    if (Speed == 3) {
      digitalWrite(12, HIGH);
    } else {
      digitalWrite(12, LOW);
    }
    delay(2000);
  }
  </code></pre>
  
  <p>Python Communication Code:</p>
  
  <pre><code>import time
  import serial
  
  # configure the serial connections (the parameters differs on the device you are connecting to)
  ser = serial.Serial(
      port='/dev/ttyAMA0',
      baudrate=9600,
  )
  
  ser.isOpen()
  
  ##Status variabelen
  
  RunStop = b'\x01'
  Speed = b'\x03'
  
  while 1:
  uartIn = ser.read()
  print (uartIn)
  time.sleep(1)
  if uartIn == b'\x01':
      ser.write(RunStop)
      print ("Run/Stop Register")
  elif uartIn == b'\x02':
      ser.write(Speed)
      print ("Speed Register")
  else:
      print ("No Register Requested")
  </code></pre>
  
  <p>GUI code:</p>
  
  <pre><code>from tkinter import *
  import time
  import serial
  
  # configure the serial connections (the parameters differs on the device you are connecting to)
  ser = serial.Serial(
      port='/dev/ttyAMA0',
      baudrate=9600,
      parity=serial.PARITY_ODD,
      stopbits=serial.STOPBITS_ONE,
      bytesize=serial.EIGHTBITS
  )
  
  ser.isOpen()
  
  root = Tk()
  root.title("Cutter")
  
  ## Layout
  
  
  
  
  
  
  
  label_1 = Label(root, text="Pieces")
  label_2 = Label(root, text="Length")
  entry_1 = Entry(root, width=9)
  
  entry_2 = Entry(root, width=9)
  
  
  label_1.grid(row=3, sticky=W, padx=(10))
  label_2.grid(row=4, sticky=W, padx=(10))
  entry_1.grid(row=3, column=1, pady=(10,10))
  entry_2.grid(row=4, column=1, pady=(10,15))
  
  
  runStop = b'\x00'
  Speed = b'\x01'
  Pieces = b'\x00'
  Length = b'\x00'
  
  
  ##pieces OK button function
  def piecesOKphase():
      x = entry_1.get()
      print("pieces: " + x)
  
  ##length OK button function
  def lengthOKphase():
      x = entry_2.get()
      print("length: " + x)
  
  def runPhase():
      global runStop
      runStop = b'\x01'
  
  def stopPhase():
      global runStop
      runStop = b'\x00'
  
  
  
  
  
  #OK and RUN / STOP buttons
  piecesOK = Button(root, text="OK", command=piecesOKphase)
  piecesOK.grid(row=3, column=2)
  
  lengthOK = Button(root, text="OK", command=lengthOKphase)
  lengthOK.grid(row=4, column=2)
  
  runButton = Button(root, text="Run", width=6, bg='#58FA58', command=runPhase)
  stopButton = Button(root, text="Stop", width=6, bg='#FA5858', command=stopPhase)
  
  runButton.grid(row=0, column=0,padx=(10,10), pady=(10,10))
  stopButton.grid(row=0, column=2)
  
  
  
  ##speed container
  
  CurrentSpeed = 1
  
  
  
  
  def delSpeed():
      global CurrentSpeed
      global speedLabel
  
      if CurrentSpeed &gt; 1:
          CurrentSpeed -= 1
          speedLabel.config(text=str(CurrentSpeed))
          speedLabel.config(text=CurrentSpeed)
  
      else:
          pass
  
  def addSpeed():
      global CurrentSpeed
  
      if CurrentSpeed &lt; 4:
          CurrentSpeed += 1
          speedLabel.config(text=CurrentSpeed)
  
      else:
          pass
  
  
  speedMin = Button(root, text="Speed -", width=6, command=delSpeed)
  
  speedLabel = Label(root, text=CurrentSpeed, font=20)
  speedLabel.grid(row=1, column=1, padx=(10))
  
  speedPlus = Button(root, text="Speed +", width=6, command=addSpeed)
  
  speedMin.grid(row=1, column=0)
  speedPlus.grid(row=1, column=2)
  
  
  #Number keyboard functions
  
  def B1phase():
      try:
          root.focus_get().insert(END, "1")
      except AttributeError:
          pass
  def B2phase():
      try:
          root.focus_get().insert(END, "2")
      except AttributeError:
          pass
  def B3phase():
      try:
          root.focus_get().insert(END, "3")
      except AttributeError:
          pass
  def B4phase():
      try:
          root.focus_get().insert(END, "4")
      except AttributeError:
          pass
  def B5phase():
      try:
          root.focus_get().insert(END, "5")
      except AttributeError:
          pass
  def B6phase():
      try:
          root.focus_get().insert(END, "6")
      except AttributeError:
          pass
  def B7phase():
      try:
          root.focus_get().insert(END, "7")
      except AttributeError:
          pass
  def B8phase():
      try:
          root.focus_get().insert(END, "8")
      except AttributeError:
          pass
  def B9phase():
      try:
          root.focus_get().insert(END, "9")
      except AttributeError:
          pass
  def B0phase():
      try:
          root.focus_get().insert(END, "0")
      except AttributeError:
          pass
  def clearPhase():
      try:
          root.focus_get().delete(0, 'end')
      except AttributeError:
          pass
  
  
  ## Number keyboard buttons
  B1 = Button(root, text="1", width=6, command=B1phase)
  B2 = Button(root, text="2", width=6, command=B2phase)
  B3 = Button(root, text="3", width=6, command=B3phase)
  B4 = Button(root, text="4", width=6, command=B4phase)
  B5 = Button(root, text="5", width=6, command=B5phase)
  B6 = Button(root, text="6", width=6, command=B6phase)
  B7 = Button(root, text="7", width=6, command=B7phase)
  B8 = Button(root, text="8", width=6, command=B8phase)
  B9 = Button(root, text="9", width=6, command=B9phase)
  B0 = Button(root, text="0", width=6, command=B0phase)
  clearButton = Button(root, text="Clear", width=6, bg='#FA5858', command=clearPhase)
  
  
  B1.grid(row=5, column=0)
  B2.grid(row=5, column=1)
  B3.grid(row=5, column=2, padx=(10,10))
  B4.grid(row=6, column=0)
  B5.grid(row=6, column=1)
  B6.grid(row=6, column=2, padx=(10,10))
  B7.grid(row=7, column=0)
  B8.grid(row=7, column=1)
  B9.grid(row=7, column=2, padx=(10,10))
  B0.grid(row=8, column=1)
  clearButton.grid(row=8, column=0)
  
  
  
  ## Manual
  
  label_4 = Label(root, text="")
  label_4.grid(row=2, sticky=W)
  label_3 = Label(root, text="Manual")
  label_3.grid(row=9, sticky=W, padx=(10), pady=(10,10))
  
  manualCut = Button(root, text="Cut", width=4)
  manualCut.grid(row=10, column=0, pady=(1,15))
  
  manualFeed = Button(root, text="Feed", width=4)
  manualFeed.grid(row=10, column=1, pady=(1,15))
  
  
  # Test function
  def testPhase():
  
      print (CurrentSpeed)
  
  manualTest = Button(root, text="Test", width=4, command=testPhase)
  manualTest.grid(row=10, column=2, pady=(1,15))
  
  
  
  
  ## OTHER
  
  
  root.mainloop()
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <p>I have used the <strong>after</strong> from Tkinter.</p>
  
  <p>The GUI starts, and the while loop runs. But I cannot click on any buttons.</p>
  
  <pre><code>from tkinter import *
  import time
  import serial
  
  # configure the serial connections (the parameters differs on the device you are connecting to)
  ser = serial.Serial(
      port='/dev/ttyAMA0',
      baudrate=9600,
      parity=serial.PARITY_ODD,
      stopbits=serial.STOPBITS_ONE,
      bytesize=serial.EIGHTBITS
  )
  ser.isOpen()
  
  
  
  
  
  ## GUI Title
  root = Tk()
  root.title("Cutter")
  
  
  
  
  
  ##Communication
  RunStop = b'\x01' ## 0 = OFF, 1 = ON
  
  Speed = b'\x03' ## 1, 2, 3, 4
  CurrentSpeed = 1
  
  Pieces = b'\x00'
  
  Pieces100 = b'\x00'
  Pieces10 = b'\x00'
  Pieces1 = b'\x00'
  
  length10000 = b'\x00'
  Length1000 = b'\x00'
  Length100 = b'\x00'
  Length10 = b'\x00'
  Length1 = b'\x00'
  
  
  
  def Communication():
      while 1:
          uartIn = ser.read()
          print (uartIn)
          time.sleep(1)
          if uartIn == b'\x01':
              ser.write(RunStop)
              print ("Run/Stop Register")
          elif uartIn == b'\x02':
              ser.write(Speed)
              print ("Speed Register")
          else:
              print ("No Register Requested")
          root.after(500, Communication)
  
  
  
  
  
  ## Functions
  def runBOT():
      global RunStop
      RunStop = b'\x01'
  
  def stopBOT():
      global RunStop
      RunStop = b'\x00'
  
  def delSpeedBOT():
      global CurrentSpeed
      global speedLabel
  
      if CurrentSpeed &gt; 1:
          CurrentSpeed -= 1
          speedLabel.config(text=str(CurrentSpeed))
          speedLabel.config(text=CurrentSpeed)
      else:
          pass
  
  def addSpeedBOT():
      global CurrentSpeed
  
      if CurrentSpeed &lt; 4:
          CurrentSpeed += 1
          speedLabel.config(text=CurrentSpeed)
      else:
          pass
  
  def piecesBOT():
      x = entryPieces.get()
      print("pieces: " + x)
  
  def lengthBOT():
      x = entryLength.get()
      print("length: " + x)
  
  
  
  
  
  ## Layout
  
  labelPieces = Label(root, text="Pieces")
  labelLength = Label(root, text="Length")
  entryPieces = Entry(root, width=9)
  entryLength = Entry(root, width=9)
  
  labelPieces.grid(row=3, sticky=W, padx=(10))
  labelLength.grid(row=4, sticky=W, padx=(10))
  entryPieces.grid(row=3, column=1, pady=(10,10))
  entryLength.grid(row=4, column=1, pady=(10,15))
  
  
  
  
  
  ## Buttons
  
  runButton = Button(root, text="Run", width=6, bg='#58FA58', command=runBOT)
  runButton.grid(row=0, column=0,padx=(10,10), pady=(10,10))
  
  stopButton = Button(root, text="Stop", width=6, bg='#FA5858', command=stopBOT)
  stopButton.grid(row=0, column=2)
  
  speedMin = Button(root, text="Speed -", width=6, command=delSpeedBOT)
  speedMin.grid(row=1, column=0)
  
  speedLabel = Label(root, text=CurrentSpeed, font=20)
  speedLabel.grid(row=1, column=1, padx=(10))
  
  speedPlus = Button(root, text="Speed +", width=6, command=addSpeedBOT)
  speedPlus.grid(row=1, column=2)
  
  piecesOK = Button(root, text="OK", command=piecesBOT)
  piecesOK.grid(row=3, column=2)
  
  lengthOK = Button(root, text="OK", command=lengthBOT)
  lengthOK.grid(row=4, column=2)
  
  
  
  
  
  #Number keyboard functions
  
  def B1phase():
      try:
          root.focus_get().insert(END, "1")
      except AttributeError:
          pass
  def B2phase():
      try:
          root.focus_get().insert(END, "2")
      except AttributeError:
          pass
  def B3phase():
      try:
          root.focus_get().insert(END, "3")
      except AttributeError:
          pass
  def B4phase():
      try:
          root.focus_get().insert(END, "4")
      except AttributeError:
          pass
  def B5phase():
      try:
          root.focus_get().insert(END, "5")
      except AttributeError:
          pass
  def B6phase():
      try:
          root.focus_get().insert(END, "6")
      except AttributeError:
          pass
  def B7phase():
      try:
          root.focus_get().insert(END, "7")
      except AttributeError:
          pass
  def B8phase():
      try:
          root.focus_get().insert(END, "8")
      except AttributeError:
          pass
  def B9phase():
      try:
          root.focus_get().insert(END, "9")
      except AttributeError:
          pass
  def B0phase():
      try:
          root.focus_get().insert(END, "0")
      except AttributeError:
          pass
  def clearPhase():
      try:
          root.focus_get().delete(0, 'end')
      except AttributeError:
          pass
  
  
  
  
  
  ## Number keyboard buttons
  B1 = Button(root, text="1", width=6, command=B1phase)
  B2 = Button(root, text="2", width=6, command=B2phase)
  B3 = Button(root, text="3", width=6, command=B3phase)
  B4 = Button(root, text="4", width=6, command=B4phase)
  B5 = Button(root, text="5", width=6, command=B5phase)
  B6 = Button(root, text="6", width=6, command=B6phase)
  B7 = Button(root, text="7", width=6, command=B7phase)
  B8 = Button(root, text="8", width=6, command=B8phase)
  B9 = Button(root, text="9", width=6, command=B9phase)
  B0 = Button(root, text="0", width=6, command=B0phase)
  clearButton = Button(root, text="Clear", width=6, bg='#FA5858', command=clearPhase)
  
  B1.grid(row=5, column=0)
  B2.grid(row=5, column=1)
  B3.grid(row=5, column=2, padx=(10,10))
  B4.grid(row=6, column=0)
  B5.grid(row=6, column=1)
  B6.grid(row=6, column=2, padx=(10,10))
  B7.grid(row=7, column=0)
  B8.grid(row=7, column=1)
  B9.grid(row=7, column=2, padx=(10,10))
  B0.grid(row=8, column=1)
  clearButton.grid(row=8, column=0)
  
  
  
  
  
  ## Manual
  
  label_4 = Label(root, text="")
  label_4.grid(row=2, sticky=W)
  label_3 = Label(root, text="Manual")
  label_3.grid(row=9, sticky=W, padx=(10), pady=(10,10))
  
  manualCut = Button(root, text="Cut", width=4)
  manualCut.grid(row=10, column=0, pady=(1,15))
  
  manualFeed = Button(root, text="Feed", width=4)
  manualFeed.grid(row=10, column=1, pady=(1,15))
  
  
  # Test function
  def testPhase():
      pass
  
  manualTest = Button(root, text="Test", width=4, command=testPhase)
  manualTest.grid(row=10, column=2, pady=(1,15))
  
  
  
  
  
  ## Running GUI and communication
  root.after(500, Communication)
  
  
  root.mainloop()
  </code></pre>
  
  <p>This doesn't work:
      Communication()
      root.mainloop()</p>