PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Python - Motor dreht aber Geschwindigkeit lässt sich über PWM nicht ändern



Chris1803
06.12.2017, 20:58
Hallo zusammen

Ich habe folgende Anordnung:
Computer A mit eingabegeräten und Computer B (Raspberry Pi) für die Motorensteuerung meines Modelllasters.
Computer A schickt an B einen Wert zwischen 0 und 10'000 für die Richtungs- und Geschwindigkeitsangabe.
Das funktioniert.
Ist der Wert zwischen 0 und 4750, dreht der Motor vorwärts, ist der Wert grösser als 5250, dreht er rückwärts. Die 10% Spatzung habe ich mir für kleinste, ungewollte Bewegungen am Joystick gelassen, wird vielleicht kleiner.
Das funktioniert.
An einem freien Pin ist eine Kontroll-LED angebracht, damit ich sehen kann, ob der Motor ein Signal bekommt, falls er stottert.
Das funktioniert.

Was nicht funktioniert ist die Änderung der Geschwindigkeit und dass die LED ihre Helligkeit an die Signalgeschwindigkeit des Motors anpasst.
Unten im Code ist das Modul Umstellen(intSpeed), durch das die Richtgung geregelt wird und wodurch das PWM-Signal erhöht oder gesenkt werden soll.
Hat jemand einen Tipp, woran es liegen könnte, dass der Motor nicht schneller oder langsamer dreht?

Was ich schon getestet habe: Die Verkabelung passt. Die Pins habe ich mit einem ähnlichen Code (war meine Vorlage) bereits angesteuert und wenn ich darüber die Drehzahl ändere, dreht der Motor schneller oder langsamer.


import sys
import time
import socket
import RPi.GPIO as gpio


#define all variables
HOST = ''
TCP_PORT = 10001
intStringStart = 0
intStringEnd = 0
intStringLen = 0
intXaxis = 0
intYaxis = 0
intBA = 0
intBB = 0
intBC = 0
intBD = 0
intBE = 0
intBF = 0
intBG = 0
intBH = 0
intBI = 0
intBJ = 0
intBK = 0
intBL = 0
intDirection = 0
fltCycle = 100
gpio.setmode(gpio.BCM)
gpio.setup(18, gpio.OUT)
gpio.setup(23, gpio.OUT)
gpio.setup(24, gpio.OUT)
pwm = gpio.PWM(23, 100)
pwmLED = gpio.PWM(18, 100)


#************************************************* ***********************************************
#Ein
def Ein():
print "Ein"
pwm.start(0)
pwmLED.start(0)

gpio.output(18, False)
gpio.output(23, False)
gpio.output(24, False)


#************************************************* ***********************************************
def Pruefer():
print "Pruefer called " + str(intYaxis)

#************************************************* ***********************************************
def Beender():
print "Shutting down GPIO"
Aus()
print "Closing socket"
connection.close()
print "Shutting down"

#************************************************* ***********************************************
def Umstellen(intSpeed):
if intSpeed < 4750:
fltCycle = float(intSpeed / 50)
gpio.output(18, True)
gpio.output(23, True)
gpio.output(24, False)
pwm.ChangeDutyCycle(fltCycle)
pwmLED.ChangeDutyCycle(fltCycle)
print str(fltCycle)

elif intSpeed > 5250:
fltCycle = float((intSpeed / 50) - 100)
gpio.output(18, True)
gpio.output(23, False)
gpio.output(24, True)
pwm.ChangeDutyCycle(fltCycle)
pwmLED.ChangeDutyCycle(fltCycle)

else:
gpio.output(18, False)
gpio.output(23, False)
gpio.output(24, False)
pwm.stop()
pwmLED.stop()


#************************************************* ***********************************************
#Aus
def Aus():
print "Aus"
gpio.output(18, False)
gpio.output(23, False)
gpio.output(24, False)
pwm.stop()
pwmLED.stop()
gpio.cleanup()


#************************************************* ***********************************************

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, TCP_PORT))
sock.listen(1)

Ein()

while True:
#Accept the connection and create new socket connection1
try:
connection, strClientAddress = sock.accept()
boConnected = True

#loop while connected
while True:
strData = connection.recv(100)
intStringStart = 0
intStringEnd = 0
intStringLen = 0
intXaxis = 0
intYaxis = 0
intBA = 0
intBB = 0
intBC = 0
intBD = 0
intBE = 0
intBF = 0
intBG = 0
intBH = 0
intBI = 0
intBJ = 0
intBK = 0
intBL = 0

#Check if strData <> null, else break loop
if strData:

#Extract X axis
try:
intStringEnd = strData.find("X:")
intStringStart = intStringEnd + 2
intStringEnd = strData.find(";", intStringStart)
intXaxis = int(strData[intStringStart:intStringEnd])
except:
intXaxis = 0
#Extract Y axis
try:
intStringEnd = strData.find("Y:")
intStringStart = intStringEnd + 2
intStringEnd = strData.find(";", intStringStart)
intYaxis = int(strData[intStringStart:intStringEnd])
except:
intYaxis = 0
#Extract Button A
try:
intStringEnd = strData.find("BA:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBA = int(strData[intStringStart:intStringEnd])
except:
intBA = 0
#Extract Button B
try:
intStringEnd = strData.find("BB:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBB = int(strData[intStringStart:intStringEnd])
except:
intBB = 0
#Extract Button C
try:
intStringEnd = strData.find("BC:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBC = int(strData[intStringStart:intStringEnd])
except:
intBC = 0
#Extract Button D
try:
intStringEnd = strData.find("BD:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBD = int(strData[intStringStart:intStringEnd])
except:
intBD = 0
#Extract Button E
try:
intStringEnd = strData.find("BE:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBE = int(strData[intStringStart:intStringEnd])
except:
intBE = 0
#Extract Button F
try:
intStringEnd = strData.find("BF:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBF = int(strData[intStringStart:intStringEnd])
except:
intBF = 0
#Extract Button G
try:
intStringEnd = strData.find("BG:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBG = int(strData[intStringStart:intStringEnd])
except:
intBG = 0
#Extract Button H
try:
intStringEnd = strData.find("BH:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBH = int(strData[intStringStart:intStringEnd])
except:
intBH = 0
#Extract Button I
try:
intStringEnd = strData.find("BI:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBI = int(strData[intStringStart:intStringEnd])
except:
intBI = 0
#Extract Button J
try:
intStringEnd = strData.find("BJ:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBJ = int(strData[intStringStart:intStringEnd])
except:
intBJ = 0
#Extract Button K
try:
intStringEnd = strData.find("BK:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBK = int(strData[intStringStart:intStringEnd])
except:
intBK = 0
#Extract Button L
try:
intStringEnd = strData.find("BL:")
intStringStart = intStringEnd + 3
intStringEnd = strData.find(";", intStringStart)
intBL = int(strData[intStringStart:intStringEnd])
except:
intBL = 0

Umstellen(intYaxis)

#close connection if Button BF (6) is pressed
if intBF == 1:
Beender()
sys.exit(0)



else:
print "Connection lost"
break

#Clean up after error or at termination
finally:
connection.close()

hbquax
07.12.2017, 06:54
Hast du den Ausgang zum Motor mit einem Voltmeter mal überprüft?
Ich kenn mich mit Python nicht aus, aber müsste da nicht eine Schleife im Programm sein?
Was für einen Motor-Treiber / Shield benutzt du, was für einen Motor und wie sieht die ganze Schaltung aus?
Bilder, Bilder, Bilder!

Was mir noch auffällt: Bei 1 dreht der Motor langsam vorwärts, bei 4749 dreht er volle Möhre vorwärts. Von 4750 bis 5250 steht er. Bei 5251 dreht der ganz langsam rückwärts und bei 10000 voll rückwärts. Ist das so gewollt? Vor allem der Sprung von voll vorwärts auf Stillstand?

Schon mal getestet, fltcycle direkt Werte zuzuweisen und geschaut, ob sich dann die Geschwindigkeit wie gewünscht verhält?

Chris1803
07.12.2017, 07:24
Hallo hbquax

Zwischenzeitlich ist eine Nacht vergangen und ich konnte noch einiges testen - habe aber die Geduld nicht mehr gefunden, das in Worte zu fassen und zu aktualisieren.
Wie ich nach einigen Stunden Schlaf festgestellt habe, ist meine Berechnung oben nicht ganz korrekt. Eigentlich soll die Berechnung eine Parabel beschreiben. Das Eingabegerät ist ja, wie oben beschrieben, ein Joystick. Ganz vorne übergibt er den Wert 0, ganz hinten 10'000. Die Berechnung soll ergeben, dass beim Wert 0 der Motor voll dreht, in der Mitte steht und ganz hinten voll in die andere Richtung dreht. Ich habe mir einen Spielraum von 5% in jede Richtung gegeben, um kleinste Bewegungen am Joystick zu ignorieren. Excel sei Dank habe ich nun die richtige Formel zur Berechnung der Werte.

Der Motor hängt über einen L298N am Raspberry und die Stromversorgung funktioniert, sonst hätte ich es nicht mit anderen Programmen testen können.

Wie von dir vorgeschlagen habe ich bereits versucht, direkt Werte einzugeben und zu schauen, was der Motor macht. Habe über eine Schlaufe einen Zähler von 0 bis 200 hochzählen lassen und das mit 50 multipliziert. Ohne Änderungen am Modul Umstellen(intSpeed) dreht der Motor und ändert Richtung und Geschwindigkeit. Das Modul funktioniert also grundsätzlich, abgesehen von meinem Rechenfehler.

Mittlerweile habe ich eine andere Vermutung. Computer A schickt ca. alle 25 Millisekunden ein Signal. Ich schätze mal, dass der RPi damit etwas überfordert ist und die Signale gar nicht so schnell umstellen kann, bzw. das PWM-Signal sofort nach der Änderung wieder eine andere Änderung macht und alles etwas überfordert ist. Ich werde heute Abend eine kurze Verzögerung von 0.03 Sekunden einbauen. Vielleicht hilft das. ich war schon einmal an dem Punkt, aber dann hat der RPi alle Eingaben komplett ignoriert.

Falls das noch nichtgs gebracht hat, stelle ich gerne noch Bilder der Schaltung zur Verfügung.

Gruss
Chris

Chris1803
07.12.2017, 22:09
So, nun bin ich wieder drei Stunden älter, frustrierter und kein bisschen weiter.
Ich habe die Berechnung korrigiert und mein Testcode funktioniert. Die gleiche Berechnung ist auch im Originalcode eingebaut und es funktioniert nicht. Motor dreht, Richtung stimmt, Geschwindigkeit nicht.
Es wird zwar der richtige Originalwert und der richtige Wert für die PWM-Einstellung ausgegeben, aber es wird nichts umgestellt.

Ich habe versucht, an mehreren Stellen time.sleep einzubauen. Einerseits im Modul Umstellen, andererseits direkt im Modul, in dem die Daten empfangen und das Modul Umstellen aufgerufen wird. 20, 30, 100, 250 oder 500 Millisekunden haben nichts geholfen. Insbesondere beim Unterbruch im Empfangsmodul brachte unangenehme Effekte, dass zwischenzeitlich empfangenen Werte mit Verzögerung ausgeführt wurden und der Motor wild herumgesprungen ist. Also wieder raus mit den ganzen Unterbrüchen, 250 Millisekunden habe ich jeweils nach den Richtungswechseln gelassen.

Wenn es am Empfänger nicht funktioniert, dann vielleicht am Sender. Also habe ich am Sender die Sendefrequenz verändert. Statt alle 50 Millisekunden wird jetzt alle 500 Millisekunden ein neues Signal geschickt. Ohne Änderung am Resultat.

RoboTrader
08.12.2017, 20:15
Da in Python die Tabulator-Einrückungen eine große Rolle spielen, würde ich die Kommentare "# ..." auch mit einrücken, also bspw. "#Extract Button L" direkt unter "intBK = 0" und nicht an den Zeilenanfang. Ich glaube, so etwas hat bei mir auch mal ein Programm "misteriös" verändert.

Vielleicht kann ich damit helfen!
Sonst weiter viel Erfolg.

Ein schönes Wochenende!

Chris1803
12.12.2017, 22:14
Ich habe nun noch einiges am Code zu optimieren versucht. Beispielsweise habe ich Print-Befehle zwischen die ganzen ChangeDutyCycle-Befehle gesetzt. Ich bekomme die Prints ausgegeben, ohne dass sich die Geschwindigkeit ändert. Habe dann noch einmal mit den Pausen auf Seiten des Senders und des Empfängers gespielt. Ausser, dass sich Verzögerungen beim Programmablauf ergeben haben und nicht mehr alle Befehle ausgeführt werden, haben sich keine Änderungen ergeben.
Nun, fürs Erste muss das reichen. Der Motor dreht und sobald ich ihn das erste Mal in den LKW einbaue, werde ich mich wieder darum kümmern. Daher würde ich den Thread als ungelöst schliessen...
Allerdings darf ich auch was positives vermelden. Ich habe zusätzlichen Code eingebaut um einen Servo für die Lenkung zu steuern. Das funktioniert. Ebenfalls über PWM, im gleichen Programm, über den gleichen RPi, lediglich von einer anderen Stromquelle gefüttert... Nun, man weiss nicht wieso, aber es funktioniert wie erwartet.