Atualmente, meu esboço está verificando um pino de entrada toda vez em volta do loop principal. Se ele detectar uma alteração, chamará uma função personalizada para responder a ela. Aqui está o código (reduzido ao essencial):
int pinValue = LOW;
void pinChanged()
{
//...
}
void setup()
{
pinMode(2, INPUT);
}
void loop()
{
// Read current input
int newValue = digitalRead(2);
// Has the input changed?
if (newValue != pinValue) {
pinValue = newValue;
pinChanged();
}
}
Infelizmente, isso nem sempre funciona corretamente para alterações muito curtas na entrada (por exemplo, pulsos breves), especialmente se loop()
estiver um pouco lento.
Existe uma maneira de fazer o Arduino detectar a alteração de entrada e chamar minha função automaticamente?
Respostas:
Você pode fazer isso usando interrupções externas. A maioria dos Arduinos apenas suporta isso em um número limitado de pinos. Para detalhes completos, consulte a documentação em
attachInterrupt()
.Supondo que você esteja usando um Uno, você pode fazer assim:
Isso será chamado
pinChanged()
sempre que uma alteração for detectada na interrupção externa 0. No Uno, isso corresponde ao pino 2. do GPIO. A numeração da interrupção externa é diferente em outras placas, portanto, é importante verificar a documentação relevante.Existem limitações para essa abordagem. A
pinChanged()
função personalizada está sendo usada como uma rotina de serviço de interrupção (ISR). Isso significa que o restante do código (tudo incluídoloop()
) é temporariamente interrompido enquanto a chamada está em execução. Para evitar interrupções em qualquer momento importante, você deve tentar tornar os ISRs o mais rápido possível.Também é importante observar que nenhuma outra interrupção será executada durante o seu ISR. Isso significa que qualquer coisa que dependa de interrupções (como o núcleo
delay()
e asmillis()
funções) pode não funcionar corretamente dentro dele.Por fim, se o seu ISR precisar alterar quaisquer variáveis globais no esboço, elas geralmente devem ser declaradas como
volatile
, por exemplo:Isso é importante porque informa ao compilador que o valor pode mudar inesperadamente, portanto, tenha cuidado para não usar cópias / caches desatualizados.
fonte
pinChanged()
deve ser o mais curto possível. Portanto, normalmente o tempo mínimo deve ser o tempo para executar apinChanged()
própria função.volatile
, se a variável global for maior que 1 byte, como someNumber, você deverá se proteger contra a interrupção de alteração de pin que ocorre entre acessos de byte pelo programa. Uma declaração comosomeNumber +=5;
envolve a adição de bytes baixos e a adição de bytes altos com o carry incluído. Esses dois (mais, para variáveis mais amplas) não devem ser divididos por uma interrupção. Desligar as interrupções e restaurá-las antes e depois da operação (respectivamente) é suficiente.Qualquer estado de mudança em qualquer pino configurado como entrada digital pode criar uma interrupção. Diferentemente dos vetores exclusivos para as interrupções causadas pelo INT1 ou INT2, o recurso PinChangeInt usa um vetor comum e, em seguida, a Interrupt Service Routine (aka ISR) para esse vetor precisa determinar qual pino foi alterado.
Felizmente, a Biblioteca PinChangeInt facilita isso.
fonte
No caso de você desejar detectar uma tensão que ultrapassa um limite , em vez de ser apenas ALTA ou BAIXA, você pode usar o comparador analógico. Esboço de exemplo:
Isso pode ser útil para itens como detectores de luz, nos quais você pode precisar detectar uma mudança de (digamos) 1V para 2V em uma entrada.
Exemplo de circuito:
Você também pode usar a Unidade de captura de entrada no processador, que lembrará a hora exata de determinadas entradas, salvando a contagem atual do timer / contador 1. Isso permite armazenar o momento exato (bem, quase exato) que o evento de ocorreu um interesse, em vez de introduzir o atraso (provavelmente de alguns microssegundos) antes que um ISR possa ser usado para capturar a hora atual.
Para aplicações críticas de tempo, isso pode dar uma precisão um pouco maior.
Exemplo de aplicação: Transforme seu Arduino em um testador de capacitor
fonte