PWM-Eingang in Raspberry Pi


9

Gibt es eine Möglichkeit, ein PWM- Signal von den Pins des Raspberry Pi zu lesen ?

Ich habe versucht, es zu googeln, aber ich habe nur die PWM- Ausgabe und nicht die Eingabe gefunden .

Antworten:


4

Die kurze Antwort: Sie können PWM auf Raspberry Pi NICHT zuverlässig lesen.

Das Lesen von PWM erfordert eine Genauigkeit von Mikrosekunden (es sei denn, Sie lesen eine sehr, sehr langsame PWM). Dies ist auf Raspberry Pi für Userland-Software nicht verfügbar, ohne an Kernelmodulen zu basteln.

Der einfachste Weg, PWM zu erfassen, besteht darin, einen billigen (<$ 0,5) Mikrocontroller mit seriellem oder I 2 C- Ausgang zu erwerben, ihn an Ihren Raspberry Pi anzuschließen und die tatsächlichen Werte vom Mikrocontroller zu lesen. Dies funktioniert sehr zuverlässig und ist sehr präzise.


1
Irgendeine Idee, wo man einen solchen IC bekommt?
Pepijn

@Pepijn Was Sie suchen, ist ein Analog-Digital-Wandler (ADC). Eine sehr häufige, die ich sehr häufig verwende, ist die 8-Kanal-10-Bit-Einheit MCP3008 , und eine andere, die ich permanent auf meinem Gerät habe, um Pi für meine Perl-Software zu testen , ist die 4-Kanal-16-Bit-Einheit ADS1115 . Letzteres erfordert ein wenig Lötarbeit, Ersteres nicht. Für die Verwendung dieser beiden Einheiten (C, Python, Perl usw.) stehen viele Codebeispiele zur Verfügung. Wenn Sie also keine eigenen schreiben möchten / können, sollte es trivial sein, loszulegen.
Stevieb

Jeder einfache Mikrocontroller reicht aus. Ich habe früher Microchip-Produkte für solche Dinge verwendet. Das Aufkommen des Arduino hat die AVR-Chips wieder in Popularität gebracht. Jetzt benutze ich nur noch ein kleines Breakout-Board mit einem Mikrocontroller und der Lebenserhaltung, die der Chip benötigt. Mein Favorit ist die Teensy 3.x-Serie.
NomadMaker

2

Dies ist eine interessante Frage, bei der Sie zu Recht sagen, dass die Google-Suche keine offensichtliche Lösung bietet! (Ich vermisse die Tage, an denen Google innerhalb von Sekunden alles beantworten konnte, was ich für meine Ausbildung / Aufgaben wissen wollte.)

Ich gehe davon aus, dass Sie die Prinzipien von PWM verstehen . Deshalb werde ich nicht darauf eingehen. Ich glaube jedoch, dass Sie theoretisch einen PWM-Wert auf einem normalen digitalen Eingangspin mit einer cleveren Codierung lesen können.

Ich gebe zu, dass ich dies nicht selbst versucht habe, aber Sie sollten in der Lage sein, die Zeit zu messen, in der der Pin hoch und die Zeit, in der er niedrig ist (was Ihnen Ihren PWM-Wert gibt), und dann die vom Lieferanten des Sensors bereitgestellte mathematische Formel zu verwenden um dies in den tatsächlichen Messwert umzuwandeln.

Diese Methode funktioniert bei einem ähnlichen Problem, bei dem ich die Pulslänge eines Ultraschallmoduls ablesen und dann in die Entfernung umwandeln musste. Zu den Problemen, die ich mir vorstellen kann, gehört die Gewährleistung zuverlässiger Messwerte!

Wenn Sie glauben, dass es helfen wird und Sie den Code sehen möchten, den ich für das Ultraschallmodul verwendet habe, sagen Sie es einfach und ich kopiere es weiter, wenn ich nach Hause komme.

Ich habe angefangen, den Code zu kopieren, aber aus irgendeinem Grund kann ich ihn auf der Website immer nur in einem kleinen Abschnitt kopieren (und ich bin zu faul, um meinen Pi aus der Garage zu holen). Hier ist also der Link dazu. Ignorieren Sie die meisten Funktionen unten, da sie sich auf die Verwendung des Moduls als Näherungssensor beziehen. http://pibot.webnode.com/products/ultrasonic-range-sensor/


Das wird gut sein, um den Code zu sehen, so dass ich eine Basis bekommen kann, um meinen eigenen Code zu starten. Wenn Sie hier einfügen können, bin ich sehr dankbar ^^
Caio Keto

Das Problem bei diesem Vorschlag ist, dass der Linux-Kernel Ihnen nicht genügend Zeit gibt, um typische RC-PWM-Arbeitszyklen (die normalerweise alle 16 Millisekunden 1000 bis 2000 Mikrosekunden betragen) mit ausreichender Genauigkeit zu lesen. Wenn wir einen Interrupt-Handler für einen GPIO-Pin-Wechsel installieren und den Zeitstempel bei High / Low-Übergängen in einem Kernelmodul erfassen könnten, wäre dies möglicherweise eine nützliche Lösung.
Jon Watte

2

Mit der piGpio C-Bibliothek kann ich eine ziemlich genaue Pulsweitenmessung durchführen: http://abyz.me.uk/rpi/pigpio/index.html

Mit dieser Bibliothek können Sie eine Rückruffunktion installieren, die bei jedem Kantenübergang auf einem GPIO-Pin ausgelöst wird und Ihnen für jeden Übergang einen Zeitstempel auf Mikrosekundenebene gibt. Denken Sie nicht, dass Sie sich bei der Genauigkeit von Mikrosekunden darauf verlassen können - aber meine Tests legen nahe, dass die Genauigkeit mindestens +/- 10 us beträgt, vielleicht sogar besser.

Viel besser als eine Besetztschleife auszuführen, die ein GPIO nach dem Levelwechsel abfragt.


+1 Es kann erwähnenswert sein, dass die Genauigkeit je nach CPU-Auslastung (insbesondere der einzelnen Kerne) variieren kann, ansonsten aber eine gute Antwort. :)
Jacobm001

1

Die lange Antwort: Sie können tatsächlich! (gut mit ein wenig Hilfe von unseren Freunden Widerstand und Kondensator)

Sie können einen PWM-Ausgang in einen analogen Spannungspegel (DAC) umwandeln und ihn mit dem ADC-Pin auf Ihrem Himbeer-Pi lesen.

Was Sie brauchen, ist ein 4k7-Widerstand und ein 0,1uF-Kondensator:

schematisch

simulieren Sie diese Schaltung - Schema erstellt mit CircuitLab

Das oben beschriebene einfache RC-Tiefpassfilter wandelt das PWM-Signal in eine Spannung um, die proportional zum Arbeitszyklus ist und von Ihrem Himbeer-Pi als Analogwert gelesen werden kann.


3
Der ADC-Pin? Und welches wäre das?
Ghanima

@ Ghana Nun, der neue Microsoft Lightning-Treiber befindet sich in der Entwicklung, erfüllt diesen Zweck jedoch recht gut (er ist auf ihren Seiten dokumentiert). Für das, was ich für BCM2837 gefunden habe, könnte es einen Hardware-ADC geben, der sich auf GPIO0 befindet (leider ist dieser nicht mit einem Header-Pin verbunden). Zumindest haben sie Hardware-PWM-Kanäle verbunden
Quest

0

Wenn Sie mit einer langsamen Antwort zufrieden sind, können Sie eine schnelle PWM durch Unterabtastung lesen. Lesen Sie einfach den GPIO in einer Schleife und wenden Sie einen Tiefpassfilter an. Die Wahrscheinlichkeit, in jedem Zyklus eine 1 zu lesen, ist proportional zur Impulsbreite. Ein einfach zu implementierendes IIR-Tiefpassfilter ist:

double acc=0.5;
const double k=0.01;
for(;;) {
  bool x=GPIO.read();
  acc+=k*(x?1:0-acc);
}

Wenn k abnimmt, verbessert sich die Auflösung, aber die Bandbreite nimmt ab.


0

Obwohl meine Antwort nicht von den Pins stammt, könnten Sie etwas verwenden, das auf einem Soundkarten-Oszilloskop basiert, um einen gepulsten Eingang zu lesen.

Menschen verwenden seit Jahren Soundkarten in Desktop-PCs, um Oszilloskope herzustellen. Es scheint, dass Sie mit einer modernen internen Soundkarte brauchbare Ergebnisse bis zu 10 kHz erzielen können. Mit einer über Raspberry Pi USB angeschlossenen Soundkarte ist Ihre maximale Frequenz möglicherweise niedriger.

Hier ist ein Beispiel für ein Soundkarten-Oszilloskop-Projekt für Linux: http://www.yann.com/de/diy-turn-your-gnulinux-computer-into-a-free-oscilloscope-29/09/2010.html


0

Dieses von mir geschriebene Python-Skript eignet sich gut zum Lesen von PWM-Signalen eines RC-Empfängers. Hochfrequenz-PWM-Signale funktionieren offensichtlich nicht, wie bereits erwähnt.

Ich habe die zehn Signalausgangspins des RC-Empfängers direkt mit den Raspberry GPIO-Pins verbunden. Der Empfänger wird über die + 5V- und GND-Pins des RPI mit Strom versorgt.

Ich habe das Skript vereinfacht, da es viele andere Dinge erledigt. Wenn Sie Fehler oder Reste finden, lassen Sie es mich wissen

import RPi.GPIO as GPIO
import time
import numpy as np
inPINS = [2,3,4,14,15,18,17,27,22,23]
smoothingWindowLength=4

def getTimex():
    return time.time()

GPIO.setup(inPINS, GPIO.IN)
upTimes = [[0] for i in range(len(inPINS))]
downTimes = [[0] for i in range(len(inPINS))]
deltaTimes = [[0] for i in range(len(inPINS))]

def my_callback1(channel):
  i = inPINS.index(channel)
  v = GPIO.input(inPINS[i])
  #GPIO.output(outPINS[0], v) # mirror input state to output state directly (forward servo value only) - don't set PWM then for this pin
  if (v==0):
    downTimes[i].append(getTimex())
    if len(downTimes[i])>smoothingWindowLength: del downTimes[i][0]
  else:
    upTimes[i].append(getTimex())
    if len(upTimes[i])>smoothingWindowLength: del upTimes[i][0]
  deltaTimes[i].append( (downTimes[i][-1]-upTimes[i][-2])/(upTimes[i][-1]-downTimes[i][-1]) )
  if len(deltaTimes[i])>smoothingWindowLength: del deltaTimes[i][0]

GPIO.add_event_detect(inPINS[0], GPIO.BOTH, callback=my_callback1)
GPIO.add_event_detect(inPINS[1], GPIO.BOTH, callback=my_callback1)

try:
  while True:
    ovl = deltaTimes[0][-smoothingWindowLength:] # output first pin PWM
    ov = sorted(ovl)[len(ovl) // 2] #ov = np.mean(ovl)
    print ov
    time.sleep(0.1)
except KeyboardInterrupt:
  GPIO.cleanup()

-3

Einfache Lösung mit hoher Genauigkeit:

Die Verwendung eines Arduino als iic-Slave oder UART-Gerät scheint einwandfrei zu funktionieren. Der Mikrocontroller kann die Informationen über die pulsIn-Methode lesen.

Für detaillierte Informationen: https://www.youtube.com/watch?v=ncBDvcbY1l4


Willkommen bei Raspberry Pi! Während dies theoretisch die Frage beantworten kann, wäre es vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Wir versuchen hier eine neue Richtlinie in Bezug auf informationslose Nur-Link-Antworten . Wenn dieser Beitrag nicht so bearbeitet wird, dass er Informationen enthält, die als Antwort dienen können, wie minimal sie auch sein mögen, wird er innerhalb von 48 Stunden in das Community-Wiki konvertiert, um die Korrektur durch die Community zu vereinfachen.
Ghanima
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.