LED als Sensor an Port Pin

Gast #3125653
Lesenswert?

Hallo,
ich versuche gerade den in folgendem Paper genannten Aufbau zu 
implementieren:
http://www.merl.com/publications/docs/TR2003-35.pdf

Dabei geht es darum eine bidrektionale kommunikation mittels LEDs 
aufzubauen. Soweit so gut, ich möchte erstmal eine LED als Empfänger 
betreiben.

Hier sieht man noch einmal wie das ganze funktioniert:
http://people.duke.edu/~sd78/projectHub/projects/optoelectronics/principle_clip_image002.jpg

Ich verstehe was dabei passiert nun habe ich folgenden code dazu 
geschrieben:

Ein Timer ISR wird alle 100µs ausgelöst und soll dann die genannte 
"Entladungsmessung" durchführen, in diesem Beispiel wird ein Zähler 
solange erhöht bis die Entladung fertig ist.

ISR(TIMER0_COMPA_vect) {
  DDRC |= (1<<(PC1));
  PORTC |=  (1<<(PC1));
  PORTC &= ~(1<<(PC0));
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
  DDRC &= ~(1<<(PC0));
  if((PORTC&(1<<PC0))) count++;
}

Die LED hängt mit der Kathode über einen Widerstand an PC0, Anode an 
PC1. Das Problem ist nun, der Zähler läuft einfach hoch ohne dass sich 
irgendetwas verändert hat. Wenn ich messe liegen an PC0 auch einfach 
noch 5V an nachdem die Pinrichtung umgedreht wurde. Vielleicht hat 
jemand eine Idee was ich falsch mache.
#3125701
Lesenswert?

Hmm

Das hier
1
An inexpensive way to make a photodetector out of an LED is to tie the
2
anode to ground and connect the cathode to a CMOS I/O pin driven high.
3

4
This reverse biases the diode, and charges the capacitance. Next switch
5
the I/O pin to input mode, which allows the photocurrent to discharge
6
the capacitance down to the digital input threshold. By timing how
7
long this takes, we get a measurement of the photocurrent and thus
8
the amount of incident light.

Hmm. das deckt sich aber nicht mit dem was du programmiert hast.

Nimm dir die Bilder her und schreib dir mal deine Pin-Bezeichnungen 
dazu. Und dann geh die Bilder (bzw. die Beschreibung) durch und sieh dir 
an, in welcher Reihenfolge du welchen Portpin wie beschalten musst. Und 
erst dann, wenn du dir 100% sicher bist, dass du die Reihenfolge der 
Ereignisse hast, erst dann setzt du dich hin und programmierst das.
Im Idealfall schreibst du dir in Stichworten die korrekte Reihenfolge 
tabellenarrtig auf und überprüfst die 3 mal gegen den Text bzw. die 
Bilder.
Gast #3125734
Lesenswert?

korrekt da war allerdings noch etwas falsch:
PC0 ---RRRR---]<----- PC1

ISR(TIMER0_COMPA_vect) {
  DDRC |= (1<<(PC0));
  DDRC |= (1<<(PC1)); // beide Ausgänge

  PORTC |=  (1<<(PC1));  // Phase EMIT
  PORTC &= ~(1<<(PC0));

  asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");

  PORTC |=  (1<<(PC0));  // Phase Reverse Bias
  PORTC &= ~(1<<(PC1));

  asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
  // Phase Discharge
  DDRC &= ~(1<<(PC0)); // Eingang
  DDRC |= (1<<(PC1)); // Ausgang

  if((PORTC&(1<<PC0))) count++; // PC0 ist noch HIGH dann zählen
}

nochmal angepasst.
#3125746
Lesenswert?

Glorb schrieb:
> korrekt da war allerdings noch etwas falsch:
> PC0 ---RRRR---]<----- PC1
>
> ISR(TIMER0_COMPA_vect) {
>   DDRC |= (1<<(PC0));
>   DDRC |= (1<<(PC1)); // beide Ausgänge
>
>   PORTC |=  (1<<(PC1));  // Phase EMIT
>   PORTC &= ~(1<<(PC0));
>
>   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
>
>   PORTC |=  (1<<(PC0));  // Phase Reverse Bias
>   PORTC &= ~(1<<(PC1));
>
>   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
>   // Phase Discharge
>   DDRC &= ~(1<<(PC0)); // Eingang
>   DDRC |= (1<<(PC1)); // Ausgang
>
>   if((PORTC&(1<<PC0))) count++; // PC0 ist noch HIGH dann zählen

PINC

> }
1
Next switch
2
the I/O pin to input mode, which allows the photocurrent to discharge
3
the capacitance down to the digital input threshold. By timing how
4
long this takes,

Also
zuerst auf Input schalten
dann Zeit messen.

Du schaltest auf Input und siehst gleich am Pin nach.
Wie ich schon sagte: Schreib dir doch erst mal in Stichworten zusammen 
wie die Reihenfolge der Ereignisse sein muss
Gast #3125763
Lesenswert?

