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

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

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: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

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

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: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

`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

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: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

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

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

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

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: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

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

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: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

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

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: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

ich hab mich mit dem wühlen und lesen in dem dok und eineigen anderen seiten im internet selber 'in's schlingern gebracht', zusätzlich einiges wohl falsch verstanden.

heut mittag hab ich dann 'bounce_time=0.2' (und andere zeitwerte) eigegeben und das wurde es besser mit dem tastenprellem, dqafür nimmt er tastendrücke etwas schlechter an, oft erst beim zweiten drücken. es ist jedenfalls nich genau gleich wiederholbar reproduzierbar was passiert und eigenlich ist das ja kein allzu wilder aufbau hier.
eben der pi, ein netzteil mit step-down-wandlern, ein steckboard und eben die schalter- mitkabeln dran und mini-krokoklemmen(die auch korrekten kontakt haben)....
hmmm...
kann das sein das ich da besser ein abgeschirmtes kabel nehmen sollte?
ich schalte ja nur die masse und nach etwa überlegung denke ich mir, das da evtl irgendwas einstrahlt auch wenn ich eigentlich der ansicht war, das das so recht störungsfrei laufen sollte?!

im augenblick jedenfalls kann man das so gerade so nutzen, manchmal muss man halt doppelt drücken, vor allem beim runter-schalten, beim hochschalten tritt das fast garnicht auf.

also 'pullup-widerstand sitzen bei mir übrigens 10k-widerstände direkt auf dem steckboard das direkt neben dem PI steht.

den gesammt-stellweg des servos noch etwas erweitern, damit werde ich nachher mal sehen ob das über 'min_puls_width=0.005' und 'max_puls_width=0.003' etwas strecken lässt, mechaanisch liesse der servo das durchaus zu, der könnte auch 180 grad statt die derzeitigen nur 90 reral mechanisch.
wenn da jemand einen besseren weg weiss immer gene her damit.

kann ich eigentlich die (wenn ich das richtig verstehe) funktion 'GEAR2SERVO' auch für das licht 'missbrauchen, dann nur mit ( 0.2, 0.5, 1) als mögliche einstellungen?
ist jetzt nur so eine idee und noch nicht genauer betrachtet.

leider gab es heute für mich das windows-update auf 1903 und das hat mich estmal nacharbeit und ein paar std zeit gekostet, sonst hätt ich schon angefangen da mal was zu coden, was ich mir so denke, so mit 'als vorlage das mit dem servo'.
noch gibt es nur einen schmierzettel der noch sehr wirr aussieht:-)
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`GEAR2SERVO` ist keine Funktion sondern eine Liste. Und natürlich kann man auch eine Liste für Helligkeitsstufen anlegen und verwenden.

Ich würde demnächst objektorientierte Programmierung auf den Lernplan setzen, damit das ``global`` aus dem Programm verschwinden kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

das 'global' nicht so prickelnd sein soll hab ich schonmal gelesen, aber das ist noch zu hoch für mich, ist ja meine erste echte programier-geschichte.

bin sschon glücklich das ich überheupt so weit gekommen bin :-) dank der tollen hlfe hier!

ähnliches ('programmieren', ähm oder sowas...) hab ich zuletzt gemacht wo ich mir ein paar batch-dateien zusammengeschreibselt hab wo ich für 'doom' eine angepasste config.sys, autoecex.bat, usw. unter DOS nutzen wollte ;-)

so ganz verstehe ich auch noch nicht alle zeilen des nun schonmal recht gut funktionierend code, aber je mehr ich lese und frage dämmert es :-)

ich bin alt, früher ging sowas besser und schneller ;-)

hab nun den code etwas optimiert:

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, bounce_time=0.001) #lichtschalter
fernlicht = Button(19, bounce_time=0.001) #fernlichtschalter
blinker_li = Button(13, bounce_time=0.001) #blinkschalter links
blinker_re = Button(6, bounce_time=0.001) #blinkschalter rechts
hupe = Button(5, bounce_time=0.001) #hupenschalter
gang_hoch = Button(11, bounce_time=0.001) #servo hoch-schalten
gang_runter = Button(9, bounce_time=0.001) #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), min_pulse_width=0.0008, max_pulse_width=0.0023)

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)
sleep(0.01)
gang_runter.when_pressed = partial(shift, -1)
sleep(0.01)

pause()

der servo macht nun fast 180° gesamtstellwinkel. opimal für das was ich machen möchte.
einzig zittert er noch etwas, aber nicht immer und gleichmässig, und eben die tasten reagieren nicht immer.
ohne 'bounce' schaltet man öfter doppelt auf einmal, mit 'bounce' reagieren die tastennicht immer auf drücken....
da muss ich noch mit den zahlen wohl etwas spielen, das ist noch nicht optimal.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@geist4711: Die She-Bang-Zeile glaube ich nicht so ganz. Oder wo kommt die `python3e`-Datei her‽

Das mit dem global betrifft auch noch andere Namen. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Da gehört dann auch `servo` rein (oder eben zumindest nicht auf Modulebene). Funktionen sollten alle Werte die sie ausser Konstanten benötigen als Argumente übergeben bekommen. Das `Servo`-Objekt sollte man also auch per `partial()` binden/übergeben.

Die `sleep()`-Aufrufe beim zuweisen der Rückruffunktionen machen keinen Sinn.

Namen sollten möglichst ohne Kommentare auskommen können. Wenn man einen Fernlichtschalter hat, sollte man den `fernlichtschalter` nennen und nicht `fernlicht` und dann ``#fernlichtschalter`` als Kommentar dahinter setzen.

Keine Abkürzungen in Namen. `*_links` statt `*_li` und `*_rechts` statt `*_re` ist verständlicher.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
from functools import partial
from signal import pause

from gpiozero import Button, AngularServo

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

current_gear = 0  # FIXME Globale Variable beseitigen.


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


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


def main():
    lichtschalter = Button(26, bounce_time=0.001)
    fernlichtschalter = Button(19, bounce_time=0.001)
    blinkschalter_links = Button(13, bounce_time=0.001)
    blinkschalter_rechts = Button(6, bounce_time=0.001)
    hupe = Button(5, bounce_time=0.001)
    
    gang_hoch = Button(11, bounce_time=0.001)
    gang_runter = Button(9, bounce_time=0.001)
    servo = AngularServo(
        25,
        initial_angle=GEAR_TO_ANGLE[current_gear],
        min_angle=min(GEAR_TO_ANGLE),
        max_angle=max(GEAR_TO_ANGLE),
        min_pulse_width=0.0008,
        max_pulse_width=0.0023,
    )
    gang_hoch.when_pressed = partial(shift, servo, +1)
    gang_runter.when_pressed = partial(shift, servo, -1)
    pause()


if __name__ == '__main__':
    main()
Das objektorientierte Programmierung noch zu hoch für Dich ist, ist ja kein Grund es nicht auf den Lernplan zu setzen. Im Gegenteil – es macht ja keinen Sinn da Sachen drauf zu setzen die man schon kann. Damit wird man dann nicht nur das ``global`` los, sondern fasst alles was zur Gangschaltung gehört in ein Objekt zusammen, statt das über das Programm zu verteilen. `GEAR_TO_ANGLE`, `shift()`, `gang_hoch`, `gang_runter`, `servo`, und `current_gear` sind dann nicht mehr einzeln, sondern in einem Objekt zusammengefasst.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

hallo,
der code schaut vom ansehen aus her sehr ordentlich aus, schöner wie mein 'konstrukt'

wo das 'e' nach python3 in der 'she-ban-zeile' (aha, heisst diese zeile so?), hmm, keine ahnung, muss ein tippfehler sein :-) ist mir nicht aufgefallen.

objektorientierung wollte ich dabei nicht 'bei seite schieben' oderso, sondern auf später verschieben, noch bin ich dabei den code überhaupt vollständig zu beherrschen und dieses dumme prellen weg zu bekommen.

daher auch noch diese 'sleep-geschichten' bei den schaltern, habe gedacht wenn ich danach ein sleep setze wird es evtl besser -und hab's nicht wieder entfernt...

habe eben auch nochmal einen ganz anderen ansatz verfolgt:
habe diese billigen china-schalter auseinander genommen.
ergebniss:
lötstellen alle taub, sprich matt -übergelötet
schlterkontakte, so ein merkwürdige feder-2-kontakte-konstruktion alle kontaktflächen sehen schrecklich aus als hätten diese kleinteile jahre im regal gelegen.
habe und 'patina' angelegt hätten.
die zerlegt und kontakltflächen angeschliffen.

naja, wirklich gehokfen hat das nicht, es scheint etwas besser geworden zu sein, mehr aber auch nicht.
die noname billig-taster die ich sonst noch hier hab, schalten auch nicht zuverlässig......

ich muss zuverlässige omron- oder sowas taster, gekapselt, besorgen.
so wird das nix, das ist unzuverlässt und irritiert/verwirrt einen dauernd.
Antworten