Motivation

In meiner Bastelkiste liegen viele Dioden herum. Neue unbenutzte, schon einmal in einem Projekt benutzt, ausgelötet, … Aber funktionieren die noch? Mit einem Allround-Bauteile-Tester wie diesem

Bauteile-Tetser

kann man die wunderbar durchchecken. Bei einzelnen Dioden ist das auch recht praktisch. Wenn man jedoch viele hintereinander testen will, ist das eine sehr aufwändige Beschäftigung. Diode einspannen, Knopf drücken, Selbsttest und Splash-Screen abwarten, Test abwarten, Diode wieder ausspannen ...

Wenn man weiß, dass es sich um eine Diode handelt, geht es mit einem Arduino, einem Widerstand deutlich einfacher.

In­halts­ver­zeich­nis

Features

Theorie

Schaltung

Status-Anzeige

Testschritte

Schritt 1: Kurschluss erkennen

Schritt 2: Diode in Durchlassrichtung erkennen

Schritt 3: Keine oder durchgebrannte Diode erkennen

Schritt 4: Diode erkennen

Software

Klasse Voltage

Klasse Adc (AdcClass)

Methode readVcc

Methode readAvgmv

Hauptprogramm (DiodenTester.ino)

Funktion setup

Funktion test

Funktion loop

Download

Features

Was soll der Tester können? Er muss erkennen, ob das Bauteil in der einer Polungsrichtung sperrt und in der anderen leitet. Das muss angezeigt werden. Am häufigsten werden Silizium-Dioden vorkommen. Die haben eine Durchlassspannung UF von etwa 0,7 V. Hat das Bauteil einen anderen Wert, soll das signalisiert werden. Dann kann man das Bauteil mit dem Allround-Tester noch einmal nachprüfen. Nach Möglichkeit soll auch eine Schottky-Diode erkannt werden. Die  haben ein UF von 0,4 V oder darunter.

Ganz wichtig: Man muss nicht auf die Polung der Diode achten müssen. Einfach das Bauteil an zwei Messkontakte halten, soll genügen.

Theorie

Zwei Pins schalten die Diode in Serie mit einem Widerstand abwechselnd in Sperr- und Durchlassrichtung. Die Spannung werden über drei ADC-Kanäle ausgewertet. Folgende Möglichkeiten müssen berücksichtigt werden:

  1. Diode in Durchlassrichtung
  2. Diode in Sperrrichtung
  3. Diode defekt, Kurzschluss
  4. Keine Diode angeschlossen oder defekt (durchgebrannt)

Die letzten beide Möglichkeiten lassen sich nicht unterscheiden.

Damit ergibt sich folgende Situation für die Polung der Pins:

Da auch Standard-Si-Dioden (UF = 0,7 V) von anderen Dioden unterschieden werden sollen, reicht leider nicht, nur U2 zu messen. Die Ausgangsstufen der Pins besitzen Innenwiderstände, an denen Spannungen von mehreren 100 mV abfallen können.

Schaltung

Die Schaltung ist extrem einfach. Beim AVR können auch die Spannungen, die an den Pins anliegen, gemessen werden, wenn die Pins im Output-Modus geschaltet sind. Man benötigt also keine weiteren Pins. Die obige Abbildung zeigt damit die vollständige Schaltung. Ein Widerstand zwischen Pin A0 (= ADC1 in der Grafik) und A1 (= ADC2) und zwei Kontakte an A1 und A2 (= ADC3). Über die Software können auch andere ADC-Pins eingestellt werden.

Zur Anzeige dienen zwei LEDs, die eingebaute LED (LED_BUILTIN an Pin 13) und die LED an TX der seriellen Schnittstelle.

Insgesamt wird also nur ein zusätzliches Bauteil, ein Widerstand als Vorwiderstand benötigt. Es wurde ein Widerstand von 470Ω gewählt. Damit fließen durch die Diode etwa 10 mA.

Status-Anzeige

Situation Anzeige
Keine Diode angeschlossen oder defekt (durchgebrannt) Beide LEDs aus
Diode defekt, Kurzschluss Beide LEDs an
Si-Diode (UF = 0,7 V) Beide LEDs blinken synchron
Andere Diode (UF ≠ 0,7 V) Beide LEDs blinken abwechselnd

So sieht es auf dem Steckbrett aus:

Testschritte

Schritt 1: Kurschluss erkennen

Gleichgültig welche Situation vorliegt, ist bei einem Kurzschluss U2 immer gleich U3.

Schritt 2: Diode in Durchlassrichtung erkennen

  Der blaue markierte Bereich ist erledigt und damit bereits ausgeschlossen.

Wenn U2 kleiner als U1 ist, liegt eine in Durchlassrichtung geschaltete Diode vor:  UF = U2 - U3.

Es bleibt noch zu unterscheiden zwischen keine Diode angeschlossen und Diode in Sperrrichtung.

Schritt 3: Keine oder durchgebrannte Diode erkennen

