Impulszähler unter Linux (Informationen zum Gasfluss erhalten wir von einem VK-G4-Zähler)

Bei der Haushaltsautomatisierung wurde festgestellt, dass der verfügbare Gasdurchflussmesser VK-G4 ein interessantes Merkmal aufweist: In die Junior-Entladung ist ein Magnet eingebaut, der den außerhalb des Geräts selbst installierten Reed-Schalter schließen kann (d. H. Für den Anschluss ist keine Genehmigung erforderlich Gasgesellschaft). Dies ist sogar im Reisepass auf dem Schalter selbst angegeben. Es wird zwar empfohlen, den "IN-Z 61 Niederfrequenz-Impulsgenerator" zu verwenden, aber in Wirklichkeit handelt es sich nur um einen Reed-Schalter, der zu einem wahnsinnigen Preis an einem Messgerät angebracht ist. Daher wurde anstelle von IN-Z 61 entschieden, den billigsten Hallsensor mit einem digitalen Ausgang (d. H. Mit einem integrierten Schmitt-Trigger) zu verwenden.

Aus dem verfügbaren wurde Hallsensor Typ SS441A entnommen. Gemäß dem Datenblatt des SS44xA codiert die dritte Ziffer ihre magnetische Empfindlichkeit, die den physischen Standort des Sensors auf dem Gaszähler bestimmt.
Als Steuerungssystem verwende ich einen Single-Board-Banana PI-Computer unter Linux (Vanilla Kernel 4.2+). Die physische Verbindung des SS44xA ist sehr einfach: Wir
verbinden den Ausgang (-) mit einem gemeinsamen Kabel;
der Ausgang (+) ist mit +5 V verbunden (und nicht mit +3,3 V);
Pin (D) ist mit dem GPIO-Port verbunden und wird über einen 4,7-kΩ-Widerstand auf +3,3 V gezogen.
Aber was war meine Überraschung, als ich keine Kernel-In-Tree-Treiber finden konnte, die nur die Anzahl der Impulse an einem bestimmten GPIO-Port zählen konnten! Ich verstehe, dass Linux kein Echtzeitbetriebssystem ist, sondern nur niederfrequente Impulse zählt ... War es wirklich mein Job?
Nach sorgfältiger Prüfung der neuesten Kernelquellen wurden zwei Zwischenlösungen entdeckt:
  1. Verwenden Sie einen Standard-UIO-Treiber. Wenn ein solches Gerät als Datei im Anwendungsprogramm geöffnet und der entsprechende Wert in das Gerät geschrieben wird, wird der nachfolgende Lesevorgang von diesem Gerät angehalten, bis eine Unterbrechung aufgrund einer Änderung des Signalpegels auf dem entsprechenden GPIO auftritt.
  2. gpio_keys. GPIO «» (button) «» (switch), , .

Für die Verwendung einer dieser Lösungen ist eine Daemon-Anwendung erforderlich, die aktiv sein muss, um die Impulszählung durchzuführen. Dies ist nicht die beste Lösung, da wir, wenn sie aus irgendeinem Grund abgeschlossen ist, eine bestimmte Anzahl von Impulsen überspringen können, was für Abrechnungszwecke sehr wichtig ist. Um die Risiken zu minimieren, wurde beschlossen, einen eigenen Gerätetreiber zu schreiben, der direkt auf Kernelebene funktioniert.
Treffen Sie sich also: einen Treiber zum Zählen von Impulsen auf einer beliebigen GPIO-Leitung , der mithilfe der Device Tree-Technologie konfiguriert werden kann.

Voraussetzungen
  • Verwendet Linux Kernel Version 4.x oder höher
  • Kernel-Header-Dateien, die zum Erstellen verwendet wurden (normalerweise in / usr / include / linux auf dem Zielsystem)
  • -
  • Device Tree
  • Device Tree ( dtc)

Für meine Arbeit verwende ich die Assembly von Armbian , und auf deren Website können Sie auch die Kernel-Quellen verwenden, auf deren Grundlage die Assembly erstellt wurde. Grundsätzlich sollte es jedoch keine Einschränkungen für die Zielbaugruppe geben.
Ich beschreibe die Montage des externen Moduls nicht (und was? Im Prinzip gibt es viele Ressourcen mit einer solchen Beschreibung), daher glauben wir, dass Sie bereits vorgefertigte Zähler.ko gpio-puls.ko-Module für Ihren Kern zusammengestellt haben. Ich beschreibe den weiteren Prozess am Beispiel von Banana PI, aber analog kann er auf jede andere Plattform übertragen werden.

Öffnen Sie das Beschreibungsschild des Steckersauf der Tafel. Wir interessieren uns für den CON3-Anschluss (GPIO-Header). Wir wählen einen beliebigen Kontakt aus und bestimmen dessen Funktionalität (zum Beispiel hat mir Pin 12 am CON3-Anschluss gefallen, an den der Socket-Port PH2 ausgegeben wird). Wir überprüfen mit dem Allwinner A20-Datenblatt (GPIO-Multiplexing-Funktionstabelle) - der ausgewählte Port sollte die Erzeugung von Interrupts unterstützen (in meinem Fall ist es EINT2 in der Spalte Multi 6). Als nächstes müssen wir die Pin-Nummer in Bezug auf GPIO bestimmen, die dem ausgewählten Port (PH2) entspricht. Es war für mich einfacher, dies direkt auf dem Arbeitsgerät zu bestimmen:

