Многопоточность / Многопроцессорная обработка с Python на Raspberry PI с подключенными моторами - PullRequest
1 голос
/ 15 января 2020

Я новичок в этом сообществе, а также в программировании. У меня есть некоторые базовые c знания в программировании на Arduino, а также в Python (ничего особенного, только мерцающие светодиоды и т. Д.).

Так что я сейчас на довольно большом проекте. Я знаю, что это может быть трудным для начала. Основой c является подключение 6 шаговых двигателей с 6 поворотными энкодерами к Raspberry PI. Чтобы получить необходимые операции ввода-вывода, я использую некоторые расширители портов I2 C.

Теперь у меня есть настройка basi c для тестирования с двумя степперами и двумя энкодерами. Когда я использую степпер или кодировщик самостоятельно в программе Python, все работает хорошо. Как только я объединяю все в одну программу, моторы замедляются. В моем понимании python просто работает через код сверху вниз. Поэтому я могу понять, почему скорость моих степперов замедляется. Есть ли способ избежать этого? Я уже читал о многопоточности и пытался ее использовать, но это ничего не изменило. Будет ли многопроцессорность решением проблемы?

Любая помощь или советы будут высоко оценены =)

#importiere Libraries

from threading import Thread
import threading
import time
from time import sleep
import RPi.GPIO as GPIO
import smbus
import sys

#PinOut

Ro1APin = 14                                        # Encoder 1 Pin A
Ro1BPin = 4                                         # Encoder 2 Pin B

Ro2APin = 18                                        # Encoder 1 Pin A
Ro2BPin = 17                                        # Encoder 2 Pin B

b = smbus.SMBus(1)                                  # Bus Aktiv

#Variablen festlegen

globalCounter1 = 0
flag1 = 0
Last_RoB1_Status = 0
Current_RoB1_Status = 0

globalCounter2 = 0
flag2 = 0
Last_RoB2_Status = 0
Current_RoB2_Status = 0

#GPIO Setup

def setup():

        b.write_byte_data(0x21,0x00,0x00)                   # I2C Device 21 alle IOS aktiv schalten (Motor 1)
        b.write_byte_data(0x20,0x00,0x00)                   # I2C Device 20 alle IOS aktiv schalten (Motor 2)

        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(Ro1APin, GPIO.IN)
        GPIO.setup(Ro1BPin, GPIO.IN)
        GPIO.setup(Ro2APin, GPIO.IN)
        GPIO.setup(Ro2BPin, GPIO.IN)

#Klasse Motor1 Rotation

class M1Rotation:

    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self):
        while True:
            b.write_byte_data(0x21,0x14,0x01)       # I2C Device 21, Bank A, Bit 0 High => Motor Stp
            sleep(0.005)
            b.write_byte_data(0x21,0x14,0x00)       # I2C Device 21, Bank A, Alle Bits 0


#Klasse Motor2 Rotation

class M2Rotation:

    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self):
        while True:
            b.write_byte_data(0x20,0x14,0x01)       # I2C Device 21, Bank A, Bit 0 High => Motor Stp
            sleep(0.005)
            b.write_byte_data(0x20,0x14,0x00)       # I2C Device 21, Bank A, Alle Bits 0


#Funktion Encoder1 Auslesen

def rotaryDeal1():
    global flag1
    global Last_RoB1_Status
    global Current_RoB1_Status
    global globalCounter1

    Last_RoB1_Status = GPIO.input(Ro1BPin)
    while(not GPIO.input(Ro1APin)):
        Current_RoB1_Status = GPIO.input(Ro1BPin)
        flag1 = 1
    if flag1 == 1:
        flag1 = 0
        if(Last_RoB1_Status == 1) and (Current_RoB1_Status == 0):
            globalCounter1 = globalCounter1  + 1
            return globalCounter1
            sleep(1)
        if(Last_RoB1_Status == 0) and (Current_RoB1_Status == 1):
            globalCounter1 = globalCounter1 -1
            return globalCounter1
            sleep(1)


#Funktion Encoder2 Auslesen

def rotaryDeal2():
    global flag2
    global Last_RoB2_Status
    global Current_RoB2_Status
    global globalCounter2

    Last_RoB2_Status = GPIO.input(Ro2BPin)
    while(not GPIO.input(Ro2APin)):
        Current_RoB2_Status = GPIO.input(Ro2BPin)
        flag2 = 1
    if flag2 == 1:
        flag2 = 0
        if(Last_RoB2_Status == 1) and (Current_RoB2_Status == 0):
            globalCounter2 = globalCounter2  + 1
            return(globalCounter2)
            sleep(1)
        if(Last_RoB2_Status == 0) and (Current_RoB2_Status == 1):
            globalCounter2 = globalCounter2 -1
            return(globalCounter2)
            sleep(1)


#Klasse Encoder1 Auslesen

class ReadEncoder1:

    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self):
        global globalCounter1
        while self._running:
            rotaryDeal1()


#Klasse Encoder2 Auslesen

class ReadEncoder2:

    def __init__(self):
        self._running = True

    def terminate(self):
        self._running = False

    def run(self):
        global globalCounter2
        while self._running:
            rotaryDeal2()


#Funktion zum Beenden

def destroy():
        GPIO.cleanup()

#Funktion Motor Threads starten

def MotorStart():
        M1Rot = M1Rotation()
        M1RotThread = Thread(target=M1Rot.run)
        M1RotThread.start()
        #M1RotThread.join()

        M2Rot = M2Rotation()
        M2RotThread = Thread(target=M2Rot.run)
        M2RotThread.start()
        #M2RotThread.join()

#Funktion Encoder Threads starten

def EncStart():
        Enc1Rd = ReadEncoder1()
        Enc1RdThread = Thread(target=Enc1Rd.run)
        Enc1RdThread.start()
        #Enc1RdThread.join()

        Enc2Rd = ReadEncoder2()
        Enc2RdThread = Thread(target=Enc2Rd.run)
        Enc2RdThread.start()
        #Enc2RdThread.join()


#Programm Start

if __name__ == '__main__':
    setup()
    MotorStart()
    EncStart()
    print(threading.enumerate())

    while True:

        print('A', globalCounter1)
        print('B', globalCounter2)
...