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.
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.
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);
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.
Vamos colocar uma parada na entrada da rotina loop() e executar até lá. Entre com os comandos “tbreak loop” e “c”:
Agora vamos executar a próxima linha e ver o conteúdo da variável ‘temperatura’. Entre com os comandos “next” e “print temperatura”:
Vamos ignorar neste primeiro momento o fato do valor estar errado e vamos ver os passos seguintes. Digite “next” duas vezes:
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():
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”:
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 Linguagem em C/C++ para Arduino da MakerHero =)