Hallo,
ich bin neu hier und ein Anfänger in Python. In meiner Projektarbeit muss ich eine schiefe Ebene bauen, die mit Laserlichtschranken versehen ist. Die Ebene ist bereits gebaut. Wenn die Kugel/Quader nach unter rollt möchte ich bei jeder Lichtschranke die Zeit ermitteln und auf einem Display ausgeben. Das Display funktioniert bereits über den I2C-Bus. Das ganze wird über den Raspberry-Pi gesteuert und in Python programmiert. Jedoch hackt es noch ein wenig mit der Programmierung. Ich lade das Programm einfach mal mit hoch.
Mein Problem ist: Wenn ich das Programm starte, wird mir die Zeit 1 ausgegeben. Jedoch wird mir nicht immer die Zeit 2/3 ausgegeben.
Mfg Simon
#Projektarbeit_Schiefe_Ebene_2017
#!/usr/bin/python
import time
import RPi.GPIO as GPIO
import lcddriver
lcd = lcddriver.lcd()
lcd.lcd_clear()
GPIO_SENSOR1_PIN = 22
GPIO_SENSOR2_PIN = 23
GPIO_SENSOR3_PIN = 24
GPIO_SENSOR4_PIN = 25
DISTANCE_1 = 10.0 # (in cm) Anpassen, falls notwendig
DISTANCE_2 = 40.0 # (in cm) Anpassen, falls notwendig
DISTANCE_3 = 90.0 # (in cm) Anpassen, falls notwendig
TIMEOUT_1 = 5 # sek.
TIMEOUT_2 = 10 # sek.
TIMEOUT_3 = 15 # sek.
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Programm starten und Sensoren initialisieren:
if __name__ == '__main__':
GPIO.setup(GPIO_SENSOR1_PIN, GPIO.IN)
GPIO.setup(GPIO_SENSOR2_PIN, GPIO.IN)
GPIO.setup(GPIO_SENSOR3_PIN, GPIO.IN)
GPIO.setup(GPIO_SENSOR4_PIN, GPIO.IN)
start_time1, end_time1 = 0, 0
end_time2 = 0, 0
# Sensor 1 und 2:
while GPIO.input(GPIO_SENSOR1_PIN) == GPIO.LOW:
time.sleep(0.1)
start_time1 = time.time()
end_time1 = 0
while GPIO.input(GPIO_SENSOR2_PIN) == GPIO.LOW and time.time()-start_time1 < TIMEOUT_1:
time.sleep(0.1)
else:
if time.time()-start_time1 >= TIMEOUT_1:
print "Timeout_1"
lcd.lcd_display_string("Timeout_1", 1)
exit()
else:
end_time1 = time.time()
speed_1 = DISTANCE_1 / (end_time1 - start_time1)
print "1. Geschwindigkeit: %.2f cm/s" % speed_1
print "1. Zeit: %.2f s" % (end_time1 - start_time1)
lcd.lcd_display_string("v: %.2f cm/s" % speed_1, 1)
lcd.lcd_display_string("t: %.2f s" % (end_time1 - start_time1), 2)
# Sensor 2 und 3:
while GPIO.input(GPIO_SENSOR2_PIN) == GPIO.LOW:
time.sleep(0.1)
start_time1 = time.time()
end_time2 = 0
while GPIO.input(GPIO_SENSOR3_PIN) == GPIO.LOW and time.time()-start_time1 < TIMEOUT_2:
time.sleep(0.1)
else:
if time.time()-start_time1 >= TIMEOUT_2:
print "Timeout_2"
lcd.lcd_clear()
lcd.lcd_display_string("Timeout_2", 1)
exit()
else:
end_time2 = time.time()
speed_2 = DISTANCE_2 / (end_time2 - start_time1)
print "2. Geschwindigkeit: %.2f cm/s" % speed_2
print "2. Zeit: %.2f s" % (end_time2 - start_time1)
lcd.lcd_clear()
lcd.lcd_display_string("v: %.2f cm/s" % speed_2, 1)
lcd.lcd_display_string("t: %.2f s" % (end_time2 - start_time1), 2)
# Sensor 3 und 4:
while GPIO.input(GPIO_SENSOR3_PIN) == GPIO.LOW:
time.sleep(0.1)
start_time1 = time.time()
end_time3 = 0
while GPIO.input(GPIO_SENSOR4_PIN) == GPIO.LOW and time.time()-start_time1 < TIMEOUT_3:
time.sleep(0.1)
else:
if time.time()-start_time1 >= TIMEOUT_3:
print "Timeout_3"
lcd.lcd_clear()
lcd.lcd_display_string("Timeout_3", 1)
exit()
else:
end_time3 = time.time()
speed_3 = DISTANCE_3 / (end_time3 - start_time1)
print "3. Geschwindigkeit: %.2f cm/s" % speed_3
print "3. Zeit: %.2f s" % (end_time3 - start_time1)
lcd.lcd_clear()
lcd.lcd_display_string("v: %.2f cm/s" % speed_3, 1)
lcd.lcd_display_string("t: %.2f s" % (end_time3 - start_time1), 2)
Schiefe Ebene mit Laserlichtschranken
@simideluxe: In Python sind Einrückungen wichtig. Daher füge hier im Forum Code in einer CodeBox ein. So wie es aussieht, sind da ein paar Zeilen falsch Eingerückt, so dass Dein Programm gar nicht laufen dürfte.
Alles unter `if __name__ == '__main__':` sollte in einer Funktion stehen und dort nur der Funktionsaufruf. Außerdem hast Du alles drei mal kopiert, statt für die Zeitmessung eine Funktion auszulagern und diese 3mal aufzurufen. Warnings sollte man nicht auf False setzen, sondern die Ursache der Warnung beheben. Ein `else` bei einer Schleife ohne `break` macht keinen Sinn, weil der else-Zweig immer durchlaufen wird. Eine zehntel Sekunde ist ein relativ langer Zeitraum. Während dieser Zeit kann eine Kugel unbemerkt durch die Lichtschranke rollen. Variablen mit werden zu belegen, die man dann nicht benutzt ist unsinnig. Das Verhindert, dass man Fehler findet, weil man irgendwo vergessen hat, den richtigen Wert zu setzen. Die Shebang-Zeile (#!) muß die erste im Programm sein. `exit` sollte man in normalen Programmen nicht benutzen.
Alles unter `if __name__ == '__main__':` sollte in einer Funktion stehen und dort nur der Funktionsaufruf. Außerdem hast Du alles drei mal kopiert, statt für die Zeitmessung eine Funktion auszulagern und diese 3mal aufzurufen. Warnings sollte man nicht auf False setzen, sondern die Ursache der Warnung beheben. Ein `else` bei einer Schleife ohne `break` macht keinen Sinn, weil der else-Zweig immer durchlaufen wird. Eine zehntel Sekunde ist ein relativ langer Zeitraum. Während dieser Zeit kann eine Kugel unbemerkt durch die Lichtschranke rollen. Variablen mit werden zu belegen, die man dann nicht benutzt ist unsinnig. Das Verhindert, dass man Fehler findet, weil man irgendwo vergessen hat, den richtigen Wert zu setzen. Die Shebang-Zeile (#!) muß die erste im Programm sein. `exit` sollte man in normalen Programmen nicht benutzen.
Code: Alles auswählen
#!/usr/bin/python
#Projektarbeit_Schiefe_Ebene_2017
import time
import RPi.GPIO as gpio
import lcddriver
GPIO_SENSOR_PINS = [22, 23, 24, 25]
SETUP = [
{'pin': 23, 'distance': 10.0, 'timeout': 5},
{'pin': 24, 'distance': 40.0, 'timeout': 10},
{'pin': 25, 'distance': 90.0, 'timeout': 15},
]
class TimeoutError(Exception):
pass
def get_lowtime(pin, timeout=1e30):
start_time = current_time = time.time()
while gpio.input(pin) == gpio.LOW:
current_time = time.time()
if current_time - start_time > timeout:
raise TimeoutError()
return current_time - start_time
def main():
# Programm starten und Sensoren initialisieren:
gpio.setmode(gpio.BCM)
gpio.setup(GPIO_SENSOR_PINS, gpio.IN)
lcd = lcddriver.lcd()
lcd.lcd_clear()
_ = get_lowtime(GPIO_SENSOR1_PIN) # Warten auf den Start
for nr, setup in enumerate(SETUP, 1):
try:
timedelta = get_lowtime(setup['pin'], setup['timeout'])
except TimeoutError:
lcd.lcd_clear()
lcd.lcd_display_string("Timeout %d" % nr, 1)
return
speed = setup['distance'] / timedelta
print "%d. Geschwindigkeit: %.2f cm/s" % (nr, speed)
print "%d. Zeit: %.2f s" % (nr, timedelta)
lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
if __name__ == '__main__':
main()
@Sirius3: Der busy-wait ist nicht gut. Dafuer gibt es wait_for_edge:
Code: Alles auswählen
def get_lowtime(pin, timeout=1e30):
start = time.time()
if GPIO.wait_for_edge(pin, GPIO_RISING, timeout=timeout * 1000) is None:
raise TimeoutError
return time.time() - start
-
- User
- Beiträge: 8
- Registriert: Donnerstag 7. Dezember 2017, 08:59
Vielen Dank für Eure schnelle und professionelle Hilfe!! Die ersten, die mir helfen
@Sirius3: Das Programm hatte Einrückungen und ist auch ausführbar aber funktioniert wie gesagt nicht richtig.
Ich probiere Euren Quellcode und melde mich dann nochmal!

Ich probiere Euren Quellcode und melde mich dann nochmal!
-
- User
- Beiträge: 8
- Registriert: Donnerstag 7. Dezember 2017, 08:59
@ Alle! Habe noch Fehlermeldungen:
- In Zeile 47 das main()
- In Zeile 31 ist der globale Name "GPIO_SENSOR1_PIN" nicht definiert
- In Zeile 47 das main()
- In Zeile 31 ist der globale Name "GPIO_SENSOR1_PIN" nicht definiert
Code: Alles auswählen
#!/usr/bin/python
#Projektarbeit_Schiefe_Ebene_2017
import time
import RPi.GPIO as GPIO
import lcddriver
GPIO_SENSOR_PINS = [22, 23, 24, 25]
SETUP = [
{'pin': 23, 'distance': 10.0, 'timeout': 5},
{'pin': 24, 'distance': 40.0, 'timeout': 10},
{'pin': 25, 'distance': 90.0, 'timeout': 15},
]
class TimeoutError(Exception):
pass
def get_lowtime(pin, timeout=1e30):
start = time.time()
if GPIO.wait_for_edge(pin, GPIO_RISING, timeout=timeout * 1000) is None:
raise TimeoutError
return time.time() - start
def main():
# Programm starten und Sensoren initialisieren:
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_SENSOR_PINS, GPIO.IN)
lcd = lcddriver.lcd()
lcd.lcd_clear()
_ = get_lowtime(GPIO_SENSOR1_PIN) # Warten auf den Start
for nr, setup in enumerate(SETUP, 1):
try:
timedelta = get_lowtime(setup['pin'], setup['timeout'])
except TimeoutError:
lcd.lcd_clear()
lcd.lcd_display_string("Timeout %d" % nr, 1)
return
speed = setup['distance'] / timedelta
print "%d. Geschwindigkeit: %.2f cm/s" % (nr, speed)
print "%d. Zeit: %.2f s" % (nr, timedelta)
lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
if __name__ == '__main__':
main()
@simideluxe: schön, dass Du Fehler gefunden hast. Da ist auch noch ein von Dir unentdeckter dabei. Ich bin mir sicher, dass Du beide beseitigen kannst.
Module werden klein geschrieben. Irgendwie ist GPIO wieder groß geworden.
Module werden klein geschrieben. Irgendwie ist GPIO wieder groß geworden.
-
- User
- Beiträge: 8
- Registriert: Donnerstag 7. Dezember 2017, 08:59
Gut "GPIO_SENSOR1_PIN" kann nicht gehen, weil es nicht deklariert ist. Ich würde jetzt auf die Liste zugreifen: "GPIO_SENSOR_PINS, 0" für den GPIO-PIN 22. Das mit main() verstehe ich nicht ganz. 

-
- User
- Beiträge: 8
- Registriert: Donnerstag 7. Dezember 2017, 08:59
Vorherige Programmfehler sind nun behoben. Beim Ausführen des Programms stoße ich nun auf ein weiteres Problem:
line 41 wird aufgerufen: TypeError: not enough arguments for format string
Aber wieso fehlen Argumente? Kann mir wieder jemand nenn Tipp geben? Danke!
line 41 wird aufgerufen: TypeError: not enough arguments for format string
Aber wieso fehlen Argumente? Kann mir wieder jemand nenn Tipp geben? Danke!
Code: Alles auswählen
#!/usr/bin/python
# Projektarbeit_Schiefe_Ebene_2017
import time
import RPi.GPIO as gpio # Einbinden der RPi.GPIO Bibliothek
import lcddriver # Einbinden des LC-Display Treibers
GPIO_SENSOR_PINS = [22, 23, 24, 25] # Erstellen einer Liste mit den GPIO_SENSOR_PINS
SETUP = [
{'pin': 23, 'distance': 10.0, 'timeout': 5},
{'pin': 24, 'distance': 40.0, 'timeout': 10},
{'pin': 25, 'distance': 90.0, 'timeout': 15},]
class TimeoutError(Exception):
pass
def get_lowtime(pin, timeout=36):
start = time.time()
if gpio.wait_for_edge(pin, gpio.RISING, timeout=timeout*1000) is None:
raise TimeoutError()
return time.time() - start
def main():
# Programm starten und Sensoren initialisieren:
gpio.setmode(gpio.BCM)
gpio.setup(GPIO_SENSOR_PINS, gpio.IN)
lcd = lcddriver.lcd()
lcd.lcd_clear()
_ = get_lowtime(GPIO_SENSOR_PINS[0]) # Warten auf den Start
for nr, setup in enumerate(SETUP, 1):
try:
timedelta = get_lowtime(setup['pin'], setup['timeout'])
except TimeoutError:
lcd.lcd_clear()
lcd.lcd_display_string("Timeout %d" % nr, 1)
return
speed = setup['distance'] / timedelta
print("%d. Geschwindigkeit" % nr, speed)
print("%d. Zeit: %.2f s" % nr, timedelta)
lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
result = speed
with open('schiefe_ebene.csv','a') as out:
for i in result:
out.write("{};{};{}\n".format(testname,i,result[i]))
if __name__ == '__main__': # Idiom erstellen
main()
@simideluxe: zähl mal, wie viele Ersetzungstellen Du hast und wie viele Argument Du angibst. Welchen Typ hat `result`? Was enthält dann gegebenenfalls `i` in der for-Schleife und was ist dann `result`?
Damit die Messung nicht zu ungenau ist, sollte in der Schleife nichts als die Messung gemacht werden und die Ausgabe erst nachträglich.
Damit die Messung nicht zu ungenau ist, sollte in der Schleife nichts als die Messung gemacht werden und die Ausgabe erst nachträglich.
-
- User
- Beiträge: 8
- Registriert: Donnerstag 7. Dezember 2017, 08:59
Das komische ist ja, dass "speed" ausgegeben wird und timedelta nicht
Die zwei Argumente müssten eigentlich schon stimmen. Mit result = speed usw... wollte ich die Werte sammeln und in eine Datei schreiben/speichern (Daran tüftel ich noch).
