SPI in der Programmiersprache Icon

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    vor ein paar Tagen habe ich mich mit ein paar lustigen ICs beschäftigt. Einer davon ist der MCP 3208-CI/P. Es handelt sich dabei um einen 12-Bit-A/D-Wandler mit SPI, 8 Kanälen in einem formschönen DIL-16-Gehäuse.

    Mit folgendem Programm, das ich in den nächsten Tagen in meine GPIO-Library integrieren werde, kann der A/D-Wandler ausgelesen werden.


    Das Interessante ist, dass die SPI-Funktionalität mit jeder beliebigen Kombination für die Zuweisung von GPIO-Pins zu MISO, MOSI, SCLK und CS erreicht wird. Es ist also nicht erforderlich, die im üblichen GPIO-Pin-Layout für die SPI-Schnittstelle angegebenen GPIO-Pins für SCLK, MOSI, MISO und CS bzw. CE zu verwenden. Dies bestätigt mich darin, dass die GPIO-Pins standardmäßig alle eine identische Funktionalität aufweisen. Lediglich die Software inkl. Bibliotheken sorgen für spezielle Funktionalität, die letztlich immer darauf basiert, dass GPIO-Pins als Eingang gesetzt oder als Ausgang mit HIGH oder LOW belegt werden.

    Somit kann ein Entwickler "seine" bevorzugten oder für das Auslesen dieses oder eines anderen SPI-fähigen Bausteins freien GPIO-Pins selber festlegen.

    Das Programm funktioniert auch für MCP 3204-CI/P, wenn man im Programm berücksichtigt, dass dieser Baustein nur 4 Kanäle besitzt.


    Beste Grüße und viel Spaß damit!


    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (7. September 2015 um 20:39)

  • Moinsen Andreas,
    schon wieder fleissig ?? ;)


    ...
    Das Interessante ist, dass die SPI-Funktionalität mit jeder beliebigen ...
    ...
    ... Dies bestätigt mich darin, dass die GPIO-Pins standardmäßig alle eine identische Funktionalität aufweisen. Lediglich die Software inkl. Bibliotheken sorgen für spezielle Funktionalität, ...
    ...

    ganz so einfach ist es nicht ;)
    Sicher ... SPI kann man mehr oder weniger problemlos per Software nachbilden.
    Aber: der Broadcom-Chip hat drei (Hardware-)SPI-Controller ... allerdings sind nur die Anschlüsse für den ersten Controller auf den Pin Header rausgeführt. In Verbindung mit dem Kernel Modul bist Du halt an die entsprechenden Pins gebunden.

    Was jetzt in Deiner Funktion z.B. noch fehlt ist die einstellbare Geschwindigkeit und das damit verbundene Timing. Eventuell auch Transfer-Modi usw. SPI ist also nicht ganz so lapidar ;)

    Näheres zum SPI des Raspberry findest Du -> hier <-

    cu,
    -ds-

  • Hallo Dreamshader,

    bei meiner Umsetzung wird keine Kernel-Unterstützung bzgl. SPI vorausgesetzt. Weder ist es erforderlich, ein SPI-Modul zu aktivieren, noch werden irgendwelche in Bibliotheken anderer Programmiersprachen verankerten Pins vorausgesetzt. Ich bin in der Wahl der vier Pins vollkommen frei.

    Durch die fallende Flanke auf den CS-Anschluss des MCP3208 wird das Auslesen vorbereitet. Durch fallende Flanken auf dem CLK-Anschluss des MCP3208 wird zunächst über den DIN-Anschluss des MCP3208 der auszulesende Kanal festgelegt.

    Die einzelnen Bits werden nach der A/D-Wandlung bereitgestellt, indem wiederum durch fallende Flanken auf dem CLK-Anschluss des MCP3208 der DOUT-Anschluss des MCP3208 ausgelesen wird.

    Das Ganze habe ich ausgiebig getestet. Es funktioniert ... zuverlässig...

    Und mit dem Algorithmus dieses Programms kann ich mehrere SPI-Anschlüsse realisieren, da ich lediglich Sätze aus SCLK, MOSI, MISO und CS festzulegen brauche.

    Beste Grüße

    Andreas

    Bilder

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Hallo Andreas,

    dass Du keine Kernel-Unterstützung ... voraussetzt habe ich schon verstanden. Auch dass Du das SPI auf beliebigen Pins nachbildest.
    Ich wollte nur mal aufzeigen, dass hinter der Funktionalität der für SPI definierten Pins des RPi keine Software-Emulation (wie Du es gemacht hast) steckt, sondern ein Stück Hardware ... eben ein SPI-Controller.
    Wobei sich "Stück Hardware" ziemlich brachial anhört ... ist halt nur ein kleiner Schatten im µmm Bereich auf irgendeinem Chip-Layer.
    Somit ist die Grund-Funktionalität aller Pins nicht identisch ... imho ist aber das SPI der einzige Ausreisser, denn für I2C und die rs232 ist afaik kein Controller vorhanden.

    cu,
    -ds-

  • Hi,


    ... imho ist aber das SPI der einzige Ausreisser, denn für I2C und die rs232 ist afaik kein Controller vorhanden.

    Das verwirrt mich jetzt etwas. Wie sicher bist du dir da?
    Ich hätte jetzt behauptet das I2C und rs232(UART) auch in Hardware vorhanden sind.

    Hab auf die schnelle keine konkrete Aussage dazu gefunden aber wäre dann nicht auch die ganze Modul(device-tree) Geschichte (die nocht nicht ganz verstanden habe) überflüssig.
    Aber vielleicht(vermutlich) vergeß ich dabei auch was wichtiges.

    -- Joh

    DON'T PANIC!

  • Hallo Joh, hallo Dreamshader,

    letztes Jahr im Sommer / Herbst bin ich auf diesen Beitrag gestoßen.

    Für mich folgt daraus, dass ich die GPIO-Pins im Prinzip beliebig konfigurieren kann und dass irgendwelche Kernel-Untiefen daraus irgendwas Sinnvolles machen. Wenn es anders wäre, würde der DeviceTree-Compiler, der aus DeviceTree-Source binäre DeviceTreeBlobs erzeugt, so gar keinen Sinn machen.

    Wenn das so richtig ist, wie ich es glaube verstanden zu haben, dann folgt daraus auch, dass die Funktionalität der GPIO-Pins - vollständig über Konfiguration voreingestellt - softwareseitig realisiert werden müssen.

    Der Programmierer, der C- oder Python-Bibliotheken nutzt, bekommt von der ganzen Umsetzung wohl nicht viel mit. Er nutzt die zur Verfügung gestellten Befehle zur Initialisierung, zum Auslesen und Setzen irgendwelcher Parameter und freut sich, wenn die - ggf. auch zusammenkopierten - Codes mal funktionieren.

    Ich als jemand, der versucht, sich losgelöst von vorgefertigten Bibliotheken, nur vom Datenblatt eines Bauteils ausgehend, diesem Bauteil nur durch Setzen von Flanken, ggf. Aktivieren von Timern, zu nähern, bekommt dann ein anderes Verständnis zur Hard- und Software.

    Umso größer ist dann auch die Freude, wenn es funktioniert.

    Ich denke, dass bzgl. DeviceTrees noch einiges auf uns zukommen wird. Insbesondere dann, wenn völlig Unbedarfte sich mit DeviceTrees vollkommen neben den Standards bewegen - oder auch Hersteller von Erweiterungen derartiges praktizieren. Und folglich irgendwelche GPIO-Anwendungen nur noch mit dem richtigen Satz an DeviceTree-Definitionen funktionieren.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (17. März 2015 um 19:19)

  • Naja ... mir war jetzt nur wichtig klarzustellen, dass es ein Unterschied ist, wenn Du das SPI so wie Du programmierst (also eine Software-Lösung) oder wenn Du die vorgegebenen Pins verwendest über die Du dann z.B. mithilfe einer Lib den Controller steuerst ...

    ah ja ... device tree ... ich fürchte, da komm ich leider doch nicht drum herum. Bisher hatte alles funktioniert - jetzt kommen 20 DS18B20 ins Spiel und schon brauchts den Eintrag.

    cu,
    -ds-

  • Hallo Andreas,
    wo findet man Deine GPIO-Library und ist das in python?
    Wenn ich die Parameter auf beliebige PINs ändere müßte ich das python script auch im Bootprozess einbauen, damit es bei jedem Neustart gilt, richtig?
    Vielen Dank für die Infos
    cmorg

  • Hallo cmorg,

    meine GPIO-Library findest Du im Icon Tutorial Teil 24 - sie ist nicht in Python geschrieben. Die Version des Icon Tutorials 12 müsste auch schon funktionieren - in diesem Teil ist die Entwicklung der GPIO-Library im Detail beschrieben.

    Wenn Du mit der GPIO-Library irgendwas machen möchtest, dann musst Du die Programmiersprache Icon installieren. Wie dies geht ist im Icon Tutorial Teil 1 beschrieben. Und wenn Du schon dabei bist, dann kannst Du auch gleich die IDE Geany installieren, konfigurieren und ein paar Anpassungen am System Geany & Icon vornehmen, um ein annähernd professionelles Entwicklungssystem zu erzeugen. Wie das geht, kannst Du im Icon Tutorial Teil 2 lesen.


    Wenn ich die Parameter auf beliebige PINs ändere müßte ich das python script auch im Bootprozess einbauen, damit es bei jedem Neustart gilt, richtig?

    Nö, jede Anwendung, die Du analog zu dem Beispielprogramm erzeugst, die ihren eigenen Satz an SPI-Pins definiert hat, nutzt diese innerhalb der Laufzeit. Wenn das Programm beendet ist, dann ist auch die SPI-Zuordnung aufgehoben und der Raspberry Pi verhält sich wie vor dem Programm.

    Und wie gesagt, es handelt sich nicht um Python, auch nicht um Skripte. Aber wenn Du es unbedingt willst, kannst Du Icon-Quellcode auch als Skript laufen lassen. Ich persönlich finde es aber besser, den Code zu compilieren und zum lauffähigen Programm zu linken. Das Programm läuft dann auch auf Systemen ohne Icon-Umgebung. Und wäre kein GPIO-Code enthalten, dann würde der Quellcode sogar auf jedem Betriebssystem compilierbar sein, auf dem Icon installierbar ist - und das sind mehr als ein Dutzend...

    Links:

    Icon Tutorial Teil 1

    Icon Tutorial Teil 2

    Icon Tutorial Teil 12

    Icon Tutorial Teil 24

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    2 Mal editiert, zuletzt von Andreas (14. Oktober 2017 um 17:23)

  • Hallo Andreas,


    ...
    Wenn Du mit der GPIO-Library irgendwas machen möchtest, ...
    ...


    ich hab' jetzt leider aus Zeitgründen Dein Tut nicht mehr komplett verfolgt ... aber gäbe es denn nicht die Möglichkeit, da eine C-Api zu integrieren?
    Mit Python geht das auch ... also Zugriff von Python aus auf ein mit C erzeugtes shared object. Hatte ich vor längerer Zeit mal angefangen, damit meine Beispiel-Programme auch mit Python nutzbar sind. Ich hab' das aber dann aus Zeitgründen auf Eis gelegt.
    Müsste doch eigentlich machbar sein, da eine C-API in die Icon-Lib zu integrieren ...
    Oder gibts das schon und ich hab' das verpasst ??

    cu,
    -ds-

  • Hallo Dreamshader,


    Oder gibts das schon und ich hab' das verpasst ??

    genau das... beides.

    Als ich noch auf Madeira weilte, habe ich mir so ein Konzept für Icon-Tutorials erstellt. Ein Ende war für Teil 29 vorgesehen. Während der Erstellung der anderen Icon Tutorials, Entwicklung kleiner Demo-Programme und auch ein paar kommerzielle Aufträge weiter, sind Ideen aufgestiegen, auf C-Libraries zugreifen zu können.

    So habe ich im Icon-Tutorial 30 beschrieben, wie ich von Icon aus auf C-Libraries zugreifen kann, im Icon Tutorial Teil 31 das gleiche für in C++ programmierte Libraries.
    In Teil 32 - so es irgendwann abgeschlossen sein sollte - geht es um den Zugriff auf Libraries, die in Cobol, D, und Prolog erstellt wurden. Wenn mir danach sein sollte, nehme ich auch noch Unicon-Libs mit auf. Aber da gab es vor zwei Jahren einen Haken: Eine Datei ist von Maschinen-Code von X86 nach ARM umzuschreiben. Da ich Assembler weder vom einen noch vom anderen Prozessor kann, habe ich's erstmal sein lassen. Ich kann zwar über 15 Programmiersprachen, darunter auch Assembler für 6502/6510 - aber mir das jetzt noch für X86 und ARM anzutun - dafür nehme ich mein Recht "als alterndes Säugetier" in Anspruch (Zitat: Prof. Dr. Rudolf Hoppe) ;)

    In diesen beiden Tutorials ist in ein paar Sätzen beschrieben, wie man Schnittstellen zu anderen Libraries programmiert - als API habe ich es sicherlich nicht bezeichnet, aber ein Name ist mir dafür sicherlich eingefallen.

    Genau, shared object war das Stichwort.
    Es ist möglich,
    - C inkl. Schnittstellen zu Icon in shared objects umzuwandeln
    - Icon-Libraries mit Schnittstellen zu C zu versehen

    Dazu sind in den beiden Tutorials einige Skripte vorgestellt und die Schritte detailliert beschrieben.

    Es sollte auch möglich sein, shared objects zu erstellen, die von allen Programmiersprachen, die shared objects unterstützen, um Schnittstellen in beliebige Richtungen (Anwendung Programmiersprache X mit Zugriff auf Library der Sprache Y) zu realisieren.

    Genau an dieser Stelle habe ich aufgehört, da mir zwar Anwendungsfälle eingefallen sind, ich aber nicht die passende Zeit fand, das umzusetzen. Und außerdem müssten dann auch Beispiele für Python dabei sein, um die große Python-Fan-Gemeinde anzusprechen. Ähem ... hust ... räusper ... :s Und bevor ich anfange, meine erste Zeile in Python zu programmieren, muss ich noch ganz dringend Assembler für X86- und ARM-Prozessoren lernen. ;)

    Danke, Dreamshader, für die Idee :thumbs1: . Ich setze es auf die Liste für die Zeit zwischen den beiden nächsten Aufträgen. Oder abends im Hotel beim nächsten Auftrag.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (17. Oktober 2015 um 22:40)

  • Hi,


    ...
    - Icon-Libraries mit Schnittstellen zu C zu versehen
    ...


    genau das ist das Stichwort ... wenn es denn mal so weit sein sollte, dann melde Dich mal ... da würde ich Dir gerne hilfreich in die Seite treten ...


    ...
    Python zu programmieren, muss ich noch ganz dringend Assembler für X86- und ARM-Prozessoren lernen. ;)
    ...

    :thumbs1:

    -ds-

  • Hallo Dreramshader,

    ich nehme Dich beim Wort!

    Beste Grüße und gut's Nächtle,

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Hi Dreamshader,

    Py... WAS?

    Eine API für Python ... OK ... kann man sicherlich leicht programmieren.

    ABER: Wer soll das testen? :s
    Du hast noch keine Zeile Python geschrieben ... ich halte da jedem Vergleich stand. 0 + 0 = ...? :-/

    Entweder gibt einer von uns beiden den Python-Widerstand auf ( :no_sad: NIEMALS! :bravo2: ) oder wir finden :auslachen: eine(n), der das Zeugs ausprobiert.

    Vielleicht einer von denen, die mal mit Python begonnen haben, aber mit den Icon-Tutorials beachtlich weit gekommen sind...

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Andreas, dreamshader:
    Jetzt habt Ihr Burschen mir wieder 1 Stunde meines Schönheitsschlafes geraubt und nach http://pdf1.alldatasheet.com/datasheet-pdf/…OM/BCM2835.html Seite 102 geschickt. Dort finde ich dann auch die 3 Controller, welche über die ALT Funktionen verwendbar sind. Jetzt aber eine Frage zum Verständnis...


    Und mit dem Algorithmus dieses Programms kann ich mehrere SPI-Anschlüsse realisieren, da ich lediglich Sätze aus SCLK, MOSI, MISO und CS festzulegen brauche.

    D.h. Du bitbangst die Leitungen von Hand - richtig?

    Für das (synchrone) SPI-Protokoll finde ich das recht angebracht, da man sich um den Input ja nur kümmern muß, wenn man sowieso (zeitgleich) sendet. Ob man beim equidistanten Rausmorsen noch einen Input mitliest, tut schließlich auch nicht weh. Insofern ist der qualitative Unterschied hinsichtlich Softwarelösung/Hardwarecontroller hier gar nicht mal so groß, wie bei asynchronen Protokollen.


    Andreas: Eine tolle Idee! :thumbs1: Da würde ich Dir doch glatt noch ein Zusatzpünktchen geben, wenn ich nur könnte!

  • Hallo Schnasseldag,

    als wenn Du es nötig hättest ... von wegen Schönheitsschlaf...ausgerechnet Du?!?!

    Richtig - Bitbanging vom Feinsten. Ich bin kein Freund davon, "fertige" Programmbibliotheken zu verwenden - ohne zu wissen / zu verstehen, was da vor sich geht. Wenn ich ein Protokoll von Grund auf selber programmieren kann - und noch dazu in der Programmiersprache Icon - dann habe ich das Protokoll, wie es sich aus dem Datenblatt erschließt, vollkommen verstanden.

    Vor einigen Wochen habe ich auf Wunsch eines anderen Users im Forum ein Tutorial erstellt, wie man zu einem x-beliebigen Sensor nur ausgehend von den Informationen des Datenblattes zu einem Programm kommt, mit diesem Sensor zu kommunizieren. Als Beispiel habe ich dem DHT22 gewählt, weil dieser recht viele interessante - auch zeitkritische Elemente - bereithält.

    Ein Knackpunkt war, wie kann man eine Zeit von 80 oder auch 25 µs messen - wenn das Betriebssystem alles andere als echtzeitfähig ist? Dies habe ich dann (ACHTUNG! So sollte man nur programmieren, wenn nichts anderes zum Ziel führt) so realisiert, dass statt der Zeiten zwischen Pegelwechseln nur die Durchläufe einer leeren Schleife zwischen Pegelwechseln gezählt werden. Dies erscheint mir beim DHT22 auch deshalb legitim, weil dieser zur Einleitung der Kommunikation für zwei unterschiedlich lange Zeiten unterschiedliche Pegel sendet.

    Ich fragte mich dann: "Warum dieses?" Es kann doch nur den Zweck verfolgen, einem Auslesemedium zu sagen, "Du, pass mal auf, das erste Signal dauert so und so lange, das zweite benötigt die und die Zeit. Und wenn Du so blöd bist, nicht echtzeitfähig zu sein, dann überleg' Dir gefälligst selber, wie Du unterschiedlich lange Pegel erkennen kannst. Denn nach den zwei Signalen kommt dann, ... ach guck selber nach, was da kommt!"

    Zwei bekannte Zeiten korrelieren mit zwei signifikant unterschiedlicher Anzahl an Schleifendurchläufen - einen Dreisatz (ähem ... Zweisatz in dem Fall) weiter weiß der Algorithmus, welche Zeit einem Schleifendurchlauf entspricht. Bei der Übertragung der Daten genügt es dann, nur die Anzahl der Schleifendurchläufe zu übermitteln, um Aussagen zu treffen, ob ein Bit gesetzt ist oder nicht. Und schon fließen die Daten aus dem Sensor...


    Synchron - asynchron...

    Hast Du meinen Beitrag zum Auslesen asynchron eingehender Daten über die serielle Schnittstelle schon gelesen? Das war auch so einer mit der Brechstange, nachdem Boardmittel nicht zum Ziel führten.

    Aber der dann gewählte Ansatz ist nur genial... und funktioniert zuverlässig.


    Beste Grüße!

    Und nichts von Quecksilbertropfen träumen - das habe ich vor ein paar Tagen erst getan! Und bin da auch einen Riesensprung weiter. Die Lösung ist oftmals wesentlich simpler...
       
    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (23. Oktober 2015 um 01:23)

  • Hi Andreas,

    das Du ein Vertreter der "Datenblattlesenden" bist, hatte ich mir schon gedacht. Sonst könnte man nicht so detaillierte Artikel schreiben. Jatzt hast Du Dich also geoutet :)

    Den Vorteil der Schleifenzählerei habe ich allerdings nicht ganz verstanden. Es ist doch eigentlich egal, ob ich innerhalb einer Schleife "nop's" (ich nenne das jetzt mal so) zähle (deren Taktzeit ich vielleicht kenne) oder die Systemzeit ermittle, "intelligent schlafe" und dann wieder die Systemzeit bemühe. Unter intelligent schlafen verstehe ich ein Sleep nur solange auszuführen, wie ich noch sicher sein kann, daß ich vor dem erwarteten Ende ggf. wieder aufwache. Die Restzeit verbringe ich genauso mit anhaltendem Pollen auf der Systemzeit.
    Also tSleep = tPulslänge - (tThreadlatenz + tSicherheitszeit). Allenfalls unterstelle ich beim Ermitteln der Systemzeit, daß dieser Call nicht zu einem impliziten ausplanen durch den Scheduler führt. Zweitens unterstelle ich, daß die Zeitgranularität bedingt durch den "längeren" Systemcall (im Vergleich zum nop) noch in einem akzeptablen Rahmen liegt. Davon abgesehen sehe ich aber zunächst kein besseres Verhalten im Vergleich zur Zeitmessung. Kleinigkeiten wie die Clockrate der CPU lassen wir mal außen vor - die kann man berücksichtigen. Das der Scheduler beide Algorithmen aushebeln kann und sie daher nicht 100% sicher sind, ist auch klar. Das ist mir schon bewußt.
    Ich sehe aber einen gravierenden Nachteil der "nop"-Schleife. Irgendwie mußt Du auch diese Schleife doch kalibriert werden?! Andernfalls bist Du doch extrem codegeneratorabhängig?!
    Und wie stellest Du sicher, daß bei dieser Kalibrierung nix schief ging (Stichwort Schedulerausplanung)? Letztendlich könnte man zwar mehrere Messungen machen und den Medianwert heranziehen...

    Vielleicht denke ich aber auch in eine völlig falsche Richtung?! In diesem Fall gib mir mal bitte etwas Starthilfe ;)

    Nein, Deinen Aktikel zur Erfassung asynchroner Daten hab' ich noch nicht gelesen - Du kannst mir ja mal einen Link darauf schicken. Mir ist noch kein Stein der Weisen zur Lösung des Problems eingefallen, ohne dabei hohe CPU-Last zu erzeugen und ohne Behandlung per Interrupt (ich meine echte Interrupts - nicht diese Pseudodinger, von denen hier oft die Rede ist). Hätte ich eine solche Idee, dann könnte ich mal über einen 433MHz Decoder nebst kleinem proprietärem Protokoll nachdenken...

    Ach ja, bei den Quecksilbertropfen bin ich dann irgendwann in der Mitte hängen geblieben. Du kannst aber gewiß sein, daß die Fragenattacke noch kommen wird :lol:

    Derweil wünsche ich Dir ein schönes Wochenende und schöne Grüße in den Westen!

    schnasseldag

  • Hallo Schnasseldag,


    Hi Andreas,

    das Du ein Vertreter der "Datenblattlesenden" bist, hatte ich mir schon gedacht. Sonst könnte man nicht so detaillierte Artikel schreiben. Jatzt hast Du Dich also geoutet :)

    Den Vorteil der Schleifenzählerei habe ich allerdings nicht ganz verstanden.

    ein kommentierter Code macht's deutlicher:

    Code
    procedure dht(pin)  
       ....
       GPIO(pin, 1, 0.04)                  # Startsignal 40 µs HIGH
       resultat := GPIO(pin)               # Auf Eingang schalten
       wait_falling(pin)                   # Auf fallende Flanke warten
       time80a := wait_raising(pin)        # Beide Phasen sollen 80 µs dauern
       time80b := wait_falling(pin)        # Rückgabe ist die Anzahl der Schleifendurchläufe bis zum Flankenwechsel

    Was ich jetzt schreibe, bezieht sich auf den DHT22 - sinngemäß gilt das aber für alle Protokolle, deren Informationsgehalt sich an unterschiedlichen langen Impulsen orientiert.

    In der "Kommunikationsphase" sendet der DHT22 zwei Impulse von 80 µs Dauer aus, zuerst LOW, dann HIGH. Wie Du und Dreamshader n einem anderen Thread über die RT-Thematik argumentiert habt, ist Linux kein Echtzeit-(Teal-Time)-Betriebssystem.
    Ich muss unterstellen, dass der DHT22 außer sein eigenes Protokoll zu unterstützen, nicht viel anderes machen wird. Also muss ich auch unterstellen, dass die 80 µs so ungefähr hinkommen. Der Raspberry Pi (und wohl Linux-Räscheknäschte allgemein) haben kein mir bekanntes Instrumentarium, das in dieser Auflösung hinreichend genau messen kann. Wenn der Prozessor gerade hochgradig ausgelastet ist, weil grad mehrere Cron-Jobs angelaufen sind, oder irgendwelche Interrupts aktiv geworden sind ... oder .... oder ... oder ... kann ich einer Zeitmessung im Bereich µs kaum Glauben schenken.

    Wenn ich dagegen obigen Code-Ausschnitt habe und dann den Code für eine der [font="Courier New"]wait()[/font]-Prozeduren nehme:

    Code
    procedure wait_falling(pin, korr, timeout)
       loop := 0
       start := &time
       while GPIO(pin) = 1 do
       {    loop +:= 1
            if \timeout then if &time – start > timeout then break
       }
       if /korr then return loop else return loop * korr
    end

    dann ist der Schleifenzähler [font="Courier New"]loop[/font] ein Maß für die vergangene Zeit. Wenn ich die von der "Kommunikationsphase" vorgegebene Zeit von 80 µs teile, dann weiß ich, wielange ein Schleifendurchlauf dauert.

    Was für [font="Courier New"]wait_falling()[/font] gilt, gilt auch für [font="Courier New"]wait_rising()[/font] - so unterschiedlich wird der Prozessor beide direkt aufeinanderfolgenden 80µs-Phase wohl nicht erleben. Wenn doch, würde dies erklären, warum der DHT22 so häufig Probleme beim Auslesen bereitet.

    Der Mittelwert aus beiden 80µs-Phasen macht die Zeitmessung dann (ein wenig) genauer und zuverlässiger. In der "Kommunikationsphase" liefern diese beiden [font="Courier New"]wait_()[/font]-Prozeduren den Wert des Schleifenzählers. Das Hauptprogramm berechnet dann nach

    Code
    time80 := 80 * (time80a + time80b)/2
     faktor := 80.0 / time80 # Umrechnungsfaktor zwischen
    # Anzahl Läufe in wait_x und Zeit in µs


    den Umrechnungsfaktor zwischen dem Schleifenzähler und der lt. Protokoll einzuhaltenden Zeitspanne.

    Bei der eigentlichen Übermittlung der Messwerte geschieht etwas anderes. Hier entscheidet die Zeitspanne eines HIGH-Pegels, ob das Bit als gesetzt oder als nicht gesetzt zu betrachten ist.


    40 Bits werden übertragen. Die [font="Courier New"]wait_falling()[/font]-Prozedur bekommt ein weiteres Argument (den vorhin berechnenten Umrechnungsfaktor Schleifenzähler => Zeit. Somit liefert diese Prozedur in der "Datenphase" einen Anhaltspunkt für die Dauer des HIGH-Pegels. Lt. Datenblatt existieren zwei Möglichkeiten 27 µs und :s 75 (?) µs. Wenn in der "Kommunikationsphase" nichts grundlegend schief gelaufen ist, sollte es möglich sein, auch bei (deutlich) veränderter Prozessorauslastung sich eindeutig für die eine oder die andere Zeitspanne des HIGH-Pegels zu entscheiden.



    Es ist doch eigentlich egal, ob ich innerhalb einer Schleife "nop's" (ich nenne das jetzt mal so) zähle (deren Taktzeit ich vielleicht kenne) oder die Systemzeit ermittle, "intelligent schlafe" und dann wieder die Systemzeit bemühe. Unter intelligent schlafen verstehe ich ein Sleep nur solange auszuführen, wie ich noch sicher sein kann, daß ich vor dem erwarteten Ende ggf. wieder aufwache. Die Restzeit verbringe ich genauso mit anhaltendem Pollen auf der Systemzeit.

    Da hast Du natürlich recht. Aber bei einem Nicht-Real-Time-Betriebssystem - insbesondere beim RPi - kann ich mich nicht auf irgendwelche [font="Courier New"]sleep()[/font]-Zeiten im zig-µs-Bereich verlassen. Und ganz sicher nicht, wenn ich eine Hochsprache dafür einsetze. Auf einem Arduino oder allgemein einem System, das außer der Abarbeitung meines Code auf einer möglichst maschinennahen Weise nichts weiter macht, kann ich mich auf µs an die echten Zeiten herantasten und sagen, "OK. Die Zeit für 27 µs ist jetzt eindeutig vorbei. Also kann es nur noch HIGH sein und das Signal braucht jetzt noch so rund 45 µs. SCHLAFEN GEHEN!" Wenn man sowas auf dem RPI versuchen würde, dann wäre sicherlich die Rate fehlerhafter Ausleseversuche deutlich größer. Der Versuch, einen [font="Courier New"]sleep[/font]-Befehl im µs-Bereich auzuführen, mündet darin, dass 1000 x 1µs-Sleep() länger als 1 ms dauert - weil nämlich auch der Befehlsauruf Zeit benötigt. Und je kürzer die Schlafzeit, umso größer wird die Abweichung.



    Also tSleep = tPulslänge - (tThreadlatenz + tSicherheitszeit). Allenfalls unterstelle ich beim Ermitteln der Systemzeit, daß dieser Call nicht zu einem impliziten ausplanen durch den Scheduler führt. Zweitens unterstelle ich, daß die Zeitgranularität bedingt durch den "längeren" Systemcall (im Vergleich zum nop) noch in einem akzeptablen Rahmen liegt. Davon abgesehen sehe ich aber zunächst kein besseres Verhalten im Vergleich zur Zeitmessung. Kleinigkeiten wie die Clockrate der CPU lassen wir mal außen vor - die kann man berücksichtigen. Das der Scheduler beide Algorithmen aushebeln kann und sie daher nicht 100% sicher sind, ist auch klar. Das ist mir schon bewußt.
    Ich sehe aber einen gravierenden Nachteil der "nop"-Schleife. Irgendwie mußt Du auch diese Schleife doch kalibriert werden?! Andernfalls bist Du doch extrem codegeneratorabhängig?!


    Genau das habe ich ja oben gemacht und beschrieben. Ich bzw. das Programm kennt die Dauer eines Schleifendurchlaufs. Ein weiterer Vorteil besteht darin, dass ich - wieder am Beispiel DHT 22 bei der Übertragung der 40 Bits - aus den unterschiedlichen Dauern "lernen" kann und meine Erkenntnisse aus den 80µs-Phasen verfeinern kann.


    Und wie stellest Du sicher, daß bei dieser Kalibrierung nix schief ging (Stichwort Schedulerausplanung)? Letztendlich könnte man zwar mehrere Messungen machen und den Medianwert heranziehen...


    Nee, mehrere Messungen sind nicht (wieder am Beispiel DHT 22), 2x80µs - dann muss es sitzen; wenn nicht, sind die anschließenden Daten nicht auswertbar.


    Vielleicht denke ich aber auch in eine völlig falsche Richtung?! In diesem Fall gib mir mal bitte etwas Starthilfe ;)

    Ich denke, es gibt hier kein "richtig" und "falsch". Alle zielführenden Wege sind richtig. Und wie gesagt, Erkenntnisse aus einem RT-System und einem Nicht-RT-System halte ich nicht für vergleichbar. Im letzteren Fall müssen andere Wege gegangen werden.


    Nein, Deinen Aktikel zur Erfassung asynchroner Daten hab' ich noch nicht gelesen - Du kannst mir ja mal einen Link darauf schicken. Mir ist noch kein Stein der Weisen zur Lösung des Problems eingefallen, ohne dabei hohe CPU-Last zu erzeugen und ohne Behandlung per Interrupt (ich meine echte Interrupts - nicht diese Pseudodinger, von denen hier oft die Rede ist). Hätte ich eine solche Idee, dann könnte ich mal über einen 433MHz Decoder nebst kleinem proprietärem Protokoll nachdenken...


    :thumbs1: Pseudodinger - sehe ich auch so...

    Link folgt ... Hier isser..


    Ach ja, bei den Quecksilbertropfen bin ich dann irgendwann in der Mitte hängen geblieben. Du kannst aber gewiß sein, daß die Fragenattacke noch kommen wird :lol:


    Mir ist das jetzt klar... :cool: Ich müsste nur mal wieder Zugang zu einem gut ausgerüsteten Labor bekommen...

    Und schöne Grüße in den Osten!

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    2 Mal editiert, zuletzt von Andreas (14. Oktober 2017 um 19:03)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!