Como eu poderia programar um comutador (baseado em relé de estado sólido ou triac) que é acionado com potência de cruzamento zero?
Para aqueles que não estão familiarizados com o assunto: Ligue a alimentação de 230V, quando a onda senoidal da linha de energia ultrapassar zero - o resultado é minimizar as perturbações eletromagnéticas resultantes do rápido aumento da corrente.
Especificamente, eu preferiria mudar o máximo possível para o software. O circuito de detecção que consiste em um pequeno transformador, um diodo e alguns resistores para manter os níveis e correntes sob controle fornece "1" quando a energia de entrada CA está na metade positiva, "0" em negativo, conectado a um pino GPIO de entrada. A saída consiste em alguns relés de estado sólido e itens essenciais para mantê-los funcionando (pull-ups, etc.), conectados aos pinos GPIO de saída.
O problema é o tempo: com 50Hz CA, obtemos 100 cruzamentos de zero em um segundo, um meio ciclo é 10ms. Para ficar a uma distância razoável do cruzamento de zero para manter o EMI baixo, não devemos ativar a saída mais de 10% após (ou antes) do evento de cruzamento de zero, isso significa tolerância de + -1ms. Isso não significa tempo de reação de 1 ms - podemos razoavelmente esperar que o próximo cruzamento de zero ocorra precisamente 10 ms após o primeiro ou o quarto - 40 ms. Trata-se de granularidade - se permitirmos 20ms para reação, deve ser entre 19 e 21ms, não 18 ou 22.
Como implementar esse GPIO de saída de disparo por timer dentro de 1ms desde que a entrada detecta uma borda ou dentro de um múltiplo fixo de 10ms desde então - de preferência com tolerância a algum viés negativo (por exemplo, o transformador e o relé introduzem um atraso de 1,6ms; então, eu quero que o gatilho dispare 8,4+ (n * 10) ms desde o pulso de entrada, dessa forma o viés neutraliza o atraso introduzido pelo circuito.) - é claro que "sob demanda do usuário", digamos, o usuário escreve "1 "para um arquivo / sys / class / ... e na oportunidade mais próxima (aproximadamente) a saída continua" ligada ". O usuário grava "0" e, quando o cruzamento de zero chega, o relé específico é desativado.
Eu acredito que isso exigiria escrever ou invadir um módulo do kernel. Você poderia me indicar o que lida com os pinos GPIO do Raspberry Pi no kernel e que tipo de temporizador eu poderia anexar a ele (a menos que já existam alguns) para obter esse tipo de funcionalidade?
Respostas:
Você não precisa hackear o kernel. Você só precisa mover o processo para fora da fila do planejador.
A partir de agora, nosso processo recebe
cat /proc/sys/kernel/sched_rt_runtime_us
milissegundos de cadacat /proc/sys/kernel/sched_rt_period_us
segmento de tempo de milissegundos, de execução ininterrupta sem risco de ser antecipado durante esse período (na prática, por padrão, no BerryBoot: 0,95s de segundo). Se precisar de mais, mexa com esses valores, mas não preciso mais para o meu propósito aqui.Estou usando uma função de timer em milissegundos (é sobre a precisão que preciso) com base no
clock_gettime()
relógio dos meus atrasos.A chamada
timer(1)
redefine, a chamadatimer(0)
retorna o tempo desde a redefinição.Você precisa vincular a
rt
biblioteca para que isso seja compilado - adicione-lrt
ao seu comando gcc.Agora, para o loop principal. Estou usando uma entrada de switch para "solicitação do usuário", mas você pode usar a rede, o timer ou o que for. Tudo o que você precisa é obter o valor booleano
in
.fonte
TRIAC_PIN
comoin
, eu teria que definir oTRIAC_PIN
como 1, aguardar um período determinado (em proporção a dimmer desejado) e, em seguida,TRIAC_PIN
volte a 0. Isso funcionaria?if(in==out) continue;
paraif(out==0) continue;
, certo? Na verdade, sou totalmente novo em programação para pi, então talvez isso não seja necessário - acho que tudo isso está acontecendo de forma síncrona (ou seja, não precisamos nos preocupar com o loop principal que está sendo chamado enquanto os loops aninhados ainda estão em execução)