Skip to content

15. InterFace and Application programming

This week I worked on making a PC software that interfaces with the PCB I made for the networking week.


After taking a look at the material and software suggested by the FabAcademy website, and asking around I have decided to build the software using Python with the PyQt5 library, as the PyQt5 has an additional studio software that helps build more beautiful interfaces in a drag and drop environment, and Python should be easy to use moving from C.


first steps into python

The first thing to do is to learn Python as I have never used it before, I prefer video content for new topics so I did some search and watched this toturial on Python, moving to python from C it was a fairly easy transition, but I have always found it hard to deal with objects and object-oriented programming and python is mostly all objects so I have my fair share of errors on the way.

first project

Now after I have watched almost 3 hours of the tutorial I felt it is enough to try and start using the language, I started with a PyQt5 tutorial project playlist from tech with tim to understand how the interface is built, and get to know the library and its functions.

I usually use Linux subsystem for windows 10 for coding, but since I am building a GUI interface and recall Neil’s interface app in input week) did not work in it I did my work in Windows 10 PowerShell and vs code.

I already had the Python3.9 environment running on my PC when I was working on the input week, I had downloaded it from windows 10 store, it can be downloaded from Python official website too.

Here is the first PyQt5 project I made following the tutorial above, I have added comments to make the code more clear.

#import needed libraries
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
from sys import argv

#define a class responsible for the gui interface
class MyWindow(QMainWindow):
    def __init__(self):#this function runs automaticly when a new object is defines
        super(MyWindow, self).__init__()
        self.setGeometry(200, 200, 600  , 600)
        self.setWindowTitle("RGB Controller")

    def initUI(self): #design UI elements
        self.label = QtWidgets.QLabel(self)     #make a label
        self.label.setText("My Lable!!!")       #name the label
        self.label.move(50 , 50)                #position the label

        self.b1 = QtWidgets.QPushButton(self)   #make a button   
        self.b1.setText("Click")                #select button text
        self.b1.clicked.connect(self.clicked)   #connect button to a function

        self.Dial = QtWidgets.QDial(self)   #make a Dial   
        self.Dial.setGeometry(300, 300, 100  , 100)#set the size and location of the dial

        self.Slider = QtWidgets.QSlider(self)   #make a slider   
        self.Slider.setGeometry(0, 300, 100  , 100) #set the size and location of the slider

    def clicked(self):  #funcution for when the button is pressed                        
        self.label.setText("you pressed the button")    

    def update(self):

def window():
    app = QApplication(sys.argv) 
    win = MyWindow() #define an object window # show the window


first project screenshot

Interface with a PCB

Now that I have some knowledge about python and PyQt5, its time to make a python code that talks to a PCB, I used the PCB that I had made in the networking week it has a UART interface that I will be using to make a GUI that controls the RGB on the board.

first I had to try and connect python to the serial interface of the PCB, for that I used this tutorial.

after I tried it and made sure it works, I added a simple modification on the python code so that the user gives the com port and the serial communication speed before it runs.

Python Code

# Importing Libraries
import serial
import time

