- LiTime Speicher und Akkus         
Seite 1 von 10 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 96

Thema: C++ fstream GPIO Trigger/Interrupt

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    10.04.2005
    Ort
    Bad Aibling
    Beiträge
    212

    C++ fstream GPIO Trigger/Interrupt

    Anzeige

    Praxistest und DIY Projekte
    Hi Mädels ... Jungs ...

    Ich baue mir gerade eine C++ Klasse für den Raspberry um einfacher mit den GPIO arbeiten zu können. Das konfigurieren und je nachdem ob Out/In kann ich den GPIO auch lesen und schreiben. Nur den als Trigger zum Auslösen von Funktionen zu benutzen habe ich Probleme. Die meisten anderen benutzen nicht fstream dafür was meiner Meinung nach Grund genug ist den zu benutzen oder es zumindest mal zu probieren.

    Hier ist die Klasse zu finden: https://git.hts-software.de/index.ht.../Gpio/Gpio.hpp in der Funktion checkTrigger ist ein unvollständiges Beispiel mit poll.

    Um aber einen GPIO als Trigger zu benutzen muss man überwachen ob dieser sich verändert. Normal macht man das mit z.B. poll, epoll. Der benötigt aber leider den Filedeskriptor den ich bei einem fstream ja nicht habe. Ich vermute mal das auch ein fstream eine Möglichkeit hat um abzufragen ob sich dieser verändert hat. Leider habe ich das auch nach längerer Suche nicht gefunden. Man findet da irgendwie immer nur die C Lösung mit poll oder besser epoll.

    Grüße
    Alexander

  2. #2
    Erfahrener Benutzer Roboter-Spezialist Avatar von schorsch_76
    Registriert seit
    25.03.2012
    Ort
    Kurz vor Neuschwanstein
    Alter
    47
    Beiträge
    456
    Hallo Alexander,

    ich würde die Datei einfach mit open() öffnen. Auf den GPIO schreibst du ja keine Datei sondern nur mal 1/0. Dann geht auch epoll/select/poll.

    Siehe zur Konvertierung OStream->file descriptor
    https://gcc.gnu.org/ml/libstdc++/2000-q1/msg00049.html

    > So will the new libstdc++ provide such a way?

    If you compile the current CVS libstdc++ with _STREAM_COMPAT, you get
    a filedesc() method on an fstream object, returning the file
    descriptor. Alternatively, you can use fstream::rdbuf()->fd()
    (which filedesc() is a short-hand for).

    Regards,
    Martin
    Vielleicht hat ja die aktuelle libstdc++ diese Methode da der Post von ca 2000 ist, muss das nicht mehr stimmen.

    Gruß
    Georg

    - - - Aktualisiert - - -

    Siehe auch https://www.ginac.de/~kreckel/fileno/

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    10.04.2005
    Ort
    Bad Aibling
    Beiträge
    212
    Mit open und poll/epoll weiß ich ja wie es geht. Deshalb mal der Versuch es anders zu machen. Bei solchen Experimenten sind schon manches mal erstaunliche Dinge entdeckt worden.

    Das erste hatte ich auch schon gefunden geht aber leider nicht:
    Code:
    ../Gpio.hpp:117:55: Fehler: »std::basic_fstream<char>::__filebuf_type {aka class std::basic_filebuf<char>}« has no member named »fd«
           pollIntPort.fd      = fileIntPortValue.rdbuf()->fd();
    Das zweite müsste ich mal probieren es sieht aber ein bisschen merkwürdig aus.

    Eigentlich dachte ich würde ein fstream das können aber scheinbar halten das die Macher der Standards für nicht wichtig das ein Programm über die Ankunft neuer Daten in Kenntnis gesetzt wird. Merkwürdig ...

    Vielleicht gibt es ja den Weg anders herum das ich zuerst mit open das File öffnen und dann den Deskriptor einem fstream übergebe. Oder so ähnlich ...

    Also nicht wirklich was ich mir vorstelle aber der Theorie nach kann man zum lesen Dateien ja auch mehrfach öffnen. Dann könnte man einfach schreiben und Daten lesen über den fstream und das überwachen für den Trigger mit open und epoll. Auch nicht wirkllich gut die Idee ...

  4. #4
    shedepe
    Gast
    Ich würde vorschlagen, dass man sich die Arbeit spart selbst eine GPIO implementierung für den Pi zu schreiben und stattdessen WiringPi verwenden. Das kann auch die Sache mit den Interrupts (http://wiringpi.com/reference/priori...s-and-threads/). Jetzt kann man sagen: ohh ok das verwendet ja einen Thread um den Zustand im Hintergrund zu pollen. Ja das stimmt. Wenn man sich aber mal anschaut wie so ein GPIO Interrupt implementiert werden kann ist das aber auch nicht tragisch. Für Interrupts gibt es prinzipiell zwei Möglichkeiten wenn man das mal aus der HighLevel Ebene von der wir kommen betrachtet. Die Erste ist: Die Hardware merkt, der Pin Zustand hat sich geändert und unterbricht des Datenfluss der CPU und springt dafür an eine hinterlegte Interrupt Addresse. Die Zweite ist: Naja dein Betriebssystem tut so als ob es ein Hardwareinterrupt ist, nimmt dir aber nur das Polling ab. Ich vermute stark dass die zweite Variante beim Raspberry verwendet ist (Ohne Garantie). Allein aus Sicherheitsgründen als auch dass die Implementierung einfacher ist.

    Ob jetzt aber das Betriebssystem für dich Pollt oder du selber (Was WiringPi macht) ist letztendlich egal (auch mit Einschränkungen - weil das Betriebssystem kann das unter Umständen besser. Deshalb meine Empfehlung: Erfinde das Rad nicht neu und verwende WiringPi dafür.

    Um dein Vorgehen aber auch noch zu diskutieren. Zum einen solltest du wissen, das Dateisystem unter /proc (wo man hintschreibt um die GPIOs zu steuern) ist nur ein virtuelles Filesystem. D.h. eigentlich wird im Hintergrund ein Syscall des Kernels aufgerufen und irgendwas gemacht. Das gleiche gilt auch fürs Lesen. Da müsste man sowie so erst mal Recherchieren ob man das überhaupt mit den normalen Methoden die es gibt um eine Änderungen des FIles mitzubekommen funktioniert (Mein Tipp wäre ja).

    Bezüglich deines Filedescriptors: Mein Vorschlag wäre: Nimm direkt die C API (also open()). Das wäre zumindest der schöne weg.
    Wenn du unbedingt fstream verwenden willst ist vermutlich das hier deine Rettung: http://www.cpptips.com/fstream

    Ich würde dabei auch darauf achten, dass ich für C++11 und nicht C++98 kompiliere.


    TLDR Nimm WiringPi und leb damit dass es dort in einem Thread gepollt wird. Ansonsten -> Nimm die C Api

    EDIT. Zum Thema: Die Macher des Standards halten etwas nicht für wichtig. Doch das tun sie, aber sie achten noch wesentlich mehr darauf dass es Plattform übergreifend funktioniert
    EDIT2: Wenn ich mir WiringPi noch mal anschaue: Vllt pollen die noch nicht mal sondern verwenden den System interrupt
    EDIT3: Schau dir eventuell auch die filesystem Erweiterung aus C++17 an: http://en.cppreference.com/w/cpp/experimental/fs


    Geändert von shedepe (15.01.2018 um 11:44 Uhr)

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    10.04.2005
    Ort
    Bad Aibling
    Beiträge
    212
    WiringPi ist meines Wissens C und eher weniger C++ auch wenn C vollständiger Sprachbestandteil von C++ ist.

    Das Rad neu erfinden in dem Sinn würde ich nur wenn ich das in C und Funktionsbasiert machen würde wie eben WiringPi es macht.

    Ob man aus dem User Space oder Kernel Space pollt ... der Unterschied könnte nicht größer sein. Wenn stimmt was geschrieben steht ist epoll die schnellste Variante und eine Kernel Schnittstelle. Das ich es jetzt anders zu machen versuche ist nicht unbedingt Performance mein erstes Ziel. Sondern nicht Funktions- sondern Objektorientier programmieren die Klassen leicht anwendbar zu machen und Fehlertoleranz, Fehleranalyse und Fehlerhandling besser zu machen.

    Über das proc fs die GPIO zu konfigurieren und zu benutzen ist nicht die schnellste Version aber aus Kernel sicht vollkommen in Ordnung. Ein Unix Grundsatz wenn nicht vielleicht sogar einer der wichtigsten alles ist eine Datei und genau auf diese weiße anzusprechen. Memory Mapped IO wäre die schnellste Version ... auch wieder wenn es stimmt was geschrieben steht. Ich habe es bisher nicht ausprobiert. Man spart sich hier den Filesystem Overhead.

    "Das wäre zumindest der schöne weg." => Das wäre der übliche Weg ... darauf können wir uns einigen.

    Compiler Option c++11 benutze ich im Moment.

    Von der Architektur her sehe ich nicht wirklich einen Unterschied zwischen der C API und WireingPi.

    http://www.cpptips.com/fstream Das ist das gleiche wie der erste Vorschlag vom schorsch_76.
    Wie bereits oben geschrieben funktioniert das bei mir nicht. Soweit mir bekannt haben die libc++ Entwickler alles nicht Standardkonforme entfernt was eigentlich sehr löblich ist.

    Zum Standard muss ich sagen ich bin mir zwar nicht ganz sicher aber relativ ... jedes Moderne Betriebsystem unterstützt solche Sachen wie poll auf die eine oder andere Art. Das glaube ich ist nicht der Grund warum es nicht vorhanden ist. Den Streams konnte man vor c++11 nur char* als Dateinamen übergeben ich hatte nie verstanden warum nicht auch einen std::string. Kaum wartet man einige Jahre und schon gibt es c++11 und man darf auch std::string übergeben ...

    Ja stimmt das mit dem filesystem aus c++17 sollte ich mir anschauen. Wollte ich auch schon aber immer wieder vergessen ...

  6. #6
    HaWe
    Gast
    soweit ich weiß, ist Linux (samt Kernel-Funktionen) in C geschrieben, nicht in C++, und der kernel besitzt ja die GPIOs - aber ich bin da absolut kein Fachmann.
    Wenn es dir nur darum geht, im Userspace auf GPIOs zuzugreifen, würde ich shedepe in jedem Falle Recht geben, dass das mit wiringPi sehr einfach und failsafe möglich ist.
    Wenn du aber schnellere Funktionen, die direkt den kernel nutzen, verwenden möchtest, wäre auch pigpio eine sehr gute Quelle, denn sie sind großenteils noch deutlich schneller als die von wiringPi.

    Ich selber verwende pigpio nicht, mir langt die wiringPi Performance, aber wenn du im RaspberryPi.org Forum nachfragst,
    https://www.raspberrypi.org/forums/v...832e3a42a7309e
    wirst du sicher sehr schnell sehr professionelle Hilfe bekommen: denn hier sind auch die Original-Autoren der beiden Libs (Henderson, Joan) sowie Mitarbeiter und Entwickler des Pis präsent und werden dir möglicherweise direkt antworten.

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    10.04.2005
    Ort
    Bad Aibling
    Beiträge
    212
    Stimmt schon das der Kernel in C geschrieben wird. Soll das nun heißen das deshalb jeder der unter Linux Software schreibt das auch in C tun muss?

    Das ich es nicht mache wegen der Performance habe ich ja vorher schon mal geschrieben. Ich will ein C++ Objekt haben das die GPIO Funktionen steuert. Klar kann ich ein Objekt um die WiringPi basteln aber Zwiebel Software ist auch nicht so mein Ding wenn ich nicht muss versuche ich zu vermeiden das ich eine Schicht um die nächste Hülle.

    In dem Raspiforum finde ich auch nur poll dafür. Die werden nicht anders reagieren als hier und nicht beim Problem helfen wollen sondern mir einreden wollen das ich es machen soll wie es alle machen.

  8. #8
    HaWe
    Gast
    Zitat Zitat von alexander_ro Beitrag anzeigen
    Stimmt schon das der Kernel in C geschrieben wird. Soll das nun heißen das deshalb jeder der unter Linux Software schreibt das auch in C tun muss?
    ...
    In dem Raspiforum finde ich auch nur poll dafür. Die werden nicht anders reagieren als hier und nicht beim Problem helfen wollen sondern mir einreden wollen das ich es machen soll wie es alle machen.
    nein, ich meinte damit nur: wenn der kernel mit Funktionen auf GPIOs zugreift, die über ein C-Programm programmiert wurden, dann spricht sicher nichts dagegen, dafür ebenfalls eingebundene C-Funktionen als Subset von C++ mit wrappern zu verwenden.
    Ich habe auch nicht gemeint, dass dafür auch schon Lösungen im Raspiforum präsentiert wurden, sondern dass du möglicherweise sehr gute neue Vorschläge bekommen wirst, falls du dein Problem dort neu postest, denn dort sind ja sehr viele extrem versierte C(++) Programmierer unterwegs, die auch die speziellen Raspi-GPIO-Funktionen sehr gut kennen.

  9. #9
    shedepe
    Gast
    Auch wenn ich sonst nicht so häufig HaWe zustimme muss ich ihm doch diesmal Recht geben, wenn vllt auch aus anderen Gründen.

    Nun fangen wir zum Einen damit an wie man unter Linux mit dem Kernel interagieren kann: Zum Einen kann man einen Syscall machen. Das sind bestimmte Funktionen die Daten in den Kernel, bzw. daraus bewegen und auf Kernelebene irgendetwas damit machen. Zum anderen kann man auch das Dateisystem unter /proc lesen und schreiben -> Das ruft im Hintergrund aber auch nur irgendwo wieder ein paar tolle Funktionen auf.

    Zum Anderen du nennst es Zwiebelsoftware, andere Leute nennen das einen guten Stil der Softwareentwicklung wenn man ein bestehendes Interface kapselt um es seinen Ansprüchen anzupassen. Weil man verhindert damit den tpyischen "Reinvent the wheel" Effekt (http://dl.acm.org/citation.cfm?id=554798 - Gibt es sogar Veröffentlichungen dazu und spart sich eine Menge arbeit. Gibt sogar mindestens ein Softwarepattern dass sich damit beschäftigt (z.B: der Adapter oder der Wrapper). Falls dich das immer noch nicht überzeugt, seeehr viel Software die man irgendwo antrifft am PC basiert darauf dass man zum einen ein einfach C Interface entwickelt hat und dann in der Sprache seiner Wahl ein Frontend drauf gesetzt hat (Was glaubst du wie die ganzen managed Sprachen C# / Java usw. implementiert sind).

    Und ein letzter Grund noch warum es durchaus Sinn mach das C interface zu wrappen. Du hast ja inzwischen vllt festgestellt, dass es zwei verschiedene Methoden gibt die GPIOs anzusteuern. Wenn du deinen Wrapper sauber baust, kannst du mit einer Zeile Code auswählen ob du die eine (wiringPi) oder die andere (pigpio) verwenden willst, ohne dass deine SOftware ein anderes Interface verwenden müsste.

    Mein Einschätzung dazu ist, dass es wesentlich unsauberer ist Dateisystem zugriffe zu wrappen als bestehenden C Code.

  10. #10
    HaWe
    Gast
    ich meinte das mit den C++ wrappern um C Funktionen herum auch so wie shedepe es schrieb, wenngleich er es auch deutlich präziser formuliert hat.
    Ich vergaß allerdings oben zu erwähnen, dass ich wiringPi gerade deswegen auch gern verwende, weil es einerseits einen fd beim öffnen zurückgibt (anstatt einen FILE* handle) und außerdem intern immer berücksichtigt, um welche Art von files es sich handelt, auf die man zugreift - inkl. Sonder-Routinen z.B. für serielle Kommunikation, u.a. wenn es um Besonderheiten wie Puffer etc. geht: ich kann mich dunkel erinnern, dass diese Tatsache auch im Raspberrypi.org C++ Forum das ein oder andere Mal diskutiert wurde.
    (Nur zur Vervollständigung, auch wenn es nicht direkt zur Lösung des TOP-Problems führt)

Seite 1 von 10 123 ... LetzteLetzte

Ähnliche Themen

  1. Benötige Hilfe zu AT32U3C und GPIO
    Von xrzr im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 10.11.2015, 19:54
  2. Respberry Pi GPIO mit C++ und QT
    Von Basti1204 im Forum Raspberry Pi
    Antworten: 0
    Letzter Beitrag: 06.03.2013, 00:01
  3. [ERLEDIGT] Raspberry Pi GPIO
    Von Kampi im Forum Raspberry Pi
    Antworten: 4
    Letzter Beitrag: 04.11.2012, 23:45
  4. GPIO-Register Ansprechen
    Von kmrish im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 7
    Letzter Beitrag: 14.07.2011, 10:45
  5. schmitt-trigger an interrupt
    Von Bluesmash im Forum Sensoren / Sensorik
    Antworten: 2
    Letzter Beitrag: 19.06.2005, 23:46

Berechtigungen

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

LiTime Speicher und Akkus