Performance do digitalWrite() no Arduino

Um dos sucessos da plataforma Arduino deve-se ao fato da facilidade de programação. O ambiente abstraí muitas informações pertinentes ao funcionamento do microcontrolador, para tornar a plataforma mais amigável possível.

 

Para se ter uma ideia, um programa compilado do Arduino, sem código nenhum (somente as declarações setup e loop) tem 444 bytes de tamanho. O ambiente inclui no código, muitos comandos necessários para o funcionamento do microcontrolador, mas que são ocultados.

 

Isso também acontece com as instruções utilizadas, como por exemplo: delay(), Serial.println(), analogRead(), map(), millis(), digitalWrite(), entre tantas outras….

 

Por trás de um simples comando digitalWrite() tem dezenas e dezenas de códigos que, com artifícios de programação, faz com que para o usuário se resuma em um única linha de comando.

 

Ah, mas que legal então!

 

Realmente, para a grande maioria de usuários essa abstração de código é uma beleza. Reduz o tempo de programação, fica mais fácil a interpretação do código. É bem mais didático.

 

Mas tudo tem seus prós e contras… Onde que se perde com isso?

 

Perde-se em principalmente em performance e tamanho, seu programa irá ficar desnecessariamente maior e mais lento e quando o projeto começar a tomar proporções maiores, pode definir o sucesso ou não da sua implementação.

 

O digitalWrite()

 

Quero mostrar aqui um exemplo prático de diferentes performances com um dos comandos mais usados durante uma programação. Ele é responsável por interligar o mundo virtual ao real. O primeiro contato com essa instrução já começa na sketch mais básica do ambiente Arduino, o hello world da plataforma: BLINK, o qual faz piscar o led da placa.

 

Vamos começar com um código básico, ligando e desligando as saídas 8 e 9 a cada 5 ms:

 

 

Compilou com tamanho final de 976 bytes.

 

Sem novidades no código até aqui… Vamos ver no osciloscópio o resultado:

 

Uso de digitalWrite

 

Temos ambas saídas ligando e desligando simultaneamente com o tempo ∆T = 5 ms como programado, perfeito!

 

Agora vamos dar um zoom no sinal bem na transição de descida do sinal:

 

 

Opaaa! Com o zoom observamos que o sinal não desce simultaneamente e acredite, o mesmo acontece com a subida. A diferença é de 4,24 us que em 16 MHz (frequência do cristal usado no Arduino UNO), corresponde a 68 ciclos de clock, entre a execução de um digitalWrite() para o outra. Parece ser rápido né, mas é muito lento para o mundo dos microcontroladores.

 

Para a maioria dos projetos, esse tempo entre as transições de pinos é excelente e pouco importa. No entanto, e se você precisar que essas transições aconteçam mais próximas? Pois bem, uma opção seria usar diretamente os registradores do microcontrolador, em vez do digitalWrite().

 

Registrador PORT

 

Nos bastidores, o digitalWrite() está fazendo um monte de coisas para você. Ele está mapeando o número do pino que você deu para um pino físico da placa. Em seguida, descobre o estado do pino. Ajusta o registrador apropriado para você. Todas essas coisas levam tempo.

 

Vamos ver o que acontece quando abrimos mão do digitalWrite().

 

Antes, uma breve e simples explicação: registradores são posições fixas na memória do microcontrolador onde cada posição desse registrador corresponde a uma função específica. Habilita-se ou desabilita-se essas funções específicas setando com valor 0 ou 1 na posição desejada.

 

Vejamos o registrador que vamos manipular: o PORTB.

 

 

PORTB mapeia o pinos digitais de 8 a 13 do Arduino, isto é, cada pino corresponde fisicamente a um bit desse registrador.

 

Os pinos que estamos usando nos testes são o 8 e 9, que correspondem ao PORTB0 (PB0) e PORTB1 (PB1) respectivamente do registrador PORTB.

 

 

Vale destacar que existem também o PORTC responsável pelos pinos A0 a A5 (PC0 a PC5) e O PORTD responsável pelos pinos 0 a 7 (PD0 a PD7), que têm o mesmo princípio de funcionamento do PORTB que veremos aqui.

 

Bom, sabendo disso, agora vamos ao novo código:

 

 

Repare que ao no lugar do digitalWrite(8, HIGH), usamos PORTB = PORTB | B00000001. Estamos escrevendo 1 diretamente no bit PORTB0 do registrador que corresponde fisicamente ao pino 8 do Arduino, ligando a saída.

 

Usamos o operador “|” que faz a operação lógica OU. Significa que onde tiver 1 na máscara B00000001 será setado em 1 no bit correspondente do registrador.

 

Já na outra parte do código, usamos o operador “&” que faz a operação lógica E. Já aqui, onde estiver setado em 0 na máscara B11111110, será setado em 0 no bit correspondente do registrador, desligando a saída.

 

Vamos visualizar o que essa pequena alteração no código fez na prática:

 

 

Alterou o tempo de 4,24 us para 140 ns, uma redução de 96% ou apenas 2 ciclos de clock.

 

Vamos ver lado a lado a diferença:

 

 

Impressionante né? Uma diferença muito significativa no tempo de execução.

 

Já no tamanho final do código tivemos uma redução também importante, de aproximadamente 20%, de 976 bytes para 776 bytes.

 

Vamos além, agora com esse outro código:

 

 

Veja que as máscaras estão diferentes. No operador de lógica OU “|” usamos B00000011 e no operador de lógica E “|” temos B11111100. Setamos os dois bits correspondentes aos pinos 8 e 9, simultaneamente na mesma instrução.

 

Olha como ficou no osciloscópio:

 

 

Os sinais mudaram simultaneamente!

 

Conclusão

 

Esse artigo visa trazer uma compreensão alternativa do ambiente Arduino. Mesmo se tratando de um ambiente de aprendizado, conseguimos ter acesso a funções avançadas. De um lado, a facilidade de programação e portabilidade entre diferentes placas, do outro, a redução de tamanho de código compilado e maior performance de execução. - "To be or not to be, that is the question”.

 

Saiba Mais

 

Lendo e Escrevendo nos pinos do Arduino com linguagem C/C++

Bits em Linguagem C - Conceito e Aplicação

E quando não havia o Arduino?

Usando os pinos digitais do Arduino

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Alexandre Fernandes dos Anjos
Graduando em engenharia de computação, técnico em eletrônica e informática. Tenho a eletrônica como hobby desde minha infância. Membro do Laboratório Hacker de Campinas - LHC, onde participo e contribuo ativamente das atividades. Atualmente trabalho como especialista em hardware, desenvolvendo soluções voltadas à IoT.

33
Deixe um comentário

avatar
 
15 Comment threads
18 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
18 Comment authors
Alexandre NunesLeonardo ArenzonLaercio Guerço RodriguesRicardo NoronhaAlexandre Fernandes dos Anjos Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Leonardo Arenzon
Visitante
Leonardo Arenzon

Excelente artigo Alexandre, parabéns!
Acredito que o Arduíno possa ser uma porta de entrada e até uma forma de despertar o interesse pelo mundo dos microcontroladores e sistemas embarcados. Porém fica difícil evoluir para projetos com maior complexidade sem ter conhecimento das características básicas da arquitetura do hardware. Acho que os fundamentos básicos até mesmo de operações lógicas e manipulação de registradores são fundamentais durante o desenvolvimento de um projeto. As pessoas que possuem esse tipo de conhecimento, com certeza se destacam pois possuem profundo domínio do que está sendo executado. Continue com seu excelente trabalho!

Laercio Guerço Rodrigues
Visitante
Laercio Guerço Rodrigues

Muito bom e esclarecedor este artigo. Para aqueles que dominam pouco os bastidores do Arduino, ficou muito fácil entender e da motivação para aplicar.

Parabéns.

Ricardo Noronha
Visitante
Ricardo Noronha

Parabéns pelo tópico, nada contra o arduino, mas essa abstração hj em dia mais prejudica do que ajuda a explicar como efetivamente funciona um MCU! Quem sabe com o tópico os interessados na plataforma n busquem mais informacoes!

Vagner Rodrigues
Visitante
Vagner da Masculino Rodrigues

Ótimo artigo, Alexandre!

Alexandre Fernandes dos Anjos
Visitante
Alexandre Fernandes

Obrigado Vagner

Larissa França
Visitante
Larissa França

Adorei o artigo!
Tem muito acadêmico montando robô sumô para pequenas competições e que sofrem com o tempo de resposta e principalmente por não conseguirem acionar portas simultaneamente utilizando o digitalWrite(). Acredito que esse artigo vai ajudar muitos alunos a ampliarem suas visões e buscarem se aprofundar mais nos microcontroladores em si.
As imagens tiradas do osciloscópio foram perfeitas para ilustrar. Parabéns e continue com o bom trabalho.

Valber
Visitante
Valber

Arduino é brinquedo de criança, um Lego.
Já deixou muito "profissional" na mão.
O pior que tem mesmo muita gente achando que é uma plataforma para desenvolver produtos.
Infelizmente pessoas tem embasado carreiras nisso.
Conheço caso onde os semáforos de trânsito estão sendo controlados por "Arduinos". Os sintomas são visíveis. Ficam apagados ou piscando em momentos que não deveriam.
Como se usa isso? Uma aplicação crítica, que não pode parar e que na minha opinião é de suporte a vida. Com Arduino? Essa turma não usa interrupções, não sabem o que é um WDT, com certeza.
Lamentável

Alexandre Nunes
Visitante
Alexandre

Sou obrigado a discordar, em parte, do amigo Valber. O que é o Arduino? Nada mais do que uma placa com Atmega, e só. Nada impede de usa-la programando no mais simples e puro C ou até mesmo em assembler. Eu muitas vezes usei esta placa para desenvolvimento de produto quando seria desnecessário um projeto de PCB sendo que poderia usar algo pronto. Claro, prefiro na maioria das vezes não usar o ambiente Arduino e suas bibliotecas prontas mas usar as minhas em C ou asssembler. Então, quando vejo alguém dizendo que Arduino não passa de brinquedo e não pode… Leia mais »

Paulo
Visitante
Paulo

Sensacional. Muito bem explicado e detalhado. Parabéns!

Gilter
Visitante
Gilter

Parabéns, muito importante mostrar esses "pequenos" detalhes que parecem irrelevantes para a nova geração Arduino mas são extremamente relevantes nas aplicações práticas. 4 microssegundos é uma eternidade em se tratando de eletrônica digital... Até mesmo aplicações corriqueiras como acionamento das bobinas de um motor de passo em altas velocidades, este atraso é suficiente para reduzir consideravelmente o desempenho. Imagine por exemplo a leitura dos sensores de um cronógrafo (equipamento para medir velocidade de projéteis). O Arduíno é uma plataforma muito interessante para desenvolvimento e aplicações didáticas, mas é muito importante compreender exatamente como funciona. Tenho um certo preconceito com alguns… Leia mais »

Arthur Teodoro
Membro
Arthur Teodoro

Muito legal o artigo, parabéns. Uma recomendação que pode interessar quem ficou assombrado com a disparidade entre os tempos é o livro AVR e Arduino, que já foi até tratado no Embarcados, nesse link: https://www.embarcados.com.br/livro-avr-e-arduino/. O livro é disponibilizado gratuitamente e pode ser um bom início nos estudos mais aprofundados sobre microcontroladores, uma vez que pode ser usada a plataforma Arduino, que é barata, fácil de usar, porém, mesmo assim, aproveitar o máximo que o ATmega pode liberar. Fica aí a dica para quem se interessou e novamente os parabéns para o Alexandre!

Rafael Machado
Visitante
Rafael

Ótimo explicação!!!
Parabéns pela didática!