schaltlogik entwickeln für 8-gang-schaltung

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 12:57

hallo leute,
bin neu hier im forum und in sachen programmierung.
für mein fahrad, ein 4-rad, quasie ein 'kettcar für erwachsene' bastel ich an einer lösung mit einem kleincomputer und display.
angedacht ist, die komplette beleuchtung, gangschaltung und gegebenenfalls später noch 'eine art dashcam' und vieleicht sogar navi dort mit zu intregrieren.

da ich einen rasperi PI 3B+ hier habe will ich das damit machen -auch wenn das evtl mit kanonen auf spatzen schiessen ist.
desweitern will ich die nutzung des pi dadurch lernen/gewöhnen.

ich nutze raspbian mit python und gpio-zero.
die englische offizielle doku hab ich immer griffbereit, aber english lesen und verstehen was die damit meinen, gerade im technischen english ist schwer, oft verstehe ich es einfach nicht.

beleuchtung hab ich soweit fertig.
einziger punkt in meinem script:
wenn man die lichthupe/bremslicht wieder abschaltet, schatet er nicht auf das vorher eigestellte um, also nicht auf 'fahrlicht' oder 'startvalue' jenachdem welches grad eingestellt ist, sondern immer auf 'fahrlicht'
hier müsste ich eigentlich den 'ist-zustand abspeichern und wieder anfragen können.
wie geht das? kann mir das einer erklären?
ab zeile 33 im code hab ich mal versucht das problem an zu gehen, funktioniert so aber nicht.

Code: Alles auswählen

#!/usr/bin/python3
from gpiozero import LED, Button, PWMLED
from time import sleep
from signal import pause
button1 = Button(26) #lichtschalter
button2 = Button(19) #fernlichtschalter
button3 = Button(13) #blinkschalter links
button4 = Button(6) #blinkschalter rechts
button5 = Button(5) #hupenschalter
button6 = Button(11) #bremslichtschalter
startvalue = 0.2 # Helligkeit bei Skriptstart
fahrlicht_vorn = 0.5 #Abblendlicht vorn, wert
fernlicht_vorn = 1 #fernlicht vorn, wert
fahrlicht_hinten = 0.5 #fahrlicht hinten ,wert
bremslicht_hinten = 1 #bremslicht hinten, wert
led1 = PWMLED(21,initial_value=startvalue) # Fahrlicht vorn
led2 = PWMLED(20,initial_value=startvalue) # Fahrlicht hinten
led3 = LED(16) # blinker links
led4 = LED(12) # blinker rechts
led5 = LED(7)  # hupe
led6 = LED(8) #
def fernlicht():
    if led1.value < 1: # wenn abgeblendet
        led1.value = 1 # dann aufblenden
        
    else: # sonst
        led1.value = fernlicht_aus # 
 
def fernlicht_aus():
    if button1.value = 1
            led1.value = fahrlicht_vorn
    else
        led1.value = startvalue
def fahrlicht_an():
    led1.value = fahrlicht_vorn
    led2.value = fahrlicht_hinten
    
def fahrlicht_aus():
    led1.value = startvalue
    led2.value = startvalue
    
def bremslicht_an():
    led2.value = bremslicht_hinten
    
def bremslicht_aus():
    led2.value = fahrlicht_hinten
def blinker_links():
    led3.blink (on_time = 0.8, off_time = 0.2)
def blinker_rechts():
    led4.blink (on_time = 0.8, off_time = 0.2)
    
button5.when_pressed = bremslicht_an
button5.when_released = bremslicht_aus
button1.when_pressed = fahrlicht_an
button1.when_released = fahrlicht_aus
button2.when_pressed = fernlicht
button3.when_pressed = blinker_links                         
button3.when_released = led3.off
button4.when_pressed = blinker_rechts
button4.when_released = led4.off
    
pause()
dann komm ich mal zum zweiten(falls ich dafür besser einen neuenthread aufmachen sollte bitte sagen)
da hab ich 1. ein ähmliches problem speichern und abfragen/ändern des 'ist zustandes'
und die logik mit einem 'up' und 'down' button 8 gänge rauf bzw runter zu schalten.

