schaltlogik entwickeln für 8-gang-schaltung

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 31. Juli 2019, 19:20

. Klar kann man Variablen nennen wie man will. Und beliebige Werte in Listen eintragen. Und wenn das Muster “aus einer Zahl auf einen Wert kommen” wie eben aus Gang zu Winkel passt, kann man das benutzen.

Aber das ganze pwmled-Zeug ist komplett daneben. Eine PWM kennt doch keinen Winkel.

Nur ist das doch nicht dein eigentliches Problem. Sondern das du in einem von mehreren Zuständen sein kannst (Licht aus, Licht an) und darauf dann wiederum temporäre Modifikationen anwendest, die nur so lange gelten, wie ein Schalter gedrückt ist. ZB Bremse oder Lichthupe. Das musst du lösen, und da kommt dann ggf ein Wert von 0-2 oder so (aus, an, richtig hell) raus. Den kannst du über so eine lookup Tabelle dann auf tatsächliche PWM Werte abbilden.

Und das ganze geclampe und co braucht es auch nicht, denn der Fahrer drückt ja nicht 10 mal die Lichthupe & dann ist 10mal heller.

Eine weg sowas zu machen ist die Zustände der diversen Schalter bitweise zu kombinieren. 1 für Licht an, 2 für bremse gedrückt. Verodert nimmt das dann Werte von 0-3 an, und DAS schlägst du dann in einer Liste mit PWMS, zb [0, 0.5, 1, 1] nach. Da ist dann nicht bremsen und nicht Licht aus, Licht an halb hell, und alle anderen Kombinationen - nur bremsen, oder bremsen mit Licht - ganz hell.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Mittwoch 31. Juli 2019, 21:17

ja genau,
ich sag mal wie ich mir das vorstelle:

man schaltet den pi an:
die beleuchtung geht auf 0.2(pwm) an, da kann man sehen ob alle lampen laufen und sieht das die anlage an ist ;-)

nun kann man bremse, fahrlicht und fernlicht an bzw aus schalten.
dabei gillt:
fahrlicht schaltet hinten und vorn 0.5(pwm) auf dauer an.

fernlicht macht die led auf100% hell, solange fernlicht gedrückt ist.
zurück dann dahin wo die helligkeit vorher war, egal ob grad fahrlicht an war oder nicht.

bremslicht geht auch nur an wenn 'gedrückt', auch auf100%, aber nur hinten, und fällt dann wieder dahin zurück wo es grad war.

hupe geht auch nur wenn gedrückt, schaltet aber 6v von externer quelle via fet und optokoppler.

blinker läuft solange die jeweiligen blinkschalter gedrückt sind, nur blinken, ohne pwm.

gänge werden geschaltet, je nach welchen schalter man drückt und es fängt immer bei '0', also 1. gang an


da man die 'gänge' ja auch durchschaltet, war das was ich da so 'zusammengebacken' hab
der halbwissende versuch, das damit auch um zu setzen, also das licht ähnlich wie die gangschaltung 'durch zu schalten' wie die gänge der gangschaltung :-)
ich glauib aber selber nicht, das das so soeinfach dann auch schon funktioniert ;-)

mir ging es ehr darum jetzt zu erfahren ob der kenner sagt: nee so wird das nie was, da mischt du listen funktionen oder wonstwas was ich da nicht beachte zusammen :-)

wobei mir tief im hinterkopf noch schwebt:
eigentlich wäre es für led's ja besser die mit ksq's zu betreiben, nur die kann man schlecht dimmen, oder pwm-ansteuern.
wobei eben der gedanke 'schwellt' alle led's zu messen(strom oder strom über die spannung eines kleinen widerstands wo man ja rechnen könnte welcher strom das wär ;-) ) und nach deren strom die pwm-ausgänge je led zu regulieren, so wie sie grad leuchten soll, also aus, testglimmen(gleichzeitig notlicht wenn akku fast leer später) halbe helligkeit, volle helligkeit(nur fernlicht und bremse).
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 31. Juli 2019, 22:03

Joa. Dann man frisch ans Werk. Eines nach dem anderen bauen. Gute Namen vergeben, damit du dich nicht selbst und ggf uns wenn wir helfen sollen verwirrst.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Mittwoch 31. Juli 2019, 22:33

jo, kommt, alles stückl für stückl.
erstmal aus dem gangschaltungs-kram was funktionierendes machen, für's licht.
da erstmal nur 'an aus/heller dunkel' und dann langsam weiter.

später dann zusammenführen.
wobei mir grad wider was in den sinn kommt:
wenn es ja 'main' gibt, gehen auch bestimmt 'unterteile' also teil 'gangschaltung' und 'beleuchtung'?

wie unterteilt man das?

so?:

def main()

def gangschaltung
-hier den code-
if __name__ == '__gangschaltung__':
gangschaltung()

def beleuchtung
-hier den code-
if __name__ == '__beleuchtung__':
beleuchtung()

if __name__ == '__main__'()
main()


geht das so?
Benutzeravatar
__blackjack__
User
Beiträge: 4676
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 31. Juli 2019, 23:14

@geist4711: Nein, wieso sollte denn `__name__` plötzlich den Wert '__gangschaltung__' haben? Das hat als Wert den Modulnamen wenn das Modul importiert wurde und den Wert '__main__' wenn das Modul als Programm ausgeführt wurde. Damit kann man dann mit dem ``if __name__ == '__main__':`` dafür sorgen, das die Funktion `main()` ausgeführt wird, wenn man das Modul als Programm ausführt, und das die Funktion *nicht* ausgeführt wird, wenn man das Modul in einer Python-Shell, oder aus einem anderen Modul heraus importiert.

`gangschaltung()` und `beleuchtung()` sind auch keine guten Namen für Funktionen, weil man für Funktionen (und Methoden) in der Regel die Tätigkeit als Namen verwendet, die von der Funktion (oder Methode) durchgeführt wird. Damit kann man sie von eher passiven Werten unterscheiden. `gangschaltung` wäre ein guter Name für ein Objekt vom Typ `Gangschaltung`, den man sich als Klasse schreiben könnte um die globale Variable für den aktuellen Gang los zu werden. Und bei `beleuchtung` könnte man etwas ähnliches mit einer Klasse `Beleuchtung` machen, die die Zustände der Beleuchtung verwaltet.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Mittwoch 31. Juli 2019, 23:27

gut, dann hab ich das mit 'main' nur falsch verstanden bzw interpretiert :-)

wollte neben dem 'main' also meinem verständniss nach dem 'hauptprogramm'
die unter-rubriken 'gangschaltung' und 'beleuchtung' bezeichen :-)

damit man schöner sehen kann welche bereich das ist :-) auch für falls später noch mehr unfug dazu kommt....

ich mach besser erstmal morgen weiter, heute genug mist verzapft :-)
und morgen versuch ich erstmal die beleuchtung ähnlich wie die gangschaltung zu gestallten :-)
so mit liste und da auswählen wie hell es wann warum werden soll...
Benutzeravatar
__blackjack__
User
Beiträge: 4676
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 1. August 2019, 10:52

Die Gangschaltung mal in eine Klasse verpackt (ungetestet):

Code: Alles auswählen

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

from gpiozero import Button, AngularServo

GEAR_CHANGE_SERVO_PIN = 15
GEAR_UP_PIN = 11
GEAR_DOWN_PIN = 9

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


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