#list availabe com ports
ports = list(
for p in ports:

#let user pick com port
boardCom = input("Enter com, example'com3' :")

#let user pick com speed
COMBaudRate = input("Enter communication speed, example'115200' :")

#initialize communication
PCB = serial.Serial(port=boardCom.upper(), baudrate=COMBaudRate, timeout=.1)

def write_read(x):
    PCB.write(bytes(x, 'utf-8'))
    data = PCB.readline()
    return data

while True:
    num = input("Enter a number: ") # Taking input from user
    value = write_read(num)
    print(value) # printing the value

Arduino Code

int x;

void setup() {

void loop() {
  while (!Serial.available());
  x = Serial.readString().toInt();
  Serial.print(x + 1);

Final results

Now its time to work on the week’s assignment, building up my code step by step, testing, and making sure every element works well, I used this tutorial box layout to get the interface to scale if the window size changed by the user, and this [tutorial] to make the Arduino code to read a string and break it apart to get the instruction, for example, the python code sends this string to the PCB <BLUE, 100>, the PCB will read < and understand that its a communication initializer, read the first work till the , symbol, saves it in a string then reads the second word… so and so, thill it reaches the > symbol as a communication ending, sends a replay, and end the string reading.

here is a video running the code, and down below are both the python and Arduino codes.


Assignment python code

# add needed libraries
import serial
import time

from PyQt5.QtWidgets import QDialog, QDial, QHBoxLayout, QVBoxLayout, QApplication, QSpinBox
from PyQt5.QtGui import QIcon
import sys

#get data from user to run serial commuinication correctly
#list availabe com ports
ports = list(
for p in ports:

#let user pick com port
boardCom = input("Enter com, example'com3' :")

#let user pick com speed
COMBaudRate = input("Enter communication speed, example'9600' :")

#initialize communication
PCB = serial.Serial(port=boardCom.upper(), baudrate=COMBaudRate, timeout=.1)

#function to send data to PCB and get a responce
def write_read(x):
    data = PCB.readline()
    return data

#set main window class
class Window(QDialog):
     # function that runs automaticly when defining a new object to this class
    def __init__(self):

        title = "Dial pplication"
        top = 40
        left = 200
        width = 450
        height = 300

        icon = "icon.png"

        self.setGeometry(top, left, width, height)

    def InitUI(self): # function to initlize window widgets
        #define RGB dials
        self.dialRed = QDial(self)
        self.dialGreen = QDial(self)
        self.dialBlue = QDial(self)

        #define RGB spin
        self.spinRed = QSpinBox(self)
        self.spinGreen = QSpinBox(self)
        self.spinBlue = QSpinBox(self  )

        #define layout, 2 horizantal, one for dials, and the other for spins
        self.hbox = QHBoxLayout()
        self.hbox2 = QHBoxLayout()
        self.vbox = QVBoxLayout()

        #add 2 horizantal layouts to the vertical layout

        # add dials and spins to the horizantal layouts

        #set vertical layout for the main window

        #link dials to spins and set ranges to 255
        self.dialRed.setRange(0, 255)
        self.spinRed.setRange(0, 255)

        self.dialGreen.setRange(0, 255)
        self.spinGreen.setRange(0, 255)

        self.dialBlue.setRange(0, 255)
        self.spinBlue.setRange(0, 255)

        #link dials to functions

    # fuction to act when the red dial is changed
    def redValue(self):
        num = self.dialRed.value()
        dataToSend = "<RED," + str(num) + ">"
        value = write_read(dataToSend.encode())

    # fuction to act when the green dial is changed
    def greenValue(self):
        num = self.dialGreen.value()
        dataToSend = "<GREEN," + str(num) + ">"
        value = write_read(dataToSend.encode())

    # fuction to act when the blue dial is changed
    def blueValue(self):
        num = self.dialBlue.value()
        dataToSend = "<BLUE," + str(num) + ">"
        value = write_read(dataToSend.encode())

# function to start the window object
def window():
    app = QApplication(sys.argv)
    window = Window()


Assignment Arduino code

#define redPin 5
#define greenPin 6
#define bluePin 3

const byte numLEDs = 2;
byte ledPin[numLEDs] = {12, 13};
unsigned long LEDinterval[numLEDs] = {200, 400};
unsigned long prevLEDmillis[numLEDs] = {0, 0};

const byte buffSize = 40;
char inputBuffer[buffSize];
const char startMarker = '<';
const char endMarker = '>';
byte bytesRecvd = 0;
boolean readInProgress = false;
boolean newDataFromPC = false;

char messageFromPC[buffSize] = {0};
int newValue = 0;

struct RGB{
      byte r;
      byte g;
      byte b;

void setup() {
  Serial.begin(9600);   // Initiate a serial communication

  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  digitalWrite(redPin, HIGH);    
  digitalWrite(greenPin, HIGH);    
  digitalWrite(bluePin, HIGH);


void loop() {
// put your main code here, to run repeatedly:



void getDataFromPC() {

    // receive data from PC and save it into inputBuffer

  if(Serial.available() > 0) {

    char x =;

      // the order of these IF clauses is significant

    if (x == endMarker) {
      readInProgress = false;
      newDataFromPC = true;
      inputBuffer[bytesRecvd] = 0;

    if(readInProgress) {
      inputBuffer[bytesRecvd] = x;
      bytesRecvd ++;
      if (bytesRecvd == buffSize) {
        bytesRecvd = buffSize - 1;

    if (x == startMarker) { 
      bytesRecvd = 0; 
      readInProgress = true;



void parseData() {

    // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(inputBuffer,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  newValue = atoi(strtokIndx);     // convert this part to an integer



void replyToPC() {

  if (newDataFromPC) {
    newDataFromPC = false;
    Serial.print("<Msg ");
    Serial.print(" recieved");



void updateValue() {

   // this illustrates using different inputs to call different functions
  if (strcmp(messageFromPC, "RED") == 0) {
    analogWrite(redPin, (255 - newValue));

  if (strcmp(messageFromPC, "GREEN") == 0) {
    analogWrite(greenPin, (255 - newValue));

  if (strcmp(messageFromPC, "BLUE") == 0) {
    analogWrite(bluePin, (255 - newValue));

Last update: June 16, 2021