0

Ok so im trying to separate my data from arduino into python GUI tkinter over serial port

Example: i have a Humidity and Temperature sensor also a light. I want Python GUI to read the serial communication and store the data in separate strings (temperature, humidity, light)

Python Code

import tkinter as tk
import serial #Serial imported for Serial communication
import time #Required to use delay functions
 
# Create the master object
root = tk.Tk()

ArduinoSerial = serial.Serial('com5',9600) #Create Serial port object called arduinoSerialData
time.sleep(2)

humidity = tk.Label(root, text=ArduinoSerial.readline())
humidity.grid(row=0, column=0)

templabel = tk.Label(root, text="Temperature :" )
tempEntry = tk.Label(root, text=ArduinoSerial.readline() )

templabel.grid(row=1, column=0)
tempEntry.grid(row=1, column=2)

root.mainloop()

Arduino Code

#include <DHT.h>
#include <Wire.h>
#include <SPI.h>

int relayPin = 5; 
int relayPinW = 6;
int sOn = 3;
char serialData;

DHT my_sensor (3, DHT22);

float temperature, humidity;

void setup(){
  Serial.begin(9600);
  my_sensor.begin();
   pinMode (relayPin, OUTPUT);
   pinMode (relayPinW, OUTPUT);
  
}

void loop() {
  
  //digitalWrite(relayPin, HIGH);
  //Serial.print("Nano - Relay Open \n");
  //delay(8000);

  //if(sOn > 0){
  //digitalWrite(relayPin, LOW);
  //Serial.print("Nano - Relay CLOSED \n");
  //delay(8000);
  //}
  
  digitalWrite(relayPinW, HIGH);
  Serial.print("Nano - Water Pump is now active \n");
  delay(8000);
  
  digitalWrite(relayPinW, LOW);
  Serial.print("Nano - Water Pump OFF \n");
  delay(8000);
  
 if(humidity > 1)
  {
     digitalWrite(6, HIGH);
     Serial.print("Humidifer Is Now ** ON ** PIN5 \n");
  } else { 
    Serial.print("ERROR with Digital Write PIN");
  }
  if(Serial.available() > 0)
  serialData = Serial.read();
  Serial.print(serialData);
 
  humidity = my_sensor.readHumidity();
  temperature = my_sensor.readTemperature();

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print("C / Humidity: ");
  Serial.print(humidity);
  Serial.println("%");
    
  
}

that works but i want the data to be separated into there own variables would i have to decode or encode? I'm very lost... THANKS!

2 Answers 2

1

First you need to do the serial reading in a thread so that it won't block the main application. Second both sides have to compromise the format of the data.

Below is an modified example based on your code:

import tkinter as tk
import serial #Serial imported for Serial communication
import threading

# Create the master object
root = tk.Tk()

ArduinoSerial = serial.Serial('com5', 9600) #Create Serial port object called arduinoSerialData

def arduino_handler():
    while True:
        data = ArduinoSerial.readline().strip()
        if data.startswith("Temperature:"):
            temperature.set(data.split(":")[1])
        elif data.startswith("Humidity:"):
            humidity.set(data.split(":")[1])

tk.Label(root, text="Humidity:").grid(row=0, column=0, sticky='w')
humidity = tk.StringVar()
tk.Label(root, textvariable=humidity).grid(row=0, column=1, sticky='w')

tk.Label(root, text="Temperature:" ).grid(row=1, column=0, sticky='w')
temperature = tk.StringVar()
tk.Label(root, textvariable=temperature).grid(row=1, column=1, sticky='w')

threading.Thread(target=arduino_handler, daemon=True).start()
root.mainloop()

Then update Arduino program to output the required format:

void loop() {
    digitalWrite(relayPinW, HIGH);
    Serial.println("Nano - Water Pump is now active");
    delay(8000);

    digitalWrite(relayPinW, LOW);
    Serial.println("Nano - Water Pump OFF");
    delay(8000);

    if(humidity > 1)
    {
        digitalWrite(6, HIGH);
        Serial.println("Humidifer Is Now ** ON ** PIN5");
    } else {
        Serial.println("ERROR with Digital Write PIN");
    }
    if (Serial.available() > 0) {
        serialData = Serial.read();
        Serial.print(serialData);

        humidity = my_sensor.readHumidity();
        temperature = my_sensor.readTemperature();

        Serial.print("Temperature:");
        Serial.println(temperature);
        Serial.print("Humidity:");
        Serial.print(humidity);
        Serial.println("%");
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Exception in thread Thread-7: Traceback (most recent call last): File "C:\Users\ii\AppData\Local\Programs\Python\Python39\lib\threading.py", line 950, in _bootstrap_inner self.run() File "C:\Users\ii\AppData\Local\Programs\Python\Python39\lib\threading.py", line 888, in run self._target(*self._args, **self._kwargs) File "c:\Users\ii\python\GUI\test2.py", line 13, in arduino_handler if data.startswith("Temperature:"): TypeError: startswith first arg must be bytes or a tuple of bytes, not str
It gives me this error.. not sure what threading would do to help this. from what im understanding theres to many things printed into the serial. which i agree. i was thinking i can simplify them down to there exact values
Example would be Tempature: 22.0 Humidity : 33.0 Water Pump 1/ON Light 1/ON and in the serial it would look like this 22.0 x 33.0 x 1 x 1
then i was thinking on spliting the "x" and storing them as floats... but im not sure on how to do that
For the exception, try changing the line data = ArduinoSerial.readline().strip() to data = ArduinoSerial.readline().decode().strip().
0

Hay, Hi
you just need to format type
means in your python code
where it is \

humidity = tk.Label(root, text=ArduinoSerial.readline())
humidity.grid(row=0, column=0)

templabel = tk.Label(root, text="Temperature :" )
tempEntry = tk.Label(root, text=ArduinoSerial.readline() )

just you unicode function means your code should look like:- \

humidity = tk.Label(root, text=unicode(ArduinoSerial.readline()))
humidity.grid(row=0, column=0)

templabel = tk.Label(root, text="Temperature :" )
tempEntry = tk.Label(root, text=unicode(ArduinoSerial.readline()) )

It will solve your issue. But this has a drawback because you are printing too many things in serial
so,
you need to optimize your Arduino code

At last one small tip:- you can use println() function instead fo print("....\n")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.