Compteur d'impulsions sous Linux (nous obtenons des informations sur le débit de gaz d'un compteur VK-G4)

Dans le processus d' automatisation domestique, il a été découvert que le débitmètre de gaz VK-G4 disponible présente une caractéristique intéressante: un aimant est intégré dans la décharge junior, ce qui peut fermer l'interrupteur à lames installé à l'extérieur de l'appareil lui-même (c'est-à-dire qu'aucune autorisation n'est requise pour le connecter compagnie gazière). Cela est même indiqué dans le passeport sur le comptoir lui-même. Certes, il est recommandé d'utiliser le «générateur d'impulsions basse fréquence IN-Z 61», mais en réalité ce n'est qu'un interrupteur à lames monté sur un compteur pour un prix insensé. Par conséquent, au lieu de l'IN-Z 61, il a été décidé d'utiliser le capteur Hall le moins cher avec une sortie numérique (c'est-à-dire avec un déclencheur Schmitt intégré).

Du capteur à effet Hall de type SS441A. Conformément à la fiche technique du SS44xA, le troisième chiffre code sa sensibilité magnétique, qui détermine l'emplacement physique du capteur sur le compteur de gaz.
En tant que système de contrôle, j'utilise un ordinateur Banana PI à carte unique exécutant Linux (noyau vanilla 4.2+). La connexion physique du SS44xA est très simple: nous
connectons la sortie (-) à un fil commun;
la sortie (+) est connectée à + 5V (et non à + 3,3V);
la broche (D) est connectée au port GPIO et tirée à travers une résistance de 4,7 kΩ à + 3,3V.
Mais quelle a été ma surprise quand je n'ai pas pu trouver de pilotes dans le noyau du noyau qui pourraient simplement compter le nombre d'impulsions sur un port GPIO donné! Je comprends que Linux n'est pas un système d'exploitation en temps réel, mais juste en comptant les impulsions basse fréquence ... Est-ce vraiment mon travail?
Après avoir examiné attentivement les dernières sources du noyau, deux solutions intermédiaires ont été découvertes:
  1. Utilisez un pilote UIO standard. Si un tel périphérique est ouvert en tant que fichier dans le programme d'application et que la valeur correspondante y est écrite, l'opération de lecture suivante de celui-ci sera suspendue jusqu'à ce qu'une interruption se produise en raison d'une modification du niveau de signal sur le GPIO correspondant;
  2. gpio_keys. GPIO «» (button) «» (switch), , .

L'utilisation de l'une de ces solutions nécessite une application démon qui doit être active pour effectuer le comptage d'impulsions. Ce n'est pas la meilleure solution, car si elle est complétée pour une raison quelconque, nous pouvons sauter un certain nombre d'impulsions, ce qui est assez critique à des fins comptables. Par conséquent, pour minimiser les risques, il a été décidé d'écrire notre propre pilote de périphérique qui fonctionnerait directement au niveau du noyau.
Alors, rencontrez: un pilote pour compter les impulsions sur une ligne GPIO arbitraire , configurable à l'aide de la technologie Device Tree.

Conditions préalables
  • Utilisé la version 4.x ou ultérieure du noyau Linux
  • Fichiers d'en-tête du noyau utilisés pour le construire (généralement situés dans / usr / include / linux sur le système cible)
  • -
  • Device Tree
  • Device Tree ( dtc)

Pour mon travail, j'utilise l'assembly d' Armbian , et sur leur site Web, vous pouvez également prendre les sources du noyau, sur la base desquelles l'assembly a été préparé. Mais, en principe, il ne devrait y avoir aucune restriction sur l'assemblage cible.
Je ne décris pas l'assemblage du module externe ici (et quoi? En principe, il y a beaucoup de ressources avec une telle description), nous pensons donc que vous avez déjà des modules counters.ko gpio-pulse.ko prêts à l'emploi assemblés pour votre noyau. Je décris le processus en utilisant l'exemple de Banana PI, mais par analogie, il peut être transféré sur n'importe quelle autre plate-forme.

Ouvrez la plaque signalétique du connecteursur le tableau. Nous sommes intéressés par le connecteur CON3 (en-têtes GPIO). Nous sélectionnons tout contact que nous aimons et déterminons sa fonctionnalité (par exemple, j'ai aimé la broche 12 du connecteur CON3, à laquelle le port de la prise PH2 est connecté). Nous vérifions avec la fiche technique Allwinner A20 (table des fonctions de multiplexage GPIO) - le port sélectionné doit prendre en charge la génération des interruptions (dans mon cas, c'est EINT2 dans la colonne Multi 6). Ensuite, nous devons déterminer le numéro de broche en termes de GPIO, qui correspond au port sélectionné (PH2). Il était plus facile pour moi de déterminer cela directement sur le périphérique de travail:

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

en même temps et vérifié que ce port n'est actuellement utilisé par rien (MUX et GPIO UNCLAIMED).

Vous pouvez maintenant créer une configuration d'arborescence de périphériques. Des exemples pour certains périphériques sont dans le code source du noyau Linux dans le dossier arch / arm / boot / dts, pour Banana le fichier PI est appelé sun7i-a20-bananapi.dts
Nous y apportons les modifications suivantes:
/ {
        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>;
        };
};


Le paramètre gpios dans le nœud est calculé comme suit:
  • Vient d'abord un lien vers le label pio;
  • Vient ensuite le numéro de banque, qui contient le port GPIO souhaité. Pour Allwinner A20, chaque banque contient 32 ports, donc le numéro de banque est défini comme la partie entière de la division de la broche GPIO par 32;
  • Vient ensuite le numéro d'identification à l'intérieur de la banque. Parce que chaque banque a 32 broches, puis cette valeur est calculée comme le reste de la division de la broche GPIO par 32;
  • Le dernier paramètre est une indication du niveau de signal considéré comme actif

Le paramètre d'interruptions dans le nœud est calculé comme suit:
  • Le premier paramètre indique le numéro d'interruption du contrôleur GPIO (pour EINT2 ce sera 2)
  • Le deuxième paramètre est IRQ_TYPE_EDGE_FALLING, qui permet la génération d'une interruption lorsque le signal passe de haut en bas (car nous avons un capteur à collecteur ouvert et tiré vers + VCC)

Nous compilons le fichier Tree Device modifié:
dtc -I dts -O dtb sun7i-a20-bananapi.dts > sun7i-a20-bananapi.dtb

Avec le résultat sun7i-a20-bananapi.dtb, nous remplaçons le fichier dans /boot/dtb/sun7i-a20-bananapi.dtb Nous écrivons les
modules du noyau counters.ko gpio-pulse.ko n'importe où dans / lib / modules / $ (uname -r) / noyau / pilotes et chargez le système cible. Sur le système cible chargé, nous donnons la commande
depmod -a

et redémarrez à nouveau. Après cela, nous regardons la sortie de la commande dmesg:
# dmesg
...
[    4.745570] counters: Class driver loaded.
[    4.749235] gpio_pulse: Device #0 gas-meter: IRQ: 53 GPIO: 226
...

Génial, les modules sont chargés et fonctionnels. Nous vérifions d'abord la fonctionnalité par programme:
# 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

(nous avons imité un signal par logiciel).

Maintenant, nous connectons le capteur Hall et nous assurons de son fonctionnement en lui apportant un aimant (par exemple, à partir d'un autocollant magnétique sur le réfrigérateur).

Épilogue


Enfin, j'ai eu le temps de poster des photos. Donc: en

fait, le capteur. Sa partie sensible est le côté sans biseaux ( à savoir, on appuie à l'appareil de mesure sous la moindre décharge).


Ensuite , on fixe le capteur de ruban isolant.


Pour plus de solidité, couper un morceau de mousse dans le compteur de gaz de la taille de l'encoche et en outre de fixer le capteur à elle.

Ensuite , on fixe cette pièce et le fil de ruban isolant


bien et c'est ce qui s'est produit en conséquence.


Pour la décision sur les fixations, veuillez ne pas vous botter les pieds, car la maison est toujours en cours de réparation et de luminaires, en fait, est un prototype.

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


All Articles