Como saber se o Display é anodo comum ou catodo comum no skecth ?

Boa tarde galera.

Encontrei na net um temporizador regressivo muito útil e de fácil montagem, exigindo poucos componentes e para iniciante seria uma boa aplicação para o dia-a-dia.

Embora simples, estava estudando o sketch e não consegui enxergar onde ele fala que o display é do tipo catodo comum. Se não fosse as linhas iniciais onde o autor diz que são necessários determinados componentes estaria sem saber o tipo. 

A parte do END também não funciona, segundo o vídeo, após setar o tempo, você poderá com um clic no encoder pausar e um longo clic você reset o timer.

Também acharia legal se o ponto DP piscasse a cada segundo.

Minha dúvida consiste em:

Como fazer para utilizar um display anodo comum ? 

Aí vai o esquematico e o codigo e o link do vídeo no youtube.

Valeu

JA

https://www.youtube.com/watch?v=acIrJ-GHCEc

 

Exibições: 4168

Anexos

As respostas para este tópico estão encerradas.

Respostas a este tópico

Boa tarde JAN,

vou tentafr te explicar como identificar (e mudar se for o caso) o tipo de display  AC ou CC.

Vamos lá. Olhando o code do cara:

Aqui ele define as constantes:

const uint8_t DIGIT_ON = LOW;         LOW significa 0V

const uint8_t DIGIT_OFF = HIGH;      HIGH significa +5V

Para um LED acender ele precisa de + no anodo e 0V no catodo.

E neste code para acender um segmento estando recebendo LOW no comum, (DIGIT), (Catodo)

será necessário HIGH  no pino do segmento. (anodo).

Ou seja para acender um segmento ele precisa de +5V no pino deste segmento.

Então no lado dos dígitos todos catodos  dos LEDs estarão ligados juntos e cada segmento será um anodo.

Se quiser usa AC (Anodo comum), inverta esta duas linhas:  HIGH/LOW,

const uint8_t DIGIT_ON = LOW;         LOW significa 0V

const uint8_t DIGIT_OFF = HIGH;      HIGH significa +5V

e inverta  todas definições dos dígitos  nas linhas abaixo de  ( onde tem 0 fica 1 e onde tem 1 fica 0),

// LED segments for digits
const PROGMEM uint8_t digits[] =                     e de

// LED segments for alpha characters
const PROGMEM uint8_t alpha[] =

Vou dar 2 exemplos de troca:  0x3f   =  0  =  0 0 1 1   1 1 1 1   mude para  0x0c  = 1 1 0 0   0 0 0 0 

                                                 0x77  =  A  =  0 1 1 1   0 1 1 1  mude para   0x88 =  1 0 0 0  1 0 0 0 

RV

PS; Achei estranho o autor não usar resistor pra limitar a corrente dos LEDs, e assim possibilitar a

queima ou o LED ou  do port do arduino.

Uma das soluções pra inverter um byte é fazer um  EXCLUSIVE  OR com 0xFF.

Por exemplo: 

0x3F  ^ 0xFF  =  0xC0

0x77  ^ 0xFF  =  0x88

RV

Entendi, 

Daria um pouco de trabalho, mais vou tentar fazer ok.

Obrigado por enquanto RV 

JA

boa tarde José.

     Sua dúvida é bem interessante e acredito que seja bem comum para a maioria das pessoas.

     A resposta é relativamente simples. Olhe o trecho de código que salientei no print a seguir:

     Como vc pode ver, onde eu marquei em "verde", está a codificação em 7 segmentos para os números de "0" a "9". Observe que é um Array de 10 valores do tipo byte ("uint8_t"). Para facilitar o entendimento, peguemos por exemplo o quinto elemento do Array, que é o valor "0x66" e que está representado em Hexadecimal (pois inicia com "0x"). Note no comentário nesta linha de programa, que o autor do código ressaltou que esse valor é a codificação em 7 segmentos para o número "4".

     Se vc traduzir este valor para binário, vai obter a sequencia de bits "0110 0110". Neste caso, cada bit corresponde a um segmento do Display, e este "mapeamento" está descrito no próprio esquemático junto ao Display. Você pode fazer o mapeamento que quiser, desde que nas ligações do circuito faça a correspondência correspondente com o programa. Neste circuito, estes bits correspondem aos pinos A5, A4, A3, A2, A1, A0, D13, e D12, e vc pode conferir isso na figura que preparei a seguir:

     Observe que o Display é do tipo "multiplexado". Ou seja, após colocar os níveis "1" e "0" nos pinos de segmentos, só vai ligar os segmentos do dígito cujo Katodo está também acionado. Os Katodos estão ligados aos pinos D4, D5, D6 e D7 (dígitos da esquerda para a direita), do Arduino. Para acionar um dígito, seu Katodo deve estar em nível "0". No print de código, você pode ver este mapeamento de dígitos no Array de 4 elementos, que salientei em "roxo", ou seja, o mapeamento indica qual pino corresponde a qual dígito (sendo que o dígito mais à esquerda é o primeiro elemento do Array, ou "digitPin[0]" ).

     Assim quando se quer ligar um dígito "n" (de 1 a 4), basta colocar em nível "0" o pino indicado pelo elemento "digitPin[n-1]" do Array "digitPin".  Na figura anterior, veja que eu acionei o dígito mais à esquerda (seria o dígito 1, ou seja n=1), via pino "D4" (ou seja, pino dado por digitPin[0] = 4).

   Note também que nos pinos A5, A4, A3, A2, A1, A0, D13, e D12, está setado o valor "0110 0110", lido do Array "segmentPin[4]" (ou seja, o valor 0x66).

   Se vc acompanhar as setas em rosa, vai ver o caminho que a corrente elétrica faz. Neste caso, um nível "1" nas saídas A5, A4, A3, A2, A1, A0, D13, e D12, fornece corrente que flui pelo segmento do dígito acionado, neste caso o dígito mais à esquerda (ou dígito 1), e os respectivos segmentos acendem, formando o número "4" em sete-segmentos.

    A conclusão é óbvia: você pode usar qualquer tipo de Display para o Hardware, seja Anodo comum ou Katodo comum. Isto porque basta alterar o Array "segmentPin[ ]" para que os segmentos sejam acionados para cada tipo de Display. Por exemplo, se o Display fosse Anodo comum, bastaria complementar bit a bit cada valor do Array conforme mostro a seguir:

const PROGMEM uint8_t digits[] =      // para Anodo comum (o "~" inverte os bits):
{
~0x3f, ~0x06, ~0x5b, ~0x4f,    // 0123
~0x66, ~0x6d, ~0x7d, ~0x07,  // 4567
~0x7f, ~0x6f                            //89
};

    Claro que para acionar um dígito de um Display Anodo comum, vc terá que colocar em nível "1", o pino correspondente ao dígito (D4, D5, D6, ou D7). Isto está na definição das constantes "DIGIT_ON" e "DIGIT_OFF" também no ínício do código. No programa atual está definido para Katodo comum. Para definir para Anodo comum ficaria assim:

// Digital state to turn each digit on or off during multiplexing   ==> para Anodo comum:
const uint8_t DIGIT_ON = HIGH;
const uint8_t DIGIT_OFF = LOW;

    Observe que para Anodo comum, o sentido das correntes invertem, já que flui do nível "1" para o nível "0", e no Anodo comum são os pinos de segmentos (A5, A4, A3, A2, A1, A0, D13, e D12) que estarão em nível "0".

     Então vc pode adequar seu programa ao seu Hardware da forma que for mais conveniente.

     Note técnica:  ao colocar o símbolo "~" na frente das constantes hexadecimais do tipo byte, vc pode obter um "warning" do compilador (de conversão "implícita"). Para evitar este warning, faça um "casting" como no exemplo a seguir:

(byte) ~0x66

    Outra forma é converter "no braço" e substituir pelo valor bruto: ~(0110 0110) = (1001 1001) = 0x99. Caso tenha dificuldade, use a calculadora do Windows para fazer a conversão bruta pra vc.

    Caso tenha alguma outra dúvida, fique à vontade para perguntar.

    Abrçs,

    Elcids

olá novamente, Maurício.

    Toda a explanação que fiz acima, está correta.

     No entanto quando olhei o código com mais cuidado, percebi que o autor já "deixou pronta" a seleção para você, seja Anodo comum ou Katodo comum. Esta seleção, dispensa vc ter que redefinir os Arrays "digits[ ]" e "alpha[ ]", ou seja, para especificar Katodo comum ou Anodo comum, não é necessário alterar os Arrays. O código já faz isso para você na linha 166:

digitalWrite(segmentPin[i], (val & 1 ? SEGMENT_ON : SEGMENT_OFF));

   Então como vc seleciona entre um tipo e outro?

   Basta alterar as definições das constantes "DIGIT_ON" e "DIGIT_OFF", nas linhas 141 e 142 do código.

   Para Katodo comum, está assim:

const uint8_t DIGIT_ON = LOW;      //  para Katodo comum.
const uint8_t DIGIT_OFF = HIGH;   //  para Katodo comum.

    Para Anodo comum basta trocar o "LOW" por "HIGH" e vice versa. Então ficaria assim:

const uint8_t DIGIT_ON = HIGH;    //  para Anodo comum.
const uint8_t DIGIT_OFF = LOW;   //  para Anodo comum.

     Feita esta alteração, veja que as linhas 143 e 144 (onde estão definidas as constantes "SEGMENT_ON" e "SEGMENT_OFF") automaticamente ajustam o nível de acionamento ("1" ou "0") para os segmentos do Display.

     Assim, estava mais fácil do que parecia. Basta mudar as definições do "DIGIT_ON" e "DIGIT_OFF " conforme mostrei acima.

     Mas espero que os detalhes que explicitei do funcionamento Hardware/Programa, ajudem a desmistificar o funcionamento dessas técnicas.

     Ah, sobre o que o "RV" mencionou sobre os resistores limitadores de corrente, seriam conveniente incluir um em série com cada segmento (portanto 8 resistores).  Um bom valor estaria entre 390 ohms e 1kohm.

    Abrçs

    Elcids

Opa Euclides,

Assim fica mais fácil. 

Mais também entendi sua explicação. 

const uint8_t DIGIT_ON = LOW; // (catodo comum)
const uint8_t DIGIT_OFF = HIGH; // (catodo comum)

/*

const uint8_t DIGIT_ON = HIGH; // (anodo comum)
const uint8_t DIGIT_OFF = LOW; // (anodo comum)

*/

const uint8_t SEGMENT_ON = (DIGIT_ON == HIGH ? LOW : HIGH);
const uint8_t SEGMENT_OFF = (DIGIT_OFF == HIGH ? LOW : HIGH);

    Isso mesmo José. Fazendo isso, os códigos das linhas originais 143, 144, e 166 fazem o resto para você.

    Em suma, estas linhas de código simplesmente invertem os níveis "0" e "1" existentes nos padrões de bits nos Arrays onde os caracteres núméricos e alfanuméricos estão definidos (os arrays "digits[ ]" e "alpha[ ]"), e também colocam os pinos D4, D5, D6 e D7 já nos níveis adequados para cada tipo de Display, não sendo necessário mais nenhuma outra ação para adequar o código ao tipo de Display.

      Mas pode ficar ainda mais simples, se você usar "#defines" no início do código para ajudar a selecionar o tipo do Display, como mostro no trecho de código a seguir (a seleção é feita na terceira linha útil do trecho de código, onde está definido "tipo_DISPLAY"):

#define  Katodo_comum 1

#define  Anodo_comum  2

#define  tipo_DISPLAY   Katodo_comum   // mudar para "Anodo_comum", se for o caso.

#if  tipo_DISPLAY == Katodo_comum


const uint8_t DIGIT_ON = LOW;     //  para Katodo comum.

const uint8_t DIGIT_OFF = HIGH;  //  para Katodo comum.


#endif

#if tipo_DISPLAY == Anodo_comum


const uint8_t DIGIT_ON = HIGH    //  para Anodo comum.

const uint8_t DIGIT_OFF = LOW;  //  para Anodo comum.