Dazu müssen die Pins umgeschaltet werden. Wenn eine intakte Diode vorliegt, ist diese nun in Durchlassrichtung geschaltet.

Wenn U2 gleich U1 ist, ist keine oder eine durchgebrannte Diode angeschlossen.

Schritt 4: Diode erkennen

Übrig bleibt nur noch der Fall, dass eine Diode -jetzt in Durchlassrichtung- vorliegt: UF = U3 - U2.

Software

Die Software sollte möglichst übersichtlich werden. Deshalb bietet es sich an möglichst viel in Klassen zu verstecken und im Hauptprogramm nur den Test zu steuern.

Klasse Voltage

Es wird mit Messwerten gearbeitet. Messwerte unterliegen immer einer Streuung. Das macht den Vergleich schwierig. Man löst das Problem, indem man Werte, die sich nicht mehr als um einen Wert ε (Epsilon) unterscheiden, als gleich ansieht. Die Klasse Voltage dient dazu diese Vergleiche durch Operator-Überladung zu kapseln.

// Repräsentiert eine Spannung in der Einheit mV
class Voltage {
public:
   uint16_t value;
   static const uint16_t epsilon = 50;

   Voltage() : value(0) {}
   Voltage(const uint16_t value) : value(value) {}

   bool operator== (Voltage& rhs) {
      if (rhs.value > value + epsilon) return false;
      if (value > rhs.value + epsilon) return false;
      return true;
   }
   bool operator<(const Voltage& l) { return value + epsilon < l.value; } // mindestens um epsilon kleiner
   bool operator>(const Voltage& l) { return value > l.value + epsilon; } // mindesten um epsilon größer

   operator int() const { return value; }
   Voltage& operator+=(const Voltage& rhs) { this->value += rhs.value; return *this; }
   Voltage& operator-=(const Voltage& rhs) { this->value -= rhs.value; return *this; }
};

inline Voltage operator+(Voltage lhs, const Voltage& rhs) { lhs += rhs; return lhs; }
inline Voltage operator-(Voltage lhs, const Voltage& rhs) { lhs -= rhs; return lhs; }

Somit werden Ausdrücke wie (U2 == U1 + U3) möglich. Der Ausdruck liefert true, wenn U2 sich nicht mehr als ε von der Summe U1+U3 unterscheidet.

Klasse Adc (AdcClass)

Diese Klasse übernimmt die Spannungsmessung per ADC. Die Parameter zur Ansteuerung der Wandler sind als enum class definiert (AdcChannel, AdcReference). Dadurch erreicht man Typsicherheit auch für Enumerationen. Man erkennt also schon zur Kompilierungszeit, wenn man falsche Parameter angegeben hat und muss sich nicht zur Laufzeit wundern, warum es nicht funktioniert.

Methode readVcc

Die im Programm benutzen Funktionen sind readVcc zur Messung der Versorgungsspannung über die intern bereit gestellte Bandgap-Spannung von 1,1 V. Für die Messung an den Testpunkte ist Vcc die Referenzspannung. Es wird der Mittelwert aus mehreren Messungen gebildet.

uint16_t AdcClass::readVcc() const {
   uint8_t i;
   uint16_t result = 0;
   ADMUX = 0x0E       // Bandgap als Input wählen
      | (1 << REFS0); // Referenz: AVCC

   if (!(ADCSRA = (1 << ADEN))) { // falls ausgeschaltet
      ADCSRA = (1 << ADEN) | ADC_PRESCALER_MASK; // ADC einschalten
      delay(10);
   }
   ADCSRA |= ADC_PRESCALER_MASK;


   // Dummy-Readout zur Stabilisierung der Bandgap-Spannungsquelle
   for (i = 0; i < VccDummyReads; i++)
   {
      ADCSRA |= (1 << ADSC);        // eine ADC-Wandlung
      while (ADCSRA & (1 << ADSC)); // auf Abschluss der Konvertierung warten
   }

   // Eigentliche Messung - Mittelwert aus VccReadCount aufeinanderfolgenden Wandlungen
   // Der Messwert liegt zwischen etwa 220 bei 5V und 380 bei 3 V
   for (i = 0; i < VccReadCount; i++)
   {
      ADCSRA |= (1 << ADSC);        // eine Wandlung "single conversion"
      while (ADCSRA & (1 << ADSC)); // auf Abschluss der Konvertierung warten
      result += ADCW;               // Ergebnisse aufaddieren
   }

   uint32_t r = (uint32_t)VccVbg * 1023 * VccReadCount / result;

   return r;
}

VccDummyReads (=10), VccReadCount (=4) und VccVbg (=1100) sind als Konstanten hinterlegt (weitere Details im Code).

Bei dem Testgerät lag Vcc bei etwa 4,8 V. Das entspricht der USB-Spannung von 5,0 V abzüglich der Durchlassspannung einer Schottky-Polungsschutz-Diode.

Methode readAvgmv

readAvgmv dient zum Auslesen von Spannungswerten. Auch hier wird eine Mittelwertbildung vorgenommen.

Voltage AdcClass::readAvgmv(const AdcChannel channel, uint8_t count) const {
   // vcc entspricht einem ADC-Wert von 1023;
   uint32_t avg = readAvg(channel, count);
   return avg * refVoltage / 1023;
}

uint16_t AdcClass::readAvg(const AdcChannel channel, uint8_t count) const {
   uint8_t  i;
   uint16_t result = 0;
   if (count > 63) count = 63;
   if (count == 0) count = 1;

   if (!(ADCSRA = (1 << ADEN))) { // falls ausgeschaltet
      ADCSRA = (1 << ADEN) | ADC_PRESCALER_MASK; // ADC einschalten
      delay(10);
   }
   ADCSRA |= ADC_PRESCALER_MASK;

   // Kanal des Multiplexers wählen
   ADMUX = ((uint8_t)analogReference << REFS0) | (uint8_t)channel;

   // Den ADC initialisieren und eine Blind-Messung machen
   ADCSRA |= (1 << ADSC);
   while (ADCSRA & (1 << ADSC));

   // Jetzt 'AdcAvgCount' mal die analoge Spannung and Kanal 'channel' auslesen
   // und dann Durchschnittswert ausrechnen.
   for (i = 0; i < count; i++)
   { // Eine Wandlung
      ADCSRA |= (1 << ADSC);
      // Auf Ergebnis warten...
      while (ADCSRA & (1 << ADSC));

      result += ADCW;
   }
   // Mittelwert zurückliefern
   return result / count;
}

Hauptprogramm (DiodenTester.ino)

Alle relevanten Parameter sind als Konstanten hinterlegt:

const uint8_t pin1 = A0;
const AdcChannel channel1 = AdcChannel::ADC0; // Pin A0

const AdcChannel channel2 = AdcChannel::ADC1; // Pin A1

const uint8_t pin3 = A2;
const AdcChannel channel3 = AdcChannel::ADC2; // Pin A2

const uint8_t ledTx = 1; // TX-Pin
const uint8_t ledBi = LED_BUILTIN; // eingebaute LED

bool toggle = false; // zum Blinken
Voltage USi(700);    // Durchlassspannung Si-Diode

Funktion setup

In setup müssen nur die Pins konfiguriert werden:

void setup() {
   pinMode(pin1, OUTPUT);
   pinMode(pin3, OUTPUT);
   pinMode(ledBi, OUTPUT);
   pinMode(ledTx, OUTPUT);
}

Funktion test

In test werden die Spannungswerte ermittelt und ausgewertet.

// Führt den Test durch. Liefert:
// -1: Keine Diode
// -2: Kurzschluss
// >0: UF
int test() {
   uint16_t vcc = Adc.readVcc();
   Adc.setReference(AdcReference::Vcc, vcc);

   // Schritt 1:
   digitalWrite(pin1, HIGH);
   digitalWrite(pin3, LOW);
   auto U2 = Adc.readAvgmv(channel2, 16);
   auto U3 = Adc.readAvgmv(channel3, 16);
   if (U2 == U3) { // Kurzschluss
      return -2;
   }

   // Schritt 2:
   auto U1 = Adc.readAvgmv(channel1, 16);

   if (U2 < U1) { // leitende Diode
      return U2 - U3;
   }

   // Schritt 3:
   // Jetzt kann noch sperrende oder keine Diode angeschlossen sein
   // Polung umkehren
   digitalWrite(pin1, LOW);
   digitalWrite(pin3, HIGH);
   U1 = Adc.readAvgmv(channel1, 16);
   U2 = Adc.readAvgmv(channel2, 16);
   U3 = Adc.readAvgmv(channel3, 16);

   if (U2 == U1) {
      return -1;
   }

   // Schritt 4:
   return U3 - U2;
}

Funktion loop

Es bleibt nur noch übrig, die LEDs zur Anzeige des Ergebnisses zu schalten:

void loop() {
   delay(200);  // Bestimmt die Blink-Frequenz
   toggle = !toggle;

   int result = test();
   if (result == -2) { // Kurzschluss, beide LEDs an
      digitalWrite(ledBi, HIGH);
      digitalWrite(ledTx, LOW);
      return;
   }

   if (result == -1) { // Keine Diode, beide LEDs aus
      digitalWrite(ledBi, LOW);
      digitalWrite(ledTx, HIGH);
      return;
   }

   auto UF = Voltage(result); // Umwandeln in Spannung zum Vergleichen

   if (UF == USi) { // Si-Diode, LEDs blinken synchron
      digitalWrite(ledBi, toggle);  // LED gegen Masse
      digitalWrite(ledTx, !toggle); // LED gegen Vcc
   }
   else {  // andere Diode, LEDs blinken abwechselnd
      digitalWrite(ledBi, toggle); // LED gegen Masse
      digitalWrite(ledTx, toggle); // LED gegen Vcc
   }
}

Download

Das Visual-Micro-Projekt zum Download. Arduino-IDE-Nutzer benutzen einfach nur die Dateien im Verzeichnis DiodenTester.