Contador de impulsos no Linux (obtemos informações sobre o fluxo de gás de um contador VK-G4)

No processo de automação doméstica, descobriu-se que o medidor de vazão de gás VK-G4 disponível tem uma característica interessante: um ímã é incorporado à descarga de baixa ordem que pode fechar a chave reed instalada fora do próprio dispositivo (ou seja, não é necessária permissão para conectá-lo) empresa de gás). Isso é indicado no passaporte no próprio balcão. É verdade que é recomendável usar o "gerador de pulsos de baixa frequência IN-Z 61", mas, na realidade, é apenas uma chave reed montada em um medidor por um preço insano. Portanto, em vez do IN-Z 61, decidiu-se usar o sensor Hall mais barato com uma saída digital (ou seja, com um gatilho Schmitt integrado).

A partir do disponível foi retirado o sensor Hall tipo SS441A. De acordo com a folha de dados do SS44xA, sua sensibilidade magnética é codificada no terceiro dígito, que determina a localização física do sensor no medidor de gás.
Como sistema de controle, eu uso um computador Banana PI de placa única executando Linux (vanilla kernel 4.2+). A conexão física do SS44xA é muito simples:
conectamos a saída (-) a um fio comum;
a saída (+) está conectada a + 5V (e não a + 3,3V);
o pino (D) é conectado à porta GPIO e puxado através de um resistor de 4,7 kΩ para + 3,3V.
Mas qual foi a minha surpresa quando não consegui encontrar drivers de árvore do kernel que pudessem contar o número de pulsos em uma determinada porta GPIO! Entendo que o Linux não é um sistema operacional em tempo real, mas apenas contando pulsos de baixa frequência ... Realmente foi meu trabalho?
Tendo analisado cuidadosamente as fontes mais recentes do kernel, duas soluções intermediárias foram descobertas:
  1. Use um driver UIO padrão. Se um dispositivo desse tipo for aberto como um arquivo no programa aplicativo e o valor correspondente for gravado nele, a operação de leitura subsequente será suspensa até que ocorra uma interrupção devido a uma alteração no nível do sinal no GPIO correspondente;
  2. gpio_keys. GPIO «» (button) «» (switch), , .

O uso de qualquer uma dessas soluções exigirá um aplicativo daemon que deve estar ativo para executar a contagem de pulsos. Esta não é a melhor solução, porque, se for concluída por qualquer motivo, podemos pular um certo número de pulsos, o que é bastante crítico para fins contábeis. Portanto, para minimizar os riscos, foi decidido escrever nosso próprio driver de dispositivo que funcionaria diretamente no nível do kernel.
Portanto, conheça: um driver para contar pulsos em uma linha GPIO arbitrária , configurável usando a tecnologia Device Tree.

Condições prévias
  • Versão do kernel Linux usada 4.x ou posterior
  • Arquivos de cabeçalho do kernel usados ​​para construí-lo (geralmente localizado em / usr / include / linux no sistema de destino)
  • -
  • Device Tree
  • Device Tree ( dtc)

Para o meu trabalho, uso o assembly da Armbian e, no site deles, você também pode usar as fontes do kernel, com base nas quais o assembly foi preparado. Mas, em princípio, não deve haver restrições no conjunto de destino.
Não descrevo a montagem do módulo externo (e o quê? Em princípio, existem muitos recursos com essa descrição), portanto acreditamos que você já tenha os contadores prontos.ko módulos gpio-pulse.ko montados para o seu núcleo. Descrevo o processo posterior usando o exemplo do Banana PI, mas por analogia, ele pode ser transferido para qualquer outra plataforma.

Abra a placa de descrição do conectorno quadro. Estamos interessados ​​no conector CON3 (GPIO Headers). Selecionamos qualquer contato que gostamos e determinamos sua funcionalidade (por exemplo, gostei do pino 12 no conector CON3, ao qual a porta do soquete PH2 está conectada). Verificamos com a folha de dados do Allwinner A20 (tabela de funções de multiplexação GPIO) - a porta selecionada deve suportar a geração de interrupções (no meu caso, é EINT2 na coluna Multi 6). Em seguida, precisamos determinar o número do pino em termos de GPIO, que corresponde à porta selecionada (PH2). Foi mais fácil determinar isso diretamente no dispositivo em funcionamento:

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

ao mesmo tempo e certificou-se que esta porta não está sendo usada atualmente por nada (MUX e GPIO UNCLAIMED).

Agora você pode criar uma configuração da Árvore de Dispositivos. Exemplos para alguns dispositivos estão disponíveis nos arquivos de origem do kernel Linux na pasta arch / arm / boot / dts; para Banana, o arquivo PI é chamado sun7i-a20-bananapi.dts.
Nele, fazemos as seguintes alterações:
/ {
        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>;
        };
};


O parâmetro gpios no nó é calculado da seguinte maneira:
  • Primeiro vem um link para o rótulo do pio;
  • A seguir, é o número do banco, que contém a porta GPIO desejada. Para o Allwinner A20, cada banco contém 32 portas; portanto, o número do banco é definido como a parte inteira da divisão do pino GPIO por 32;
  • Em seguida é o número do pino dentro do banco. Porque cada banco possui 32 pinos, esse valor é calculado como o restante da divisão do pino GPIO por 32;
  • O último parâmetro é uma indicação de qual nível de sinal é considerado ativo

O parâmetro interrupts no nó é calculado da seguinte maneira:
  • O primeiro parâmetro indica o número de interrupção do controlador GPIO (para EINT2 será 2)
  • O segundo parâmetro é IRQ_TYPE_EDGE_FALLING, que permite gerar uma interrupção quando o sinal passa de alto a baixo (porque temos um sensor coletor aberto e puxado para + VCC)

Nós compilamos o arquivo da Árvore de Dispositivos modificado:
dtc -I dts -O dtb sun7i-a20-bananapi.dts > sun7i-a20-bananapi.dtb

Com o sun7i-a20-bananapi.dtb resultante, substituímos o arquivo em /boot/dtb/sun7i-a20-bananapi.dtb. Escrevemos os
módulos do kernel counters.ko gpio-pulse.ko em qualquer lugar em / lib / modules / $ (uname -r) / kernel / drivers e carregue o sistema de destino. No sistema de destino carregado, damos o comando
depmod -a

e reinicie novamente. Depois disso, examinamos a saída do comando dmesg:
# dmesg
...
[    4.745570] counters: Class driver loaded.
[    4.749235] gpio_pulse: Device #0 gas-meter: IRQ: 53 GPIO: 226
...

Ótimo, os módulos estão carregados e funcionais. Verificamos a funcionalidade primeiro programaticamente:
# 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

(imitamos um sinal por software).

Agora, conectamos o sensor Hall e garantimos sua operacionalidade, trazendo algum ímã para ele (por exemplo, de um adesivo magnético na geladeira).

Posfácio


Finalmente, tive tempo para postar fotos. Então:

Na verdade, o sensor. A sua parte sensível é o lado sem chanfros (isto é, que pressioná-lo para o contador sob o mínimo de descarga).


Em seguida, fixar o sensor com fita isolante.


Para maior resistência, cortar um pedaço de espuma para o contador de gás para o tamanho do recesso e, em seguida, fixar o sensor a ele.

Em seguida, fixar esta peça e o fio com fita isolante.


Bem e foi o que aconteceu como resultado:


para a decisão sobre fixadores, não chute o pé, porque a casa ainda está passando por reparos e acessórios, de fato, é um protótipo.

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


All Articles