Auf und abzählen mit Switch an GPIO

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ich möchte gerne hoch unter Runter zählen mit 2 Tastern wobei 24 der höchste Wert ist und 1 der niedrigste.

Soweit bin ich schon gekommen:

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
    input_state = GPIO.input(20)
    if input_state == False:
        print('Button + Pressed')
        time.sleep(0.2)
    input_state = GPIO.input(21)
    if input_state == False:
        print('Button - Pressed')
        time.sleep(0.2)
jetzt muss ich ja irgendwie ein count bauen was hoch zählt mit Button+ und runter mit Button - wobei der höchste Wert nicht überschritten, oder der niedrigste Wert nicht unterschritten werden darf.
Gerne möchte ich noch eine Zahl vorgeben zum Beispiel soll der Zähler bei Start des Programms auf 5 stehen.

Kann mir da Jemand helfen?
Zuletzt geändert von Anonymous am Mittwoch 26. April 2017, 20:19, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: die Stellen im Code, wo Du hoch und runterzählen willst, hast Du ja schon mit print herausgefunden. Wo ist noch das Problem, eine Variable zu definieren und zu dieser dann 1 oder -1 zu addieren?
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

Sirius3 hat geschrieben: Wo ist noch das Problem, eine Variable zu definieren und zu dieser dann 1 oder -1 zu addieren?
Dann nicht zu vergessen noch eine if Abfrage ob der Wert > 24 bzw < 1 ist um die Grenzen nicht zu überschreiten. Das ist Standard Python Code. Siehe https://www.tutorialspoint.com/python/p ... _types.htm und https://www.tutorialspoint.com/python/p ... f_else.htm
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Och menno, ich hab damit doch noch nix gemacht, aber ich bin schon weiter :)

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
count = 0

GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
    input_state = GPIO.input(20)
    if input_state == False:
        print('Button + Pressed', count)
        count = count + 1
        time.sleep(0.2)
    input_state = GPIO.input(21)
    if input_state == False:
        print('Button - Pressed', count)
        count = count - 1
        time.sleep(0.2)
Das andere kapier ich noch nicht.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: Du weißt doch prinzipiell was if ist, da Du es ja benutzt. Jetzt mußt Du nur noch die Bedingung, ob count im richtigen Bereich liegt einbauen, also ist count groß genug, dass man noch eins abziehen kann, oder klein genug, dass man noch eins draufaddieren kann.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ich habs so gedacht:

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
count = 0
var = 24
var = 1

GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
    input_state = GPIO.input(20)
    if input_state == False:
        if var >= 1:
        if var <= 24:
        print('Button + Pressed', count)
        count = count + 1
        time.sleep(0.2)


    input_state = GPIO.input(21)
    if input_state == False:
        print('Button - Pressed', count)
        count = count - 1
        time.sleep(0.2)
aber das Programm mag das so nicht.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: gibt es auch einen Grund, warum das Programm das so nicht mag? Vielleicht eine Fehlermeldung?
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

yepp:

Code: Alles auswählen

pi@carcam:~/AntOverPowerTable $ ./level.py
  File "./level.py", line 16
    if var <= 24:
     ^
IndentationError: expected an indented block
so hab ich auch versucht, kommt aber derselbe Fehler:

Code: Alles auswählen

    if input_state == False:
         if count > 24:
         count = 24
        elif count < 1.0:
         count = 1
        print('Button + Pressed', count)
        count = count + 1
        time.sleep(0.2)
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: in Python muß jeder Block eingerückt sein; ein Block ist z.B. das, was getan soll, wenn die if-Bedingung erfüllt ist. Danach muß die nächste Zeile wieder soweit ausgerückt werden, dass sie mit der if-Zeile übereinstimmt.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Hab ich soweit verstanden, leider fängt das Programm jetzt gleich an zu zählen und geht auch über 24 bzw. unter 1

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
count = 0

while True:
    input_state = GPIO.input(20)
    if input_state == False:
        if count > 24:
                count = 24
        elif count < 1:
                count = 1
    print('Button + Pressed', count)
    count = count + 1
    time.sleep(0.2)


    input_state = GPIO.input(21)
    if input_state == False:
        print('Button - Pressed', count)
        count = count - 1
        time.sleep(0.2)
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

Das sieht doch schon ganz gut aus :-). Du erhöhst/erniedrigst aber immer nach der Grenzabfrage immer noch den Counter. Nimm doch einfach der Erhöhen/Erniedrigen in die if Abfrage rein :wink:
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Danke framp, jetzt darf er nur nicht von alleine los laufen:

Code: Alles auswählen

#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
count = 1

while True:
    input_state = GPIO.input(20)
    if input_state == False:
        if count < 24:
                count = count + 1
    print('Button + Pressed', count)
    time.sleep(0.2)


    input_state = GPIO.input(21)
    if input_state == False:
        print('Button - Pressed', count)
        count = count - 1
        time.sleep(0.2)
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: welche Zeile zu welchem if-Block gehört, entscheidet sich über die Einrückung. Jetzt schau mal ganz genau, was wie weit eingerückt ist.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Super! Danke für eure geduldige Hilfe

Ich habe zwar noch viel zu tun und zu lernen, aber ich will das unbedingt hin bekommen.

Falls Jemand mal gucken will was ich vorhabe:

viewtopic.php?f=5&t=40376

Jetzt versuche ich mal die RPM in mein level.py zu importieren und die RPM hinter den Level zu schreiben.

Wenn ich nicht weiter komme,darf ich bestimmt noch mal fragen. :oops:
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

:thumbsup:

Sirius3 und ich haben beide Konfuzius im Hinterkopf gehabt:

Gib einem Hungernden einen Fisch und er ist satt
lehre einem Hungernden zu Fischen und er ist immer satt

Der Code zu schreiben wäre für uns beide ein Klacks gewesen ... aber so hast Du ihn Dir selbst erarbeitet :-)
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ja ich bin auch schon viel weiter, ich habe jetzt "meinen" Code in den RPM Reader eingebaut:

...

Code: Alles auswählen

if __name__ == "__main__":

   import time
   import pigpio
   import readRPM
   import RPi.GPIO as GPIO
   import time

   GPIO.setmode(GPIO.BCM)
   GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
   GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
   count = 5

   RPM_GPIO = 4
   RUN_TIME = 9600.0
   SAMPLE_TIME = 2.0

   pi = pigpio.pi()

   p = readRPM.reader(pi, RPM_GPIO)

   start = time.time()

   while (time.time() - start) < RUN_TIME:

    input_state = GPIO.input(20)
    if input_state == False:
        if count < 24:
         count = count + 1
         RPM = p.RPM()
         print('Level', count, 'RPM={}'.format(int(RPM+0.5)))
         time.sleep(SAMPLE_TIME)

    input_state = GPIO.input(21)
    if input_state == False:
       if count > 1:
        count = count - 1
        RPM = p.RPM()
        print('Level', count, 'RPM={}'.format(int(RPM+0.5)))
        time.sleep(SAMPLE_TIME)


    RPM = p.RPM()
    time.sleep(SAMPLE_TIME)
    print("RPM={}".format(int(RPM+0.5)))

   p.cancel()

   pi.stop()
Die RPM tickern jetzt durch und bei Level + oder - switcht er halt den Level hoch oder runter, dann zeigt er wieder die RPM an.

Nun noch meine Werte aus der Tabelle verknüpfen das er anzeigt:
Du bist in Level "6" machst ">60" RPM das entspricht einer Leistung von "105" Watt

Muss ich da ein Array bauen, oder eine Matrix, oder kann ich gar eine *.csv einlesen?

Aber nu erstmal Feierabend und DANKE nochmal. :D
Danoo
User
Beiträge: 14
Registriert: Dienstag 12. April 2022, 12:50

Moin,
da ich momentan das gleiche Problem habe und einfach nicht weiterkomme wollte ich nachfragen ob mit wer helfen könnte.
Also das Programm soll nur durch die Eingänge ein Punktestand anzeigen und durch eine andere Taste soll soll das Scoreboard wieder zurückgesetzt werden.


Soweit bin ich:


#\pytone.exe
#cmd cd pfade
#python -m pip install --upgrade pip
#pip install keyboard

# Import libraries
from linecache import getline as lesen
import os, sys, time, tkinter as tk, operator, random, RPi.GPIO as GPIO, spidev, datetime, locale

import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
move=GPIO.input(18) # Pin 18
GPIO.setup(17,GPIO.IN,pull_up_down=GPIO.PUD_UP)
move=GPIO.input(17) # Pin 17
GPIO.setup(27,GPIO.IN,pull_up_down=GPIO.PUD_UP)
move=GPIO.input(27) # Pin 27

LeftPlayer = 0
RightPlayer = 0
LeftPlayer_str = str(0)
RightPlayer_str = str(0)

with open("/home/pi/clicks.txt", 'w') as f:
f.write(RightPlayer_str + ':' + LeftPlayer_str)
print(RightPlayer_str + ':' + LeftPlayer_str)
f.close()
while True:
move=GPIO.input(17)
if move == False:

RightPlayer += 1
with open("/home/pi/clicks.txt", 'w') as f:
RightPlayer_str = str(RightPlayer)
f.write(LeftPlayer_str + ':' + RightPlayer_str)
f.close()
print(LeftPlayer_str + ':' + RightPlayer_str)
time.sleep(0.5)

move=GPIO.input(18)
if move == False:

LeftPlayer += 1
with open("/home/pi/clicks.txt", 'w') as f:
LeftPlayer_str = str(LeftPlayer)
f.write(LeftPlayer_str + ':' + RightPlayer_str)
f.close()
print(LeftPlayer_str + ':' + RightPlayer_str)
time.sleep(0.5)


move=GPIO.input(27)
if move == False:

RightPlayer=0
LeftPlayer=0
with open("/home/pi/clicks.txt", 'w') as f:
LeftPlayer_str = str(LeftPlayer)
RightPlayer_str = str(RightPlayer)
f.write(LeftPlayer_str + ':' + RightPlayer_str)
f.close()
print(LeftPlayer_str + ':' + RightPlayer_str)
time.sleep(0.5)
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Jeder Import gehört in eine eigene Zeile. 10 Importe in einer Zeile sind definitiv nicht lesbar.
Deshalb wird wohl auch time 2x importiert; os, sys, tkinter, operator, random, spidev, datetime und locale werden importiert, aber nicht benutzt.

Variablennamen schreibt man generell komplett klein. Man speichert nicht die Stringrepresentation einer Zahl in einer eigenen Variable, sondern konvertiert bei der Ausgabe. Dazu benutzt man Format-Strings.
Bei with braucht man kein close. Du hast viermal den identischen Code zum Schreiben in eine Datei.
Am Ende des Programms muß man verlässlich GPIO.cleanup aufrufen.

Code: Alles auswählen

from RPi import GPIO
import time

def write_clicks(left_player, right_player):
    with open("/home/pi/clicks.txt", 'w') as file:
        text = f"{left_player}:{right_player}"
        file.write(text)
        print(text)

def initialize():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
    GPIO.setup(17,GPIO.IN,pull_up_down=GPIO.PUD_UP)
    GPIO.setup(27,GPIO.IN,pull_up_down=GPIO.PUD_UP)

def main():
    try:
        initialize()
        left_player = right_player = 0
        while True:
            move = GPIO.input(17)
            if move == 0:
                right_player += 1
                write_clicks(left_player, right_player)
                time.sleep(0.5)

            move = GPIO.input(18)
            if move == 0:
                left_player += 1
                write_clicks(left_player, right_player)
                time.sleep(0.5)

            move = GPIO.input(27)
            if move == 0:
                left_player = right_player = 0
                write_clicks(left_player, right_player)
                time.sleep(0.5)
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    main()
Und wo ist nun Dein konkretes Problem? Was funktioniert nicht so, wie Du es willst?
Danoo
User
Beiträge: 14
Registriert: Dienstag 12. April 2022, 12:50

Dankeschön für die schnelle Antwort, also wenn ich das Programm starte auf dem PI dann schreibt er immer

0:1
1:1
0:0
und das wiederholt sich dann immer.

Leider habe ich noch nicht ganz verstanden wieso er das macht.
Da ich noch nicht so viel Erfahrung habe und es trotzdem gerne verstehen möchte würde es mich freuen wenn mir wer ein bissen hilft :)
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Na, dann stehen halt Deine Eingänge immer auf HIGH. Wir kennen hier ja Deine Hardwareverdrahtung nicht.

Man sollte keine magischen Zahlen im Code verstreuen, sondern nutzt statt dessen Konstanten.
Statt Polling benutzt man entsprechende Funktionen um Änderungen am Eingang zu detektieren.
So blockieren sich auch die einzelnen Tasten nicht gegenseitig.

Code: Alles auswählen

from RPi import GPIO
from queue import Queue
import time

PIN_LEFT_PLAYER = 17
PIN_RIGHT_PLAYER = 18
PIN_RESET = 27

def write_clicks(left_player, right_player):
    with open("/home/pi/clicks.txt", 'w') as file:
        text = f"{left_player}:{right_player}"
        file.write(text)
        print(text)

def initialize():
    queue = Queue()
    GPIO.setmode(GPIO.BCM)
    for pin in [PIN_LEFT_PLAYER, PIN_RIGHT_PLAYER, PIN_RESET]:
        GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.add_event_detect(pin, GPIO.FALLING, callback=queue.put, bouncetime=200)
    return queue

def main():
    try:
        queue = initialize()
        left_player = right_player = 0
        while True:
            pin = queue.get()
            if pin == PIN_LEFT_PLAYER:
                left_player += 1
            elif pin == PIN_RIGHT_PLAYER:
                right_player += 1
            elif pin == PIN_LEFT_PLAYER:
                left_player = right_player = 0
            write_clicks(left_player, right_player)
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    main()
Antworten