Ich verstehe es so wie auf den Bildern gezeigt: Reverse Bias und dann 
Input. Mein Fehler ist vielleicht, dass ich das immer wieder im Timer 
stattfinden lasse. Was ich eigentlich zum Test erst einmal zeigen will: 
Das Programm läuft, die LED ist unbeleuchtet, nichts passiert. Sobald 
diese beleuchtet wird soll der Zähler hochzählen bis die LED wieder 
unbeleuchtet ist.
#3125768
Lesenswert?

Glorb schrieb:
> Ich verstehe es so wie auf den Bildern gezeigt: Reverse Bias und dann
> Input.

Schau dir nicht nur die Bilder an. Lies auch den Text!
Denn wann gewartet wird, siehst du in den Bildern nicht.

Das steht eindeutig:

zuerst wird auf reverse geschaltet, wodurch die 'Kapazität' geladen 
wird. Ok. da wirst du ein bischen warten müssen

Danach auf Input schalten

und jetzt hängt es davon ab, wie lange es dauert bis der Eingangspin 
wieder auf 0 gefallen ist, ob man davon ableitet das die LED beleuchtet 
ist oder nicht.

Die Zeit NACH dem Umschalten auf Input ist das entscheidende!
Gast #3125902
Lesenswert?

d.h. ich habe etwa folgendes modell:

Timer_ISR() {
   if((PINC&(1<<PC0))) count++;
}


void main() {
   timer_setup();

   DDRC |= (1<<(PC0));
   DDRC |= (1<<(PC1));
   while(1) {
      cli();
      PORTC |=  (1<<(PC0));  // Phase Reverse Bias
      PORTC &= ~(1<<(PC1));
      asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
      DDRC &= ~(1<<(PC0));
      sei();
   }
}

ich stehe noch etwas auf dem schlauch wie man sieht, pseudocode zum 
ablauf ist willkommen.
Gast #3126044
Lesenswert?

ich habe einen Erfolg zu vermelden :).

Meine version ist noch nicht genau das was ich haben will aber es 
scheint zu gehen:
void main() {
  uart_init();

measure:
  count = 0;

  DDRC |= (1<<(PC0));
  DDRC |= (1<<(PC1)); // beide Ausgänge

  PORTC |=  (1<<(PC0));  // Phase Reverse Bias
    PORTC &= ~(1<<(PC1));

  asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");

  DDRC &= ~(1<<(PC0));
  PORTC &= ~(1<<(PC0)); // das war wichtig!

  while((PINC&(1<<PC0))) count++;

  if(count>5000) goto measure;

  {
    char buffer[32];
    sprintf(buffer,"count: %d",count);
    put_stamped(buffer);
  }

  goto measure;
  while(1) {}
  return 0;
}


Auf jedenfall kann ich jetzt eine Anzahl sehen wenn die LED entladen 
wird, halte ich eine Taschenlampe drauf ist die Zahl klein, im 
Tageslicht ist sie groß. Wie es sein sollte. Natürlich muss ich das 
ganze nun noch auf den Timer umbauen!
#3126885
Lesenswert?

Moin moin...

Hab mal ein paar Versuche dazu gemacht:
(Die Zahlenwerte in Klammern wurden mit untenstehendem, kleinen Prog. 
emittelt)

1.)Bestrahlung mit 60W Reflektor-Glühlampe

a) mit roten LEDs ging garnix.
b) gelbe LEDs: gut (dunkel ca. 1640; max. hell: 5)
c) grüne LEDs: gut (dunkel ca. 1640; max. hell: 5)


2.) LED mit LED bestrahlen (Kopf an Kopf)
Vorweg: eine rote LED als Sender, zeigt keine Wirkung bei beliebigen 
Empfänger-LEDs.

a) rote LED als Empfänger zeigt auch keine Wirkung, egal womit sie 
bestrahlt wird. Selbst mit nem roten Laserpointer bestrahlt, zeigte sie 
keine verwertbare Reaktion.

Empf.-LED, bestrahl mit anderer LED:

b) gelb, mit gelb bestrahlt = gut  (dunkel ca. 1640; max.hell: ca. 480)

c) grün, mit grün bestrahlt = besser  (dunkel ca. 1640; max.hell: ca. 
300)

d) gelb, mit grün bestrahlt = beste (dunkel ca. 1640; max.hell: ca. 200)

e) grün, mit gelb bestrahlt = s. schlecht (dunkel ca. 1640; max.hell: 
ca. 1610)


Fazit:
2c) grün/grün ist vielversprechend, zumal damit eine bidirektionale 
optische Kopplung, durch beidseitige Umpolung der LEDs, möglich wird...



++++++++++++++++++++++++++++++++++++++++++
Das Testprogramm in Bascom, mit Ausgabe auf Terminalprog über 
USB/serial(TTL) mit TX an PinB.4..:

$regfile = "attiny85.dat"
$crystal = 1000000
$hwstack = 40
$swstack = 16
$framesize = 32


Ddrb = &B000010
Dim A As Word

Open "ComB.4:1200,8,N,1,inverted" For Output As #1

Do

  Set Portb.0
  Waitus 40
  Reset Portb.0

   While Pinb.0 = 1
    Incr A
   Wend

 Print #1 , "Counts:    " ; A
 A = 0

Loop

Close #1
End

++++++++++++++++++++++++++++++++++++++++++++++

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren