Practical Hands-On Project-Based PYTHON With Real-World Project Example Python Programming Course For Anyone From Children,... (Idris, Farouk Blake, Michael) (Z-Library)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 116

Practical Hands-On Project-Based PYTHON

With Real-World Project Example


A Python Programming Course for Anyone: From Children, Total Beginners,
Hobbyists to Programmers
Get An Automatic Car Wash System Codes with Python (GUI) And C++ (Controller).
All Simulated, Tested and Proven GUI & Control System Project Codes with
Schematics.
Table of Contents
About The Authors
This book for who?
What can you expect to learn here?
Introduction
Final Outcome of This Programming Training Course
A Brief Explanation of How it works.
Before we move any further: What’s The Codes Involved in Python 3 Language?
Setting up Raspbian on Raspberry Pi 4
What is Raspberry pi 4
Hardware required for this Project
The Steps for installing raspbian on raspberry pi
Steps for configuring raspberry pi and connecting to a network
Setting up Arduino IDE
What is Arduino IDE?
Downloading and installing Arduino IDE
Setting up Arduino libraries
Libraries used in Home Car Wash Control System
Adding libraries to Arduino IDE
The Components used in this project
What’s The Codes Involved in C++ Language for the Controller?
Variables used in project
Input / Output devices variables
GUI Process variables sent to Arduino Controller
GUI Variables sent to Raspberry Pi by Arduino Controller
Variables for setting optimum temperature, water and soap level
GUI used in this project
GUI Features
Sections of GUI
How to Run the Project
How to flash Arduino Programs into Arduino Microcontroller
Implementation Process
Arduino IDE
Open Arduino Code
Project Block Diagram
Project Execution Sequence
Project Schematic
Results on Proteus Simulation
Proteus version required
Required Libraries
Proteus Simulation
Accessing Raspberry Pi For Remote GUI
Remote Desktop Settings
Enable Remote Desktop Settings
Configure Wifi Network
Open Remote Desktop Connection
Configure IP Address for Pi
Login to Raspberry Pi
Raspberry Pi Activate on Remote Desktop
The Final Results Shown on GUI and Hardware in Action
System with Hardware Prototype
System Finding Home
First Water Cycle Started
Soap Cycle Started
Second Water Cycle Started
Car Washed
List of Figures
Figure 1 Raspberry Pi 4
Figure 2 OS available for Raspberry Pi
Figure 3 Rufus interface
Figure 4 Raspberry Pi Home Screen
Figure 5 Wifi configure window on Raspberry Pi
Figure 6 Wifi Icon on Raspberry Pi
Figure 7 Arduino IDE to download
Figure 8 Arduino IDE download options
Figure 9 Arduino IDE extracted folder
Figure 10 Arduino IDE
Figure 11 Arduino Libraries downloaded
Figure 12 libraries folder for adding a library
Figure 13 Arduino Mega 2560
Figure 14 Two-channel active low relay module
Figure 15 DHT11 sensor
Figure 16 Ultrasonic sensor
Figure 17 GUI used in project
Figure 18 Top Frame of GUI
Figure 19 Middle frame of GUI
Figure 20 Bottom Frame of GUI
Figure 21 Project Block Diagram
Figure 22 Project execution sequence
Figure 23 Connections of components with Arduino
Figure 24 Arduino and Raspberry Pi connection
Figure 25 Proteus Libraries to be installed
Figure 26 Proteus library location
Figure 27 Proteus simulation
Figure 28 Ultra sonic hex file location
Figure 29 Arduino Mega 2560 hex file location
Figure 30 Remote Desktop Settings
Figure 31 Enable Remote Desktop
Figure 32 IP address Info
Figure 33: Remote Desktop Option
Figure 34 Remote Desktop connection window
Figure 35 Warning message
Figure 36 Raspberry Pi log in page
Figure 37 Raspberry Pi Desktop on Remote PC
List of Tables
Table 1 Arduino Mega 2560 Specifications
Table 2 Raspberry Pi 4 Specifications
Table 3 Relay module specifications
Table 4 DHT11 specifications
Table 5 Ultrasonic sensor specifications
Table 6 I/O devices variables
Table 7 GUI start process variables
Table 8 GUI variables sent to pi
Table 9 variables for setting optimum conditions
Free eBook Available for Download: Click Here to Download
About The Authors
Michael Blake and Farouk Idris are PLC-HMI & Control programmers. Well, actually, they are
more than that. With over 20 years of experience in the industrial automation field. With deep
appreciation for his friend who introduced him to this in 1997 after finishing his diploma program in
Electrical & Electronics.
Over the years, he has engaged with many system integrators and companies in Singapore and
Southeast Asia. Utilizing self-taught skills, networking, and leverage mentality, he works with the
industry's best tools, people, and companies.

By joint venture between the best minds who possess a similar capacity, they take up a key role in
teaching PLC-HMI and control programming to as many people as possible, cutting short the
learning curves and fears.
All rights reserved and Disclaimer.
No part of this publication shall be reproduced or stored in any retrieval system, mechanical or
electronic, or transmitted in any form or by any means; electronic, mechanical, recording, or
otherwise, without the author's prior written permission.
Although the author has made every effort to ensure that the information in this book is correct at
present, the authors and publisher do not assume and hereby disclaim any liability to any party for
any loss, damage, or disruption caused by any errors or omissions, whether such errors or omissions
resulting from negligence, accident, or any other possible cause. This book cannot assume any
responsibility whatsoever. All contents are original contents by Michael Blake and Farouk Idris.
This book is not authorized or endorsed by any entity.

This book serves as a best practices guide. The results are unique. Our track record has shown those
who contribute effort follow the best practices guide shown here and continue to work on it,
achieving sustainable and long-term results.
This book for who?
Our goal is to expose you to programming, especially Python programming, and as a bonus,
programming in the C++ environment too. We want to help you build your own programs that work.
This does not mean just games and stuff, but actual working, running, and producing results projects.
When you sleep or go do your things, the projects you developed are working. While this book
focuses on projects that are accessible to local networks. We have upcoming projects dealing with
Python, C++, and IoT where the project will be accessible through mobile devices.
While developing a foundation is crucial, immersing yourself in an actual live project gives you a
hardcore edge, not forgetting a sense of drive and purpose that lasts a lifetime. This book is for those
who believe they are the key person regardless of any age who never dealt with any programming
before. You may be fascinated with stories of your friends doing lots of coding on multiple
platforms, so you’ll find breakthroughs here. This book is really for those who want to learn quickly,
diving into cool projects, learning the tricks and hacks by solving the problems while creating those
projects. This book is perfect for all levels of individuals, from hobbyists, seasoned or beginner
programmers, and freelancers. For students attending schools or higher education and their teachers
who want to build their pupils with project-based programming, this book will be an excellent choice
compared to their existing textbook to make learning easier and more interesting.
What can you expect to learn here?
This book's purpose is simple. We want you to master programming, but this book focused on
Python and C++ programming. There is full-blown information on how to do Python, C++, and
other programming on the internet, but all the information is in pieces. What you will encounter in
this book is that all information will be integrated. This sets you to a solid foundation in the general
programming approach. As you work through this book, you soon realize that we are setting you to
play with the big boys in any industry that needs automation through programming. This will make
it easy for you to grasp any programming language when you set yourself to learn further. We will
not tell you what you’ll learn, but you'll touch on the most critical elements like the keywords,
instructions, functions, statements, control flows, methods, lists, loops, code modularization,
dictionaries, files, classes, objects, and interfaces. Bear in mind that you will program two kinds of
controllers that take care of all the ins, outs and display on a Monitor what is happening in real-time.
This is a huge deal for someone who has no or a little background. But if you are an experienced
programmer, you can adopt the content and skills shared in this book to implement your projects.
Introduction

Final Outcome of This Programming Training Course


We will start learning Python Programming and C++ programming with an actual Control
System project. This is an automated process of automated car washing system. It has
different components in it, which include:
Graphical User Interface to send commands to the system related to the car
wash process and view the status and progress of the car wash process.
Arduino Mega 2560 to control the wash process and send parameters to GUI.
Water pump and soap pump to spray water and soap mixture on the car.
Relays to control water pump, soap pump, and inverter motor.
Temperature, water, and soap level detection sensor
Raspberry pi 4 to display GUI to the user.
Explanation of How GUI works.

A brief introduction related to the working of the Home Car Wash Control System is given
in this heading, with details covered in the next part. At the start of the process, the GUI is
displayed to the user, from which the user can select different parameters related to the
process, including:

Car type

Total Cycles for the wash process


Total Water Spray Cycles
Total Soap Spray Cycles
Delay between water and soap spray
Delay between soap and next water spray
Then on pressing the start button, the system finds its home position, checks the
temperature, water level, and soap level, and if it satisfies the optimal conditions, then the
process starts with all the progress displayed on the GUI. Once the war cash process is
completed, the user is promoted to the next car settings, and once those settings are done,
the process repeats itself for the new car.

Before we move any further: What’s The Codes Involved in Python 3


Language?
A brief introduction outline of the codes used in this project is attached here as we
understand some of you may not want to download it from our website. But if you want you
can get it in the last chapter of this training course.

Please take note: In chapter 5, we have included all the C++ codes for the controller
shown in the list below:

For now, a sneak peek on the how the GUI codes look like. The good news is that you can
customize the codes to anything you want when you request the actual codes from us.
Filename: GUI.py
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'GUI_Resp1.ui'


#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# ran again. Do not edit this file unless you know what you are doing.
(Take Note: Don’t Worry We Have A Supplementary Guide Solely To Teach You
How To Do It Right)

import serial
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox

global signalWP # WPF


global signalSP # SPF
global signalM #MF
global signalMStatus ## MR, MH
global signalWL # WLL
global signalSL # S

chk = 0
finish = 0;

count = 0;
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(997, 842)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(5)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setStyleSheet("background-color: rgb(181, 243, 255);")
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(5, 0, 5, 0)
self.verticalLayout.setSpacing(5)
self.verticalLayout.setObjectName("verticalLayout")
self.top = QtWidgets.QFrame(self.centralwidget)
self.top.setFrameShape(QtWidgets.QFrame.NoFrame)
self.top.setFrameShadow(QtWidgets.QFrame.Raised)
self.top.setObjectName("top")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.top)
self.horizontalLayout.setContentsMargins(0, 10, 0, 0)
self.horizontalLayout.setSpacing(10)
self.horizontalLayout.setObjectName("horizontalLayout")
self.topLeft = QtWidgets.QFrame(self.top)
self.topLeft.setStyleSheet("border: 2px solid black;")
self.topLeft.setFrameShape(QtWidgets.QFrame.NoFrame)
self.topLeft.setFrameShadow(QtWidgets.QFrame.Raised)
self.topLeft.setObjectName("topLeft")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.topLeft)
self.verticalLayout_2.setContentsMargins(10, 0, 10, 10)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.waterLevelLabel = QtWidgets.QLabel(self.topLeft)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.waterLevelLabel.setFont(font)
self.waterLevelLabel.setStyleSheet("border:none;")
self.waterLevelLabel.setObjectName("waterLevelLabel")
self.verticalLayout_2.addWidget(self.waterLevelLabel, 0, QtCore.Qt.AlignHCenter)
self.waterLevelSensor = QtWidgets.QLabel(self.topLeft)
self.waterLevelSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.waterLevelSensor.setFrameShape(QtWidgets.QFrame.NoFrame)
self.waterLevelSensor.setText("")
self.waterLevelSensor.setPixmap(QtGui.QPixmap("icons8-water-level-60.png"))
self.waterLevelSensor.setAlignment(QtCore.Qt.AlignCenter)
self.waterLevelSensor.setObjectName("waterLevelSensor")
self.verticalLayout_2.addWidget(self.waterLevelSensor)
self.horizontalLayout.addWidget(self.topLeft)
self.topMiddle = QtWidgets.QFrame(self.top)
self.topMiddle.setStyleSheet("border: 2px solid black;")
self.topMiddle.setFrameShape(QtWidgets.QFrame.NoFrame)
self.topMiddle.setFrameShadow(QtWidgets.QFrame.Raised)
self.topMiddle.setObjectName("topMiddle")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.topMiddle)
self.verticalLayout_3.setContentsMargins(10, 5, 10, 5)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.tempLabel = QtWidgets.QLabel(self.topMiddle)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.tempLabel.setFont(font)
self.tempLabel.setStyleSheet("border: none;")
self.tempLabel.setObjectName("tempLabel")
self.verticalLayout_3.addWidget(self.tempLabel, 0,
QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.temperature = QtWidgets.QLCDNumber(self.topMiddle)
self.temperature.setFrameShape(QtWidgets.QFrame.Box)
self.temperature.setObjectName("temperature")
self.verticalLayout_3.addWidget(self.temperature)
self.horizontalLayout.addWidget(self.topMiddle)
self.topRight = QtWidgets.QFrame(self.top)
self.topRight.setMinimumSize(QtCore.QSize(500, 0))
self.topRight.setStyleSheet("border: 2px solid black;")
self.topRight.setFrameShape(QtWidgets.QFrame.NoFrame)
self.topRight.setFrameShadow(QtWidgets.QFrame.Raised)
self.topRight.setObjectName("topRight")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.topRight)
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_4.setSpacing(0)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.topRightUp = QtWidgets.QFrame(self.topRight)
self.topRightUp.setStyleSheet("border: none;")
self.topRightUp.setFrameShape(QtWidgets.QFrame.NoFrame)
self.topRightUp.setFrameShadow(QtWidgets.QFrame.Raised)
self.topRightUp.setObjectName("topRightUp")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.topRightUp)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.sensorStatusLabel = QtWidgets.QLabel(self.topRightUp)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.sensorStatusLabel.setFont(font)
self.sensorStatusLabel.setStyleSheet("border: none;")
self.sensorStatusLabel.setObjectName("sensorStatusLabel")
self.verticalLayout_5.addWidget(self.sensorStatusLabel, 0,
QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.sensorStatusLabels = QtWidgets.QFrame(self.topRightUp)
font = QtGui.QFont()
font.setPointSize(8)
self.sensorStatusLabels.setFont(font)
self.sensorStatusLabels.setStyleSheet("border: none;")
self.sensorStatusLabels.setFrameShape(QtWidgets.QFrame.NoFrame)
self.sensorStatusLabels.setFrameShadow(QtWidgets.QFrame.Raised)
self.sensorStatusLabels.setObjectName("sensorStatusLabels")
self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.sensorStatusLabels)
self.horizontalLayout_15.setContentsMargins(40, 0, 0, 0)
self.horizontalLayout_15.setSpacing(35)
self.horizontalLayout_15.setObjectName("horizontalLayout_15")
self.homeSensorLabel = QtWidgets.QLabel(self.sensorStatusLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.homeSensorLabel.setFont(font)
self.homeSensorLabel.setObjectName("homeSensorLabel")
self.horizontalLayout_15.addWidget(self.homeSensorLabel)
self.forwardSensoLabel = QtWidgets.QLabel(self.sensorStatusLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.forwardSensoLabel.setFont(font)
self.forwardSensoLabel.setObjectName("forwardSensoLabel")
self.horizontalLayout_15.addWidget(self.forwardSensoLabel)
self.reverseSensorLabel = QtWidgets.QLabel(self.sensorStatusLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.reverseSensorLabel.setFont(font)
self.reverseSensorLabel.setObjectName("reverseSensorLabel")
self.horizontalLayout_15.addWidget(self.reverseSensorLabel)
self.verticalLayout_5.addWidget(self.sensorStatusLabels,0, QtCore.Qt.AlignBottom)
self.verticalLayout_4.addWidget(self.topRightUp)
self.topRightDown = QtWidgets.QFrame(self.topRight)
self.topRightDown.setStyleSheet("border: none;")
self.topRightDown.setFrameShape(QtWidgets.QFrame.NoFrame)
self.topRightDown.setFrameShadow(QtWidgets.QFrame.Raised)
self.topRightDown.setObjectName("topRightDown")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.topRightDown)
self.horizontalLayout_2.setContentsMargins(5, 0, 5, 5)
self.horizontalLayout_2.setSpacing(5)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.home = QtWidgets.QFrame(self.topRightDown)
self.home.setFrameShape(QtWidgets.QFrame.NoFrame)
self.home.setFrameShadow(QtWidgets.QFrame.Raised)
self.home.setObjectName("home")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.home)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.homeSensor = QtWidgets.QLabel(self.home)
self.homeSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.homeSensor.setText("")
self.homeSensor.setPixmap(QtGui.QPixmap("icons8-home-100.png"))
self.homeSensor.setAlignment(QtCore.Qt.AlignCenter)
self.homeSensor.setObjectName("homeSensor")
self.horizontalLayout_3.addWidget(self.homeSensor)
self.horizontalLayout_2.addWidget(self.home)
self.forward = QtWidgets.QFrame(self.topRightDown)
self.forward.setFrameShape(QtWidgets.QFrame.NoFrame)
self.forward.setFrameShadow(QtWidgets.QFrame.Raised)
self.forward.setObjectName("forward")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.forward)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setSpacing(0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.forwardSensor = QtWidgets.QLabel(self.forward)
self.forwardSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.forwardSensor.setText("")
self.forwardSensor.setPixmap(QtGui.QPixmap("icons8-fast-forward-100.png"))
self.forwardSensor.setAlignment(QtCore.Qt.AlignCenter)
self.forwardSensor.setObjectName("forwardSensor")
self.horizontalLayout_4.addWidget(self.forwardSensor)
self.horizontalLayout_2.addWidget(self.forward)
self.reverse = QtWidgets.QFrame(self.topRightDown)
self.reverse.setFrameShape(QtWidgets.QFrame.NoFrame)
self.reverse.setFrameShadow(QtWidgets.QFrame.Raised)
self.reverse.setObjectName("reverse")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.reverse)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_6.setSpacing(0)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.reverseSensor = QtWidgets.QLabel(self.reverse)
self.reverseSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.reverseSensor.setText("")
self.reverseSensor.setPixmap(QtGui.QPixmap("icons8-rewind-100.png"))
self.reverseSensor.setAlignment(QtCore.Qt.AlignCenter)
self.reverseSensor.setObjectName("reverseSensor")
self.verticalLayout_6.addWidget(self.reverseSensor)
self.horizontalLayout_2.addWidget(self.reverse)
self.verticalLayout_4.addWidget(self.topRightDown)
self.horizontalLayout.addWidget(self.topRight)
self.verticalLayout.addWidget(self.top)
self.middle = QtWidgets.QFrame(self.centralwidget)
self.middle.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middle.setFrameShadow(QtWidgets.QFrame.Raised)
self.middle.setObjectName("middle")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.middle)
self.horizontalLayout_5.setContentsMargins(0, 10, 0, 0)
self.horizontalLayout_5.setSpacing(10)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.middleLeft = QtWidgets.QFrame(self.middle)
self.middleLeft.setStyleSheet("border: 2px solid black;")
self.middleLeft.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middleLeft.setFrameShadow(QtWidgets.QFrame.Raised)
self.middleLeft.setObjectName("middleLeft")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.middleLeft)
self.verticalLayout_7.setContentsMargins(10, 0, 10, 10)
self.verticalLayout_7.setSpacing(0)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.soapLevelLabel = QtWidgets.QLabel(self.middleLeft)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.soapLevelLabel.setFont(font)
self.soapLevelLabel.setStyleSheet("border: none;")
self.soapLevelLabel.setObjectName("soapLevelLabel")
self.verticalLayout_7.addWidget(self.soapLevelLabel,0,
QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.soapLevelSensor = QtWidgets.QLabel(self.middleLeft)
self.soapLevelSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.soapLevelSensor.setText("")
self.soapLevelSensor.setPixmap(QtGui.QPixmap("icons8-soap-dispenser-80.png"))
self.soapLevelSensor.setAlignment(QtCore.Qt.AlignCenter)
self.soapLevelSensor.setObjectName("soapLevelSensor")
self.verticalLayout_7.addWidget(self.soapLevelSensor)
self.horizontalLayout_5.addWidget(self.middleLeft)
self.middleCenter = QtWidgets.QFrame(self.middle)
self.middleCenter.setStyleSheet("border: 2px solid black;")
self.middleCenter.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middleCenter.setFrameShadow(QtWidgets.QFrame.Plain)
self.middleCenter.setObjectName("middleCenter")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.middleCenter)
self.verticalLayout_8.setContentsMargins(10, 5, 10, 5)
self.verticalLayout_8.setSpacing(0)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.humidityLabel = QtWidgets.QLabel(self.middleCenter)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setUnderline(True)
font.setWeight(75)
self.humidityLabel.setFont(font)
self.humidityLabel.setStyleSheet("border: none;")
self.humidityLabel.setObjectName("humidityLabel")
self.verticalLayout_8.addWidget(self.humidityLabel, 0,
QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.humidity = QtWidgets.QLCDNumber(self.middleCenter)
self.humidity.setObjectName("humidity")
self.verticalLayout_8.addWidget(self.humidity)
self.horizontalLayout_5.addWidget(self.middleCenter)
self.middleRight = QtWidgets.QFrame(self.middle)
self.middleRight.setMinimumSize(QtCore.QSize(500, 0))
self.middleRight.setLayoutDirection(QtCore.Qt.LeftToRight)
self.middleRight.setStyleSheet("border: 2px solid black;")
self.middleRight.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middleRight.setFrameShadow(QtWidgets.QFrame.Raised)
self.middleRight.setObjectName("middleRight")
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.middleRight)
self.verticalLayout_9.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_9.setSpacing(0)
self.verticalLayout_9.setObjectName("verticalLayout_9")
self.middleRightTop = QtWidgets.QFrame(self.middleRight)
self.middleRightTop.setStyleSheet("border: none;")
self.middleRightTop.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middleRightTop.setFrameShadow(QtWidgets.QFrame.Raised)
self.middleRightTop.setObjectName("middleRightTop")
self.verticalLayout_17 = QtWidgets.QVBoxLayout(self.middleRightTop)
self.verticalLayout_17.setContentsMargins(9, 9, 9, 9)
self.verticalLayout_17.setSpacing(6)
self.verticalLayout_17.setObjectName("verticalLayout_17")
self.pumpMotorStatus = QtWidgets.QLabel(self.middleRightTop)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setItalic(False)
font.setUnderline(True)
font.setWeight(75)
font.setStrikeOut(False)
font.setKerning(True)
self.pumpMotorStatus.setFont(font)
self.pumpMotorStatus.setStyleSheet("border: none;")
self.pumpMotorStatus.setObjectName("pumpMotorStatus")
self.verticalLayout_17.addWidget(self.pumpMotorStatus, 0,
QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
self.pumpMotorLabels = QtWidgets.QFrame(self.middleRightTop)
font = QtGui.QFont()
font.setPointSize(8)
self.pumpMotorLabels.setFont(font)
self.pumpMotorLabels.setStyleSheet("border: none;")
self.pumpMotorLabels.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.pumpMotorLabels.setFrameShadow(QtWidgets.QFrame.Raised)
self.pumpMotorLabels.setObjectName("pumpMotorLabels")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.pumpMotorLabels)
self.horizontalLayout_7.setContentsMargins(35, 0, 0, 0)
self.horizontalLayout_7.setSpacing(30)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.waterPumpLabel = QtWidgets.QLabel(self.pumpMotorLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.waterPumpLabel.setFont(font)
self.waterPumpLabel.setObjectName("waterPumpLabel")
self.horizontalLayout_7.addWidget(self.waterPumpLabel)
self.soapPumpLabel = QtWidgets.QLabel(self.pumpMotorLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.soapPumpLabel.setFont(font)
self.soapPumpLabel.setObjectName("soapPumpLabel")
self.horizontalLayout_7.addWidget(self.soapPumpLabel)
self.motorLabel = QtWidgets.QLabel(self.pumpMotorLabels)
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.motorLabel.setFont(font)
self.motorLabel.setObjectName("motorLabel")
self.horizontalLayout_7.addWidget(self.motorLabel)
self.verticalLayout_17.addWidget(self.pumpMotorLabels, 0, QtCore.Qt.AlignBottom)
self.verticalLayout_9.addWidget(self.middleRightTop)
self.middleRightDown = QtWidgets.QFrame(self.middleRight)
self.middleRightDown.setEnabled(True)
self.middleRightDown.setStyleSheet("border: none;")
self.middleRightDown.setFrameShape(QtWidgets.QFrame.NoFrame)
self.middleRightDown.setFrameShadow(QtWidgets.QFrame.Raised)
self.middleRightDown.setObjectName("middleRightDown")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.middleRightDown)
self.horizontalLayout_6.setContentsMargins(5, 0, 5, 5)
self.horizontalLayout_6.setSpacing(5)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.waterPump = QtWidgets.QFrame(self.middleRightDown)
self.waterPump.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.waterPump.setFrameShadow(QtWidgets.QFrame.Raised)
self.waterPump.setObjectName("waterPump")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.waterPump)
self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_8.setSpacing(0)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.waterPumpSensor = QtWidgets.QLabel(self.waterPump)
self.waterPumpSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.waterPumpSensor.setText("")
self.waterPumpSensor.setPixmap(QtGui.QPixmap("icons8-pump-100.png"))
self.waterPumpSensor.setAlignment(QtCore.Qt.AlignCenter)
self.waterPumpSensor.setObjectName("waterPumpSensor")
self.horizontalLayout_8.addWidget(self.waterPumpSensor)
self.horizontalLayout_6.addWidget(self.waterPump)
self.soapPump = QtWidgets.QFrame(self.middleRightDown)
self.soapPump.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.soapPump.setFrameShadow(QtWidgets.QFrame.Raised)
self.soapPump.setObjectName("soapPump")
self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.soapPump)
self.verticalLayout_10.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_10.setSpacing(0)
self.verticalLayout_10.setObjectName("verticalLayout_10")
self.soapPumpSensor = QtWidgets.QLabel(self.soapPump)
self.soapPumpSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.soapPumpSensor.setText("")
self.soapPumpSensor.setPixmap(QtGui.QPixmap("icons8-pump-100.png"))
self.soapPumpSensor.setAlignment(QtCore.Qt.AlignCenter)
self.soapPumpSensor.setObjectName("soapPumpSensor")
self.verticalLayout_10.addWidget(self.soapPumpSensor)
self.horizontalLayout_6.addWidget(self.soapPump)
self.motor = QtWidgets.QFrame(self.middleRightDown)
self.motor.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.motor.setFrameShadow(QtWidgets.QFrame.Raised)
self.motor.setObjectName("motor")
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.motor)
self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_9.setSpacing(0)
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.motorSensor = QtWidgets.QLabel(self.motor)
self.motorSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
self.motorSensor.setText("")
self.motorSensor.setPixmap(QtGui.QPixmap("icons8-stepper-motor-100.png"))
self.motorSensor.setAlignment(QtCore.Qt.AlignCenter)
self.motorSensor.setObjectName("motorSensor")
self.horizontalLayout_9.addWidget(self.motorSensor)
self.horizontalLayout_6.addWidget(self.motor)
self.verticalLayout_9.addWidget(self.middleRightDown)
self.horizontalLayout_5.addWidget(self.middleRight)
self.verticalLayout.addWidget(self.middle)
self.bottom = QtWidgets.QFrame(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.bottom.sizePolicy().hasHeightForWidth())
self.bottom.setSizePolicy(sizePolicy)
self.bottom.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottom.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottom.setObjectName("bottom")
self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.bottom)
self.horizontalLayout_10.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.horizontalLayout_10.setContentsMargins(0, 8, 0, 8)
self.horizontalLayout_10.setSpacing(10)
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.bottomLeft = QtWidgets.QFrame(self.bottom)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.bottomLeft.sizePolicy().hasHeightForWidth())
self.bottomLeft.setSizePolicy(sizePolicy)
self.bottomLeft.setStyleSheet("border: 2px solid black;")
self.bottomLeft.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottomLeft.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottomLeft.setObjectName("bottomLeft")
self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.bottomLeft)
self.verticalLayout_11.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_11.setSpacing(0)
self.verticalLayout_11.setObjectName("verticalLayout_11")
self.parameters = QtWidgets.QGroupBox(self.bottomLeft)
font = QtGui.QFont()
font.setPointSize(15)
self.parameters.setFont(font)
self.parameters.setStyleSheet("border:none;")
self.parameters.setTitle("")
self.parameters.setFlat(False)
self.parameters.setObjectName("parameters")
self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.parameters)
self.horizontalLayout_11.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_11.setSpacing(0)
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
self.labels = QtWidgets.QFrame(self.parameters)
self.labels.setStyleSheet("border: none;")
self.labels.setFrameShape(QtWidgets.QFrame.NoFrame)
self.labels.setFrameShadow(QtWidgets.QFrame.Raised)
self.labels.setObjectName("labels")
self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.labels)
self.verticalLayout_12.setObjectName("verticalLayout_12")
self.CarTypeLabel = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setFamily("MS Shell Dlg 2")
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.CarTypeLabel.setFont(font)
self.CarTypeLabel.setObjectName("CarTypeLabel")
self.verticalLayout_12.addWidget(self.CarTypeLabel)
self.overallCycleLabel = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.overallCycleLabel.setFont(font)
self.overallCycleLabel.setObjectName("overallCycleLabel")
self.verticalLayout_12.addWidget(self.overallCycleLabel)
self.delaySoap = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.delaySoap.setFont(font)
self.delaySoap.setObjectName("delaySoap")
self.verticalLayout_12.addWidget(self.delaySoap)
self.soapSprayCycle = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.soapSprayCycle.setFont(font)
self.soapSprayCycle.setObjectName("soapSprayCycle")
self.verticalLayout_12.addWidget(self.soapSprayCycle)
self.waterSprayCycle = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.waterSprayCycle.setFont(font)
self.waterSprayCycle.setObjectName("waterSprayCycle")
self.verticalLayout_12.addWidget(self.waterSprayCycle)
self.delayWater = QtWidgets.QLabel(self.labels)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.delayWater.setFont(font)
self.delayWater.setObjectName("delayWater")
self.verticalLayout_12.addWidget(self.delayWater)
self.horizontalLayout_11.addWidget(self.labels)
self.inputBoxes = QtWidgets.QFrame(self.parameters)
self.inputBoxes.setStyleSheet("border:none;")
self.inputBoxes.setFrameShape(QtWidgets.QFrame.NoFrame)
self.inputBoxes.setFrameShadow(QtWidgets.QFrame.Raised)
self.inputBoxes.setObjectName("inputBoxes")
self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.inputBoxes)
self.verticalLayout_13.setSpacing(10)
self.verticalLayout_13.setObjectName("verticalLayout_13")
self.carType = QtWidgets.QComboBox(self.inputBoxes)
self.carType.setStyleSheet("background-color: rgb(255, 255, 255);")
self.carType.setObjectName("carType")
self.carType.addItem("")
self.carType.addItem("")
self.carType.addItem("")
self.verticalLayout_13.addWidget(self.carType)
self.OC = QtWidgets.QSpinBox(self.inputBoxes)
self.OC.setStyleSheet("background-color: rgb(255, 255, 255);")
self.OC.setObjectName("OC")
self.verticalLayout_13.addWidget(self.OC)
self.DS = QtWidgets.QSpinBox(self.inputBoxes)
self.DS.setStyleSheet("background-color: rgb(255, 255, 255);")
self.DS.setObjectName("DS")
self.verticalLayout_13.addWidget(self.DS)
self.SSC = QtWidgets.QSpinBox(self.inputBoxes)
self.SSC.setStyleSheet("background-color: rgb(255, 255, 255);")
self.SSC.setObjectName("SSC")
self.verticalLayout_13.addWidget(self.SSC)
self.WSC = QtWidgets.QSpinBox(self.inputBoxes)
self.WSC.setStyleSheet("background-color: rgb(255, 255, 255);")
self.WSC.setObjectName("WSC")
self.verticalLayout_13.addWidget(self.WSC)
self.DW = QtWidgets.QSpinBox(self.inputBoxes)
self.DW.setStyleSheet("background-color: rgb(255, 255, 255);")
self.DW.setObjectName("DW")
self.verticalLayout_13.addWidget(self.DW)
self.horizontalLayout_11.addWidget(self.inputBoxes)
self.verticalLayout_11.addWidget(self.parameters)
self.buttons = QtWidgets.QFrame(self.bottomLeft)
self.buttons.setStyleSheet("border: none;")
self.buttons.setFrameShape(QtWidgets.QFrame.NoFrame)
self.buttons.setFrameShadow(QtWidgets.QFrame.Raised)
self.buttons.setObjectName("buttons")
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.buttons)
self.horizontalLayout_12.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_12.setSpacing(0)
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
self.Start = QtWidgets.QFrame(self.buttons)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.Start.sizePolicy().hasHeightForWidth())
self.Start.setSizePolicy(sizePolicy)
self.Start.setFrameShape(QtWidgets.QFrame.NoFrame)
self.Start.setFrameShadow(QtWidgets.QFrame.Raised)
self.Start.setObjectName("Start")
self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.Start)
self.horizontalLayout_13.setObjectName("horizontalLayout_13")
self.start = QtWidgets.QPushButton(self.Start)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.start.sizePolicy().hasHeightForWidth())
self.start.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.start.setFont(font)
self.start.setStyleSheet("background-color: rgb(5, 255, 193);\n"
"border-radius: 25px;\n"
" border: 2px solid black;\n"
"height: 50px;\n"
"width: 50px;\n"
"")
self.start.setObjectName("start")
self.horizontalLayout_13.addWidget(self.start)
self.horizontalLayout_12.addWidget(self.Start)
self.animateButton = QtWidgets.QFrame(self.buttons)
self.animateButton.setStyleSheet("border-radius: 50px;")
self.animateButton.setFrameShape(QtWidgets.QFrame.NoFrame)
self.animateButton.setFrameShadow(QtWidgets.QFrame.Raised)
self.animateButton.setObjectName("animateButton")
self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.animateButton)
self.horizontalLayout_14.setObjectName("horizontalLayout_14")
self.update = QtWidgets.QPushButton(self.animateButton)
self.update.setStyleSheet("background-color:rgb(255, 0, 127);\n"
"border: 2px solid black;")
self.update.setText("")
self.update.setObjectName("update")
self.horizontalLayout_14.addWidget(self.update)
self.notDefined2 = QtWidgets.QPushButton(self.animateButton)
self.notDefined2.setStyleSheet("background-color: rgb(255, 85, 0);\n"
"border-radius: 25px;\n"
"border: 2px solid black;\n"
"")
self.notDefined2.setText("")
self.notDefined2.setObjectName("notDefined2")
self.horizontalLayout_14.addWidget(self.notDefined2)
self.notDefined1 = QtWidgets.QPushButton(self.animateButton)
self.notDefined1.setStyleSheet("background-color: rgb(0, 85, 255);\n"
"border-radius: 25px;\n"
"border: 2px solid black;\n"
"")
self.notDefined1.setText("")
self.notDefined1.setObjectName("notDefined1")
self.horizontalLayout_14.addWidget(self.notDefined1)
self.IO = QtWidgets.QPushButton(self.animateButton)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.IO.sizePolicy().hasHeightForWidth())
self.IO.setSizePolicy(sizePolicy)
self.IO.setStyleSheet("background-color: rgb(255, 255, 0);\n"
"border-radius: 25px;\n"
"border: 2px solid black;\n"
"")
self.IO.setText("")
self.IO.setObjectName("IO")
self.horizontalLayout_14.addWidget(self.IO)
self.horizontalLayout_12.addWidget(self.animateButton, 0,
QtCore.Qt.AlignRight|QtCore.Qt.AlignBottom)
self.verticalLayout_11.addWidget(self.buttons)
self.horizontalLayout_10.addWidget(self.bottomLeft)
self.bottomRight = QtWidgets.QFrame(self.bottom)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.bottomRight.sizePolicy().hasHeightForWidth())
self.bottomRight.setSizePolicy(sizePolicy)
self.bottomRight.setStyleSheet("border: 2px solid black;")
self.bottomRight.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottomRight.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottomRight.setObjectName("bottomRight")
self.verticalLayout_14 = QtWidgets.QVBoxLayout(self.bottomRight)
self.verticalLayout_14.setObjectName("verticalLayout_14")
self.bottomFrameBottom = QtWidgets.QFrame(self.bottomRight)
self.bottomFrameBottom.setStyleSheet("border: none;")
self.bottomFrameBottom.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottomFrameBottom.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottomFrameBottom.setObjectName("bottomFrameBottom")
self.verticalLayout_18 = QtWidgets.QVBoxLayout(self.bottomFrameBottom)
self.verticalLayout_18.setObjectName("verticalLayout_18")
self.progressLabel = QtWidgets.QLabel(self.bottomFrameBottom)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.progressLabel.setFont(font)
self.progressLabel.setStyleSheet("border: none;")
self.progressLabel.setObjectName("progressLabel")
self.verticalLayout_18.addWidget(self.progressLabel)
self.progressBar = QtWidgets.QProgressBar(self.bottomFrameBottom)
self.progressBar.setStyleSheet("border: 2px solid black; \n"
"background-color: rgb(4, 217, 15); \n")
self.progressBar.setAlignment(QtCore.Qt.AlignCenter)
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.verticalLayout_18.addWidget(self.progressBar)
self.verticalLayout_14.addWidget(self.bottomFrameBottom, 0, QtCore.Qt.AlignVCenter)
self.bottomRightTop = QtWidgets.QFrame(self.bottomRight)
self.bottomRightTop.setStyleSheet("border: none;")
self.bottomRightTop.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottomRightTop.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottomRightTop.setObjectName("bottomRightTop")
self.verticalLayout_15 = QtWidgets.QVBoxLayout(self.bottomRightTop)
self.verticalLayout_15.setObjectName("verticalLayout_15")
self.operationLabel = QtWidgets.QLabel(self.bottomRightTop)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.operationLabel.setFont(font)
self.operationLabel.setStyleSheet("border: none;")
self.operationLabel.setObjectName("operationLabel")
self.verticalLayout_15.addWidget(self.operationLabel)
self.operationMessageDisp = QtWidgets.QLabel(self.bottomRightTop)
self.operationMessageDisp.setMinimumSize(QtCore.QSize(0, 0))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.operationMessageDisp.setFont(font)
self.operationMessageDisp.setStyleSheet("background-color: rgb(0, 0, 0);\n"
"color: rgb(194, 194, 194);\n"
"border-radius: 20px;\n"
"")
self.operationMessageDisp.setAlignment(QtCore.Qt.AlignCenter)
self.operationMessageDisp.setObjectName("operationMessageDisp")
self.verticalLayout_15.addWidget(self.operationMessageDisp)
self.verticalLayout_14.addWidget(self.bottomRightTop)
self.bottomRightMiddle = QtWidgets.QFrame(self.bottomRight)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.bottomRightMiddle.sizePolicy().hasHeightForWidth())
self.bottomRightMiddle.setSizePolicy(sizePolicy)
self.bottomRightMiddle.setStyleSheet("border: none;")
self.bottomRightMiddle.setFrameShape(QtWidgets.QFrame.NoFrame)
self.bottomRightMiddle.setFrameShadow(QtWidgets.QFrame.Raised)
self.bottomRightMiddle.setObjectName("bottomRightMiddle")
self.verticalLayout_16 = QtWidgets.QVBoxLayout(self.bottomRightMiddle)
self.verticalLayout_16.setObjectName("verticalLayout_16")
self.faultMessageLabel = QtWidgets.QLabel(self.bottomRightMiddle)
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.faultMessageLabel.setFont(font)
self.faultMessageLabel.setStyleSheet("border: none;")
self.faultMessageLabel.setObjectName("faultMessageLabel")
self.verticalLayout_16.addWidget(self.faultMessageLabel)
self.faultMessageDisp = QtWidgets.QLabel(self.bottomRightMiddle)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.faultMessageDisp.setFont(font)
self.faultMessageDisp.setStyleSheet("background-color: rgb(0, 0, 0);\n"
"color: rgb(194, 194, 194);\n"
"border-radius: 20px;\n"
"")
self.faultMessageDisp.setAlignment(QtCore.Qt.AlignCenter)
self.faultMessageDisp.setObjectName("faultMessageDisp")
self.verticalLayout_16.addWidget(self.faultMessageDisp)
self.verticalLayout_14.addWidget(self.bottomRightMiddle)
self.horizontalLayout_10.addWidget(self.bottomRight)
self.verticalLayout.addWidget(self.bottom)
MainWindow.setCentralWidget(self.centralwidget)

self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

self.WSC.setValue(1)
self.SSC.setValue(1)
self.DW.setValue(5)
self.DS.setValue(5)
self.OC.setValue(1)
self.temperature.display(0)
self.humidity.display(0)
self.start.clicked.connect(self.start_process)
self.update.clicked.connect(self.update_process)
self.IO.clicked.connect(self.io_diagnostic)
self.progressBar.setValue(0)

def retranslateUi(self, MainWindow):


_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.waterLevelLabel.setText(_translate("MainWindow", "Water Level"))
self.tempLabel.setText(_translate("MainWindow", "Temperature \'C"))
self.sensorStatusLabel.setText(_translate("MainWindow", "Sensors Status"))
self.homeSensorLabel.setText(_translate("MainWindow", "HOME"))
self.forwardSensoLabel.setText(_translate("MainWindow", "FORWARD"))
self.reverseSensorLabel.setText(_translate("MainWindow", "REVERSE"))
self.soapLevelLabel.setText(_translate("MainWindow", "Soap Level"))
self.humidityLabel.setText(_translate("MainWindow", "Humidity %"))
self.pumpMotorStatus.setText(_translate("MainWindow", "Pumps & Motor Status"))
self.waterPumpLabel.setText(_translate("MainWindow", "Water Pump"))
self.soapPumpLabel.setText(_translate("MainWindow", "Soap Pump"))
self.motorLabel.setText(_translate("MainWindow", "Motor"))
self.CarTypeLabel.setText(_translate("MainWindow", "Car Type"))
self.overallCycleLabel.setText(_translate("MainWindow", "Overall Cycles"))
self.delaySoap.setText(_translate("MainWindow", "Delay Soap (Sec)"))
self.soapSprayCycle.setText(_translate("MainWindow", "Soap Spray Cycle"))
self.waterSprayCycle.setText(_translate("MainWindow", "Water Spray Cycle"))
self.delayWater.setText(_translate("MainWindow", "Delay Water (Sec)"))
self.carType.setItemText(0, _translate("MainWindow", "MiniCar"))
self.carType.setItemText(1, _translate("MainWindow", "Sedan"))
self.carType.setItemText(2, _translate("MainWindow", "MPV"))
self.start.setText(_translate("MainWindow", "Start"))
self.progressLabel.setText(_translate("MainWindow", "Progress"))
self.operationLabel.setText(_translate("MainWindow", "Operation"))
self.operationMessageDisp.setText(_translate("MainWindow", " Current Operation..."))
self.faultMessageLabel.setText(_translate("MainWindow", "Fault Messages"))
self.faultMessageDisp.setText(_translate("MainWindow", " Fault Messages..."))

def io_diagnostic(self):
io_diagnostic_msg = QMessageBox()
io_diagnostic_msg.setWindowTitle("IO Diagnostic")
io_diagnostic_msg.setText("Do you wanna run IO Diagnostic")
io_diagnostic_msg.setIcon(QMessageBox.Question)
io_diagnostic_msg.setStandardButtons(QMessageBox.Cancel|QMessageBox.Ok)
io_diagnostic_msg.setDefaultButton(QMessageBox.Ok)
io_diagnostic_msg.exec_()

def stop_process(self):
stop_msg = QMessageBox()
stop_msg.setWindowTitle("Warning")
stop_msg.setText("Do you want to Halt the Process?")
stop_msg.setIcon(QMessageBox.Question)
stop_msg.setStandardButtons(QMessageBox.Cancel|QMessageBox.Ok)
stop_msg.setDefaultButton(QMessageBox.Ok)
stop_msg.exec_()

def update_process(self):
global finish
print("update")
line2 =""
while True:
line2 = ser.readline().decode('utf-8').rstrip()
print(line2)
#time.sleep(1)

############ Water Levels ################


global chk
if line2 == "WLL" and chk == 0:
print(line2)
print(chk)
self.waterLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(245, 10, 10);")
self.faultMessageDisp.setText("")
ser.write(b"PiRec0\n")
#time.sleep(1);
line2= ""
chk = 1
break

if line2 == "WLF" and chk == 0:


print(line2)
print(chk)
self.waterLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(245, 10, 10);")
self.faultMessageDisp.setText("Water Level Sensor Fault !!!")
ser.write(b"PiRec0\n")
#time.sleep(1);
line2= ""
chk = 1
break

if line2 == "WLH" and chk == 0:


print(line2)
print(chk)
self.waterLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(78, 245, 66);")
self.faultMessageDisp.setText("")
ser.write(b"PiRec0\n")
#time.sleep(1);
line2= ""
chk = 1
break

if line2 == "SLL" and chk == 1:


print(line2)
print(chk)
self.soapLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(245, 10, 10);")
self.faultMessageDisp.setText("")
ser.write(b"PiRec1\n")
#time.sleep(1);
line2= ""
chk = 2
break;

if line2 == "SLF" and chk == 1:


print(line2)
print(chk)
self.soapLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(245, 10, 10);")
self.faultMessageDisp.setText("Soap Level Sensor Fault !!!")
ser.write(b"PiRec1\n")
#time.sleep(1);
line2= ""
chk = 2
break;

if line2 == "SLH" and chk == 1:


print(line2)
print(chk)
self.soapLevelSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(78, 245, 66);")
self.faultMessageDisp.setText("")
ser.write(b"PiRec1\n")
#time.sleep(1);
line2= ""
chk = 2
break;

if chk == 2:
if len(line2) > 0:
if line2[0] == "t":
l= len(line2)
if l == 1:
signalTemp = line2[1]
else:
signalTemp= line2[1:l]

print(signalTemp)
print(chk)
self.temperature.display(int(signalTemp))
if int(signalTemp) == 0:
self.faultMessageDisp.setText("DHT11 Sensor Fault !!!")
else:
self.faultMessageDisp.setText("")
ser.write(b"PiRec2\n")
#time.sleep(1);
line2= ""
chk = 3
break;

if chk == 3:
if len(line2) > 0:
if line2[0] == "h":
l= len(line2)
if l == 1:
signalHum = line2[1]
else:
signalHum = line2[1:l]
print(signalHum)
print(chk)
self.humidity.display(int(signalHum))
if int(signalHum) == 0:
self.faultMessageDisp.setText("DHT11 Sensor Fault !!!")
else:
self.faultMessageDisp.setText("")
ser.write(b"PiRec3\n")
#time.sleep(1);
line2= ""
chk = 4
break;

if line2 == "MF" and chk == 4:


print(line2)
print(chk)
self.motorSensor.setStyleSheet("background-color: rgb(157, 157, 157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec4\n")
#time.sleep(1);
line2= ""
chk = 5
break;

if line2 == "MO" and chk == 4:


print(line2)
print(chk)
self.motorSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(78, 245, 66);")
ser.write(b"PiRec4\n")
#time.sleep(1);
line2= ""
chk = 5
break;

if line2 == "SSH" and chk == 5:


print(line2)
print(chk)
self.homeSensor.setStyleSheet("background-color:rgb(78,245, 66);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec5\n")
#time.sleep(1);
line2= ""
chk = 6
break;

if line2 == "NSH" and chk == 5:


print(line2)
print(chk)
self.homeSensor.setStyleSheet("background-color: rgb(157,157,157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec5\n")
#time.sleep(1);
line2= ""
chk = 6
break;

if line2 == "SSF" and chk == 6:


print(line2)
print(chk)
self.forwardSensor.setStyleSheet("background-color: rgb(78, 245, 66);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec6\n")
#time.sleep(1);
line2= ""
chk = 7
break;

if line2 == "NSF" and chk == 6:


print(line2)
print(chk)
self.forwardSensor.setStyleSheet("background-color: rgb(157,157,157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec6\n")
#time.sleep(1);
line2= ""
chk = 7
break;

if line2 == "SSR" and chk == 7:


print(line2)
print(chk)
self.reverseSensor.setStyleSheet("background-color: rgb(78, 245, 66);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec7\n")
#time.sleep(1);
line2= ""
chk = 8
break;

if line2 == "NSR" and chk == 7:


print(line2)
print(chk)
self.reverseSensor.setStyleSheet("background-color: rgb(157,157,157);\n"
"border-radius: 20px;\n"
"border: 4px solid black;")
ser.write(b"PiRec7\n")
#time.sleep(1);
line2= ""
chk = 8
break;

if line2 == "WPO" and chk == 8:


print(line2)
print(chk)
self.waterPumpSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(78, 245, 66);")
ser.write(b"PiRec8\n")
#time.sleep(1);
line2= ""
chk = 9
break;

if line2 == "WPF" and chk == 8:


print(line2)
print(chk)
self.waterPumpSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(157, 157, 157);")
ser.write(b"PiRec8\n")
#time.sleep(1);
line2= ""
chk = 9
break;

if line2 == "SPO" and chk == 9:


print(line2)
print(chk)
self.soapPumpSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(78, 245, 66);")
ser.write(b"PiRec9\n")
#time.sleep(1);
line2= ""
chk = 10
break;

if line2 == "SPF" and chk == 9:


print(line2)
print(chk)
self.soapPumpSensor.setStyleSheet("border-radius: 20px;\n"
"border: 4px solid black;\n"
"background-color: rgb(157, 157, 157);")
ser.write(b"PiRec9\n")
#time.sleep(1);
line2= ""
chk = 10
break;

if chk == 10:
if len(line2) > 0:
if line2[0] == "p":
l= len(line2)
if l == 1:
progress = line2[1]
else:
progress = line2[1:l]

print(progress)
print(chk)
self.operationMessageDisp.setText(progress)
ser.write(b"PiRec10\n")
#time.sleep(1);
line2= ""
chk = 11
break;

if chk == 11:
if len(line2) > 0:
if line2[0] == "g":
l= len(line2)
if l == 1:
percentage = line2[1]
else:
percentage = line2[1:l]

print(percentage)
print(chk)
self.progressBar.setValue(int(percentage))
ser.write(b"PiRec11\n")
#time.sleep(1);
line2= ""
chk = 12
break;

if line2 == "FIN" and chk == 12:


print(line2)
print(chk)
finish = 1
self.progressBar.setValue(100)
self.operationMessageDisp.setText("Car Washed !!!")
ser.write(b"PiRec12\n")
time.sleep(3);
self.operationMessageDisp.setText("")
self.progressBar.setValue(0)
line2= ""
chk = 0
break;

if line2 == "NFIN" and chk == 12:


print(line2)
print(chk)
ser.write(b"PiRec12\n")
#time.sleep(1);
line2= ""
chk = 0
break

#time.sleep(3)
if finish == 0:
self.update.animateClick()
if finish == 1:
finish = 0

def start_process(self):

carType = self.carType.currentText()
wsc = self.WSC.value()
ssc = self.SSC.value()
dw = self.DW.value()
ds = self.DS.value()
oc = self.OC.value()

self.operationMessageDisp.setText("Waiting to Start")
self.faultMessageDisp.setText("")

msg = QMessageBox()
msg.setWindowTitle("Car Wash Parameters")
msg.setText("Overall Cycles: "+str(oc)+"\nWater Spray Cycle: "+str(wsc)+
"\nSoap Spray Cycle: "+str(ssc)+"\nDelay Water: "+str(dw)+"\nDelay Soap: "+str(ds))
msg.setInformativeText("Car Type "+ carType + " is selected!")
msg.setInformativeText("Car Type "+ carType + " is selected!")
msg.setIcon(QMessageBox.Information)
x = msg.exec_()

############Communication Code###############
#ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
#ser.flush()
msg="\n"
chk_serial = 0
print("start")
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()
while True:
if chk_serial == 0:
ser.write(carType.encode('utf-8'))
ser.write(msg.encode('utf-8'))

line = ser.readline().decode('utf-8').rstrip()
print(line)
#time.sleep(1)
if line == "car_rec":
chk_serial = 1
if chk_serial == 1:
ser.write(str(wsc).encode('utf-8'))
ser.write(msg.encode('utf-8'))

line = ser.readline().decode('utf-8').rstrip()
print(line)
#time.sleep(1)
if line == "wsc_rec":
chk_serial = 2
if chk_serial == 2:
ser.write(str(ssc).encode('utf-8'))
ser.write(msg.encode('utf-8'))

line = ser.readline().decode('utf-8').rstrip()
print(line)
#time.sleep(1)
if line == "ssc_rec":
chk_serial = 3
if chk_serial == 3:
ser.write(str(dw).encode('utf-8'))
ser.write(msg.encode('utf-8'))

line = ser.readline().decode('utf-8').rstrip()
print(line)
#time.sleep(1)
if line == "dw_rec":
chk_serial = 4
if chk_serial == 4:
ser.write(str(ds).encode('utf-8'))
ser.write(msg.encode('utf-8'))

line = ser.readline().decode('utf-8').rstrip()
print(line)
#time.sleep(1)
if line == "ds_rec":
chk_serial = 5
if chk_serial == 5:

ser.write(str(oc).encode('utf-8'))
ser.write(msg.encode('utf-8'))
line = ser.readline().decode('utf-8').rstrip()
print(line)
if line == "oc_rec":
chk_serial = 6
self.update.animateClick()
break;

if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Download Python 3 Codes Here
We know this is a lot to take in. So, to make your life easier we have prepared for you to
download all the GUI Python 3 codes and the controller C++ codes that will receive
inputs from Home, Reverse & Forward sensors, Soap & Water barrel sensors,
Temperature and Humidity Sensors, and control pumps and ac motor inverter.
Go here to download
The Detail Explanation of the System Graphical User Interface (GUI)
Here is the GUI designed for Car Wash System using Qt designer and its programming is done in
python language. Multiple QWidgets and QFrames are embed in this PyQt5 application that
interact with user to take input and display output of the sensors.

In this customized GUI, frames and widgets are aligned according to grid with correct placement
of each window so user can easily visualize and understand it, furthermore, its pixels and images
are automatically adjusted to any desired screen. In demo video, local GUI is running on
1280x780 resolution screen while remote GUI is running on 1920x1080 that depicts that GUI is
purely responsive to any screen.

All The Libraries Included in This Program


First of all, in order to start developing GUI we need several libraries to be installed and included
in the program which will be later use in the program. In car wash GUI development, we import
libraries which includes serial, time, QtCore, QtGui, QtWidgets and QMessageBox.
The PyQt5 Python module provides access to the Qt APIs as its sub-module. In this case, you are
importing the QtCore, QtWidgets, and QtGui sub-modules. The basic purpose of these libraries to
utilize the required functionality.
Serial libraries allow us to read and write data from the serial as in this project we are trying to
communicate between two devices Raspberry Pi and Arduino. Before starting the system Arduino
request Raspberry Pi to send the initial parameters that include “overall cycles”, “water spray
cycles”, “soap spray cycles”, “delay water”, “delay soap” and last but on the least is “car type”.
Data types of Cycles and Delay are in integers while the Car Type is in string format. As soon as
Arduino get the required parameter it will start processing and transmitting data back to
Raspberry Pi via serial port. Transmitting data include sensors data their current state, current
operation and progress of the whole process.

Time library is used to create some delay in the GUI program, we need such delay while program
is in state of receiving parameters from the Arduino and changing state on display. It takes time
parameter in milliseconds.
For designing and layout of the GUI we need multiple widgets, input, output fields and display
panels to show temperature and humidity. Before sending the parameters, GUI show a message
box to confirm the sending parameters for that purpose we used QMessageBox library.

The Inputs and Outputs Parameters


The interface communication between Arduino and Raspberry Pi takes place via serial
communication using specific serial port. In order to receive and transmit data we need some
variables that can store some value or state of the sensors. These variables can be used in the
program anywhere required.
After getting the required input parameters from the Raspberry Pi that include “overall cycles”,
“water spray cycles”, “soap spray cycles”, “delay water”, “delay soap” and “car type”, now
Arduino will transmit sensor data to Pi that include water and soap level which is directly coming
from the ultrasonic sensor interfaced with microcontroller unit. Secondly it will send water and
soap pump status along with the motor and its direction either forward or reverse that is interfaced
with relays. DHT11 temperature and humidity sensor is used to measure the respective parameter,
which transmit to Raspberry Pi for display of the current values of temperature and humidity in
degree Celsius and percentage respectively.
In the figure above, there are some global variables used in the program named as signalWP,
signalSP, signalM, signalMStatus, signalWL and signalSL. These variables are used to receive
the state of water pump, soap pump, motor, motor status, water level and soap level respectively.
The possible outcomes will be cater in the checks used later in the program.
Variables such as chk, finish and count are initialized and declared with zero value. These
variables will be used in the code to change state on trigger and for any repetitive task.

The Structure of GUI


In car wash system GUI, program is divided into classes and definitions. Main class contains all the
definitions. In python language, definitions are regarded as functions. In GUI, main class named as
“ui_MainWindow” is created which contains all the structure of the GUI.
User Interface has a main window which contains definition of “setup_ui”. Initially a window is
created of size 997 by 842 pixels. Furthermore, vertical and horizontal size policy is set as preferred
while window is stretched horizontally by 5 pixels. Size policy is a property of QWidgets, which is
accessed as shown in the figure below. Moreover, background-color of the main window is set as a
rgb(181, 243, 255) which comes under the property of stylesheet. Such kind of properties we used in
CSS language that is widely used for designing purposes. Afterwards, layout is aligned as vertically,
margin as 5 pixels from top and bottom, and spacing as 5 pixels among each widget used in central
widget is adjusted for the central widget known as main window.

Basic structure of GUI contains three major parts TOP, MIDDLE and BOTTOM. Each part further
contains widgets, frames, I/O options, sensor outputs, progress bar and more.
First, the top, middle and bottom frame is created and in top and middle frame three more frames are
created while in the last frame 2 frames are created. Three main frames are aligned vertically while
the frames inside the major frames are aligned horizontally.
The Top Frame
Below is the top frame that represent water level, temperature and sensor status of home, forward
and reverse.

Top frame shape is selected as ‘NoFrame’ while frame shadow as ‘Raised’. Its content margins for
right side are set as 10 pixels and spacing as 10 pixels. Border for frame is set in the stylesheet
property as 2px solid black. Top frame contains right, center, and left frames. All these frames are
layout as horizontally.

The Water Level Sensor

In top left frame, label and frame is added for water level sensor. Frame is created in top frame as
topLeft by using this code “self.topLeft = QtWidgets.QFrame(self.top)”. Geometry settings are set
using the python code line for frame as No frame
“self.topLeft.setFrameShape(QtWidgets.QFrame.NoFrame)” and frame shadow as raised by using
“self.topLeft.setFrameShadow(QtWidgets.QFrame.Raised)”. Water level label point size is set as 16,
weight as 75 and text is made bold and underline. Water level widget is aligned horizontally center
with the design property for "background-color: rgb(157, 157, 157);\n" "border-radius: 20px;\n" and
"border: 4px solid black;"). This widget also contains an icon for water level sensor. Icons can be
add as “self.waterLevelSensor.setPixmap(QtGui.QPixmap("icons8-water-level-60.png"))” Idle state
for water level sensor is grey as our water level is above the defined level it will turns green
otherwise red.

The Temperature

Top middle frame depicts temperature value in degree Celsius. For this, temperature label along with
QLcdNumber is added in a top middle frame. Properties for font is same as set in top left frame
while content margins are set as 10, 5, 10 , 5 for left, top, right and bottom resepectively. Label
widget is aligned vertically and horizontally in center. Temperature widget is imported as
QLcdNumber that tells you the current temperature of the atmosphere.
The Top Right Frame

Top right frame is one of the main frame of the GUI, it contains home, forward and reverse sensor
that will tells the current position and direction of the moving motor. Initially when system starts it’s
on the home position then it will move in forward direction and then in reverse and then again
forward until it finds home position. It comprises of two frames topRightUp and topRightDown. Top
right up frame contains the label and has the same property for labels which include bold, underline,
point size 16 and weight size 75.
The Top Right Up

Top right up frame surrounds three labels for each sensor home, forward and reverse with point size
10, weight as 75 and text as bold. Alignment for these labels is set as Align Bottom along with
spacing of 35 pixels and margins from left side is given as 40 pixels.
The Top Right Down

Top right down has three frames, home, forward and reverse. Design and font properties are same
for all the three sensor frames and label point size 10, text weight 75, and spacing among each label
is 35 pixels. Moreover, content margins are set as 5, 0, 5, 5 for left, top, right and bottom
respectively. Each sensor contains the specific image for the sensor and it gets activate and change
its color to green when motor is in either condition. Design properties are ("background-color:
rgb(157, 157, 157);\n" "border-radius: 20px;\n" and "border: 4px solid black;").
Motor sensor status code snippets with their parameters are attached below.
The Home Sensor

The Forward Sensor


The Reverse Sensor
The Middle Frame

Middle frame has been created which contains several parameters including soap level, humidity,
pumps and motor status.

Middle frames have three more frames which are horizontally aligned along with some geometry,
margins, frames and shadow properties. Middle frame shape is selected as ‘NoFrame’ while frame
shadow as ‘Raised’. Its content margins for right side is set as 10 pixels and spacing as 10 pixels.
Border for frame is set in the stylesheet property as 2px solid black. Middle frame contains right,
center, and left frames.

The Soap Level


In middle left frame, label and frame is added for soap level sensor. Frame is created in middle
frame as middle by using this code “self.middleLeft = QtWidgets.QFrame(self.middle)”. Geometry
settings are set using the python code line for frame as No frame
“self.middleLeft.setFrameShape(QtWidgets.QFrame.NoFrame)” and frame shadow as raised by
using “self.middleLeft.setFrameShadow(QtWidgets.QFrame.Raised)”. Soap level label point size is
set as 16, weight as 75 and text is made bold and underline. Soap level widget is aligned horizontally
center with the design property for "background-color: rgb(157, 157, 157);\n" "border-radius:
20px;\n" and "border: 4px solid black;"). This widget also contains an icon for soap level sensor.
Icons can be add as “self.soapLevelSensor.setPixmap(QtGui.QPixmap("icons8-soap-dispenser-
80.png"))” Idle state for soap level sensor is grey as our soap level is above the defined level it will
turns green otherwise red.

The Humidity
Humidity frame is placed as middle center frame of the middle frame
Middle center frame depicts humidity value in percentage. For this, temperature label along with
QLcdNumber is added in a middle center frame. Properties for font is same as set in middle left
frame while content margins are set as 10, 5, 10, 5 for left, top, right and bottom respectively. Label
widget is aligned vertically and horizontally in center. Humidity widget is imported as QLcdNumber
that tells you the current humidity of the atmosphere.

The Middle Right


Middle right frame is one of the main frame of the GUI, it contains water pump, soap pump and
motor sensor that will tells the status of water pump, soap pump and motor. Initially when system
starts it’s not active as soon as either of the pump or motor activated it will get activates. It
comprises of two frames middleRightTop and middleRightDown. Middle right top frame contains
the label and has the same property for labels which include bold, underline, point size 16 and
weight size 75.

The Middle Right Top

Middle right top frame surrounds three labels for each soap pump, water pump and motor with point
size 10, weight as 75 and text as bold. Alignment for these labels are set as Align Bottom along with
spacing of 30 pixels and margins from left side is given as 35 pixels.
The Middle Right Down

Top right down has three frames, home, forward and reverse. Design and font properties are same
for all the three sensor frames and label point size 10, text weight 75, and spacing among each label
is 35 pixels. Moreover, content margins are set as 5, 0, 5, 5 for left, top, right and bottom
respectively. Each sensor contains the specific image for the sensor and it gets activate and change
its color to green when motor is in either condition. Design properties are ("background-color:
rgb(157, 157, 157);\n" "border-radius: 20px;\n" and "border: 4px solid black;").
The Water Pump Frame
The Soap Pump Frame

The Motor Frame


The Bottom Frame

Bottom frame is designed for user to get inputs from it and to display the progress, current operation
and fault messages. Bottom frame is added in the central widget. Its size policy include horizontal
and vertical stretch that is set to zero. Frame and shadow properties are set to “NoFrame” and
“Raised” respectively. Content margins is set using “self.horizontalLayout_10.setContentMargins(0,
8, 0, 8)” while the spacing as “self.horizontalLayout_10.setSpacing(10)”.

The Bottom Left


Bottom left frame is created which comprises of different parameter necessary to start the program.
Its size policy and frames properties are set as “NoFrame” and “Raised” while content margins from
all side are set to zero along with spacing.
The Parameters

Parameters of car wash system encompasses of car type, overall cycles of the process, delay needed
after soap cycle, soap sprinkles cycle, water sprinkle cycle and delay needed after water spray. These
are parameters required to start a car washing system. In car type, we have a drop-down menu which
gives us options of MiniCar, Sedan and MPV. On the other hand, cycles are number of iterations of
that particular procedure. Parameters frame in terms of designing consist of labels for each particular
heading. QComboBox is set for car type to enable drop down menu feature and for cycle and delay
QSpinBox is declared to select any positive integer.
Properties are declared in the same manner as before and its properties are adjusted as shown in the
image below.

Labels are created in a group box and its font family is selected as “MS Shell Dlg 2”, point size as 15
and weight as 75 and to dominate the text it has to keep bold. All the labels are created one after the
other in a sequential manner.
Input boxes are defined as QSpinBoxes for each parameter except car type in the picture below.
The Buttons

We have integrated a pushbutton to start the process, it will take input parameters from the user
interface and then send it to microcontroller unit via serial communication. Button is created in the
bottom left side of the frame and its properties are set as “NoFrame” and “Raised” in geometry of
the button. Its content margins and spacing are set to zero pixels. Color, border, border-radius, height
and width for the button is set by accessing the style sheet properties of the button.

The Bottom Right

In bottom right frame, progress bar along with operation and fault messages labels are inserted. All
properties are same as set before in earlier frame.
The Progress Bar

The Current Operation


The Fault Messages
The Default Values
Values for each input parameter is set as a default parameter by the following line of codes.
Setting up Raspbian on Raspberry Pi 4

What is Raspberry pi 4
The Raspberry Pi is a microcontroller that uses python language and supports parallel
processing with Linux based Raspbian operating system installed on it. It's a single
computer board equipped with a Quad-core Cortex-A72 processor, which requires less
processing energy and saves room by maintaining costs low. The Raspberry Pi 4 module is
shown in the figure below.

Figure 1 Raspberry Pi 4

It has distinct ports in parallel for various operations. There are 4 USB ports (2 USB 3.0
ports; 2 USB 2.0 ports) and one Ethernet port connecting Raspberry Pi to the port.
Raspberry Pi has its own Wireless Fidelity and Bluetooth port (Wi-Fi). Raspberry Pi utilizes
the operating system separated, known to be Raspbian. It has two micro HDMI ports,
audio/video, and a camera connector to connect the screen. The 5-volt source is linked. A
400MHz video-core IV multimedia is provided by Raspberry Pi. The SONAR, light-
emitting diode (LEDs), and engine driver pins link GPIO pins. Two models, A and B, are
available for the raspberry pi. In short, Raspberry pi 4 is a good processor for extensive and
graphical tasks.

Hardware required for this Project


One raspberry pi 4 with 1GB or 2GB ram
One micro SD-card (16GB or 32 GB)
One monitor with keyboard and mouse or laptop with HDMI display
One micro HDMI to HDMI cable for the laptop or one micro HDMI to VGA cable
for the monitor.
One USB to Type C cable for powering up raspberry pi.
One 5v/ 3A power supply.

The Steps for installing raspbian on raspberry pi


Open the following link to download the raspbian OS for raspberry pi:

https://www.raspberrypi.org/software/operating-systems/

Different versions of OS are available; choose any of them according to the free
space available in the SD-Card of the raspberry pi.
Figure 2 OS available for Raspberry Pi

Click on the download button to start downloading the disk image file of the
selected OS.
After downloading the disk image, the next step is to boot the disk image file on the
SD card. For this download “Rufus” on your laptop using the following link

https://rufus.ie/en/

Download, install and open Rufus.


Insert the micro-SD-card in the laptop to boot it.
Select the inserted micro-SD-card in the device option in the Rufus.
Select the disk image file of raspberry pi OS in the boot selection option.
Figure 3 Rufus interface

Now insert the micro-SD-card into the slot available on the raspberry pi.
Connect the one end of the USB to Type C cable to the Type C slot present in the
raspberry pi and the other end to the power supply.

Connect the “micro-HDMI” slot of the micro-HDMI to VGA cable to the “HDMI0”
port on the raspberry pi and the other end to the VGA of the monitor.
Power on the supply.
After some time, the raspberry pi OS desktop environment will be displayed on the
monitor screen.

Steps for configuring raspberry pi and connecting to a network


Following OS environment will be displayed on the screen after the OS is
successfully installed:
Figure 4 Raspberry Pi Home Screen

Click on the next to select the country, language, and time zone. Then change the
password from the default “raspberry” to one of your choosing. The username is by
default “pi.”
Then the window for the Wi-Fi connection will appear. Select your desired Wi-Fi
network available and click on next. Give the password for the Wi-Fi, and your
raspberry pi will be connected to the internet.

Figure 5 Wifi configure window on Raspberry Pi

After this, the initial configuration will be complete.


You can also connect to other Wi-Fi available by clicking on the “Wi-Fi option”
present on the top right of the raspberry pi window.”

Figure 6 Wifi Icon on Raspberry Pi


Now open the “terminal,” a black icon on the top left of Pi window at fourth place,
and type the following commands to update pi and install remote desktop

1. sudo apt update


2. sudo apt-get install raspberrypi-ui-mods xinit xserver-xorg
3. sudo reboot
4. sudo apt install xrdp

The last step is to enable the “SSH” on raspberry pi by going to the “raspberry pi
configuration” then “interfaces” and then to the “SSH.” Now the Pi is configured to
be used.
Setting up Arduino IDE

What is Arduino IDE?


Arduino IDE is used to code Arduino Mega 2560 in this project. It is the most common and
popular IDE used for the different microcontroller series of Arduino such as Arduino Uno,
Arduino Mega 2560, etc. The main features of this IDE include a simple and user-friendly
interface and fast and efficient debugging and testing tools with the addition of the Serial
monitor, which makes it very easy for professionals to use.

Downloading and installing Arduino IDE


To download the latest version of IDE, go to the following link

https://www.arduino.cc/en/software

Arduino IDE 1.8.15 is the latest IDE available up till now.

Figure 7 Arduino IDE to download

Select the windows from the download option as shown in figure 8, and this will
download the Arduino IDE 1.8.15.

Figure 8 Arduino IDE download options

Extract the downloaded folder “arduino-nightly-windows” to the place where you


want to keep the Arduino IDE.
After successful extraction, a folder named “arduino-nightly” will be created in the
selected extraction location. This folder contains the Arduino IDE.
Open the folder, and it will be like the one shown below:

Figure 9 Arduino IDE extracted folder

Select the highlighted “Arduino” application as shown in figure 9.


The Arduino IDE will open, and it will look like the one in the figure below:
Figure 10 Arduino IDE

The Arduino IDE is successfully installed and opened.


Setting up Arduino libraries
There are different libraries available in the Arduino IDE, which contains many built-in
functions related to different input/output devices. This heading deals with how to use
those libraries in the Arduino sketch.

Libraries used in Home Car Wash Control System


The libraries used in the Arduino sketch of Home Car Wash Control System are shown
below:
#include<Wire.h>

This library is used to communicate with the I2C devices connected to the Arduino. In this
project, if any I2C device is used, then this library must be included.

#include <SPI.h>

This library is used to communicate with the Serial Peripheral Interface (SPI) devices
connected to the Arduino. In this project, if any SPI device is used, then this library must be
included.

#include<SoftwareSerial.h>

This library is used to use the serial as a virtual terminal in the Proteus simulation of this
project.

#include <Adafruit_GFX.h> and #include <Adafruit_SSD1306.h>

These two libraries are used to connect OLED with Arduino. OLED can be used with
Arduino for debugging code since the serial monitor of Arduino is used as a means of
communication between Arduino and Raspberry pi.

#include <dht.h>

This library is used to communicate with the DHT11 module connected to the Arduino. The
DHT module is used to measure the temperature and humidity in this project.

Adding libraries to Arduino IDE


There are two ways to add libraries to the Arduino IDE:

1. Manually downloading and adding


2. Automatically downloading from Arduino IDE
The first method of manually downloading and adding is used in this project. Most of the
above-mentioned libraries are already included in the Arduino IDE, and only three are
required to be downloaded from the internet. The required libraries are downloaded from
different sources on the internet and then added to the Arduino IDE. The libraries are
provided by the vendor in the folder named “Arduino Libraries” as shown below.
Figure 11 Arduino Libraries downloaded

These libraries should be placed in the “libraries” folder present in the Arduino IDE’s
extracted folder, as shown in the figure below:

Figure 12 libraries folder for adding a library

Once the libraries are placed in the folder shown above, the Arduino IDE is ready to
compile and upload the program to the Arduino Mega 2560.
The Components used in this project

The different components used in this project are briefly discussed below:

Arduino Mega 2560

Arduino Mega2560 is used in this project for controlling different input/ output devices. It is
used as the main control unit. This microcontroller board is based on Atmega 2560.

Figure 13 Arduino Mega 2560

The above diagram shows the Arduino Mega 2560. It consists of 54 digital input or output
pins. Due to many pins, this microcontroller is commonly used in projects with many
input/output devices. Its specifications are shown below in the table below:
Table 1 Arduino Mega 2560 Specifications

Input Voltage 7-12V


DC Current per I/O Pin 20 mA
Operating Voltage 5V
Analog Input Pins 16
Input Voltage(limit) 6-20V
Digital I/O Pins 54
Flash Memory 256 KB
DC Current per 3.3V Pin 50 mA
Clock Speed 16 MHz
Weight 37 g
Width 53.3 mm
Length 101.52 mm
EEPROM 4 KB

Download C++ Controller Codes Here


Again, we like to mention to make your life easier we have prepared for you to download
all the GUI Python 3 codes and the controller C++ codes that will receive inputs from
Home, Reverse & Forward sensors, Soap & Water barrel sensors, Temperature and
Humidity Sensors, and control pumps and ac motor inverter.
Go here to download
What are The Codes Involved in C++ Language for the Controller?
A brief introduction outline of the codes used in this project. We are attaching it here as
we understand some of you may not want to download it from our website.

Filename: car_wash_code.ino
#include<EEPROM.h>
#include<Wire.h>
#include <SPI.h>
#include<SoftwareSerial.h>
#include <dht.h>

dht DHT;

#define relay_water_pump 4 //relay trigger pin for water pump


#define relay_soap_pump 5 //relay trigger pin for soap pump
#define relay_reverse_inverter 6 //relay trigger pin for reverse inverter
#define relay_forward_inverter 7 //relay trigger pin for forward inverter

#define forward_limit_s 13 //forward limit sensor


#define home_s 12 // home sensor
#define reverse_limit_s 11 // reverse limit sensor

#define DHT_Pin 10 // temperatue and humidity pin


#define trigger 9
#define echo 8
#define trigger2 3
#define echo2 2

#define SCREEN_WIDTH 128 // OLED display width, in pixels


#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for
128x32

int check = 1;
int count = 1;

long total_cycle = 1;
long water_cycle = 1;
long soap_cycle = 1;
long w_s_delay = 3;
long s_w_delay = 3;

int optimal_temperature1 = 25;


int optimal_temperature2 = 50;
long optimal_water_level = 10;
long optimal_soap_level = 10;
int time_for_cycle = 10; //in seconds

String input;
String car_type = "nill";

int chk_serial = 0;
bool all_good = false;
bool start = false;

String water_level_s = "WLL"; //WLH,WLL,WLF


String soap_level_s = "SLL"; //SLH,SLL,SLF
String home_sensor_s = "NSH"; //NSH,SSH
String forward_sensor_s = "NSF"; //NSF,SSF
String reverse_sensor_s = "NSR"; //NSR,SSR
String water_pump_s = "WPF"; //WPF,WPO
String soap_pump_s = "SPF"; //SPF,SPO
String motor_s = "MF"; //MF,MO
String temperature = "0";
String humidity = "0";
String progress = "0";
String percentage = "0";
String finish_s = "NFIN"; //FIN,NFIN

void setup() {

Serial.begin(9600);
io_setup();

void loop() {

percentage = "0";
finish_s = "NFIN";
receive_gui_parameters();
do{
temp_hum();
water_level();
soap_level();

}
while(all_good == false);
find_home();
start = true;
if(start == true)
{
vehicle_wash_process(total_cycle,water_cycle,soap_cycle);
finish_s = "FIN";
send_initial_par_to_pi();
}
all_good = false;

Filename: Io_s_setup.ino
void io_setup()
{
pinMode(relay_water_pump, OUTPUT);
pinMode(relay_soap_pump, OUTPUT);
pinMode(relay_reverse_inverter, OUTPUT);
pinMode(relay_forward_inverter, OUTPUT);

pinMode(forward_limit_s, INPUT_PULLUP);
pinMode(reverse_limit_s, INPUT_PULLUP);
pinMode(home_s, INPUT_PULLUP);

pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);

pinMode(trigger2, OUTPUT);
pinMode(echo2, INPUT);

digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, HIGH);
digitalWrite(relay_soap_pump, HIGH);
digitalWrite(relay_water_pump, HIGH);

Filename: motors.ino

void motor_fwd()
{
digitalWrite(relay_forward_inverter, LOW);
digitalWrite(relay_reverse_inverter, HIGH);
motor_s = "MO";

if(count == 1)
{
forward_sensor_s = "SSF";
reverse_sensor_s = "NSR";
home_sensor_s = "NSH";
send_initial_par_to_pi();
count=2;
}
if(count == 3)
{
forward_sensor_s = "SSF";
reverse_sensor_s = "NSR";
home_sensor_s = "NSH";
send_initial_par_to_pi();
count=4;
}
}
void motor_bwd()
{
motor_s = "MO";
digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, LOW);
if(count == 2)
{
forward_sensor_s = "NSF";
reverse_sensor_s = "SSR";
home_sensor_s = "NSH";
send_initial_par_to_pi();
count=3;
}
}
void motor_stop()
{
motor_s = "MF";
water_pump_s = "WPF";
soap_pump_s = "SPF";
forward_sensor_s = "NSF";
reverse_sensor_s = "NSR";
home_sensor_s = "SSH";
send_initial_par_to_pi();
digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, HIGH);
digitalWrite(relay_water_pump, HIGH);
digitalWrite(relay_soap_pump, HIGH);
if(count == 4)
{
count=1;
}
}

void find_home()
{
int check_home = 0;
while( check_home == 0)
{
int loop_count = 0;
progress = "System finding home !!!";
send_initial_par_to_pi();
int loop_limit = (time_for_cycle * 1000)/100;
if (digitalRead(home_s))
{
digitalWrite(relay_forward_inverter, LOW);
digitalWrite(relay_reverse_inverter, HIGH);
motor_s = "MO";
forward_sensor_s = "SSF";
reverse_sensor_s = "NSR";
home_sensor_s = "NSH";
send_initial_par_to_pi();

do
{
if (!digitalRead(home_s))
{
digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, HIGH);
motor_s = "MF";
forward_sensor_s = "NSF";
reverse_sensor_s = "NSR";
home_sensor_s = "SSH";
progress = "Home Reached !!!";
send_initial_par_to_pi();
loop_count = loop_limit;
check_home = 1;
return;

}
else
{
loop_count++;
}
delay(100);
}
while(loop_count < loop_limit);
loop_count = 0;

digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, LOW);
motor_s = "MO";
forward_sensor_s = "NSF";
reverse_sensor_s = "SSR";
home_sensor_s = "NSH";
send_initial_par_to_pi();
do
{
if (!digitalRead(home_s))
{
digitalWrite(relay_forward_inverter, HIGH);
digitalWrite(relay_reverse_inverter, HIGH);
motor_s = "MF";
forward_sensor_s = "NSF";
reverse_sensor_s = "NSR";
home_sensor_s = "SSH";
progress = "Home Reached !!!";
send_initial_par_to_pi();
loop_count = loop_limit;
check_home = 1;
return;

}
else
{
loop_count++;
}
delay(100);
}
while(loop_count < loop_limit);
}
else
{
progress = "System at home !!!";
send_initial_par_to_pi();
check_home = 1;
return;
}

Filename: receive_gui_parameters.ino

void receive_gui_parameters()
{
chk_serial = 0;
while( chk_serial != 6)
{

if ( chk_serial == 0){
if (Serial.available() > 0) {
car_type = Serial.readStringUntil('\n');
Serial.println("car_rec");
chk_serial = 1;
}
}
if ( chk_serial == 1)
{
if (Serial.available() > 0) {
water_cycle = Serial.readStringUntil('\n').toInt();
Serial.println("wsc_rec");
chk_serial = 2;
}
}
if ( chk_serial == 2)
{
if (Serial.available() > 0) {
soap_cycle = Serial.readStringUntil('\n').toInt();
Serial.println("ssc_rec");
chk_serial = 3;
}
}
if ( chk_serial == 3)
{
if (Serial.available() > 0) {
w_s_delay = Serial.readStringUntil('\n').toInt();
Serial.println("dw_rec");
chk_serial = 4;
}
}
if ( chk_serial == 4)
{
if (Serial.available() > 0) {
s_w_delay = Serial.readStringUntil('\n').toInt();
Serial.println("ds_rec");
chk_serial = 5;

}
}
if ( chk_serial == 5)
{
if (Serial.available() > 0) {
total_cycle = Serial.readStringUntil('\n').toInt();
Serial.println("oc_rec");
chk_serial = 6;
}
}
}

Filenam: send_gui_parameters.ino
void send_initial_par_to_pi()
{
int chk = 0;
while (chk == 0)
{
Serial.println(water_level_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');
if (reply == "PiRec0")
{

chk = 1;
}
}
}

while (chk == 1)
{
Serial.println(soap_level_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec1")
{

chk = 2;
}
}
}
while (chk == 2)
{
Serial.print("t");
Serial.println(temperature);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec2")
{

chk = 3;
}
}
}

while (chk == 3)
{
Serial.print("h");
Serial.println(humidity);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec3")
{

chk = 4;
}
}
}

while (chk == 4)
{
Serial.println(motor_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec4")
{

chk = 5;
}
}
}
while (chk == 5)
{
Serial.println(home_sensor_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec5")
{

chk = 6;
}
}
}

while (chk == 6)
{
Serial.println(forward_sensor_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec6")
{

chk = 7;
}
}
}

while (chk == 7)
{
Serial.println(reverse_sensor_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec7")
{

chk = 8;
}
}
}

while (chk == 8)
{
Serial.println(water_pump_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec8")
{

chk = 9;
}
}
}

while (chk == 9)
{
Serial.println(soap_pump_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec9")
{

chk = 10;
}
}
}

while (chk == 10)


{
Serial.print("p");
Serial.println(progress);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec10")
{

chk = 11;
}
}
}

while (chk == 11)


{
Serial.print("g");
Serial.println(percentage);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec11")
{

chk = 12;
}
}
}
while (chk == 12)
{
Serial.println(finish_s);
Serial.println("");
if (Serial.available() > 0)
{
String reply = Serial.readStringUntil('\n');

if (reply == "PiRec12")
{

chk = 13;
}
}
}

Filename: soap_spray.ino
void soap_spray()
{
digitalWrite(relay_water_pump, HIGH);
while(check != 3)
{
digitalWrite(relay_water_pump, HIGH);
digitalWrite(relay_soap_pump, LOW);
water_pump_s = "WPF";
soap_pump_s = "SPO";
progress = "Soap Wash Cycle in Progress";
send_initial_par_to_pi();

motor_fwd();
if(!digitalRead(forward_limit_s))
{
while(!digitalRead(forward_limit_s))
{
}
check = 1;
while(digitalRead(reverse_limit_s))
{
digitalWrite(relay_soap_pump, LOW);
water_pump_s = "WPF";
soap_pump_s = "SPO";
send_initial_par_to_pi();
motor_bwd();
}
if(!digitalRead(reverse_limit_s))
{
while(!digitalRead(reverse_limit_s))
{
}
check = 2;
while(digitalRead(home_s))
{
digitalWrite(relay_soap_pump, LOW);
water_pump_s = "WPF";
soap_pump_s = "SPO";
send_initial_par_to_pi();
motor_fwd();
}
}
if(!digitalRead(home_s))
{
while(!digitalRead(home_s))
{
}
check = 3;
motor_stop();
}
}
}
}

Filename: temp_and_hum.ino
void temp_hum()
{
int data=DHT.read11(DHT_Pin);
int temp= DHT.temperature;
int hum=DHT.humidity;

temperature = String(temp);
humidity = String (hum);
if (temp < optimal_temperature1)
{
send_initial_par_to_pi();
all_good = false;
}
else if (temp >= optimal_temperature1 && temp <= optimal_temperature2)
{
send_initial_par_to_pi();

all_good = true;

}
else
{
send_initial_par_to_pi();
all_good = false;

Filename: vehicle_wash_process.ino
void vehicle_wash_process(int total_cycles, int water_cycles, int soap_cycles)
{
int total_c = 1;
int water_c = 1;
int soap_c = 1;
int prog = 0;
int w_prog = 0;
int s_prog = 0;
int w_prog2 = 0;
while (total_c <= total_cycles)
{
while (water_c <= water_cycles)
{
check = 1;
water_spray();
progress = "First Water Spray done";
send_initial_par_to_pi();
w_prog = (33 / ((total_cycles +1)-total_c)) * (1/((water_cycles + 1)- water_c));
prog = w_prog + s_prog + w_prog2;
percentage = String(prog);
send_initial_par_to_pi();
water_c++;

}
delay(w_s_delay*1000);

while (soap_c <= soap_cycles)


{
check = 1;
soap_spray();
progress = "Soap Spray done";
send_initial_par_to_pi();
s_prog = (33 / ((total_cycles +1)-total_c)) *(1/((soap_cycles + 1)- soap_c));
prog = w_prog + s_prog + w_prog2;
percentage = String(prog);
send_initial_par_to_pi();
soap_c++;

}
delay(s_w_delay*1000);
water_c = 1;
while (water_c <= water_cycles)
{
check = 1;
water_spray();
progress = "Second Water Spray done";
send_initial_par_to_pi();
w_prog2 = (33 / ((total_cycles +1)-total_c)) * (1/((water_cycles + 1)- water_c));
prog = w_prog + s_prog + w_prog2;
percentage = String(prog);
send_initial_par_to_pi();
water_c++;

total_c++;
water_c = 1;
soap_c = 1;

start = false;
}

Filename: water_and_soap_level.ino

void water_level()
{
long duration, distance;

digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(5);
digitalWrite(trigger, LOW);

duration = pulseIn(echo, HIGH);


distance = convert_to_dis(duration);

if (distance == 0)
{
water_level_s = "WLF";
send_initial_par_to_pi();
all_good = false;
}
if (distance <= optimal_water_level)
{
water_level_s = "WLH";
send_initial_par_to_pi();
if (all_good == true)
{
all_good = true;
}
else
{
all_good = false;
}
}
else if (distance != 0 && distance > optimal_water_level)
{
water_level_s = "WLL";
send_initial_par_to_pi();
all_good = false;
}

void soap_level()
{
long duration, distance;
digitalWrite(trigger2, LOW);
delayMicroseconds(2);
digitalWrite(trigger2, HIGH);
delayMicroseconds(5);
digitalWrite(trigger2, LOW);

duration = pulseIn(echo2, HIGH);


distance = convert_to_dis(duration);

if (distance == 0)
{
soap_level_s = "SLF";
send_initial_par_to_pi();
all_good = false;
}

if (distance <= optimal_soap_level)


{
soap_level_s = "SLH";
send_initial_par_to_pi();
if (all_good == true)
{
all_good = true;
}
else
{
all_good = false;
}
}
else if (distance != 0 && distance > optimal_soap_level)
{
soap_level_s = "SLL";
send_initial_par_to_pi();
all_good = false;
}

long convert_to_dis(long dur)


{
return dur / 29 / 2;
}

Filename: water_spray.ino

void water_spray()
{
digitalWrite(relay_soap_pump, HIGH);
while(check != 3)
{
digitalWrite(relay_soap_pump, HIGH);
digitalWrite(relay_water_pump, LOW);
water_pump_s = "WPO";
soap_pump_s = "SPF";
progress = "Water Wash Cycle in Progress";
send_initial_par_to_pi();
motor_fwd();
if(!digitalRead(forward_limit_s))
{
while(!digitalRead(forward_limit_s))
{
}

check = 1;
while(digitalRead(reverse_limit_s))
{
digitalWrite(relay_water_pump, LOW);
water_pump_s = "WPO";
soap_pump_s = "SPF";
send_initial_par_to_pi();
motor_bwd();
}
if(!digitalRead(reverse_limit_s))
{
while(!digitalRead(reverse_limit_s))
{
}
check = 2;
while(digitalRead(home_s))
{
digitalWrite(relay_water_pump, LOW);
water_pump_s = "WPO";
soap_pump_s = "SPF";
send_initial_par_to_pi();
motor_fwd();
}
}
if(!digitalRead(home_s))
{
while(!digitalRead(home_s))
{
}
check = 3;
motor_stop();
}
}
}
}
Raspberry pi 4

Raspberry Pi 4 is used in this project to run GUI, which is a computationally extensive task.
It is also used to serially communicate with Arduino in the bi-directional mode so that it can
send the GUI parameters to Arduino and receive the progress and current operations from
Arduino. . Its specifications are shown below in the table below:
Table 2 Raspberry Pi 4 Specifications

Input Voltage 5v
Input current supply 3A
DC Voltage per I/O Pin 3.3v
Digital I/O Pins 54
Clock Speed 1.5 GHz
Weight 46 g
Dimensions 88 mm x 55mm x 19.5 mm
SD-Card support 32 GB

Two-Channel Active Low 5v Relay Modules

The relay modules are used in this project to control the water pump, soap pump, and axis
inverter. The two-channel active low relays are used as shown in the figure below:

Figure 14 Two channel active low relay module

The term active low means that this relay is turned on when a low voltage signal is applied
to its trigger pin, and the term two-channel means that this relay module consists of two
switches that two trigger pins can control. The specifications of the relay module are shown
in the table below:
Table 3 Relay module specifications

Trigger Voltage 5v
DC Switching Voltage 30v
AC Switching Voltage 250v AC
Maximum current 10 A
Trigger Level Active Low

Temperature and Humidity Sensor DHT11

The temperature sensor used in this project is DHT11. It is used to detect temperature and
atmospheric moisture. It has long-term stability and reliability.

Figure 15 DHT11 sensor

This sensor consists of a resistive element and a sense of wet negative temperature
coefficient device. It has advantages like fast response, steadiness, and reliability. It has four
pins, and its specifications are shown in the table below:
Table 4 DHT11 specifications

Name DHT-11
Input Voltage 5V
Humidity Range 20 - 90%
Temperature Range 0 – 50 C

Ultrasonic Sensor
The ultrasonic sensor is used in this project to find the water and the soap level. The model
used for the ultrasonic sensor is the HC-SRO4 ultrasonic module, as shown below:

Figure 16 Ultrasonic sensor

The specifications of the ultrasonic sensor are shown in the table below:
Table 5 Ultrasonic sensor specifications

Power supply 5v dc
Current 15ma
Distance Range 2cm – 400cm
Dimensions 45 mm x 20mm x 15 mm
Variables used in the project
There are different variables declared and used to complete the scope of this project. These
variables are discussed in the tables shown below:

Input / Output devices variables


The variable used for the input and output devices with their names and respective I/O
devices are shown in the below table:
Table 6 I/O devices variables

Variable name Pin on Arduino I/O Device name and


function
relay_water_pump 4 Water Pump on/off
switch
relay_soap_pump 5 Soap Pump on/off switch
relay_forward_inverter 7 Inverter forward on/off
switch
relay_reverse_inverter 6 Inverter reverse on/off
switch
home_s 12 Home Sensor input
forward_limit_s 13 Forward Sensor input
reverse_limit_s 11 Reverse Sensor input
DHT_Pin 10 Temperature Sensor
trigger 9 Water Level Sensor
echo 8 Water Level Sensor
trigger2 3 Soap Level Sensor
echo2 2 Soap Level Sensor

GUI Process variables sent to Arduino Controller


The essential variables initialized by the user on the GUI, which are sent to the Arduino for
the wash process, are shown in the below table:
Table 7 GUI start process variables

Variable name Functionality


total_cycle It decides the number of times whole wash process will run.
water_cycle It decides the number of times water wash process will run in each
cycle.
soap_cycle It decides the number of times soap wash process will run in each
cycle.
w_s_delay It decided the delay in seconds between the water and soap process.
s_w_delay It decided the delay in seconds between the soap and next water
process.

GUI Variables sent to Raspberry Pi by Arduino Controller


These variables contain the signals sent from Arduino to the Raspberry pi, and then the
relative data is displayed on the GUI.
Table 8 GUI variables sent to pi
Variable name Functionality
water_level_s This indicates the level of water in the water tank
soap_level_s This indicates the level of soap in the soap tank
home_sensor_s This indicates the home position of inverter
forward_sensor_s This indicates the forward motion of inverter
reverse_sensor_s This indicates the reverse motion of inverter
water_pump_s This indicates the on/off status of water pump
soap_pump_s This indicates the on/off status of soap pump
motor_s This indicates the on/off status of inverter.
temperature This indicates the temperature
humidity This indicates the humidity
progress This indicates the current operation of the process
percentage This indicated the completed percentage of the project
finish_s This indicates the process finish signal

Variables for setting optimum temperature, water, and soap level


Three variables can be used to set the optimum temperature and optimum water and soap
level, as shown in the table below.
Table 9 variables for setting optimum conditions

Variable name Functionality


optimal_temperature1 This sets the lower range of optimum
temperature for wash process.
optimal_temperature2 This sets the upper range of optimum
temperature for the wash process.
optimal_water_level This sets the optimum water level for the
wash process.
optimal_soap_level This sets the optimum soap level for the
wash process.
time_for_cycle This indicated the total time axis inverter
takes to reach from reverse to forward
position in seconds
GUI used in this project
Graphical User Interface is an important phase of this project. A customized and responsive
GUI has been developed for the user to control the functionality of the system. By using this
GUI, users can easily access and visualize the whole car wash system. GUI is developed
using the most popular and industrial level tool known as PyQt5 along with Qt designer.

Figure 17 GUI used in the project

GUI Features
GUI performs bi-directional communication, which means it sends data to Arduino, takes
signals from the Arduino, and displays it on GUI. GUI has several sections that take inputs
which includes Car Type. We have allotted three options for car type, i.e., MiniCar, Sedan,
and MPV. The Arduino's acknowledgment will display the sensor, pump and motor status,
and soap and water level status. Furthermore, the current status of the process, progress, and
the finish message are also displayed on the GUI.

Sections of GUI
GUI is particularly divided into three frames top, middle and bottom. Each frame has its
own subdivisions of frame known as left, right, and center. Below we will discuss each
frame.
Top Frame
Figure 18 Top Frame of GUI

In the top frame, we have further divisions of frames into top Right, top Left, and top
Center, which contain sensor status, water level, and temperature, respectively.

Middle Frame

Figure 19 Middle frame of GUI

In the middle frame, we have further divisions of frames into middle Right, middle Left, and
middle Center, which contains pump and motor sensor status, soap level, and humidity,
respectively.
Bottom Frame

Figure 20 Bottom Frame of GUI

In the bottom frame, we have further divisions of frames into the bottom Right and bottom
Left. Frame bottom Right contains a progress bar, current operation status, and fault
messages, while Frame bottom Left contains parameters and combo Boxes for each
parameter, respectively.
How to Run the Project
The folder named “Smart Car Wash data” is provided by the vendor, which contains all
codes, Proteus simulations, installation files, and libraries. To run the Arduino sketch,
perform the following steps.

Open the ino file named “car_wash_code” present in the following directory
\Smart Car Wash data\Codes\Arduino code\car_wash_code
Run and flash it (See below: “How to flash Arduino Programs into Arduino
Microcontroller” for steps to flash) on the Arduino MEGA. Make sure that the
components are connected with Arduino according to the schematics shown in the
below headings.
Place the folder named “gui” in the raspberry pi and open the “final_gui.py” file
with “Python 3” or “Thonny IDE.” This will load the GUI on the screen.
The directory for the “gui” file is below:
Smart Car Wash data\Codes\Raspberry pi code\gui

How to flash Arduino Programs into Arduino Microcontroller


To implement the system, we need to flash the program in the microcontroller, but before
flashing it, we need to connect our hardware with the appropriate microcontroller pins as
described in the schematic. Also, make sure to include all the libraries as mentioned in the
book.
Implementation Process
Connect Arduino cable with your desktop for the implementation process.

Arduino IDE
Download and Install Arduino IDE. Install all the relevant libraries as defined in this book.
Open Arduino Code
Now open “car_wash_code.ino,” this is the main file, and all others are functions files.

End of the step of flashing to the controller


Project Block Diagram
The overall block diagram of the project is shown below:

Figure 21 Project Block Diagram


Project Execution Sequence

This project is executed in the following sequence shown below:


Project Schematic
The connections of all the components with Arduino are shown in the figure below:

Figure 23 Connections of components with Arduino

Similarly, the connection of Arduino with Raspberry Pi is shown below:

Figure 24 Arduino and Raspberry Pi connection


Results on Proteus Simulation
Most of this project's parts can be designed, tested, and verified in the “Proteus” software
with only GUI and pi- mega communication not included. However, some steps need to be
covered before running the Proteus simulation.

Proteus version required


This project's schematic is built on “Proteus 8.11 SPO,” so for this schematic to run, one
must have at least Proteus 8.11 SPO. First, the vendor will provide the setup of this Proteus
version. Then, all required steps need to be completed to install that setup.

Required Libraries
There are a few Proteus components libraries that must be included in Proteus before
running the schematic, as shown below:

Figure 25 Proteus Libraries to be installed

These libraries are provided by the vendor in a folder named “Proteus Libraries.” All need to
be done is to copy those libraries to the Proteus directory i.e.
“C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY” as
shown below:

Figure 26 Proteus library location

Proteus Simulation
The Proteus simulation used in this project is shown below:
Figure 27 Proteus simulation

For this simulation to run, a hex file is to be placed in the Arduino Mega 2560 as well as the
two Ultrasonic sensors named Water Level and the Soap Level by double-clicking on them
and then placing the hex file in the locations as shown below:

Figure 28 Ultrasonic hex file location

Similarly, the hex file location for Arduino Mega 2560 is as below:
Figure 29 Arduino Mega 2560 hex file location

The hex files are provided by the vendor in the folder named “HEX Files.”
Accessing Raspberry Pi For Remote GUI
Raspberry Pi is set up remotely to run Graphical User Interface (GUI) on a remote desktop.
For this purpose, the following configuration needs to be done.

Remote Desktop Settings


The first step is to enable the remote desktop connection parameter in the laptop's network
settings or where you want to access remote GUI. For this, click on windows button at the
bottom left corner of your screen. Type “Remote Desktop Settings” and select the respective
option. Another window will prompt up with remote desktop settings.

Figure 30 Remote Desktop Settings

Enable Remote Desktop Settings


A settings window will be open that contains an option of “Enable Remote Desktop.”
Currently, it is in the “OFF” state. Turn it “ON” to enable the remote desktop functionality.
This functionality enables you to connect to and control this PC from a remote device using
a Remote Desktop client. You will be able to work from another device as if you were
working directly on this PC.
Figure 31 Enable Remote Desktop

Configure Wifi Network


For remote connection with raspberry pi, you have to make sure you have a stable internet
connection through which your remote pc and raspberry pi will be connected. In my case, I
enable hotspot through my cell phone that has a username as “Umer#House.”
Connect your pi with a 5v adapter or connect it via remote desktop/pc via Type C cable. It
will power up your raspberry pi. Now find the IP address of the raspberry pi connected to
the selected network using “IP scanner” or any other tool. In my case, on my cell phone, two
devices are connected via hotspot; one is a remote desktop, and the second is raspberry pi, as
shown below:

Figure 32 IP address Info

Open Remote Desktop Connection


After finding the IP address of Pi, click on the windows button in the bottom left corner of
the screen and type “Remote Desktop Connections.”

Figure 33: Remote Desktop Option

Configure IP Address for Pi


After clicking on the Remote Desktop Connection option, another window will pop up.
Enter the IP address of Raspberry Pi, which was allocated to Pi.

Figure 34 Remote Desktop connection window

Press connect, it will pop up a warning window, press ok to continue.


Figure 35 Warning message

Login to Raspberry Pi
Raspberry Pi login window will pop up running on the IP address provided by the cell phone
hotspot. Enter the username, which is by default “pi,” and the password set for pi.

Figure 36 Raspberry Pi log in page

Raspberry Pi Activate on Remote Desktop


After providing the credentials, now you have your raspberry pi active on a remote desktop.
Figure 37 Raspberry Pi Desktop on Remote PC
The Final Results Shown on GUI and Hardware in Action

System with Hardware Prototype


Set parameters for the car and then press ok to start the system. It will pop up the parameters
you have entered, as shown in the figure below.

System Finding Home


Initially, when the system starts, the motor will find its home position before beginning its
spray cycles.
First Water Cycle Started
As the system finds its home position now, it will start the water pump and sprinkle it over
the whole car. In hardware, it will light up the Green Led on hardware. First, it will go up
until the forward limit sensor is triggered, then reverses direction until it reaches the reverse
limit sensor, and it reaches the home position.
Soap Cycle Started
After completing the first water cycle, the system will start a soap pump and sprinkle it over
the whole car. In this process, the system adopts the same strategy as followed in the water
cycle. In hardware, White Led will light up for Soap Pump.
Second Water Cycle Started
In the final phase, the water sprinkle is repeated to wash the car and complete its progress.
Car Washed
Hence, your car is washed!

Free eBook Available for Download: Click Here to Download


Next Practical Python Project

You might also like