Schiefe Ebene mit Laserlichtschranken

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Donnerstag 7. Dezember 2017, 09:22

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)
Sirius3
User
Beiträge: 6667
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon Sirius3 » Donnerstag 7. Dezember 2017, 10:46

@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.

  1. #!/usr/bin/python
  2. #Projektarbeit_Schiefe_Ebene_2017
  3. import time
  4. import RPi.GPIO as gpio
  5. import lcddriver
  6.  
  7. GPIO_SENSOR_PINS = [22, 23, 24, 25]
  8.  
  9. SETUP = [
  10.     {'pin': 23, 'distance': 10.0, 'timeout': 5},
  11.     {'pin': 24, 'distance': 40.0, 'timeout': 10},
  12.     {'pin': 25, 'distance': 90.0, 'timeout': 15},
  13. ]
  14.  
  15. class TimeoutError(Exception):
  16.     pass
  17.  
  18. def get_lowtime(pin, timeout=1e30):
  19.     start_time = current_time = time.time()
  20.     while gpio.input(pin) == gpio.LOW:
  21.         current_time = time.time()
  22.         if current_time - start_time > timeout:
  23.             raise TimeoutError()
  24.     return current_time - start_time
  25.  
  26. def main():
  27.     # Programm starten und Sensoren initialisieren:
  28.     gpio.setmode(gpio.BCM)
  29.     gpio.setup(GPIO_SENSOR_PINS, gpio.IN)
  30.     lcd = lcddriver.lcd()
  31.     lcd.lcd_clear()
  32.    
  33.     _ = get_lowtime(GPIO_SENSOR1_PIN) # Warten auf den Start
  34.  
  35.     for nr, setup in enumerate(SETUP, 1):
  36.         try:
  37.             timedelta = get_lowtime(setup['pin'], setup['timeout'])
  38.         except TimeoutError:
  39.             lcd.lcd_clear()
  40.             lcd.lcd_display_string("Timeout %d" % nr, 1)
  41.             return
  42.         speed = setup['distance'] / timedelta
  43.         print "%d. Geschwindigkeit: %.2f cm/s" % (nr, speed)
  44.         print "%d. Zeit: %.2f s" % (nr, timedelta)
  45.         lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
  46.         lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
  47.    
  48. if __name__ == '__main__':
  49.     main()
Benutzeravatar
__deets__
User
Beiträge: 1518
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon __deets__ » Donnerstag 7. Dezember 2017, 13:19

@Sirius3: Der busy-wait ist nicht gut. Dafuer gibt es wait_for_edge:

  1. def get_lowtime(pin, timeout=1e30):
  2.     start = time.time()
  3.     if GPIO.wait_for_edge(pin, GPIO_RISING, timeout=timeout * 1000) is None:
  4.         raise TimeoutError
  5.     return time.time() - start
simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Donnerstag 7. Dezember 2017, 13:50

Vielen Dank für Eure schnelle und professionelle Hilfe!! Die ersten, die mir helfen :D @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!
simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Donnerstag 7. Dezember 2017, 16:45

@ Alle! Habe noch Fehlermeldungen:
- In Zeile 47 das main()
- In Zeile 31 ist der globale Name "GPIO_SENSOR1_PIN" nicht definiert

  1. #!/usr/bin/python
  2. #Projektarbeit_Schiefe_Ebene_2017
  3. import time
  4. import RPi.GPIO as GPIO
  5. import lcddriver
  6.  
  7. GPIO_SENSOR_PINS = [22, 23, 24, 25]
  8.  
  9. SETUP = [
  10.         {'pin': 23, 'distance': 10.0, 'timeout': 5},
  11.         {'pin': 24, 'distance': 40.0, 'timeout': 10},
  12.         {'pin': 25, 'distance': 90.0, 'timeout': 15},
  13. ]
  14.  
  15. class TimeoutError(Exception):
  16.     pass
  17.  
  18. def get_lowtime(pin, timeout=1e30):
  19.     start = time.time()
  20.     if GPIO.wait_for_edge(pin, GPIO_RISING, timeout=timeout * 1000) is None:
  21.         raise TimeoutError
  22.     return time.time() - start
  23.  
  24. def main():
  25.     # Programm starten und Sensoren initialisieren:
  26.     GPIO.setmode(GPIO.BCM)
  27.     GPIO.setup(GPIO_SENSOR_PINS, GPIO.IN)
  28.     lcd = lcddriver.lcd()
  29.     lcd.lcd_clear()
  30.  
  31.     _ = get_lowtime(GPIO_SENSOR1_PIN) # Warten auf den Start
  32.  
  33.     for nr, setup in enumerate(SETUP, 1):
  34.         try:
  35.             timedelta = get_lowtime(setup['pin'], setup['timeout'])
  36.         except TimeoutError:
  37.             lcd.lcd_clear()
  38.             lcd.lcd_display_string("Timeout %d" % nr, 1)
  39.             return
  40.         speed = setup['distance'] / timedelta
  41.         print "%d. Geschwindigkeit: %.2f cm/s" % (nr, speed)
  42.         print "%d. Zeit: %.2f s" % (nr, timedelta)
  43.         lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
  44.         lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
  45.  
  46. if __name__ == '__main__':
  47.     main()
  48.  