#endif

    Reforço a questão dos resistores: se vc for montar o circuito, é altamente aconselhável colocar um resistor em série com cada linha de segmento do Display, para limitar a corrente pelos LEDs dos segmentos. O valor dependeria da intensidade luminosa dos LEDs, mas normalmente valores entre 390 ohms e 1kohm são de bom tamanho. Ao todo seriam 8 resistores, conforme vc pode ver na figura a seguir:

     A colocação dos resistores nas linhas de segmento, também garante que a luminosidade seja igual cada caracter que seja exibido (se vc colocar em série com a linha comum, seja Anodo ou Katodo, a luminosidade mudará conforme a quantidade de LEDs ligados, ou seja, será diferente para cada padrão de caracter).

     Espero ter colaborado. Desculpe trocar seu nome no segundo post.

    Abrçs.

    Elcids.

Boa noite Elcids,/RV,

fiz a mudança do código, e compilei sem erros. 

Também inseri no circuito os resistores para evitar a queima das portas do arduino. 

Em anexo o cod modificado: 

Obrigado por enquanto Elcids (também me desculpe que mudei seu nome na ultima resposta).

Vou trabalhar na documentação (desenho e esquemático para postar aqui no fórum). 

Abçs

JA

Anexos

ok José.

    Que bom que colocou os resistores. Como eu disse antes, além de limitar a corrente de saída dos pinos do Atmega328 do Arduino, os resistores permitem você determinar a corrente mais adequada para os LEDs do Display, conforme a luminosidade que vc deseja. Se tiver dificuldade em calcular a corrente, me avise aqui que te instruo a fazer.

    Me lembrei que vc mencionou que alguma parte do código original, não estava funcionando adequadamente. Infelizmente não tive tempo de analisar a lógica de funcionamento do código original, pra saber se há algo que poderia não funcionar corretamente. Caso vc confirme que há algum problema, informe aqui, que te ajudo a resolver.

    Outra coisa:  como há chaves mecânicas no Sistema, não analisei se o autor do código tratou o "bouncing" das chaves (a trepidação mecânica que faz com que vários acionamentos ocorram quando se aciona apenas uma vez a chave). Caso não exista este tratamento, e se vc tiver problema com o "bouncing", avisa aqui que também te instruo a tratar isso. O tratamento pode ser feito via circuito, programa, ou ambos os métodos.

     Boa sorte com seu Sistema.

     Abrçs

     Elcids

Boa tarde JAN,

testei o code aqui e verifiquei que  ele não cancela a contagem  quando em pausa e  é 

apertado por um tempo maior o botão.

Deveria fazer como no  video , mas realmente não faz

Verifiquei todo o code e não encontrei razão para esta falha. Então resolvi verificar na biblioteca.

Estudei esta biblioteca que é usada para o botão. A  MD_KeySwitch, e verifiquei que ela tem um erro.

No arquivo   MD_KeySwitch.cpp  a linha 107  está assim:

  if (!b || !bitRead(_enableFlags, REPEAT_ENABLE))  

Se  o inverso da variável b   "or" com o inverso do bit "0" de _enableFlags  for igual a 1, 

significa que o botão foi apertado por um tempo grande e deveria informar para o code

o valor " KS_LONGPRESS  " .

Acontece que "b" é o valor do botão apertado  = 1  e o bit 0 de _enableFlags   também é 1.

 Inverso de 1 or inverso de 1 = 0;

Acho que tem um erro nesta linha da biblioteca.

Pra testar eu modifiquei a linha para:

if (b || !bitRead(_enableFlags, REPEAT_ENABLE))        ( removi o sinal de inverso da variável b),

e testei aqui e funcionou. 

Depois faz esta modificação e faz um teste ai, e conta pra gente.

RV

Boa noite a todos,

Rui, realmente hoje a tarde o nosso amigo Elcids verificou o sketch e comentou a mesma coisa.

Na parte da programação do END estava em ordem. 

Disse também que a biblioteca te dá a possibilidade de você programar o tempo do longpress.

Também se der uma olhada na biblioteca, verás que o tempo entre press, longpress, doblepress e o repeat é de apenas 50 miisegundos, motivo pelo qual ele ajustou o programa.

Também foi alterado para utilizar os DP duplo central (meu display tem dois pontos entre o 2º e 3 digito).

Estou postando o sketch modificado. 

Quando terminada a documentação, postarei aqui para os demais membros e visitantes. 

Mesmo assim também testarei seu cod e depois dou o feddback

Abçs 

JA

RV,

esqueci de atachar, ai vai.

Sds 

Anexos

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço