Seite 1 von 1

while und for loop kombiniert

Verfasst: Montag 7. Dezember 2020, 14:51
von mochtend
Hallo Leute,

hab die Suche zu diesem Thema ausprobiert aber mit dem Titel im Thema keinen Treffer erhalten.

Ich möchte gerne eine while und eine for loop miteinander kombinieren, allerdings macht diese loop Kombination nicht so ganz was ich mir vorstelle.

Hier mein Code:

Code: Alles auswählen

Ist_Wert = 0
Soll_Wert = 5
Out = [1, 1, 0, 0]

if Ist_Wert < Soll_Wert:
    GPIO.output(13, 1)
    time.sleep(1)
    GPIO.output(13, 0)
    while Ist_Wert < Soll_Wert:
        for i in range(0,len(Out)):
            time.sleep(1)
            GPIO.output(26, Out[i])
            time.sleep(1)
            GPIO.output(19, Out[i-1])
            Ist_Wert += 1
            print("Ist_Wert ", Ist_Wert)
            if Ist_Wert == Soll_Wert:
                GPIO.output(13, 1)
                time.sleep(1)
                GPIO.output(13, 0)
Was ich aus dem print bekomme ist:
Ist_Wert 1
.
.
.
Ist_Wert 8


Mein Ziel hierbei ist es meine GPIO´s in einem bestimmten Muster schalten zu lassen. Zu Beginn der Schleife wird ein Button betätigt und wenn die Schleife zu ende ist, wird dieser Button nochmals betätigt.
Meine loop zählt zwar bis 5 und betätigt dann den Button, allerdings zählt die loop danach weiter bis 8...

Hat hier jemand eine Idee wie man das Problem lösen kann?

Mfg mochtend

Re: while und for loop kombiniert

Verfasst: Montag 7. Dezember 2020, 15:00
von Sirius3
Variablennamen werden generell komplett klein geschrieben.
Eine for-Schleife über einen Index macht man nicht, weil man direkt über die Werte iterieren kann.

Code: Alles auswählen

ist_wert = 0
soll_wert = 5
out_values = [1, 1, 0, 0]

if ist_wert < soll_wert:
    GPIO.output(13, 1)
    time.sleep(1)
    GPIO.output(13, 0)
    while ist_wert < soll_wert:
        previous_out = out_values[-1]
        for out in out_values:
            time.sleep(1)
            GPIO.output(26, out)
            time.sleep(1)
            GPIO.output(19, previous_out)
            previous_out = out
            ist_wert += 1
            print("Ist_Wert ", ist_wert)
            if ist_wert == soll_wert:
                GPIO.output(13, 1)
                time.sleep(1)
                GPIO.output(13, 0)
Der for-Schleife ist es doch egal, ob da irgendein Soll_wert größer oder kleiner einem Ist_wert ist; die läuft den ganzen Range ab.
Wahrscheinlich möchtest Du gar nicht zwei Schleifen, sondern nur eine, nämlich eine, die bis soll_wert läuft.

Code: Alles auswählen

from itertools import cycle
ist_wert = 0
soll_wert = 5
out_values = [1, 1, 0, 0]

GPIO.output(13, 1)
time.sleep(1)
GPIO.output(13, 0)

previous_out = out_values[-1]
for i, out in zip(range(ist_wert, soll_wert), cycle(out_values)):
    print("Ist_Wert ", i)
    time.sleep(1)
    GPIO.output(26, out)
    time.sleep(1)
    GPIO.output(19, previous_out)
    previous_out = out

GPIO.output(13, 1)
time.sleep(1)
GPIO.output(13, 0)

Re: while und for loop kombiniert

Verfasst: Dienstag 8. Dezember 2020, 09:03
von mochtend
Hey Sirius3,

vielen Dank für deine Variante aus dem zweiten Code-Abschnitt!!!
Genau sowas ich brauche :)

Werde mich jetzt mal intensiv mit diesen itertools auseinandersetzen das ist ja richtig nützlich!
Weißt du zufällig wo ich näheres zu diesen itertools und evtl zu dem out in zip() finde?

Mfg mochtend :)

Re: while und for loop kombiniert

Verfasst: Dienstag 8. Dezember 2020, 09:16
von Sirius3
Wie bei allen Fragen zur Standardbibliothek, in der Dokumentation: https://docs.python.org/3/library/itertools.html, https://docs.python.org/3/library/functions.html#zip

Re: while und for loop kombiniert

Verfasst: Dienstag 8. Dezember 2020, 09:26
von mochtend
Danke :)

Re: while und for loop kombiniert

Verfasst: Dienstag 8. Dezember 2020, 12:46
von mochtend
Hey bevor der Thread geschlossen wird wollte ich noch eine kurze Frage stellen.
Und zwar möchte ich einen Encoder fernsteuern können.
Dieser Encoder muss nach der Wahrheitstabelle OutA = [1, 1, 0, 0] & OutB = [0, 1, 1, 0] angesteuert werden, damit er im Uhrzeigersinn schaltet -> das mache ich ja mit den out_values = [1, 1, 0, 0] und mit dem previous_out = out_values[-1].

Der Programmschnipsel von Sirius funktioniert einwandfrei, allerdings bin ich jetzt am nächsten Problem angelangt, woran ich mich schon seit ein paar Stunden probiere...
Wenn ich nun einen soll_wert von 8 habe wird der ist_wert auch 8 mal um 1 erhöht wunderbar!
Aber wenn ich jetzt als soll_wert eine 10 habe wird der Wert um 10 erhöht, allerdings wird beim nächsten mal erhöhen dann ein Problem auftreten...
Das Problem ist, dass dann bei out = 1 und previous_out = 1 stehen geblieben wird und beim nächsten mal erhöhen nicht bei out = 1 und previous_out = 0 angefangen wird sondern von den Endwerten des letzten durchlaufs (out = 1, previous_out = 1) weitergezählt wird.

Dieses Problem habe ich also mit allen Werten die nicht durch 4 teilbar sind.
Hatte überlegt es mithilfe von Modulo zu lösen aber das erscheint mir nach ein bisschen rumprobieren als nicht zielführend...

Hat da jemand eine schlaue Idee zu oder kann mir etwas Empfehlen was mir in dieser Richtung helfen kann?

Re: while und for loop kombiniert

Verfasst: Dienstag 8. Dezember 2020, 14:00
von mochtend
Ach quatsch völlig falsche Fehlerbeschreibung sorry.....
kann ich meinen Beitrag hier drüber irgendwie löschen oder bearbeiten?
Hab keinen Button dafür gefunden....

Hier mal der grobe Code:

Code: Alles auswählen

from tkinter import *
from tkinter import ttk
from itertools import cycle

import smbus
import time
import RPi.GPIO as GPIO

GPIO.setwarnings(False) 
GPIO.setmode(GPIO.BCM)          

GPIO.setup(19, GPIO.OUT)                        
GPIO.output(19, GPIO.LOW)                   
GPIO.setup(26, GPIO.OUT)                  
GPIO.output(26, GPIO.LOW)                   



"""----------------Graphical User Interface----------------"""
# Implementierung des User Interface
window = Tk()                                 
window.title("User Interface")            
window.geometry('800x480')                     
# Hinzufügen der Tabs
tab_control = ttk.Notebook(window)
# Anzahl der Tabs
tab1 = ttk.Frame(tab_control)
# Namensgebung der Tabs
tab_control.add(tab1, text='Encoder')
# Anzeige der Tabs auf "GUI"
tab_control.pack(expand=1, fill='both')


"""------------------------Funktionen für Encoder Tab-----------------------------"""
val_enc_spin = 0     
delay_encoder = 0.3


def EncoderTestInkr():
    val_enc_spin = EncoderSpinbox.get()          
    print("Value in Spinbox: ", val_enc_spin)
    """Encoder-Variablen"""
    ist_wert = 0
    soll_wert = int(val_enc_spin)
    out_values = [1, 1, 0, 0]
    
    if ist_wert < soll_wert:
        GPIO.output(13, 1)
        time.sleep(Delay_Encoder)
        GPIO.output(13, 0)
        previous_out = out_values[-1]
        for i, out in zip(range(ist_wert, soll_wert), cycle(out_values)):
            print("out", out, "\n",
                  "previous_out", previous_out, "\n",
                  "ist_Wert", ist_wert, "\n")
            time.sleep(Delay_Encoder)
            GPIO.output(26, out)
            time.sleep(Delay_Encoder)
            GPIO.output(19, previous_out)
            ist_wert += 1
            previous_out = out
            if ist_wert == soll_wert:
                GPIO.output(13, 1)
                time.sleep(Delay_Encoder)
                GPIO.output(13, 0)


"""GUI Encoder-Tab"""
# Button Inkrementierung
EncoderButtonInkr = Button(tab1, text = "Inkrementierung", command = EncoderTestInkr)
EncoderButtonInkr.place(x = 128, y = 40)
LabelButtons = Label(tab1, text = "Test der Inkrementierung des Encoders")
LabelButtons.place(x = 10, y = 10)
# Spinbox Encoder
EncoderSpinbox = Spinbox(tab1, from_ = 0, to = 99, width = 5)
EncoderSpinbox.place(x = 530, y = 40) 
LabelSpinbox = Label(tab1, text = "Eingabe: Soll-Wert")
LabelSpinbox.place(x = 500, y = 10)  
Also wenn ich jetzt den Wert 3 in die Spinbox eingebe und auf Inkrementierung drücke, läuft die Schleife solange bis der Sollwert erreicht ist.
Wenn ich dann den Wert ändere und wieder auf Inkrementierung drücke, starte ich nicht mit dem vorherigen Wert von out und previous_out, sondern starte wieder von out = 1 und previous_out = 0
Hatte eben einen dicken Denkfehler drin.
Immer wenn ich auf Inkrementierung drücke will ich ja nicht wieder bei out = 1 und previous_out = 0 starten sondern ich will bei den vorherigen out und previous_out ansetzen und von da weiter "zählen".