Benutzeravatar
__deets__
User
Beiträge: 1518
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon __deets__ » Donnerstag 7. Dezember 2017, 16:58

Na, versuch doch mal selbst rauszufinden, was damit gemeint sein koennte. Ein bisschen Muehe zu verstehen, was da passiert, darfst du dir schon geben :roll:
Sirius3
User
Beiträge: 6667
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon Sirius3 » Donnerstag 7. Dezember 2017, 17:00

@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.
simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Donnerstag 7. Dezember 2017, 17:57

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. :?
Benutzeravatar
__deets__
User
Beiträge: 1518
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon __deets__ » Donnerstag 7. Dezember 2017, 18:11

simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Freitag 8. Dezember 2017, 13:56

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!

  1. #!/usr/bin/python
  2. # Projektarbeit_Schiefe_Ebene_2017
  3. import time
  4. import RPi.GPIO as gpio # Einbinden der RPi.GPIO Bibliothek
  5. import lcddriver    # Einbinden des LC-Display Treibers
  6.  
  7. GPIO_SENSOR_PINS = [22, 23, 24, 25] # Erstellen einer Liste mit den GPIO_SENSOR_PINS
  8.  
  9. SETUP = [
  10.         {'pin': 23, 'distance': 10.0, 'timeout': 5},
  11.         {'pin': 24, 'distance': 40.0, 'timeout': 10},
  12.         {'pin': 25, 'distance': 90.0, 'timeout': 15},]
  13.  
  14. class TimeoutError(Exception):
  15.     pass
  16.  
  17. def get_lowtime(pin, timeout=36):
  18.     start = time.time()
  19.     if gpio.wait_for_edge(pin, gpio.RISING, timeout=timeout*1000) is None:
  20.         raise TimeoutError()
  21.     return time.time() - start
  22.  
  23. def main():
  24.     # Programm starten und Sensoren initialisieren:
  25.     gpio.setmode(gpio.BCM)
  26.     gpio.setup(GPIO_SENSOR_PINS, gpio.IN)
  27.     lcd = lcddriver.lcd()
  28.     lcd.lcd_clear()
  29.  
  30.     _ = get_lowtime(GPIO_SENSOR_PINS[0]) # Warten auf den Start
  31.  
  32.     for nr, setup in enumerate(SETUP, 1):
  33.         try:
  34.             timedelta = get_lowtime(setup['pin'], setup['timeout'])
  35.         except TimeoutError:
  36.             lcd.lcd_clear()
  37.             lcd.lcd_display_string("Timeout %d" % nr, 1)
  38.             return
  39.         speed = setup['distance'] / timedelta
  40.         print("%d. Geschwindigkeit" % nr, speed)
  41.         print("%d. Zeit: %.2f s" % nr, timedelta)
  42.         lcd.lcd_display_string("v: %.2f cm/s" % speed, 1)
  43.         lcd.lcd_display_string("t: %.2f s" % timedelta, 2)
  44.  
  45.  
  46.         result = speed
  47.         with open('schiefe_ebene.csv','a') as out:
  48.             for i in result:
  49.                 out.write("{};{};{}\n".format(testname,i,result[i]))
  50.  
  51.  
  52. if __name__ == '__main__':      # Idiom erstellen
  53.  
  54.     main()
  55.  
Sirius3
User
Beiträge: 6667
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon Sirius3 » Freitag 8. Dezember 2017, 14:13

@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[i]`?

Damit die Messung nicht zu ungenau ist, sollte in der Schleife nichts als die Messung gemacht werden und die Ausgabe erst nachträglich.
simideluxe
User
Beiträge: 6
Registriert: Donnerstag 7. Dezember 2017, 08:59

Re: Schiefe Ebene mit Laserlichtschranken

Beitragvon simideluxe » Freitag 8. Dezember 2017, 14:34

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).

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder