-         

Seite 1 von 5 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 45

Thema: AT90S2343: LED als Blinklicht und Lichtsensor

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    07.11.2005
    Beiträge
    20

    AT90S2343: LED als Blinklicht und Lichtsensor

    Anzeige

    Moin alle,

    ich habe ein 'kleines' Problem und bräuchte dabei mal Eure Hilfe:

    Vor ein paar Tagen habe ich im Internet einen sehr interessanten Artikel darüber gelesen, wie man eine LED am µ-Controller als Signalindikator (Blinken, Dauerlicht) und 'gleichzeitig' als Lichtsensor benutzen kann (siehe Link 1 und Link 2).

    Wie sie zum Leuchten gebracht wird, ist klar - als Sensor wird sie benutzt, in dem man einfach nur ihre lichtabhängige Kapazität mißt. Dazu wird die LED in Sperrrichtung an +Ub gelegt, und danach über den normalen Strombegrenzungswiderstand entladen. Die Zeit, die sich daraus ergibt, ist ein Maß für die lichtabhängige Kapazität.

    Zur Verdeutlichung dazu folgendes Bild:



    Aus dem PDF-Dokument bzw. den darin enthaltenen Oszillogrammen habe ich entnommen, daß eine Meßperiode von 100 µs ausreichen sollte, um festzustellen, ob die LED angeleuchtet wird oder nicht.

    Ich bin, was die Atmel-Programmierung angeht, noch blutiger Anfänger, habe aber trotzdem mal probiert, in AVR-Basic ein kleines Programm dafür zu schreiben (siehe Anhang). Als µ-Controller habe ich den AT90S2343 genommen, da ich davon noch einen übrig habe.

    Das Grundgerüst ist relativ einfach und noch nicht optimiert, das Programm macht folgendes:

    - die LED blinkt drei mal kurz, einmal lang als Indikator für den Programmstart und die bevorstehende Messung
    - jetzt folgt 1 s Pause (LED dunkel), dann die Messung
    - nun blinkt die LED drei mal kurz und signalisiert das Ende der Messung
    - jetzt wird das Ergebnis der Messung ausgegeben: Ein mal lang blinken -> LED wurde angeleuchtet oder zwei mal lang blinken -> LED wurde nicht angeleuchtet

    Bei der Messung gehe ich wie folgt vor: Ich schalte die LED in Sperrrichtung an +Ub, warte 1 ms (zwecks 'Aufladen' ihrer Kapazität) und starte dann Timer0. Wenn dieser überläuft (nach ca. 255 µs), verzweige ich in eine Unterroutine, in der der eine Ausgang auf Eingang umgeschaltet und dann abgefragt wird. Aus der Unterroutine kommend, wird mir der Zustand des Einganges nun per LED ausgegeben.

    So weit, so gut. Das Problem dabei ist, es ändert sich nichts. Der Eingang bleibt laut Messung immer auf '1'.

    Was mache ich falsch und wie mache ich es richtig?

    Ich freue mich auf Eure Antworten und bin für jeden Hinweis dankbar!

    Viele Grüße,

    Radio Eriwan

    Code:
    '
    $regfile = "2343DEF.dat"
    $crystal = 1000000
    '
    Dim A As Byte
    Dim An_oder_aus As Bit
    '
    Config Timer0 = Timer , Prescale = 1                        'Timer0 als Timer konfigurieren
    Stop Timer0                                                 'Timer0 wieder anhalten, da er bei Konfiguration gleich gestartet wird
    Timer0 = 0                                                  'Timer0 auf '0' setzen - Tcnt0 soll auch gehen!?
    On Timer0 Tim0_isr                                          'Bei Überlauf (>255) zu Tim0_isr springen
    Enable Timer0                                               'Timer-Interrupt einschalten
    Enable Interrupts                                           'Interrupt-Handling einschalten
    '
    Config Portb = &B00000000                                   'Grundzustand einstellen -> alle Pins als Eingänge
    Portb = &B11111111                                          'Pullup-Widerstände zuschalten
    '
    Do
    '
    Config Portb.3 = Output
    Config Portb.4 = Output
    Portb.4 = 0
    '
    For A = 1 To 3
      Portb.3 = 1
      Waitms 50
      Portb.3 = 0
      Waitms 1000
    Next A
    Portb.3 = 1
    Waitms 1000
    Portb.3 = 0
    Waitms 1000
    '
    Portb.4 = 1
    Waitms 1
    Start Timer0                                                'Vor Ablauf der folgenden Wartezeit sollte die Messung fertig sein
    Waitms 1
    '
    For A = 1 To 3
      Portb.3 = 1
      Waitms 50
      Portb.3 = 0
      Waitms 50
    Next A
    Waitms 1000
    '
    If An_oder_aus = 0 Then
      Portb.3 = 1
      Waitms 1000
      Portb.3 = 0
      Waitms 1000
    End If
    If An_oder_aus = 1 Then
      Portb.3 = 1
      Waitms 1000
      Portb.3 = 0
      Waitms 1000
      Portb.3 = 1
      Waitms 1000
      Portb.3 = 0
      Waitms 1000
    End If
    '
    Loop
    '
    Tim0_isr:
      Stop Timer0
      An_oder_aus = 0
      Config Portb.4 = Input
      An_oder_aus = Pinb.4
      Config Portb.4 = Output
      Portb.4 = 0
      Timer0 = 0
    Return
    '
    End

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Sowas hab ich auch mal Versuch mit ner LED, allerdings nicht die C-Änderung versucht zu messen, sondern die LED als Stromquelle verwendet und via A/D-Wandler ausgemessen.

    Bild c.) ist mir nicht ganz klar. Wie soll sich die LED denn entladen? IN ist hochohmig. Und mit den Kapazitäten wird's auch nicht einfach. Die C einer LED würd ich im pF-Bereich ansiedeln oder ein paar 100 fF. Das gegen die um einiges größere Port-Kapazität auszumessen dürfte sehr schwer sein, vor allem weil die Kapazitätsänderung noch kleiner ausfällt. Und mir ist auch nicht klar, wie man den von der LED erzeugten Strom unterdrückt/rausrechnet.

    Bei der A/D-Wandler-Lösung geh ich über Transimpedanzwandler und nachgeschalteten Verstärker um niederohmig genug für den ADC des AVR zu sein. Das ist aber alles *sehr* verrauscht und die Werte sehr klein, vor allem bei Schummerlicht oder normaler Raumbeleuchtung.

    Wenn ich's richtig verstehe, willst du nur ein binäres on/off messen können und nicht die Umgebungshelligkeit?

    Evtl geht's dann viel simpler: Die LED in Sperrichtung an den Analog-Komparator. Den anderen Port des AnaComp via Trimmpoti auf festes Potential. Parallell zur LED nen großen Widerstand. Bei Beleuchtung setzt die LED Ladungsträger frei und bildet eine Spannung zwischen ihren Anschlüssen, die teilweise durch den R parallel zu ihr wieder abfliesst. U=I*R eben. Versuch mal verschiedene Werte für R so um 1MOhm oder höher. Den Ausgang des AnaComp kannst du abfragen und abhängig davon ne 2te LED an/aus schalten.
    Disclaimer: none. Sue me.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    07.11.2005
    Beiträge
    20
    Hallo Sprinter,

    die Idee mit dem A/D-Wandler klingt auch sehr interessant!

    Ich würde nur gerne erstmal 'mein' Prinzip zum funktionieren bringen, da dies dann auch auf den ganz kleinen Atmels ohne A/D-Wandler laufen könnte/würde.

    Die LED-Kapazität soll sich über den Vorwiderstand plus Eingangswiderstand des µ-Controllers gegen Masse entladen. Was mir nur nicht ganz klar ist: Wie mache ich das programm-technisch? Ich setze den betreffenden Pin ja vorher auf +Ub, um die LED 'aufzuladen'. Was aber dann? Ein einfaches Umschalten auf 'Eingang' scheint nicht die Lösung zu sein. Leider habe ich im Datenblatt des AT's weder ein Bild mit einer typischen Ein- bzw. Ausgangsbeschaltung gefunden, noch die Angabe eines Eingangswiderstandes.

    Wenn ich die Oszillogramme richtig interpretiere, dann kann ich von folgenden Kapazitäten ausgehen:

    - LED wird beleuchtet -> Entladung dauert ca. 60 µs -> C = 55 nF
    - LED wird nicht beleuchtet -> Entladung dauert ca. 900 µs -> C = 820 nF

    Als Widerstand habe ich bei der Berrechnung nur den Vorwiderstand mit 220 Ohm genommen (+Ub = 5 V); den Ri des µ-Controllers also vernachlässigt. Wenn ich als Eingangswiderstand z.B. noch mal 10 kOhm dazurechne, dann sind es 5,4 nF und 81 nF. In der Realität dürfte die Kapazität aber noch geringer sein, weil der Eingang mit Sicherheit mehr als 10 kOhm hat.

    Das PDF-Dokument sagt dazu:

    Zitat Zitat von Die trickreichen Ingenieure von Mitsubishi
    ... The actual measurement is made in "Discharge" mode shown in Figure 5c. Since the current flowing into a CMOS input is extremely small, the low value current limiting resistor has little impact on the voltage seen at the input pin. ...
    Das Programm der Mitsubishi-Ingenieure läuft übrigens auf einem 8 pol. PIC. Vielleicht sollte ich zwecks Eingangswiderstand dazu mal ein PIC-Datenblatt 'wälzen'.

    Im übrigen wird ja genau genommen nicht die Kapazität gemessen, sondern nur nach einer vorgegebenen Zeit abgefragt, ob die Kapazität der LED noch ge- oder schon entladen ist.

    Weiß jemand weiter?

    Viele Grüße,

    Radio Eriwan

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Oben hab ich noch was geschrieben zum ADC.

    Kapazitätsmessung kann man so machen (AT90S2313 geht prima):
    C über einen Port des Analog Comparators (AC) und Vorwiderstand aufladen. Bei LED kann der Vorwiderstand natürlich wegfallen. Den anderen Port des AC auf Vcc/2 legen. Wenn der C voll ist, den LED-Pin auf hochohmigen Eingang und den C über einen externen R entladen. R geht von Port nach GND.
    Zeitmessung: Timer1 wird auf 0 gesetzt und in dem Moment gestartet, wo man anfängt, den C zu entladen. Den Ausgang des AC konfiguriert man zum eingang des InputCapture. In dem Moment, wo der AC seine Polarität wechselt, wird der Stand von Timer1 im ICR1 gemerkt. Die so gemessene Zeit ist direkt proportional zum C (AFAIR bis auf 4 Taktzyklen Versatz). Im Faktor stecken noch die Taktfrequenz, R und ln(2).

    Das ganze geht bestimmt auch anders rum: C entladen und über einen AC-Pin durch aktiviertem Pullup aufladen. Die Pullups liegen so bei 50-80kOhm, dürften also zu klein sein. Dann könnte man den Entlade-R sparen.

    ::EDIT::

    Den Eingangswiderstand kannst du mit mehreren 100 MOhm oder einigen GOhm ansetzen.
    Disclaimer: none. Sue me.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    07.11.2005
    Beiträge
    20
    Hi,

    wir hatten wohl gerade zeitgleich geschrieben!

    Zitat Zitat von SprinterSB
    Wenn ich's richtig verstehe, willst du nur ein binäres on/off messen können und nicht die Umgebungshelligkeit?
    Genau das! Mit Veränderung der Meßzeit könnte ich dann sogar den Umschaltzeitpunkt hell/dunkel bestimmen bzw. festlegen.

    Aber sag mal, habe ich da etwas übersehen, oder hat der 2343 keinen Analog-Komparator? Einen 2313 habe ich (noch) nicht.

    Ich habe nun nochmal das Datenblatt des AT's durchgearbeitet und dabei folgendes gelesen:

    I/O Pin Pull-up 30 - 150 kOhm
    und

    Input Leakage Current I/O Pin (Vcc = 6 V) 8 µA
    Aus letzterem ergäbe sich ein Ri von genau 750 kOhm!

    Bleibt nur die Frage, wie bekomme ich den Pin zwecks Entladung auf Masse ohne daß er danach als Eingang geschaltet dieses Setzen auf '0' als Eingangswert interpretiert?!?

    Grummel, grübel...

    Viele Grüße,

    Radio Eriwan

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Das Entladen geht wie gesagt durch hochohmig-schalten des Pins. Entladen wird über einen R parallel zum C, der beim Aufladen ja nicht weiter stört. Bei den Größen geht das Entladen allerdings *sehr* schnell, der C einer LED liegt wie gesagt in Bereich von einigen pF. Wie groß die Kapazitätsänderung dC/dI ist hab ich auch keinen Schimmer (I=Intensität). Jedenfalls ist das stark anhängig von der LED und ihrer Temperatur, evtl ist die Kapazität auch spannungsabhängig.

    Zeitmessung geht evtl auch über den INT0. AC scheint das Winz-Teil keinen zu haben: LED laden, INT0 scharf machen, Port auf IN ohne pullup. Polling würd ich nicht empfehlen, sondern über Interrupt, weil du dann die Zeit kennst zwischen INT0-IRQ und Auslesen bzw Anhalten des Timers.

    Zu den Werten wie Input Leakage Current etc kann ich nix sagen, sind vermutlich nur Maximalwerte und unterliegen zudem einer recht starken Streuung, wie die Pullups auch.

    Evtl gehen auch andere Aufbauten... mal die Brainware 1.0 ankurbeln
    Disclaimer: none. Sue me.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    07.11.2005
    Beiträge
    20
    Hi Sprinter,

    was genau meinst Du mit "hochohmig-schalten des Pins"?

    Wenn ich jetzt mal Dein Beispiel nehme:

    Ich schalte der LED (Kapazität sagen wir mal beleuchtet 10 pF) einen 1 MOhm Widerstand parallel. Ri des µ-Controllers nehmen wir mal mit 100 MOhm an und vernachlässigen selbiges. Dann würde eine vollständige Entladung bei Beleuchtung ca. 50 µs dauern. Wäre also noch gut zu erfassen.

    Ich habe nur Schwierigkeiten, daß als Programm umzusetzen. Pin auf 'High' setzen ist klar, danach dann einfach nur als Eingang mit 'Config Portb.4 = Input' und 'An_oder_aus = Pinb.4'? So hatte ich das bisher gemacht, leider ohne Erfolg.

    Mit den ganzen INT's stehe ich nämlich noch ein wenig auf Kriegsfuß...

    Es grüßt...

    ...Radio Eriwan

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Also mit BASIC kann ich dir net helfen und was sich hinter dem ominösen Config verbirgt. Meine BASIC-Zeiten sind spätestens siet den Anfängen von C64 passé.

    Die I/Os der AVRs kannst du auf 2 Arten als IN verwenden: Mit pullup und ohne. Ohne pullup ist das ganze hochohmig.

    IN, highZ: DDRx.y=0, PORTx.y=0 (default)
    IN+pullupDRx.y=0, PORTx.y=1

    Welche SFRs man anfassen muss, um den INT0 einzustellen, kannst du im Datenblatt finden. Am transparentesten wär es, die SFRs dann so zu setzen, wie es im Datenblatt steht. Welche Zauberworte man BASIC da zuflüstern muss -- keine Ahnung. Vielleicht geht das ja auch in BASIC direkt hinzuschreiben?
    Disclaimer: none. Sue me.

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    07.11.2005
    Beiträge
    20
    Hi Sprinter,

    ich hatte in meinem Programm auch mal die Pullup's weggelassen, ging leider trotzdem nicht.

    Ich vermute mal, daß das vorherige Setzen des Ausganges auf '1' das Problem ist. Beim Umschalten auf Eingang bleibt sie wohl im Register und erscheint dann als Eingangswert. Wenn ich nämlich statt einer '1' eine '0' ausgeben lasse, dann lies er die ein. Merkwürdig!

    Mit den INT's werde ich mich nochmal speziell beschäftigen.

    Mal schauen, ob ich das doch noch irgendwie gelöst bekomme...

    Danke für Deine Hilfe!

    Viele Grüße,

    Radio Eriwan

  10. #10
    Gast
    Config Portb = &B00011000 'Grundzustand einstellen -> Pins als Eingänge(ausser 3,4)
    Portb = &B11100111 'Pullup-Widerstände zuschalten

    waitms 1000 = wait 1

    spart speicher und ablaufzeit.
    mfg psft

Seite 1 von 5 123 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •