Como interpretar a direção de rotação de um seletor giratório digital com um PIC: 5 etapas
Como interpretar a direção de rotação de um seletor giratório digital com um PIC: 5 etapas
Anonim

O objetivo deste Instructable é ilustrar como fazer a interface de uma chave rotativa digital (codificada em quadratura) com um microcontrolador. Não se preocupe, vou explicar o que significa codificado em quadratura para nós. Esta interface e o software que o acompanha permitirão que o microcontrolador reconheça a direção de rotação para cada movimento de um detentor para outro. Recentemente, usei este tipo de chave em um projeto de microcontrolador que exigia que um ponto de ajuste de pressão fosse inserido usando um botão com 16 detenções em vez de botões para cima / para baixo. A ideia era permitir ao usuário "discar" a pressão desejada. Como resultado, tivemos que desenvolver uma rotina de software para obter as informações de posição da chave e deduzir a direção de rotação a fim de aumentar ou diminuir o ponto de ajuste de pressão para o sistema principal. Neste Instrutível, abordarei a interface física para o microcontrolador, a teoria de operação da chave rotativa, a teoria de operação do software bem como a rotina de dedução. Por fim, mostrarei minha aplicação da rotina de deduções. À medida que progredimos, tentarei manter as coisas um tanto genéricas para que a ideia possa ser aplicada no maior número de plataformas possível, mas também compartilharei o que fiz para que você possa ver um aplicativo específico.

Etapa 1: peças

Para implementar isso, você precisará de: Uma chave rotativa (codificada em quadratura) Puxe resistoresPlataforma de microcontrolador adequadaPara meu projeto, usei um codificador óptico Grayhill 61C22-01-04-02. A folha de dados da chave rotativa exige resistores pull up de 8,2 k ohm nas duas linhas de dados provenientes da chave. Você vai querer verificar a folha de dados do codificador que você optar por usar. A chave rotativa que usei também pode ser solicitada com uma chave de botão axial. É um recurso útil para confirmar seleções que foram discadas, etc., mas não discutirei sua interface aqui. Eu tenho uma "plataforma de microcontrolador adequada" listada porque (eu acho) isso pode ser implementado em mais de uma plataforma. Tenho visto muitas pessoas usando outros microcontroladores para Instructables, então quero mostrar a abordagem geral também. Eu escrevi todo o código no PIC Basic Pro para uso com um Microchip PIC16F877A. Na verdade, o principal que você precisa no microcontrolador é a capacidade de interromper quando houver uma alteração lógica em qualquer um dos dois pinos. No PIC16F877A, isso é chamado de interrupção de alteração PORTB. Pode haver outros nomes para ele em outros controladores. Esse recurso de interrupção do microcontrolador é parte do que torna essa implementação tão elegante.

Etapa 2: Interface de Hardware

Uma solução "simples" seria ter uma chave "single pole-16 throw" com 16 conexões para o microcontrolador. Cada saída do interruptor seria então ligada a um pino no microcontrolador para que cada posição do seletor pudesse ser verificada pelo microcontrolador. Este é um uso excessivo de pinos de E / S. As coisas ficam ainda piores se quisermos mais de 16 posições (detenções) disponíveis para nós no switch. Cada posição extra no switch exigiria uma entrada extra para o microcontrolador. Isso rapidamente se torna um uso muito ineficiente de entradas em um microcontrolador. Entre na beleza da chave rotativa. A chave rotativa tem apenas duas saídas para o microcontrolador listadas como A e B na planilha de dados. Existem apenas quatro níveis lógicos possíveis que essas linhas podem assumir: AB = 00, 01, 10 e 11. Isso reduz muito o número de linhas de entrada que você deve usar para conectar a chave ao microcontrolador. Portanto, reduzimos o número de linhas de entrada para apenas duas. O que agora? Parece que realmente precisamos de 16 estados diferentes, mas esta nova opção tem apenas quatro. Atiramos no próprio pé? Não. Leia. Vamos cobrir um pouco da teoria por trás da operação da chave rotativa para explicar.

Etapa 3: Teoria de Operação de Hardware

A detecção da direção de rotação é possível usando o interruptor "single pole-16 throw" mencionado acima, mas usa muitas entradas no microcontrolador. Usar a chave rotativa reduz o número de entradas para o microcontrolador, mas agora precisamos interpretar os sinais vindos da chave e traduzi-los para uma direção de rotação. Mencionei anteriormente que a chave era codificada em quadratura. Esta também é uma das elegâncias chave nesta solução. Isso significa que há um código de 2 bits fornecido pelo switch que corresponde à posição do switch. Você pode estar pensando: "Se houver uma entrada de dois bits para o microcontrolador, como representamos todas as 16 posições?" Esta é uma boa pergunta. Não representamos todos eles. Precisamos apenas saber as posições relativas do botão para que possamos determinar a direção de rotação. A posição absoluta do botão é irrelevante. Para rotação no sentido horário, o código que a chave fornece se repete a cada quatro detenções e é codificado em cinza. Codificado em cinza significa que há apenas uma mudança de bit para cada mudança de posição. Em vez da entrada AB contando para a rotação no sentido horário em binário como este: 00, 01, 10, 11, ela muda assim: 00, 10, 11, 01. Observe que para o último padrão, há apenas uma entrada mudando entre conjuntos. Os valores no sentido anti-horário para a entrada AB para o microcontrolador serão parecidos com estes: 00, 01, 11, 10. Isso é simplesmente o reverso do padrão no sentido horário com AB = 00 listado primeiro. Dê uma olhada nos diagramas para uma explicação mais visual.

Etapa 4: Teoria de Operação do Software

A rotina que deduz a direção de rotação é acionada por interrupção. O microcontrolador que você selecionar precisa ser capaz de interromper a qualquer momento em que houver uma mudança em qualquer um dos (pelo menos) dois pinos quando a interrupção estiver habilitada. Isso é chamado de interrupção de alteração PORTB no PIC16F877A. Sempre que a chave for girada, o microcontrolador será interrompido e a execução do programa será enviada para a Rotina de Serviço de Interrupção (ISR). O ISR descobrirá rapidamente para que lado o switch foi girado, definirá um sinalizador de forma adequada e retornará rapidamente ao programa principal. Precisamos que isso aconteça rapidamente, caso o usuário gire a chave muito rápido. Sabemos que o padrão AB codificado em cinza se repete a cada quatro posições, portanto, se fizermos a rotina funcionar para as transições entre essas quatro posições, ela funcionará para todas as outras. Observe que em um ciclo de quatro posições, existem quatro arestas. Uma borda de subida e uma borda de descida para a entrada A, bem como para a entrada B. O microprocessador será interrompido cada vez que houver uma borda, o que significa que o microcontrolador será interrompido sempre que o botão for girado. Como resultado, o ISR precisa descobrir para que lado o botão foi girado. Para nos ajudar a descobrir como fazer isso, voltamos para a forma de onda para rotação no sentido horário. Observe que sempre que A tem uma borda, seu novo valor é sempre diferente daquele de B. Quando o botão vai da posição 1 para a 2, A faz a transição da lógica-0 para a lógica-1. B ainda é 0 para esta transição e não corresponde ao novo valor de A. Quando o botão vai da posição 3 para 4, A tem uma borda descendente enquanto B permanece em lógico-1. Observe novamente que B e o novo valor de A são diferentes. Agora, podemos ver que sempre que A causa a interrupção durante a rotação no sentido horário, seu novo valor é diferente daquele de B. Vamos verificar B para ver o que acontece. B tem uma borda ascendente quando a chave faz a transição da posição 2 para 3. Aqui, o novo valor de B é o mesmo que A. Olhando para a última borda restante para a rotação no sentido horário, B tem uma borda descendente movendo-se da posição 4 para 5. (A posição 5 é igual à posição 1.) O novo valor de B é igual a A aqui também! Agora podemos fazer algumas deduções! Se A causa a interrupção e o novo valor de A é diferente daquele de B, a rotação foi no sentido horário. Além disso, se B causa a interrupção e o novo valor de B é igual a A, então a rotação foi no sentido horário. Vamos examinar rapidamente o caso da rotação no sentido anti-horário. Assim como a rotação no sentido horário, a rotação no sentido anti-horário causará quatro interrupções em um ciclo: duas para a entrada A e duas para a entrada B. A entrada A tem uma borda ascendente quando o botão se move da posição 4 para 3 e uma borda descendente se move da posição 2 para 1 Quando o botão giratório se move da posição 4 para a 3, o novo valor de A é igual ao valor de B. Observe que quando A se move da posição 2 para a 1, seu novo valor é igual ao de B também. Agora, podemos ver que quando A causa a interrupção e seu novo valor corresponde ao de B, a rotação era no sentido anti-horário. Rapidamente, examinaremos a entrada B para verificar tudo. B causará uma interrupção quando o botão se mover da posição 5 (que é o mesmo que 1) para 4 e quando o botão se mover da posição 3 para 2. Em ambos os casos, o novo valor de B não corresponde ao valor existente de A, que é o oposto dos casos em que B causa a interrupção da rotação no sentido horário. Esta é uma boa notícia. Tudo confere como deveria. Para resumir, se A causar a interrupção e seu novo valor não corresponder ao valor de B ou se B causar a interrupção e o novo valor de B corresponder ao valor de A, sabemos que houve rotação no sentido horário. Podemos verificar os outros casos para rotação no sentido anti-horário no software ou podemos supor que, porque não foi no sentido horário, foi no sentido anti-horário. Minha rotina simplesmente fazia suposições.