class GearChange:
    
    def __init__(self, gear_to_angle, servo_pin, gear_up_pin, gear_down_pin):
        self._current_gear = 0
        self._gear_to_angle = gear_to_angle
        self._servo = AngularServo(
            servo_pin,
            initial_angle=self._gear_to_angle[self.current_gear],
            min_angle=min(self._gear_to_angle),
            max_angle=max(self._gear_to_angle),
            min_pulse_width=0.0008,
            max_pulse_width=0.0023,
        )
        self._gear_up_button = Button(gear_up_pin)
        self._gear_up_button.when_pressed = partial(self.change, +1)
        self._gear_down_button = Button(gear_down_pin)
        self._gear_down_button.when_pressed = partial(self.change, -1)

    @property
    def gear_count(self):
        return len(self._gear_to_angle)

    @property
    def current_gear(self):
        return self._current_gear
    
    @current_gear.setter
    def current_gear(self, value):
        self._current_gear = clamp(value, 0, self.gear_count - 1)

    def change(self, direction):
        self.current_gear += direction
        self._servo.angle = self._gear_to_angle[self.current_gear]


def main():
    lichtschalter = Button(26)
    fernlichtschalter = Button(19)
    blinkschalter_links = Button(13)
    blinkschalter_rechts = Button(6)
    hupe = Button(5)
    
    _gear_change = GearChange(
        GEAR_TO_ANGLE, GEAR_CHANGE_SERVO_PIN, GEAR_UP_PIN, GEAR_DOWN_PIN
    )
    pause()


if __name__ == '__main__':
    main()
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Donnerstag 1. August 2019, 11:04

cool, war mir garnicht klar das man 'class' auch dafür nutzen kann.
das werd ich mir merken und später nutzen :-) danke!
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Freitag 2. August 2019, 12:23

heute hab ich wider bissel was getan:

Code: Alles auswählen

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

from gpiozero import Button, AngularServo, LED, PWMLED

GEAR_TO_ANGLE = [-90, -64.3, -38.6, -12.9, 12.8, 38.5, 64.2, 90]
STUFE_ZU_PWM = [0.0, 0.2,0.6,1]

current_gear = 0  # FIXME Globale Variable beseitigen.
led_startvalue = 0.2

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

def clamp2(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)-1)
    servo.angle = GEAR_TO_ANGLE[current_gear]

def shift2(fahrlicht, direction):
    global led_startvalue
    led_startvalue = clamp2(led_startvalue + direction, 0, len(STUFE_ZU_PWM)-1)
    led.angle = STUFE_ZU_PWM[led_startvalue]


def blinker_links():
    blinker_links_led3.blink (on_time = 0.8, off_time = 0.2)

def blinker_rechts():
    blinker_rechts_led4.blink (on_time = 0.8, off_time = 0.2)

def hupe_an():
    hupen_led
    
def hupe_aus():
    hupen_led



def main():
    fahricht_hoch = Button(26)
    fahrlicht_runter = Button(19)
    blinkschalter_links = Button(13)
    blinkschalter_rechts = Button(6)
    hupenschalter = Button(5)
    bremslichtschalter = Button(10)
    gang_hochschalter = Button(11)
    gang_runterschalter = Button(9)

    blinker_links_led3 = LED (16)
    blinker_rechts_led4 = LED (12)

    hupen_led = LED(7) 
    
    fahrlicht = PWMLED(21,initial_pwm=STUFE_ZU_PWM[led_startvalue],
        min_angle=min(STUFE_ZU_PWM),
        max_angle=max(STUFE_ZU_PWM),
    )
    
    fernlicht = PWMLED(20,initial_value = led_startvalue)

    
    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)

    fahrlicht_hoch.when_pressed = partial(shift2, fahrlicht, +1)
    fahrlicht_runter.when_pressed = partial(shift2, fahrlicht, -1)

    blinkschalter_links.when_pressed = blinker_links
    blinkschalter_rechts.wehn_pressed = blinker_rechts

    hupenschalter.when_pressed = hupe_an
    hupenschalter.when_preleased = hupe_aus
    
    pause()


if __name__ == '__main__':
    main()

anmerkung:hupe ist erstmal nur rudimentär drin, glaube die funktioniert so noch nicht, das ist aber erstmal unwichtig :-)

script gestartet und:
fehlermeldung:
>>> %Run fahrlicht+gangschaltung_1.py
Traceback (most recent call last):
File "/home/pi/python/fahrlicht+gangschaltung_1.py", line 93, in <module>
main()
File "/home/pi/python/fahrlicht+gangschaltung_1.py", line 60, in main
fahrlicht = PWMLED(21,initial_pwm=STUFE_ZU_PWM[led_startvalue],
TypeError: list indices must be integers or slices, not float
>>>

ich verstehe das so, das ich dort keine 'komma-werte'(float) eintragen darf.
wie ändere ich das bzw behebe ich den fehler -oder wie erlaube ich in der liste float-werte?

die sonst noch darin steckenden fehler (servo.angle durch led.angle ersetzt in 'def shift2' zb) hoffe ich dann später selbst weg zu bekommen, aber da steh ich grad auf den schlauch...
Sirius3
User
Beiträge: 10895
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 2. August 2019, 12:42

@geist4711: was ist der Sinn von `clamp2`? Wie unterscheidet sich diese Funktion von `clamp`?

Was soll ein Index von 0.2 denn bedeuten? Was willst Du mit der Zeile aussagen?
PWMLED hat auch kein min_angle oder max_angle-Argument.
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 2. August 2019, 12:59

Ich habe dir schon gesagt, dass der Ansatz wie er bei der Gangschaltung greift NICHT geeignet ist zur Kontrolle für Bremsen und Licht. Bremsen ist nicht ein Schritt NACH Licht. Und auch nicht davor. Das passiert unabhängig voneinander. Gleiches gilt für die Lichthupe. Mal dir mal die vier möglichen Zustände, die das bremslichtsystem haben kann auf.

Nix
Bremsen
Bremsen+Licht
Licht

Dies sind in KEINE simple lineare Abfolge zu bringen. Da gibt es beliebige Sprünge. Und das muss der Code erlauben. Ich habe dir schon einen Weg genannt, wie man sowas darstellen kann. Lies nochmal meine Antwort, und Versuch das zu verstehen. Du kannst ja auch fragen stellen. Aber einfach den bestehenden Code kopieren und hoffen das klappt - geht nicht. Mit der Fahrradpumpe kannst du nunmal keinen Schaltkranz wechseln. Auch nicht durch heftiges draufhauen.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Freitag 2. August 2019, 13:05

ich bin dabei schrittweise das was 'gangschaltung' macht, auf die pwmled zu übertragen.
also hab ich erstmal 'grob' alles doppelt geschrieben, dann in led-bezeichnungen geändert und wollte nun die gemachten fehler langsam ausmerzen :-)

hintergrund: 0, 0.2, 0.6, 1 soll die pwm-value werden, so wie in dem ersten script, wo ich die lampenschaltung hatte:

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 = 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()

ich will also diese 'beleuchtungslogik' so umsetzen wie die 'gangschaltungslogik'
und zuerst stolper ich nun darüber das ich keine 'float-werte' in die liste setzen darf und da komm ich grad schon ins schwimmen.
schon schwer genug das zu versuchen so um zu modeln wie bei der gangschaltung ;-)
und das wird sicher nicht der letzte fehler sein der da (noch) ist.....

@deets: ja, ich muss das nochmal lesen, und vor allem verstehen was du da geschrieben hast ;-) ich frage dann gern nochmal an.

bin so ein holzkopf der seine erfahrungen machen muss und 'einfach erstmal loslegt' ;-)
aber wer hinfällt, kann auch wieder aufstehen :-)

lichtblitz:
meintest du man müsste die pwm=werte mit ganzen zahlen gleich setzen zb

0=0.0(pwm-wert)
1=0.2(pwm-wert)
2=0.6(pwm-wert)
3=1(pwm-wert)

wie binde ich diese 'tabelle dann ein, also das die pwmled weiss das diese liste die verschiedenen pwmwerte sind?

diese 'listenwerte'(links die ganzen zahlen) könnte ich dann als schaltzustände der 'modifizierten gangschaltung nutzen?! richtig?
__deets__
User
Beiträge: 6857
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 2. August 2019, 13:29

Die letzte Tabelle ist eine lookup tabelle, wie vorher schon GEARS2SERVO. Und ja, DAS kannst du benutzen. Schrieb ich auch schon. shift und clamp hingegen sind komplett ueberfluessig. Du schaltest keinen Licht-Gang hoch, und du musst auch nichts beschraenken. Das ist das mental komplett falsche modell, und da gibt es auch keinen schrittweisen weg, davon weg zu kommen, zu dem richtigen modell. Es ist in die falsche richtung gelaufen, und ausser Zeitverschwendung ist da kein Gewinn.
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Freitag 2. August 2019, 13:40

ja da hast du recht, aber:
ich habe gelernt was NICHT geht :-)
für mich auch ein gewinn ;-)

wenn ich dich recht verstehe, meinst du ich soll nicht 'lichtghänge' schalten wie ich das versucht hab, sondern das anders lösen.

und ich hatte gedacht das des eine 'schlaue lösung' das so zu machen, damit ich über den weg hinbekomme was ich will,

nämlich fahrlicht an/aus
und wenn es mal gebraucht(getastet) wird nur von fernlicht an oder nur hinten bremslicht an und später wieder in den eigentlich gerade laufende helligkeit des 'fahrlichtes' wieder zurück schalten....

ich mach mir da mal eine skitze anhand ich dann die zustände besser sehe als sie nur im kopf zu haben...
geist4711
User
Beiträge: 47
Registriert: Montag 29. Juli 2019, 11:48

Freitag 2. August 2019, 16:30

hier mal die skitze oder 'schaltverlauf':

Programmstart
---> Fahrlicht an ---> Fahrlicht vorn und hinten, pwm 0.6
---> Fahrlicht aus --> fahrlicht vorm und hinten pwm 0.0

---> Fernlicht an ---> Fahrlicht, vorn pwm 1
---> Fernlicht aus ---> Fahrlicht vorn pwm 0.6 oder pwm 0, wenn Fahrlicht an oder aus

---> Bremslicht an ---> Fahrlicht hinten pwm 1
---> Bremslicht aus ---> Fahrlicht hinten pwm 0.6 oder pwm 0, wenn Fahrlich an oder aus

---> hupe an ---> hupe an
---> hupe aus ---> hupe aus

---> blinker links ---> blinker inks blinkt solange blinker an
---> blinker rechts blinkt solang blinker an

hab bissel drüber sinniert und kann die pwm 0.2 wenn man das programm einschaltet als startvalue auch weg lassen, ich krieg das schon mit, wenn eine lampe nicht will :-)
das spart auch einen weiteren schaltzustand.

soweit ist das ganze geschalte auch kein problem, hab des ja auch schon so im alten script
fas 'erschlagen'.

wo es knifflig wird ist:
wie sag ich dem fern- und brems-licht wohin es zurück-schalten soll, beim ausschalten?!

kann ich beim einschalten der beleuchtung irgendwohin den 'ist-zustand' hinschreiben, der dann auch beim start erstmal auf =0 steht?

sodass sich das bremslicht und fernlicht wenn es aus geht von da den ausgangswert wieder holt und dahin zurückschaltet?

kann ich eine variable 'istzustand = 0' angeben, die ich beim anschalten vom licht 0 auf 0.6 setze und diese wenn fernlicht/ bremslicht wieder aus geht dann abfrage und dahin da licht dann wieder zurücksetze?

hab schon gelesen das sowas wohl geht, aber mir ist die funktionsweise nicht begreiflich, wie das dort erklärt wird.

selbst mit der lookup-tabelle:
0 = pwm 0
1 = pwm 0.6
2 = pwm 1
( wie muss ich die bennen? 'pwmtabelle' zb?)
kann ich zwar sagen 'geh nach 0,1,2' und dann geht pwm auf 0 , 0.6 , 1

aber die 'rückabfrage' hätte ich dann ja noch nicht wenn das fern- oder brems-licht dann aus geht? :-)
daran 'hakt' ja auch die alte schaltung.
Antworten