Wie funktionieren digitale Klimmzüge?

Ich habe eine lahme Frage. Wie funktionieren digitale Klimmzüge? Ich frage, weil ich den DHT11-Treibercode nicht verstehe. Beispielcode:

bcm2835_gpio_write(pin, HIGH); usleep(500000); // 500 ms bcm2835_gpio_write(pin, LOW); usleep(20000); Es sendet das Startsignal an DHT11, aber es muss 500 ms lang LOW und dann 20 us lang HIGH sein, aber hier werden die Signale invertiert. Also, warum funktionieren Klimmzüge? Schema:

Sind Sie sicher, dass Sie den richtigen Treibercode haben? Ich sehe den Treibercode, den Sie hier erwähnen, nicht: github.com/adafruit/DHT-sensor-library
In diesem Code ändern sie den Treibermodus explizit auf Input, wenn sie den Pullup hochziehen lassen, und auf Output, wenn sie ihn überschreiben möchten.
@caveman Das ist Arduino-Code. Ich brauche Raspberry Pi-Code.

Antworten (3)

Der DHT11 ist ein Feuchtigkeits- und Temperatursensor, der eine Single-Wire-Kommunikation zwischen dem Mikrocontroller und dem Sensor verwendet.

Geben Sie hier die Bildbeschreibung ein

Im obigen Diagramm ist der 5K-Widerstand der Pullup-Widerstand, der mit Vdd (Stromversorgung) verbunden ist. Er hält die DATA-Leitung in einem hohen (1) Zustand, wenn keine Signale von beiden Enden der DATA-Leitung vorhanden sind.

Wenn der Mikrocontroller Daten an den Sensor senden möchte, treibt er die Leitung für eine 0 auf Masse (dies wird als "Senken" bezeichnet), und für eine 1 verlässt er die Leitung einfach in einen Hochimpedanzmodus und lässt den Pullup-Widerstand treiben die Linie hoch.

Wenn der Sensor Daten an den Mikrocontroller zurücksendet, wird der Mikrocontroller die E/A-Leitung ebenso als hochohmigen Eingang konfigurieren. Dadurch kann der Sensor Daten senden, indem er die Leitung nach Bedarf für eine 0 niedrig pulsiert. Er treibt die Leitung auch nicht hoch, sondern lässt den Widerstand hochziehen.

Der "normale" Zustand für jedes Ende der DATA-Leitung besteht also darin, dass sowohl der Mikrocontroller als auch der Sensor ihre Pins in einem hochohmigen Zustand haben und die Leitung nur bei Bedarf auf Masse treiben, um an das andere Ende zu senden.

Ein Pull-up wird verwendet, um ein Signal auf einen hohen Zustand zu treiben, beispielsweise Vdd, wenn kein Treiber, der in der Lage ist, das Signal hoch zu treiben, in der Schaltung/dem Netz/der Vorrichtung, die das Signal ausgibt, verfügbar ist. Ein Beispiel für einen solchen Ausgang wäre ein Open-Drain-Ausgang.

Die Idee besteht darin, einen Widerstand zwischen dem Signal und Vdd zu verwenden, bei dem der Wert des Widerstands schwach genug ist, damit das Signal in den niedrigen Zustand (GND in meinem Beispiel) gezogen werden kann, wenn es von der Ausgangsschaltung niedrig angesteuert wird. Wenn das Signal nicht niedrig angesteuert wird, wird es unter Verwendung des schwachen Widerstands auf seinen hohen Zustand hochgezogen. Ich neige dazu, Widerstandswerte von 10k oder 47k zu verwenden.

Die gleiche Argumentation gilt für Pulldowns, aber dort möchten Sie das Signal mit einem schwachen Widerstand niedrig treiben.

Hier ist ein bisschen mehr von dem Code. Der Pullup ist während der fraglichen Zeilen grundsätzlich nicht aktiv, da der gpio-Pin als Ausgang gesetzt ist. Später wird der Pin jedoch als Eingang festgelegt. An diesem Punkt erstellt der Pullup einen Standardzustand von 1. Aber der Sensor kann und wird ihn nach unten ziehen, um Daten an den Prozessor zurückzusenden.

  // Set GPIO pin to output
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);  <<----OUTPUT, so pullup doesn't really do anything.
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);  // Why twice?  Probably just sloppy coding.

  bcm2835_gpio_write(pin, HIGH);
  usleep(500000);  // 500 ms
  bcm2835_gpio_write(pin, LOW);
  usleep(20000);

  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); <<---- INPUT, pullup is significant now.

  data[0] = data[1] = data[2] = data[3] = data[4] = 0;

  // wait for pin to drop?
  while (bcm2835_gpio_lev(pin) == 1) {
    usleep(1);
  }

  // read data!
  for (int i=0; i< MAXTIMINGS; i++) {
    counter = 0;
    while ( bcm2835_gpio_lev(pin) == laststate) {
        counter++;
        //nanosleep(1);         // overclocking might change this?
        if (counter == 1000)
          break;
    }

Als Nebenbemerkung zeigt ein schnelles Durchlesen dieses Codes, dass er etwas mehr zusammengehackt ist als der Arduino-Sensortreiber in ihrem Git-Baum. Wenn dies nicht funktioniert, wäre es wahrscheinlich sinnvoll, den Arduino-Code neu zu schreiben, indem er portiert wird.