Zweites Signal beim Fototransistor

fischertechnik in General
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
haferfleks
Beiträge: 15
Registriert: 05 Jun 2025, 13:48

Zweites Signal beim Fototransistor

Beitrag von haferfleks » 09 Sep 2025, 08:48

Hallo,

ich habe an meinem TXT 4.0 eine Lichtschranken-LED (O7) und einen Fototransistor (I4) angeschlossen. Die controller.py sieht wie folgt aus:

Code: Alles auswählen

import fischertechnik.factories as txt_factory

txt_factory.init()

txt_factory.init_input_factory()
txt_factory.init_output_factory()

TXT_M = txt_factory.controller_factory.create_graphical_controller()
TXT_M_I4_photo_transistor = txt_factory.input_factory.create_photo_transistor(TXT_M, 4)
TXT_M_O7_led = txt_factory.output_factory.create_led(TXT_M, 7)

txt_factory.initialized()
und der Code:

Code: Alles auswählen

from time import sleep, time
from lib.controller import *


def callback2(event):
    start = time()
    while TXT_M_I4_photo_transistor.is_bright():
        sleep(0.001)
    end = time()
    print("duration %f" % (end - start))


TXT_M_I4_photo_transistor.add_change_listener("bright", callback2)


TXT_M_O7_led.set_brightness(0)
TXT_M_O7_led.set_brightness(512)
sleep(1)
TXT_M_O7_led.set_brightness(0)
sleep(1)
TXT_M_O7_led.set_brightness(512)
sleep(1)
TXT_M_O7_led.set_brightness(0)
sleep(0.1)
Als Resultat erhalte ich die beiden 1s Lichtsignale und zusätzlich jeweils ein sehr kurzes zusätzliches Signal:

Code: Alles auswählen

Program starts ...

duration 0.993381
duration 0.000035
duration 0.993475
duration 0.000031

Program finished.
Ich habe mehrere Fototransistoren durchprobiert. Das Verhalten tritt bei allen auf. Wo hat das zweite Signal seinen Ursprung? Spiegelungen bzw. Reflexionen kann ich ausschließen. PWM sollte auch keine Rollen spielen, da ich als Wert 512 angebe. Bei einem Wert von 256 merke ich den Einfluss der PWM. Die macht sich auch anders bemerkbar.

Gruß
haferfleks

Benutzeravatar
calliope
Beiträge: 50
Registriert: 11 Mär 2025, 12:02

Re: Zweites Signal beim Fototransistor

Beitrag von calliope » 09 Sep 2025, 10:40

Das Ereignis Callback Event kommt beim anschalten und beim ausschalten. Du blockierst aber in der Ereignis Funktion nach dem anschalten Ereignis bis das Licht aus ist. Wenn die Funktion dann endet steht das ausschalten Ereignis schon in der Warteschlange und wird sofort ausgelöst. Das Ereignis blockiert dann nicht, weil das Licht schon vorher aus war.

Also keine while Schleife im Ereignis und die letzte time in einer globalen Variable speichern.

FG Lutz
I²C für Calliope, TXT 4.0 und RX Controller.
https://git.fischertechnik-cloud.com/users/i2c/projects

haferfleks
Beiträge: 15
Registriert: 05 Jun 2025, 13:48

Re: Zweites Signal beim Fototransistor

Beitrag von haferfleks » 09 Sep 2025, 12:08

Hallo calliope,

vielen Dank für deine Antwort.
calliope hat geschrieben:
09 Sep 2025, 10:40
Das Ereignis Callback Event kommt beim anschalten und beim ausschalten...
Ich bin davon ausgegangen, dass wenn ich der Methode add_change_listener als erstes Argument "bright" mitgebe, dass dann nur der Übergang dunkel -> hell meine Callback-Funktion auslöst. Habe den Pythoncode, der bei der graphischen Programmierung parallel erstellt wird, meiner Erwartung entsprechend angepasst, was zu dem Fehlverhaklten führte. In der Methode run() der Klasse EventWorker ist zu erkennen, dass bei jeder Änderung des Zustandes des Fototransistors die Callback-Funktion aufgerufen wird und das erste Argument lediglich der Name der Property ist:

Code: Alles auswählen

class EventWorker(object):

    def __init__(self, target, property_name, callback):
        """@ParamType target fischertechnik.controller.IOUnit
        @ParamType property string"""
        self.__target = target
        self.__property_name = property_name
        self.__callback = callback
        self.__prev_value = self.__get_value()

    @property
    def callback(self):
        return self.__callback

    @property
    def target(self):
        return self.__target

    @property
    def property_name(self):
        return self.__property_name

    def run(self):
        current_value = self.__get_value()
        if current_value != self.__prev_value:
            self.__prev_value = current_value
            self.__callback(Event(self.__property_name, self.__target))

    def __get_value(self):

        get_value = getattr(self.__target, self.__property_name, None)
        if get_value is not None:
            return get_value

        get_value = getattr(self.__target, 'get_' + self.__property_name, None)
        if get_value is not None:
            return get_value()

        get_value = getattr(self.__target, 'is_' + self.__property_name, None)
        if get_value is not None:
            return get_value()
Ich habe es jetzt so gelöst, dass ich am Anfang der Callback-Funktion ein

Code: Alles auswählen

    if not TXT_M_I4_photo_transistor.is_bright():
        return
ergänzt habe.

Edit:
Besser und schöner ist:

Code: Alles auswählen

def callback2(event):
    if not event.target.is_bright():
        return
Viele Grüße
haferfleks

Antworten