Etapa 5: Software

Não usei as interrupções integradas no PIC Basic Pro. Usei alguns arquivos que incluí no meu código de Darrel Taylor para conduzir a rotina. É aqui que pertence um grande crédito a Darrel! Os arquivos são gratuitos. Basta visitar seu site para obter mais informações, outros aplicativos e para baixar os arquivos. Você pode pular esta parte se não estiver usando um PIC com interrupções Darrel Taylor. Basta configurar as interrupções conforme necessário na plataforma que você está usando. Para configurar as interrupções Darrel Taylor (DT), há duas coisas a fazer: 1.) Incluir os arquivos DT_INTS-14.bas e ReEnterPBP.bas em seu code.2.) Copie e cole isso em seu código. Macro ASMINT_LIST; IntSource, Label, Type, ResetFlag? INT_Handler RBC_INT, _ISR, PBP, sim endm INT_CREATEENDASMInsira tabs e espaços como o gráfico no final do Instructable para que você possa ver as coisas um pouco mais facilmente em seu código. Você precisará modificá-lo ligeiramente para atender às suas necessidades. Em Etiqueta, substitua ISR pelo nome da sub-rotina que é seu ISR. Não se esqueça do sublinhado! Você precisa! Para fazer as interrupções funcionarem, há mais duas coisas a fazer: 1.) Escreva o ISR. Você escreverá isso da mesma forma que escreveria uma sub-rotina PBP, exceto que você precisará inserir @ INT_RETURN no final da sub-rotina em vez de RETURN. Isso reconhecerá a interrupção e retornará a execução do programa de onde parou no loop principal. Dentro do ISR, você precisa limpar o sinalizador de interrupção para que seu programa não seja pego em uma interrupção recursiva. A simples leitura do PORTB é tudo o que precisa ser feito para limpar o sinalizador de interrupção no PIC16F877A. Cada microcontrolador diferente tem uma maneira diferente de limpar os sinalizadores de interrupção. Verifique a planilha de dados do seu microcontrolador.2.) Quando você atingir o ponto em seu código em que deseja habilitar a interrupção, use esta linha de código: @ INT_ENABLE RBC_INT Quando você deseja desabilitar a interrupção, simplesmente use: @ INT_DISABLE RBC_INTHá muito de coisas reunidas no que acabei de cobrir, então vou resumir rapidamente. Até agora, seu programa deve ser parecido com isto:; Qualquer configuração necessária ou codeINCLUDE "DT_INTS-14.bas" INCLUDE "ReEnterPBP.bas" macro ASMINT_LIST; IntSource, Label, Type, ResetFlag? INT_Handler RBC_INT, _myISR, PBP, sim endm INT_CREATEENDASM; Qualquer outra configuração necessária ou código @ INT_ENABLE RBC_INT; Código que precisa saber para que lado o botão está girando @ INT_DISABLE RBC_INT; Outro códigoEND; Fim do programmyISR:; código ISR aqui @ INT_RETURN (Tabela de configuração do manipulador de interrupção) Acho que é aqui que qualquer pessoa que não esteja usando interrupções PIC ou DT pode entrar novamente. Agora, precisamos realmente escrever o ISR para que o microcontrolador saiba para que lado o botão está girando. Lembre-se da seção da teoria do software que podemos deduzir a direção de rotação se conhecermos a entrada que causou a interrupção, seu novo valor e o valor da outra entrada. Aqui está o pseudocódigo: Leia PORTB em uma variável de rascunho para limpar o sinalizador de interrupção. Verifique se A causou a interrupção. Se verdadeiro, compare A e B. Verifique se for diferente, se for diferente, foi a rotação no sentido horário Senão, foi no sentido anti-horário EndifCheck se B causou a interrupção. Se verdadeiro, compare A e B Verifique se for diferente, se for o mesmo, era rotação no sentido horário Else, era no sentido anti-horário EndifReturn from interruptComo sabemos se uma mudança em A ou B causou a interrupção? Descobrir o novo valor da entrada alterada e da outra entrada (inalterada) é fácil porque podemos lê-los dentro do ISR. Precisamos saber qual era o estado de cada um antes que a execução fosse enviada ao ISR. Isso acontece na rotina principal. A rotina principal fica parada e espera que uma variável de byte que chamamos CWflag seja definida como 1 ou limpa como 0 pelo ISR. Após cada mudança confirmada do botão giratório ou se não houver atividade do botão giratório, a variável é definida como 5 para indicar um estado ocioso. Se o sinalizador for definido ou apagado, a rotina principal imediatamente incrementa ou diminui a pressão do ponto de ajuste apropriadamente com base na rotação e, em seguida, define a variável CWflag de volta para 5 porque o botão está ocioso novamente. Como a rotina principal verifica o CWflag, ela também documenta o estado dos valores da chave rotativa A e B. Isso é realmente simples e tem a seguinte aparência: oldA = AoldB = BNão há nada muito sofisticado aqui. Basta incluir essas duas linhas no início do loop que verifica a rotação do CWflag. Estamos apenas atualizando os valores lógicos das entradas do botão rotativo dentro do loop de incremento / decremento na rotina principal para que possamos ver qual entrada causou a interrupção quando o ISR é executado. Aqui está o código ISR: ABchange: scratch = PORTB 'Ler PORTB para limpar o sinalizador de interrupção' Se A causar a interrupção, verifique B para o sentido de rotação IF oldA! = A THEN 'Se A e B são diferentes, era rotação no sentido horário IF A! = B THEN GOTO CW 'Caso contrário, era rotação anti-horária ELSE GOTO CCW ENDIF ENDIF' Se B causar a interrupção, verifique A para o sentido de rotação SE oldB! = B THEN 'Se A e B são iguais, era rotação no sentido horário SE A == B ENTÃO GOTO CW 'Caso contrário, era rotação no sentido anti-horário ELSE GOTO CCW ENDIF ENDIFCW: CWflag = 1 @ INT_RETURNCCW: CWflag = 0 @ INT_RETURNI incluí o código ISR em um arquivo AB_ISR.bas porque o as guias no código não estão aparecendo da maneira que deveriam. Agora, como o ISR tem os valores antigos para as entradas A e B, ele pode determinar qual entrada causou a interrupção, compará-la com a outra entrada (inalterada) e determinar a direção de rotação. Tudo que a rotina principal tem a fazer é verificar o CWflag para ver em qual direção o botão girou (se tiver girado) e aumentar ou diminuir um contador, ponto de ajuste ou o que você quiser ou precisar. Espero que isso ajude e não tenha sido muito confuso. Este tipo de interface é especialmente útil se o seu sistema já estiver usando interrupções, pois esta é apenas mais uma interrupção a ser adicionada. Aproveitar!