# grep '(PH2)' /sys/kernel/debug/pinctrl/1c20800.pinctrl/pinmux-pins
Pin 226 (PH2): (MUX UNCLAIMED) (GPIO UNCLAIMED)

gleichzeitig und sichergestellt dass dieser Port derzeit von nichts verwendet wird (MUX und GPIO UNCLAIMED).

Jetzt können Sie eine Gerätebaumkonfiguration erstellen. Beispiele für einige Geräte finden Sie im Quellcode des Linux-Kernels im Ordner arch / arm / boot / dts. Für Banana heißt die PI-Datei sun7i-a20-bananapi.dts.
Darin nehmen wir folgende Änderungen vor:
/ {
        model = "Banana Pi BPI-M1";
        compatible = "sinovoip,bpi-m1", "allwinner,sun7i-a20";

...

        counters {
                compatible = "gpio-pulse-counter";
                gas-meter@0 {
                    label = "Gas meter";
                    pinctrl-names = "default";
                    pinctrl-0 = <&ext_counter_bananapi>;
                    /* CON3, pin 12: PH2 - pin 226 (Multi6 function: EINT2) */
                    /* bank: 226 / 32 = 7, pin into the bank 226 % 32 = 2 */
                    gpios = <&pio 7 2 GPIO_ACTIVE_LOW>;
                    interrupt-parent = <&pio>;
                    interrupt-names = "counter-edge-falling";
                    interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* PH2 / EINT2 */
                };
        };

&pio {
        ...

        /* External counter */
        ext_counter_bananapi: counter_pins@0 {
                allwinner,pins = "PH2";
                allwinner,function = "gpio_in";
                allwinner,drive = <SUN4I_PINCTRL_10_MA>;
                allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
        };
};


Der Parameter gpios im Knoten wird wie folgt berechnet:
  • Zuerst kommt ein Link zum Pio-Label;
  • Als nächstes folgt die Banknummer, die den gewünschten GPIO-Port enthält. Bei Allwinner A20 enthält jede Bank 32 Ports, sodass die Banknummer als ganzzahliger Teil der Division des GPIO-Pins durch 32 definiert ist.
  • Als nächstes kommt die PIN-Nummer in der Bank. weil Jede Bank hat 32 Pins, dann wird dieser Wert als Rest der Division des GPIO-Pins durch 32 berechnet.
  • Der letzte Parameter gibt an, welcher Signalpegel als aktiv angesehen wird

Der Interrupt-Parameter im Knoten wird wie folgt berechnet:
  • Der erste Parameter gibt die Interrupt-Nummer des GPIO-Controllers an (für EINT2 ist es 2).
  • Der zweite Parameter ist IRQ_TYPE_EDGE_FALLING, der die Erzeugung eines Interrupts ermöglicht, wenn das Signal von hoch nach niedrig wechselt (weil wir einen Sensor mit offenem Kollektor haben und auf + VCC gezogen werden).

Wir kompilieren die geänderte Gerätebaumdatei:
dtc -I dts -O dtb sun7i-a20-bananapi.dts > sun7i-a20-bananapi.dtb

Mit der resultierenden sun7i-a20-bananapi.dtb überschreiben wir die Datei in /boot/dtb/sun7i-a20-bananapi.dtb. Wir schreiben die
Kernelmodule counter.ko gpio-puls.ko irgendwo in / lib / modules / $ (uname -r) / Kernel / Treiber und laden Sie das Zielsystem. Auf dem geladenen Zielsystem geben wir den Befehl
depmod -a

und neu starten. Danach schauen wir uns die Ausgabe des Befehls dmesg an:
# dmesg
...
[    4.745570] counters: Class driver loaded.
[    4.749235] gpio_pulse: Device #0 gas-meter: IRQ: 53 GPIO: 226
...

Großartig, die Module sind geladen und funktionsfähig. Wir überprüfen die Funktionalität zuerst programmatisch:
# cat /sys/class/counters/counter0/values/count
0
# echo 1 > /sys/class/counters/counter0/values/pulse
# cat /sys/class/counters/counter0/values/count
1
# echo 1 > /sys/class/counters/counter0/values/pulse
# echo 1 > /sys/class/counters/counter0/values/pulse
# cat /sys/class/counters/counter0/values/count
3

(Wir haben ein Signal per Software nachgeahmt).

Jetzt schließen wir den Hallsensor an und stellen seine Funktionsfähigkeit sicher, indem wir einen Magneten anbringen (z. B. von einem Magnetaufkleber am Kühlschrank).

Nachwort


Endlich hatte ich Zeit Bilder zu posten. Also:

Eigentlich der Sensor. Sein empfindlicher Teil ist die Seite ohne Abschrägungen (das heißt, wir drücken, um das Messgerät unter der mindestensen Entladung).


Dann haben wir den Sensor mit Isolierband fixieren.


Für Stärke, ein Stück Schaumstoff in die Gaszähler für die Größe der Aussparung geschnitten und dann um den Sensor zu beheben.

Dann wir dieses Stück und den Draht mit Isolierband fixieren.


Well und das ist, was als Ergebnis passiert ist.


Für die Entscheidung über Verbindungselemente treten Sie bitte nicht mit den Füßen, weil Das Haus wird noch repariert und es handelt sich in der Tat um einen Prototyp.

Source: https://habr.com/ru/post/de386647/


All Articles