mein bisheriger code sieht so aus:

Code: Alles auswählen



    #!/usr/bin/python3
    from gpiozero import LED, Button, PWMLED, AngularServo
    from time import sleep
    from signal import pause
    button1 = Button(26) #lichtschalter
    button2 = Button(19) #fernlichtschalter
    button3 = Button(13) #blinkschalter links
    button4 = Button(6) #blinkschalter rechts
    button5 = Button(5) #hupenschalter
    button6 = Button(11) #servo hoch-schalten
    button7 = Button(9) #servo runter-schalten
    startvalue = -90
    servo = AngularServo(25, initial_angle = -90 , min_angle=-90, max_angle=90,) # schaltungsservo
    # min_puls_width = 0.5 max_puls_width = 3 
    def gang_1():
        servo.angle = -90
        
    def gang_2():
        servo.angle = -64.3
        
    def gang_3():
        servo.angle = -38.6
        
    def gang_4():
        servo.angle = -12.9
        
    def gang_5():
        servo.angle = 12.8
        
    def gang_6():
        servo.angle = 38.5
      
    def gang_7():
        servo.angle = 64.2
     
    def gang_8():
        servo.angle = 90 
        
    while True:
        button5.when_pressed = gang_1
        sleep(0.1)
        button6.when_pressed = gang_3
        sleep(0.1)
        button7.when_pressed = gang_8
        sleep(0.1)
    pause()
    
3 gänge schalten mit 3 schaltern funktioniert schonmal, aber eigentlich will ich ja nur mit button 6 und 7 rauf- und runter schalten....

später will ich noch mit tkinter eine simple gui machen. diese soll nur den derzeitigen gang anzeigen und mit display-knöpfen die gangschaltung anlernen lassen, also:
man drückt 'settings'
fährt von null bis 100% die verstellmöglichkeit des servos langsam ab(rauf- runter-knopf am display(nicht gänge rauf/runter am lenker))
und kann auf 'speichern' sowie gang-zahl-knopf (1-8) ablegen welcher wert welchem ganz zugewiesen wird.
nach zb 10sec soll man aus dem setting automatisch raus 'fallen' oder eben 'sichern' drücken ginge auch.

hat jemand einen lösungsansatz, wie man die 'gangschalt-logik' aufbauen könnte?
wie lege ich zb eine liste (gang 1-8 an) um dort die servo-angel-daten hin zu schreiben um dann diese zum schalten zu verwenden also wieder aus zu lesen?

fragen über fragen....

nachsatz: ich habe schwere konzentrations-probleme und kann entweder korrekte rechtschreibung schreiben oder mich darauf konzentrieren WAS ich schreibe, also den inhalt meines textes. ich gebe dem korrekten inhalt und das man versteht was ich sagen möchte den vorzug ;-) statt der korrekten schreibweise, zb gross/kleinschreibung...
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 18:25

habe heute den ganzen tag in python-lehrgängen etc gelesen und gesucht, ich find eienfach keinen ansatz.

oder ich begreife nicht wie man das schreiben würde.

weg1, den ich sehe aber nicht weiss wie ich ihn in befehle schreiben soll:
die jetzigen vorbereiteten def gang1 bis def gang8 nehmen und verknüpfen, das bei button6 bzw button 7 immer einen schritt weiter geschaltet wird 'entlang' dieser 'def gänge'.

weg2:
ich mache eine datei oder soetwas auf, wo fogendes drin steht:
zuerst wird festgelegt das es gang 1 -8 gibt und nicht mehr oder weniger, in einer art tabelle?
es wird festgelegt das immer mit gang1 gestartet wird, bei programmstart(dafür gäbe es startvalue, soweit bin ich schon)

dann bräuchte ich 'etwas' das aufzeichnet(für später auszulesen)welcher gang gerade eingestellt ist, und das immer beim drücken von button6 oder 7(6=up 7=down) ein gang hoch oder runter geschaltet werden soll.

weiss jemand ob es für soetwas tutorials gibt, in deutsch? ich finde da nichts was mir erklärt wie man das macht, erstaunlich eigentlich, oder bin ich ur zu blind beim suchen weil ich die falschen suchanfragen stelle?

auchso, eins noch:
ich erwarte natrürlich nicht das mir jemad da den vollen fertigen code schreibt und ich dann nur kopiere und dann nix dabei lerne :-) mir reicht, nehm mal funktion 'xy' die würde von gang1 zu 2 schalten können wenn du 'dies und das schreibst' und ich muss das dann selber erweitern auf alle gänge.
wenn es dann 'hakt' frag ich nach um weiter zu kommen.
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 29. Juli 2019, 19:57

Für dein Gangschaltungs-Problem ist die Lösung eine Variable einzuführen, die den aktuellen Gang vorhält. Der Druck auf einen der beiden Knöpfe addiert bzw subtrahiert 1 davon, und stellt sicher man schaltet nicht tiefer oder höher als möglich. Die konkreten Winkel für einen Gang legt man in eineR Datenstruktur ab. Dadurch sind die schnell und einfach zu ändern.

Eine kurze Skizze (iPad ist nicht so geil zum coden):

Code: Alles auswählen

GEAR2SERVO = [-90, -75, ....]

CURRENT_GEAR = 0 # 0-7, so sind Computer halt 

der clamp(value, lower, upper):
     return max(min(upper, value), lower)

def shift(direction):
     global CURRENT_GEAR
     CURRENT_GEAR = clamp(CURRENT_GEAR + direction, 0, 7)
     servo.angle = GEAR2SERVO[CURRENT_GEAR]
Shift musst du dann nur mit 1oder -1 aufrufen.

Und dann noch ein paar Anmerkungen:
- statt Kommentaren die Nummern erklären schreib Variablen Namen, die selbsterklärend sind. Also hupenschalter statt button5. Und schon versteht man es überall. Hilft garantiert auch besser wenn die konzentration mal schlapp macht.
- wenn du ein Standard-servo hast, wird das immer wieder in 0 Stellung gehen, wenn deine Kiste angeschaltet wird. Sei dir dessen bewusst, und stell sicher, dass das nix kaputt macht.
- auch für dein Licht-Problem besteht eine mögliche Lösung in der Nutzung einer Variable, die sich eben merkt, was gewählt war bevor man bremst.
- Die gui mit dem anlernen würde ich mir an deiner Stelle sparen. Das ist SEHR viel Aufwand für eine sehr kurzen Moment an dem du das brauchst. Da gib’s genug andere Baustellen.
Zuletzt geändert von __deets__ am Montag 29. Juli 2019, 20:14, insgesamt 1-mal geändert.
Grund: direction vergessen....
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 20:22

hallo, danke für deine antwort.

ist CURRENT_GEAR nicht quasie das selbe wie bei mit 'startvalue'?
oder ist das ein begriff den ich brauche damit pythion weiss das es einer von mehreren gängen ist?
die einzelnen winkel, muss ich die dann statt wie jetzt mit gang_1=, gang_2=, etc. mit je einem 'def'
in die klammer von 'GEARSERVO=' setzen damit das bei 'servo.angle =' von GEAR2SERVO umgesetzt wird?

mit 0-7 is mir klar :-)

mit dem shift hiesse dann :

Code: Alles auswählen

def
    button6.when_pressed = CURREND GEAR shift +1 #ein gang hoch

def
    button7.when_pressed = CURREND GEAR shift -1 #ein gang runter
mit dem licht, was wir da noch fehlt:
da müsste ich also 2 variablen setzen die dann 1 oder 0 sein können und diese dann einlesen beim abschalten des brems- und fern-licht's.
könnte ich die dann
flicht = 0 #fernlicht
blicht = 0 #bremslicht

nennen?
wie frage ich die dann ab?
Zuletzt geändert von geist4711 am Montag 29. Juli 2019, 20:35, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 10895
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 29. Juli 2019, 20:34

`CURRENT_GEAR` (eigentlich `current_gear`) ist der Gang, den man jeweils um 1 erhöhen oder verringern kann, `startvalue` ist dagegen ein Winkel, der sich halt nicht so einfach ändern läßt.
`shift` ist eine Funktion, die man auch aufrufen muß.
`GEAR2SERVO` braucht nur die Winkel, keine `def`.

Code: Alles auswählen

from functools import partial
GEAR2SERVO = [-90, -64.3, -38.6, -12.9, 12.8, 38.5, 64.2, 90] 

servo_hoch = Button(11)
servo_runter = Button(9)

current_gear = 0
servo = AngularServo(25,
    initial_angle=GEAR2SERVO[current_gear],
    min_angle=min(GEAR2SERVO),
    max_angle=max(GEAR2SERVO))

def clamp(value, lower, upper):
    return max(min(upper, value), lower)

def shift(direction):
    global current_gear
    current_gear = clamp(current_gear + direction, 0, len(GEAR2SERVO))
    servo.angle = GEAR2SERVO[current_gear]

servo_hoch.when_pressed = partial(shift, +1)
servo_runter.when_pressed = partial(shift, -1)
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 20:51

dann müsste 'mein code' dann also so aussehen:

Code: Alles auswählen


#!/usr/bin/python3
from gpiozero import LED, Button, PWMLED, AngularServo
from time import sleep
from signal import pause
from functools import partial

button1 = Button(26) #lichtschalter
button2 = Button(19) #fernlichtschalter
button3 = Button(13) #blinkschalter links
button4 = Button(6) #blinkschalter rechts
button5 = Button(5) #hupenschalter
servo_hoch = Button(11) #servo hoch-schalten
servo_runter = Button(9) #servo runter-schalten

GEAR2SERVO = [-90, -64.3, -38.6, -12.9, 12.8, 38.5, 64.2] 

current_gear = 0
servo = AngularServo(25,
    initial_angle=GEAR2SERVO[current_gear],
    min_angle=min(GEAR2SERVO),
    max_angle=max(GEAR2SERVO))

def clamp(value, lower, upper):
    return max(min(upper, value), lower)

def shift(direction):
    global current_gear
    current_gear = clamp(current_gear + direction, 0, len(GEAR2SERVO))
    servo.angle = GEAR2SERVO[current_gear]

servo_hoch.when_pressed = partial(shift, +1)
servo_runter.when_pressed = partial(shift, -1)
startvalue = -90

pause()


edit:
es funktioniert! vielen vielen dank!
eins hab ich noch:
der billige doppel-taster prellt wohl, kann man da mit sleep oder besser pause was machen?

eben beim testen, ich krieg noch ein:
File "/home/pi/python/servo-test.py", line 29, in shift
servo.angle = GEAR2SERVO[current_gear]
IndexError: list index out of range

wenn ich über 7x button_up drücke :-)
funktionieren, bis uf des prellen, tut es aber bestens
Zuletzt geändert von geist4711 am Montag 29. Juli 2019, 21:17, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 29. Juli 2019, 21:15

Prellen heißt auf Englisch bounce und wird in gpiozero behandelt.
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 29. Juli 2019, 21:21

startvalue brauchst du in dem Code doch nicht mehr. Und WENN du ihn bräuchtest, dann sollte er wohl eher sein was auch immer der erste wert in GEAR2SERVO ist. Das kann ja durch kalibration abweichen. Und last but not least: immer noch ganz bescheidene Namen. Neben den schon genannten buttonX statt gleich den richtigen Namen zu nehmen jetzt neu: servo_hoch. Du schaltest doch einen GANG hoch.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 21:38

stimmt.#
werd das noch ändern, such grad wie ich `bounce' korrekt eingebunden kriege :-)
diese englischen doc sind furchtbar ;-)
lesen und verstehen was gemeint ist, ist da zweierlei :-)
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 21:56

code jetzt (bounce funktioniert noch nicht):

Code: Alles auswählen


#!/usr/bin/python3e
from gpiozero import LED, Button, PWMLED, AngularServo
from time import sleep
from signal import pause
from functools import partial

fahrlicht = Button(26) #lichtschalter
fernlicht = Button(19) #fernlichtschalter
blinker_li = Button(13) #blinkschalter links
blinker_re = Button(6) #blinkschalter rechts
hupe = Button(5) #hupenschalter
gang_hoch = Button(11, bounce=1) #servo hoch-schalten
gang_runter = Button(9, bounce =1) #servo runter-schalten

GEAR2SERVO = [-90, -64.3, -38.6, -12.9, 12.8, 38.5, 64.2, 90] 

current_gear = 0
servo = AngularServo(25,
    initial_angle=GEAR2SERVO[current_gear],
    min_angle=min(GEAR2SERVO),
    max_angle=max(GEAR2SERVO))

def clamp(value, lower, upper):
    return max(min(upper, value), lower)

def shift(direction):
    global current_gear
    current_gear = clamp(current_gear + direction, 0, len(GEAR2SERVO))
    servo.angle = GEAR2SERVO[current_gear]

gang_hoch.when_pressed = partial(shift, +1)

gang_runter.when_pressed = partial(shift, -1)

pause()

__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 29. Juli 2019, 22:01

Was heißt funktioniert nicht? Das sieht auch recht kurz aus, zumindest bei dem von mir bevorzugten pigpio wäre die Angabe in Millisekunden - und da ist 1 etwas sehr optimistisch kurz.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Montag 29. Juli 2019, 22:03

die schreiben immer da im docu was von 'in seconds' ?

denn müsste da ja 500 oderso hin, das das 'gescheit' entprellt...
nu kommt bei programmstart:

File "/home/pi/python/servo-test.py", line 12, in <module>
gang_hoch = Button(11, bounce=500) #servo hoch-schalten
File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 124, in __call__
self = super(GPIOMeta, cls).__call__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'bounce'

mist... warum is mein englisch bloss so schlecht!?! grumpf....

edit: ich mach für heute pause, mir qualmt der kopf :-)

vielen vielen dank aber an alle helfenden!

es ist super das es bis hierher schonmal funktioniert :-)
jetzt muss das fast nurnoch 'am rad' auch funktionieren....
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 29. Juli 2019, 22:26

Englisch hin oder her, die offizielle Doku kennt auch kein bounce. Sondern bounce_time. Und das muss in Sekunden angegeben werden. Damit es sinnvoll ist, können das auch Bruchteile sein. Also zb 0.1 für 100ms.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Dienstag 30. Juli 2019, 00:31

ja, das hab ich eben bei jemandem der die option genutzt hab auch gesehen und werde das morgen antesten.
in der docu:
https://gpiozero.readthedocs.io/en/stab ... se-classes
steht zwar was von bounce, aber ich hab da nichts gefunden das man das dann
bounce_time=<zeit>
schreiben soll.

so wird das mit der angabe für
min_puls_width = <zeit> und max_puls_width = <zeit>
wohl auch sein, das ich nicht rausgelesen hab wie man das richtig schreibt, ds es auch funzt..

sofern ich das richtig herausgelesen hab, kann man damit die stellweite des servos vergrössern, also bei mir zb statt nur 90° gesamt-stellweg dann eventuell, 120° wenn möglich , oder gar mehr. wollte ich eigentlich ausprobieren, befehl passt aber nicht, gibt ne fehlermeldung.
finde die beschreibung aber auch grad nicht....
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dienstag 30. Juli 2019, 08:32

Ich weiß nicht wie du auf den Link kommst. Du benutzt Button. Der ist hier dokumentiert: https://gpiozero.readthedocs.io/en/stab ... tml#button

Und da steht auch bounce_time.

Servos sind in https://gpiozero.readthedocs.io/en/stab ... gularservo beschrieben. Dort sind die Parameter für die Pulsweite aufgeführt. Auch die sind in Sekunden (2/1000 sind 0.002, ergo 2ms). Vor allem aber sind sie anders geschrieben als du sie zitierst.
Antworten