Search code examples
pythonuser-interfaceraspberry-pi3gpio

Manipulating Raspbery PI's DC motor speed while running GUI


Raspberry Pi beginner

I am programming GUI application(using PyQt5) for controlling DC motor. So far I am able to control my motor via motor driver and change it's speed in terminal(using PWM).

The problem comes when I want my motor controller code in my GUI application, because when I run function for motor movement my time.sleep(x) stops the whole GUI application, so I can not make changes on motor's speed.

I found that threading would probably save my problem, but I don't know how to modify speed while thread is running.

Here is my code for running motor:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

# set pins as output
GPIO.setup(4,GPIO.OUT)
GPIO.setup(18,GPIO.OUT)
GPIO.setup(17,GPIO.OUT)


p = GPIO.PWM(17,80)
p.start(40)
p.ChangeDutyCycle(50)

GPIO.output(18,GPIO.LOW)
GPIO.output(4,GPIO.HIGH)
print("4 is HIGH")
time.sleep(5)
p.ChangeDutyCycle(70)#speed change

#change direction of motor spinning
GPIO.output(4,GPIO.LOW)
GPIO.output(18,GPIO.HIGH)
print("18 is HIGH")



p.stop()
GPIO.cleanup()

Python for GUI:

from PyQt5 import QtWidgets,uic, QtCore

...

def start():
    while True:
        #run motor here


dlg.btn_start.clicked.connect(start)

...

I hope that I didn't make this more complicated than it already is, thank you all for answers!

Best regards!


Solution

  • Solution:

    I made it work with Python multiprocessing.

    My program is now separated in two processes:

    1.The GUI process, which runs the GUI and signal which runs a function for speed change when slider is changed. And whenever slider's position is changed the value is saved into text file.

    2.Motor process is process which is reading the same file all the time and applying value from file to motor speed. If that value is set to 0, motor is Off.

    I assume this is not the only solution and of course not the best, but it works for me.

    I hope that will help to some of you too!

    Cheers!

    And of course the code:

    from PyQt5 import QtWidgets,uic, QtCore
    from PyQt5.QtWidgets import QMessageBox,QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog
    from PyQt5.QtCore import QTimer,QTime
    from PyQt5.QtGui import QIcon
    import time
    from multiprocessing import Process, Queue, Value
    
    app = QtWidgets.QApplication([])
    dlg = uic.loadUi("Motor.ui")
    
    
    def startMotor():
        try:
            while True:
                time.sleep(0.01)
                file = open("test.txt", "r") 
                a=file.read()
                file.close()
                if int(a) == 0:
                    print("OFF")
                    #motor is off
                else:
                    #motor is ON
                    print("ON, speed is:", a)
        except:
            print("Abort...")
    
    def runProgram():
        dlg.show()
        app.exec()
    
    
    def changeSpeed():
        dlg.label.setText(str(dlg.slider.value()))
    
        file = open("test.txt","w") 
        file.write(str(dlg.slider.value()))
        file.close() 
    
    #when slider's value is changed
    dlg.slider.valueChanged.connect(changeSpeed)
    
    
    if __name__ == '__main__':
        #On Program load    
        p1 = Process(target=startMotor,args=())
        p2 = Process(target=runProgram,args=())
    
        p1.start()
        p2.start()
    
        p1.join()
        p2.join()
    

    If anyone is interested in learning the basics of PyQt5 design, check my YouTube channel where I explain the basics: Link