Como depurar Aplicações Arduino com o Wokwi Deixe um comentário

No post anterior nós vimos como usar o Wokwi para simular um projeto Arduino, interconectando os componentes e executando a aplicação. Neste post vamos ver como depurar aplicações usando o Wokwi, ou seja, para encontrar problemas no nosso código.

Conhecendo um pouco o GDB

Um depurador (debug) é um utilitário que possibilita analisar o comportamento de uma aplicação, fornecendo recursos como:

  • Executar o programa uma linha de cada vez
  • Executar o programa até que ele chegue a uma certa linha (breakpoint)
  • Verificar o conteúdo de uma variável
  • Alterar o conteúdo de uma variável

Desenvolvido inicialmente por Richard Stallman, o GDB (GNU debugger) é o depurador usado em muitos sistemas Unix-like (como o Linux). Uma adaptação (port) para os microcontroladores AVR (como os usados no Arduino Uno, Nano e outros) faz parte do projeto avr-gcc, que é usado na retaguarda da IDE do Arduino.

O GDB permite depuração tanto ao nível do fonte em uma linguagem de alto nível (como o C e C++) como ao nível de assembly e linguagem de máquina. Neste post vamos nos concentrar na depuração no nível do fonte.

Comandos do GDB

O GDB trabalha por comandos digitados (finalizados por Enter). As tabelas a seguir mostram alguns dos comandos, [linha] é um número de linha no fonte, [rotina] é o nome de uma rotina e [variável] é o nome de uma variável. Você pode digitar o comando completo ou apenas a sigla indicada na tabela

Execução do programa

Comando Sigla Descrição
continue c Executa a partir da posição atual
next n Executa a linha atual (não entra em rotinas)
step s Executa o próximo passo (entra em rotinas)
finish fin Executa até o retorno da rotina atual
Ctrl C Interrompe o programa

Pontos de parada (breakpoints)

Comando Sigla Descrição
info breakpoints I b Lista todos os pontos de parada programados
break [rotina] b [rotina] Coloca um ponto de  parada no início da rotina
break [linha] b [linha ] Coloca um ponto de parada na linha
tbreak [rotina] tb [rotina] Coloca um ponto de  parada temporário no início da rotina. Um ponto de parada temporário é retirado automaticamente quando a execução para nele
tbreak [linha] tb [linha] Coloca um ponto de parada temporário na linha
clear [rotina] cl [rotina] Remove os pontos de parada na rotina
clear [linha] cl [linha] Remove os pontos de parada na linha

Manipulação de variáveis

Comando Sigla Descrição
print [variavel] p [variavel] Mostra o valor da variável
set [variavel] = [valor] s [varialvel] = [valor] Altera o valor da variável

Montagem e Código de Teste

Para o nosso tutorial, vamos usar uma montagem simples com um Arduino Uno e um sensor de temperatura NTC, baseado no exemplo em: https://wokwi.com/projects/299330254810382858.

O objetivo do nosso código é acender o LED do Uno quando a temperatura passar de 37°C. Propositalmente eu cometi alguns erros que vamos diagnosticar e corrigir com o auxílio do GDB.

Código com erros propositais - Wokwi
Código com erros propositais – Wokwi

O projeto pode ser visto em https://wokwi.com/projects/331909293817201235.

Depurando o Código

Abra o projeto pelo link acima, clique na seta ao lado de Save e use a opção “Save a Copy” para criar uma cópia que você possa alterar.

Criando uma cópia do projeto
Criando uma cópia do projeto

Primeiro vamos confirmar que o programa tem problemas. Inicia a simulação (usando o botão ▶ no painel de simulação). Clique no sensor de temperatura, experiente mudar a temperatura e veja o comportamento do LED L (vermelho);

Simulação do projeto
Simulação do projeto

Confirmado que temos problemas, pare a simulação (botão ■).

Digite F1 (com o cursor no painel do código), “GDB”, e selecione “Start Web GDB Session (debug build)”. Uma nova guia será aberta, na primeira vez você terá que esperar um tempo até o GDB ser instalado. Ao final será apresentado “(gdb):” indicando que o GDB está pronto para receber um comando.

Wokwi Web GDB
Wokwi Web GDB

Vamos colocar uma parada na entrada da rotina loop() e executar até lá. Entre com os comandos “tbreak loop” e “c”:

Inserção de uma parada na entrada da rotina loop()
Inserção de uma parada na entrada da rotina loop()

Agora vamos executar a próxima linha e ver o conteúdo da variável ‘temperatura’. Entre com os comandos “next” e “print temperatura”:

Conteúdo da variável ‘temperatura’
Conteúdo da variável ‘temperatura’

Vamos ignorar neste primeiro momento o fato do valor estar errado e vamos ver os passos seguintes. Digite “next” duas vezes:

Confirmação que a condição "if" está incorreta
Confirmação que a condição “if” está incorreta

Hum, a temperatura está abaixo de 37 e acendemos o LED… a condição do ‘if’ está incorreta. Vamos corrigir isso. Feche a aba do gdb e pare a simulação. Altere a linha do ‘if’ para:

  if (temperatura > 37.0)

Execute de novo e veja que o comportamento do LED melhorou, mas a temperatura limite está errada (um pouco acima de 46°). Vamos investigar agora o cálculo da temperatura.

Pare a simulação, digite F1, selecione “Start Web GDB Session (debug build)”. Coloque o breakpoint em loop e execute até lá (como fizemos agora pouco). Em seguida, ao invés de “next” use “step”. Ao contrário do “next”, “step” entra no código das rotinas. Digitando várias vezes “step” você vai entrar até no código do analogRead():

Analisando o analogRead()
Analisando o analogRead()

Não queremos depurar o analogRead(), por isso vamos usar o comando “finish” para executar até a volta. Neste ponto ainda estamos no meio da execução da linha “soma +=converte(analogRead(A0));”. Use “next” para ir para linha seguinte (sem entrar passo a passo na rotina converte), e veja o valor de soma através de “print soma”:

Analise de que converte() funcionou
Analise de que converte() funcionou

O valor da soma após uma leitura está correto, o que indica que converte() funcionou. Digite “next” até sair do “for”, prestando a atenção em quantas leituras são feitas. Repare que só fizemos 4 leituras da temperatura, o nosso “for” está incorreto!

Vamos corrigir isso. Feche a aba do gdb e pare a simulação. Altere a linha do “for” para:

for (int i = 1; i <= 5; i++) {

Obs.: A forma acima é da contagem “humana”: contamos 1, 2, 3, 4, 5. A forma mais tradicional em C é contar como um computador: 0, 1, 2, 3, 4; neste caso seria:

for (int i = 0; i < 5; i++).

Execute a simulação e veja que agora está funcionando correto.

Neste exemplo rápido nós vimos como:

  • Iniciar o GDB dentro do wokwi
  • Executar até um ponto do programa (usando um ponto de parada temporário)
  • Executar o programa linha a linha e passo a passo
  • Executar o programa até sair da rotina atual
  • Examinar o conteúdo de uma variável

Conclusão

Neste artigo vimos o básico da depuração de aplicações no Wokwi usando o GDB e usamos este conhecimento para encontrar e corrigir erros em uma aplicação exemplo. Uma documentação mais completa pode ser vista em https://docs.wokwi.com/pt-BR/gdb-debugging.

E então, você já usou este recurso do Woki? Conte a sua experiência nos comentários!

E se estiver interessado em aprender mais sobre aimulção de Arduino usando o Wokwi, você pode conferir o Curso de Programação em C/C++ para Arduino da MakerHero =)

Faça seu comentário

Acesse sua conta e participe