• #by-own #raspberrypi #developRobot

Kapitel 06: Motorsteuerung

Hinweis: Wie die einzelnen Hardware Komponenten so wie die benötigten evtl. weiteren elektronischen Zusatzteile (Widerstände, Transistoren, Stromversorgung) angeschlossen werden, ist in der Rubrik Elektronik nachzuschlagen. In dieser Rubrik wird ausschließlich die Software-Entwicklung betrachtet.

Die Motorsteuerung soll per Tastendruck möglich sein. Dies ist jedoch hier erst von sekundärer Bedeutung. Da wir uns eine ebene Tiefer an der Hardware befinden, werden wir hier nur die einzelnen Richtungen Programmieren. Die Konvertierung von Tastendruck zu Steuerungsbefehl (FORWARD, BACKWARD,RIGHT...) wird in der Java-Applikation dann später vorgenommen.

Für die Motoren kommen normale DC-Motoren zum Einsatz. Damit muss eine eigene Motorsteuerung implementiert werden. Um verschieden Drehgeschwindigkeiten und Drehrichtungen zu realisieren werden pro  Motor drei Pins des RaspberryPi benötigt. Somit werden für beide Motoren 6-Pins benötigt.

Die Drehgeschwindigkeit wird dabei über ein PWM Signal gesteuert. Es handelt sich dabei um einen prozentualen Anteil im Wertebereich von 0-100. Die zwei anderen Pins dienen der Stromzufuhr, welche je nach Drehrichtung auf HIGH oder LOW gesetzt werden können.

Es sind 2 Motoren Verbaut:

  • Motor MA
    • rechter Antriebsmotor
    • GPIOS:
      • 17 - PWM Signal, 27 und 22 für Stromzufuhr, je nach Drehrichtung auf LOW oder HIGH zu setzen.
  • Motor MB
    • linker Antriebsmotor
    • GPIOS:
      • 13 - PWM Signal, 5 und 6 für Stromzufuhr, je nach Drehrichtung auf LOW oder HIGH zu setzen.

Der RaspberryPi bietet die Mögichkeit beliebige GPIO Pins dafür zu verwenden. Sprich jeder GPIO kann als PWM geber dienen oder das HIGH/LOW Signal auspielen. Es sollte jedoch immer darauf geachtet werden, keine sonder GPIO's zu verwenden, wie z.B. die I2C GPIO's, da man sich sonst evtl. Erweiterungen verbaut.

Die Folgende Tabelle gibt einen kleinen Ausblick auf die Ansteuerrung der Motoren in den vier Grundrichtungen:

GPIO

FORWARD

BACKWARD

LEFT

RIGHT

Motor MA        
9 HIGH LOW HIGH LOW
10 LOW HIGH LOW HIGH
Motor MB        
8 HIGH LOW LOW HIGH
25 LOW HIGH HIGH LOW

Das PWM-Signal kann dabei z.B. konstant auf dem Wert 50 bleiben, was zur halben Dreh-Geschwindigkeit des Motors bedeutet. Für Kurven muss das PWM Signal für eine Seite hoch gesetzt und für die andere Seite ggf. heruntergesetzt werden, so das unterschiedliche Drehzahlen pro Seite erreicht werden. Folglich fährt der Roboter dann in einer Kurve.

Bei uns ist dies mit einer Konstante gelöst, die "self.deffForCurve". Dieser Wert wird für eine Kurve dem PWM-Signal hinzugezogen oder abgezogen, so dass der Roboter eine Kurve fährt.

Der Programmcode für die Motoren sollte nun verständlich sein:

import time
import asyncio
import sys, getopt
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

GPIO_PWM_LEFT = 13
GPIO_LEFT_V = 5
GPIO_LEFT_GRND = 6

GPIO_PWM_RIGHT = 17
GPIO_RIGHT_V = 27
GPIO_RIGHT_GRND = 22

class DC_Motor:

#FORWARD, BACKWARD, RIGHT, LEFT, CURVERIGHTFORWARD, CURVERIGHBACKWARD, CURVELEFTBACKWARD, CURVELEFTFORWARD, STOP


    def __init__(self):

        global GPIO_PWM_LEFT
        global GPIO_LEFT_V
        global GPIO_LEFT_GRND

        global GPIO_PWM_RIGHT
        global GPIO_RIGHT_V
        global GPIO_RIGHT_GRND

        #Pins Motor A -> MotorLeft
        GPIO.setup(GPIO_PWM_LEFT, GPIO.OUT)#PWM
        GPIO.setup(GPIO_LEFT_V, GPIO.OUT) # V - Forward, High
        GPIO.setup(GPIO_LEFT_GRND, GPIO.OUT) # Grnd - Forward, LOW

        #Pins Motor B -> MotorRight
        GPIO.setup(GPIO_PWM_RIGHT, GPIO.OUT) #PWM
        GPIO.setup(GPIO_RIGHT_V, GPIO.OUT) # V -Forward, High
        GPIO.setup(GPIO_RIGHT_GRND, GPIO.OUT) # Grnd - Forward, LOW
        #PWM for Controll
        self.PWM_LEFT = GPIO.PWM(GPIO_PWM_LEFT, 100)
        self.PWM_RIGHT = GPIO.PWM(GPIO_PWM_RIGHT, 100)

        pause = 0.01 # time between pwn signal
        self.PWM_LEFT.start(0)
        self.PWM_RIGHT.start(0)
        #currentDirection
        self.speed = 0
        self.diffForCurve = 40

    def setMotorOrder(self,direction,speed):
        self.speed = float(speed)
        if direction == 'FORWARD':
            self.forward()
        elif direction == 'BACKWARD':
            self.backward()
        elif direction == 'RIGHT':
            self.right()
        elif direction == 'LEFT':
            self.left()
        elif direction == 'CURVERIGHTFORWARD':
            self.curverightforward()
        elif direction == 'CURVERIGHBACKWARD':
            self.curverighbackward()
        elif direction == 'CURVELEFTBACKWARD':
            self.curveleftbackward()
        elif direction == 'CURVELEFTFORWARD':
            self.curveleftforward()
        elif direction == 'STOP':
            self.stop()
        else:
            print ('Directio not Implement')


    def stop(self):
        self.PWM_LEFT.ChangeDutyCycle(0)
        self.PWM_RIGHT.ChangeDutyCycle(0)
        GPIO.output(GPIO_LEFT_V, GPIO.LOW)
        GPIO.output(GPIO_RIGHT_V, GPIO.LOW)
        GPIO.output(GPIO_LEFT_GRND, GPIO.LOW)
        GPIO.output(GPIO_RIGHT_GRND, GPIO.LOW)


    def forward(self):
        GPIO.output(GPIO_LEFT_V, GPIO.HIGH)
        GPIO.output(GPIO_RIGHT_V, GPIO.HIGH)
        GPIO.output(GPIO_LEFT_GRND, GPIO.LOW)
        GPIO.output(GPIO_RIGHT_GRND, GPIO.LOW)
        self.PWM_LEFT.ChangeDutyCycle(self.speed)
        self.PWM_RIGHT.ChangeDutyCycle(self.speed)

    def backward(self):
        GPIO.output (GPIO_LEFT_V, GPIO.LOW)
        GPIO.output (GPIO_RIGHT_V, GPIO.LOW)
        GPIO.output (GPIO_LEFT_GRND, GPIO.HIGH)
        GPIO.output (GPIO_RIGHT_GRND, GPIO.HIGH)
        self.PWM_LEFT.ChangeDutyCycle( self.speed)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed)


    def left(self):
        GPIO.output (GPIO_LEFT_V, GPIO.HIGH)
        GPIO.output (GPIO_RIGHT_V, GPIO.LOW)
        GPIO.output (GPIO_LEFT_GRND, GPIO.LOW)
        GPIO.output (GPIO_RIGHT_GRND, GPIO.HIGH)
        self.PWM_LEFT.ChangeDutyCycle( self.speed)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed)

    def right(self):
        GPIO.output (GPIO_LEFT_V, GPIO.LOW)
        GPIO.output (GPIO_RIGHT_V, GPIO.HIGH)
        GPIO.output (GPIO_LEFT_GRND, GPIO.HIGH)
        GPIO.output (GPIO_RIGHT_GRND, GPIO.LOW)
        self.PWM_LEFT.ChangeDutyCycle( self.speed)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed)

    def curverightforward(self): # CURVERIGHTFORWARD
        GPIO.output(GPIO_LEFT_V, GPIO.HIGH)
        GPIO.output(GPIO_RIGHT_V, GPIO.HIGH)
        GPIO.output(GPIO_LEFT_GRND, GPIO.LOW)
        GPIO.output(GPIO_RIGHT_GRND, GPIO.LOW)
        self.PWM_LEFT.ChangeDutyCycle( self.speed-self.diffForCurve)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed+self.diffForCurve)

    def curveleftforward(self): # CURVELEFTFORWARD
        GPIO.output(GPIO_LEFT_V, GPIO.HIGH)
        GPIO.output(GPIO_RIGHT_V, GPIO.HIGH)
        GPIO.output(GPIO_LEFT_GRND, GPIO.LOW)
        GPIO.output(GPIO_RIGHT_GRND, GPIO.LOW)
        self.PWM_LEFT.ChangeDutyCycle( self.speed+self.diffForCurve)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed-self.diffForCurve)

    def curverighbackward(self): # CURVERIGHBACKWARD
        GPIO.output (GPIO_LEFT_V, GPIO.LOW)
        GPIO.output (GPIO_RIGHT_V, GPIO.LOW)
        GPIO.output (GPIO_LEFT_GRND, GPIO.HIGH)
        GPIO.output (GPIO_RIGHT_GRND, GPIO.HIGH)
        self.PWM_LEFT.ChangeDutyCycle( self.speed-self.diffForCurve)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed+self.diffForCurve)

    def curveleftbackward(self): # CURVELEFTBACKWARD
        GPIO.output (GPIO_LEFT_V, GPIO.LOW)
        GPIO.output (GPIO_RIGHT_V, GPIO.LOW)
        GPIO.output (GPIO_LEFT_GRND, GPIO.HIGH)
        GPIO.output (GPIO_RIGHT_GRND, GPIO.HIGH)
        self.PWM_LEFT.ChangeDutyCycle( self.speed+self.diffForCurve)
        self.PWM_RIGHT.ChangeDutyCycle( self.speed-self.diffForCurve)

Damit die Motoren auch über den Websocket die Befehle erhalten können, muss nun noch ein Websocket Client für die Motorsteuerung geschrieben werden. Dieser sendet wie jeder von uns geschriebene Client zunächst seinen Namen zum Websocket Server und kann dann Nachrichten empfangen oder senden. In diesem Fall muss der Client nur die Befehle Empfangen können.

import asyncio
import websockets
import DC_Motor

async def wsclient():
	async with websockets.connect('ws://localhost:9000') as websocket:
		motor = DC_Motor.DC_Motor()
		await websocket.send('Name:'+'motorControllWS')
		while True:
			msg = await websocket.recv()
			values = msg.split(':')
			motor.setMotorOrder(values[0],values[1])
			#msg = await websocket.send('MotorControllSet'+msg)
			#print(values)

#This have to be the last line!
asyncio.get_event_loop().run_until_complete(wsclient())
© 2019 by-own
Wir benutzen Cookies

Wir nutzen Cookies auf unserer Website. Einige von ihnen sind essenziell für den Betrieb der Seite, während andere uns helfen, diese Website und die Nutzererfahrung zu verbessern (Tracking Cookies). Sie können selbst entscheiden, ob Sie die Cookies zulassen möchten. Bitte beachten Sie, dass bei einer Ablehnung womöglich nicht mehr alle Funktionalitäten der Seite zur Verfügung stehen.