
Passo 1 de 8
Identifique a etapa da falha
Classifique a falha antes de alterar o firmware e confirme a gravação antes de investigar o comportamento observado.
Trilha de aprendizado · Nível 10 · Tutorial 9
Localizar e corrigir falhas de compilação e execução em firmware com estados, temporizadores, interrupções e PWM, usando a IDE local, saídas de diagnóstico e casos reproduzíveis.
Identifique a etapa da falha
Classifique a falha antes de alterar o firmware e confirme a gravação antes de investigar o comportamento observado. 2 min
Encontre a causa na mensagem da IDE
Use a primeira mensagem relevante da IDE para corrigir símbolos e definições de vetor de forma localizada. 3 min
Prepare um caso que possa ser repetido
Estabeleça uma referência conhecida, registre uma sequência de teste e reduza uma variante sem eliminar a evidência necessária. 3 min
Torne o fluxo observável
Marque pontos do firmware com um sinal reservado, interprete o que um LED ou traço realmente mostra e limite a interferência do diagnóstico. 2 min
Diferencie as causas de falta de resposta
Diferencie bloqueio, erro de estado e falhas no atendimento de interrupções com marcas de fluxo e sequências reproduzíveis. 3 min
Descubra quem está alterando o recurso
Audite escritores de pinos e temporizadores para localizar configurações sobrescritas e conflitos de recursos. 3 min
Localize a falha nos dados compartilhados
Audite acessos entre ISR e loop, reconstrua intercalações vulneráveis e escolha uma proteção mínima conforme o tipo de dado. 3 min
Aplicação final: corrija e verifique o conjunto
Aplique uma correção localizada em uma variante reproduzível e confirme, pela mesma sequência de testes, o comportamento do botão, da sinalização temporal e do PWM. 3 min

Passo 1 de 8
Classifique a falha antes de alterar o firmware e confirme a gravação antes de investigar o comportamento observado.
Antes de mudar o firmware, descubra em que etapa ele parou. O fluxo tem quatro etapas:
Cada etapa exige uma evidência diferente. Um LED com comportamento inesperado só é evidência de execução; ele não explica um erro que impediu a compilação ou a gravação.

Localize a interrupção no fluxo antes de escolher a próxima ação.
Use a evidência produzida na etapa correspondente. Leia a saída completa da IDE, mas separe o diagnóstico específico do resumo final genérico.
| Etapa | O que está acontecendo | Evidência principal | Próxima pergunta |
|---|---|---|---|
| Compilação | Código é traduzido | Diagnóstico com arquivo e linha | Qual construção a mensagem aponta? |
| Ligação | Definições são combinadas | Mensagem sobre símbolo ou definição | Qual definição falta ou se repete? |
| Gravação | Programa vai para a placa | Mensagem de transferência da IDE | A placa, porta e conexão foram aceitas? |
| Execução | Versão gravada começa a rodar | Observação da montagem após reset | O comportamento coincide com o esperado? |
Dica
A ordem importa: só investigue o comportamento da nova versão depois que a IDE confirmar a gravação. Até lá, não conclua que uma mudança no código “não funcionou”.
Você altera o código para mudar o ritmo do LED. A IDE mostra erro de gravação. Mesmo assim, o LED continua piscando como antes.
Qual é a conclusão mais bem sustentada?
Escolha a etapa que precisa ser resolvida antes de interpretar o LED.
| Observação | Conclusão válida |
|---|---|
| A IDE falhou ao gravar | A nova versão pode não estar na placa |
| O LED mantém o padrão antigo | A placa pode estar executando a versão anterior |
| Ainda não há confirmação de gravação | Não é válido diagnosticar a lógica nova |
Qual ação vem primeiro?
Escreva pelo menos 20 caracteres (0/20).
Associe cada situação à etapa em que a evidência deve ser examinada primeiro.
Escreva pelo menos 80 caracteres (0/80).
Exemplo
Use este formato na sua resposta:

Passo 2 de 8
Use a primeira mensagem relevante da IDE para corrigir símbolos e definições de vetor de forma localizada.
Quando a IDE falhar, não comece pelo resumo final, como “erro ao compilar”. Leia o primeiro diagnóstico que aponta um arquivo, uma linha e um problema específico. Mensagens abaixo dele podem ser consequências do mesmo erro.
Siga este roteiro:
Assim, você evita corrigir sintomas em cascata ou alterar nomes ao acaso.
O fluxo visual mostra por que a primeira mensagem específica deve guiar a investigação.

A primeira mensagem específica costuma apontar a construção que deve ser verificada primeiro.
Exemplo
Exemplo de leitura:
sketch.ino:24:5: error: 'OCR1AA' was not declared in this scope
A parte útil não é o resumo de falha ao fim da saída. Ela informa o arquivo (sketch.ino), a linha (24), a coluna (5) e o identificador que a compilação não reconheceu (OCR1AA). Ao abrir essa linha, compare o nome usado com o registrador esperado, OCR1A.
Nem todo símbolo não reconhecido tem a mesma causa. Use o contexto do arquivo, da placa selecionada e da linha indicada para separar hipóteses.
No Uno R3, símbolos como OCR1A, TCCR1B e TIMER1_COMPA_vect pertencem ao ambiente AVR. Se a placa selecionada não for compatível com AVR, esses nomes não representam o hardware selecionado. Volte à seleção da placa antes de editar o firmware.
Se a placa for o Uno R3 e apenas um nome próximo falhar, examine a grafia. OCR1AA não é um registrador válido: acrescentar ou remover um caractere pode ser a única correção necessária.
Dica
Outras possibilidades dependem do contexto:
.ino, o ambiente Arduino normalmente prepara inclusões básicas. Não conclua que falta um cabeçalho apenas porque um símbolo falhou..cpp, a inclusão necessária pode realmente não estar presente nesse próprio arquivo. Para usar construções de ISR AVR nele, verifique se ele inclui o cabeçalho apropriado.A evidência deve combinar mensagem, arquivo e configuração atual.
Qual é a melhor primeira ação diante de OCR1AA was not declared in this scope em uma linha do seu sketch, com Uno R3 selecionado?
Escreva pelo menos 30 caracteres (0/30).
Um erro de ligação como “multiple definition of __vector_11” costuma indicar que duas partes do programa definiram a mesma rotina de interrupção. A causa pode estar em dois trechos do sketch ou em um arquivo incluído.
Não troque o nome do vetor apenas para fazer o erro desaparecer. Para a comparação A do Timer1 no Uno R3, o vetor continua sendo TIMER1_COMPA_vect. Procure todas as ocorrências de ISR( e deixe um único responsável por esse vetor. Se houver comportamentos necessários nas duas rotinas, reúna o registro mínimo de eventos em uma única ISR curta e deixe o processamento para o loop().
Mantenha somente uma definição para o vetor de comparação A do Timer1.
#include <avr/interrupt.h>
volatile bool tickPendente = false;
ISR(TIMER1_COMPA_vect) {
tickPendente = true;
}
Complete o nome do vetor na única definição de ISR destinada à comparação A do Timer1. A correção não é criar outro nome: é associar a rotina ao vetor correto e garantir que não exista uma segunda definição dele.
Escreva pelo menos 15 caracteres (0/15).
Após mudar uma grafia, uma inclusão ou uma definição duplicada, compile de novo imediatamente. Só depois avalie a próxima mensagem que permanecer. Uma correção localizada pode eliminar vários avisos derivados.
Use uma sequência curta de verificação:
Enquanto a compilação falha, não investigue o comportamento da placa: a nova versão ainda não está pronta para ser gravada.
Uma saída mostra primeiro OCR1AA was not declared in this scope na linha 24 e, depois, um resumo “erro ao compilar”. Após trocar apenas OCR1AA por OCR1A, qual mensagem deve orientar sua próxima ação se a compilação ainda falhar?
Escreva pelo menos 45 caracteres (0/45).

Passo 3 de 8
Estabeleça uma referência conhecida, registre uma sequência de teste e reduza uma variante sem eliminar a evidência necessária.
Um caso reproduzível é uma receita de teste: outra execução, nas mesmas condições, deve permitir comparar o resultado. Antes de remover ou alterar código, registre:
“Não funciona” não é reproduzível. Já “após reset, D13 alterna; após um pressionamento estável em D2, D3 troca de brilho” define uma sequência verificável.

A mesma montagem, condição inicial e sequência tornam significativa a comparação entre versões.
Atenção
Monte somente em baixa tensão e alimente a placa por uma única conexão USB apropriada. Use resistor em série com o LED externo para manter a corrente pequena. Desconecte o USB antes de mudar fios. Não conecte uma segunda fonte ao pino de 5 V ou a VIN durante esta prática.
Crie um sketch novo na sua IDE. Copie os três blocos a seguir no mesmo arquivo e nesta ordem. Esta referência mantém responsabilidades separadas:
ticks e permanece curta;loop() lê ticks como instantâneo protegido;Compile e grave a referência antes de testar uma variante. Só compare o comportamento após a IDE confirmar a gravação.
Bloco 1 — cole no início do mesmo sketch.
#include <avr/interrupt.h>
#include <util/atomic.h>
const uint8_t PINO_BOTAO = 2;
const uint8_t PINO_PWM = 3;
volatile uint16_t ticks = 0;
bool leituraAnterior = HIGH;
bool botaoEstavel = HIGH;
unsigned long mudouEm = 0;
const unsigned long DEBOUNCE_MS = 30;
bool brilhoAlto = false;
void configurarTimer1() {
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31249; // 500 ms com prescaler 256
TIFR1 = _BV(OCF1A); // limpa pendência
TIMSK1 = _BV(OCIE1A); // comparação A
TCCR1B = _BV(WGM12) | _BV(CS12); // CTC e prescaler 256
}
ISR(TIMER1_COMPA_vect) {
PINB = _BV(PB5); // alterna D13
ticks++;
}
Bloco 2 — cole logo após o bloco 1.
void setup() {
pinMode(PINO_BOTAO, INPUT_PULLUP);
pinMode(PINO_PWM, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
analogWrite(PINO_PWM, 40);
configurarTimer1();
}
Bloco 3 — cole após o bloco 2. O sketch estará completo. Compile, grave e confira visualmente o resultado na sua montagem.
void loop() {
bool leitura = digitalRead(PINO_BOTAO);
unsigned long agora = millis();
if (leitura != leituraAnterior) {
leituraAnterior = leitura;
mudouEm = agora;
}
if ((agora - mudouEm >= DEBOUNCE_MS) &&
(leitura != botaoEstavel)) {
botaoEstavel = leitura;
if (botaoEstavel == LOW) {
brilhoAlto = !brilhoAlto;
analogWrite(PINO_PWM, brilhoAlto ? 180 : 40);
}
}
uint16_t copiaTicks;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
copiaTicks = ticks;
}
(void)copiaTicks;
}
Após a gravação bem-sucedida e um reset: - D13 alterna visualmente aproximadamente a cada 500 ms. - O LED externo em D3 começa com brilho baixo. - Após um pressionamento estável em D2, D3 muda para brilho mais alto. - Após soltar e pressionar D2 de novo de forma estável, D3 retorna ao brilho baixo. - D13 continua alternando durante os acionamentos.
Resultado visual esperado, não uma medição de precisão: a alternância observada de D13 ocorre aproximadamente a cada 500 ms, e o brilho percebido em D3 depende também do LED e do ambiente.
Faça a sequência sem Monitor Serial:
Registre observações, não causas. Exemplo útil: “referência; reset; D13 alternou visualmente; primeiro pressionamento mudou D3 para brilho alto; segundo pressionamento retornou ao brilho baixo”.
Use esta mesma sequência para a referência e para cada variante.
| Ação | Resultado esperado | Seu observado |
|---|---|---|
| Reset e espera | D13 alterna; D3 em brilho baixo | Anote |
| Primeiro pressionamento estável em D2 | D3 muda para brilho alto | Anote |
| Soltura de D2 | D3 mantém o brilho atual | Anote |
| Segundo pressionamento estável | D3 volta ao brilho baixo; D13 continua | Anote |
Ao investigar uma variante, mantenha a referência intacta e trabalhe em uma cópia. Retire ou neutralize uma função por vez, compile, grave e repita a sequência registrada.
Uma simplificação só é útil se o sintoma continuar e se as dependências do sintoma permanecerem. Se a pergunta é “D3 muda de brilho após D2?”, retirar temporariamente o Timer1 pode ser uma redução válida: botão e PWM continuam presentes. Remover a leitura de D2, porém, invalida a comparação, porque o evento que deveria provocar a mudança desapareceu.
Após cada alteração isolada, anote o que permaneceu, o que foi retirado e se o sintoma ainda ocorreu.
Atenção
Ordene um procedimento para investigar uma variante sem perder a capacidade de comparar resultados.
Coloque as ações na ordem mais confiável.
O sintoma de uma variante é: “D3 não muda de brilho após um pressionamento estável em D2”. Qual simplificação mantém uma comparação válida para investigar a participação do Timer1?

Passo 4 de 8
Marque pontos do firmware com um sinal reservado, interprete o que um LED ou traço realmente mostra e limite a interferência do diagnóstico.
Uma marca de diagnóstico responde a uma pergunta delimitada: “a execução chegou até este ponto?” Escolha pontos que separem caminhos possíveis: antes e depois de uma chamada suspeita, na transição de estado ou na entrada e na saída de uma ISR.
No caso-base, reserve D7 para a marca. Não use D13, que já é a sinalização temporal, nem D3, que permanece sob PWM. Assim, o diagnóstico não disputa o pino cuja função você quer verificar.
Para observar um nível persistente por LED, desconecte o USB e monte um LED próprio em D7: D7 → resistor em série → ânodo do LED; cátodo → GND. Use corrente pequena, como nas práticas anteriores. Reconecte somente depois de conferir a montagem. Se tiver osciloscópio ou analisador lógico, também pode observar D7 diretamente com a ponta no pino e a referência do instrumento no GND da montagem.

D7 é uma marca independente: D13 e D3 continuam disponíveis para observar as funções originais.
No sketch de referência do step anterior, não copie outro setup() nem outro loop(). Faça somente estas alterações localizadas:
const uint8_t PINO_MARCA = 7;.setup() que já existe, acrescente a configuração de D7.analogWrite(...) e baixo logo depois dela.Esse primeiro teste usa uma chamada que realmente existe no caso-base. Ela normalmente retorna muito rápido: o LED em D7 pode não mostrar nada visível, mas um instrumento pode revelar um pulso. Em uma variante que contenha uma chamada realmente suspeita, use as mesmas duas marcas ao redor daquela chamada, sem alterar sua posição no fluxo.
Linhas para acrescentar ao sketch de referência. A segunda parte substitui somente a chamada analogWrite(...) que já está dentro de if (botaoEstavel == LOW).
// Acrescente perto das outras constantes globais:
const uint8_t PINO_MARCA = 7;
// Acrescente dentro do setup() que já existe:
pinMode(PINO_MARCA, OUTPUT);
digitalWrite(PINO_MARCA, LOW);
// Dentro de loop(), substitua apenas esta linha existente:
// analogWrite(PINO_PWM, brilhoAlto ? 180 : 40);
// por estas três linhas:
digitalWrite(PINO_MARCA, HIGH); // antes da chamada
analogWrite(PINO_PWM, brilhoAlto ? 180 : 40);
digitalWrite(PINO_MARCA, LOW); // só ocorre após o retornoApós um pressionamento estável no caso-base: D3: alterna entre os níveis de brilho 40 e 180. D7 com LED: pode parecer apagado, pois a marca é muito curta. D7 com instrumento: pulso que sobe antes de analogWrite e desce após a chamada. Se uma chamada substituída não retornar: D7 com LED: permanece aceso. D7 com instrumento: sobe e permanece em nível alto durante a observação.
O resultado é físico, não uma saída no Monitor Serial. Com um LED, o pulso curto pode não ser perceptível; com instrumento, procure uma subida seguida de descida em D7.
A marca alta antes de uma chamada e baixa depois dela tem uma interpretação limitada, mas útil:
Para marcar uma ISR, o princípio é o mesmo: coloque D7 alto na entrada e baixo antes de sair. Não use delay(), laços de espera nem uma marca baseada apenas em millis(). Se a hipótese for interrupções globais desabilitadas, uma observação dependente de serviços temporais pode falhar junto com aquilo que você tenta investigar.
Dica
Um LED mostra bem um nível persistente ou uma mudança lenta. Ele não mede a duração de um pulso: brilho fraco, apagado ou aparentemente contínuo não prova quantos microssegundos D7 ficou alto.
Para pulsos na entrada e saída de ISR, use um osciloscópio ou analisador lógico próprio, se disponível. Trabalhe apenas na montagem de baixa tensão, confirme que os níveis aceitos pelo instrumento são compatíveis e conecte primeiro a referência de terra ao GND da montagem. Uma marca deve ser curta e sem espera; depois de inseri-la, repita a sequência conhecida e compare se o sintoma mudou.
Após um pressionamento estável, um osciloscópio mostra em D7 um pulso alto de poucos microssegundos: há uma borda de subida e, logo depois, uma borda de descida. O LED externo em D7 parece não mudar. Qual conclusão é mais bem sustentada?
Você suspeita que uma variante manteve as interrupções globais desabilitadas. Qual marca é mais adequada para verificar se o fluxo passa por uma região do loop()?

Passo 5 de 8
Diferencie bloqueio, erro de estado e falhas no atendimento de interrupções com marcas de fluxo e sequências reproduzíveis.
Um LED parado é um sintoma, não um diagnóstico. Para separar causas, observe marcas em três regiões independentes:
loop();Compare essas marcas após uma sequência conhecida: reset, pressionar o botão, manter pressionado, soltar e aguardar. Uma hipótese ganha força quando explica o conjunto de evidências — não apenas uma saída imóvel.
Importante: o PWM é gerado pelo hardware. Um LED com brilho PWM pode continuar aceso mesmo se o loop() estiver bloqueado. Da mesma forma, o Timer1 pode continuar comparando enquanto sua ISR não é atendida.

As comparações e o PWM podem permanecer ativos no hardware enquanto o atendimento do firmware falha.
Use as marcas como evidência combinada. Elas devem ser curtas e não usar delay(); ao investigar interrupções indisponíveis, não faça a marca depender somente de millis().
| Hipótese | Evidência mais útil | Interpretação inicial |
|---|---|---|
| Espera bloqueante no loop | Marca antes da chamada aparece; a posterior atrasa | O fluxo não retorna durante a espera |
| Condição de estado impossível | Marca do loop continua; transição esperada não ocorre | O evento não satisfaz a regra de transição |
| ISR excessivamente longa | Entrada da ISR aparece; saída demora | A ISR retém a execução e adia o loop |
| Interrupções desabilitadas | Comparação ocorre; entrada da ISR não aparece | O evento de hardware não está sendo atendido |
Uma sequência conhecida também revela erros lógicos sem depender de “acontecer por acaso”. Suponha que, após reset, o firmware esteja em ESPERA e que um pressionamento de botão deva levá-lo a ATIVO.
No trecho abaixo, a condição pede simultaneamente botão pressionado e estado ATIVO. Como o botão é justamente o evento que deveria sair de ESPERA, essa transição nunca acontece. A marca do loop pode continuar normal; o que falta é a marca de entrada em ATIVO.
Trecho para inspecionar: o estado inicial é ESPERA.
if (botaoPressionado && estado == ATIVO) {
estado = ATIVO;
marcaEntradaEstado();
}Outro erro frequente preserva a condição correta, mas apaga o tempo decorrido. Se esta linha estiver dentro do trecho executado repetidamente enquanto o estado é AGUARDANDO, a referência é renovada antes de completar 500 ms. A condição temporal permanece falsa.
A evidência esperada é: o fluxo principal continua passando, mas a transição temporal não ocorre. Verifique se a marca de entrada no estado foi alterada uma única vez na transição, e não em toda passagem pelo estado.
Trecho para inspecionar: entradaEstado deveria representar o instante de entrada no estado.
case AGUARDANDO:
entradaEstado = millis();
if (millis() - entradaEstado >= 500) {
estado = ATIVO;
}
break;Relacione cada hipótese à observação que mais diretamente a sustenta.
Toque em um item e depois no par correspondente.
Durante o teste, o LED PWM em D3 mantém o brilho, mas a resposta ao botão parou. A marca periódica do fluxo principal também deixou de aparecer. Qual é o próximo teste mais discriminante?

Passo 6 de 8
Audite escritores de pinos e temporizadores para localizar configurações sobrescritas e conflitos de recursos.
Quando uma função deixa de responder, não suponha que a última linha alterada seja a causa. Faça uma auditoria dos escritores: para cada recurso, registre sua função esperada, todos os trechos que podem configurá-lo ou comandá-lo e quando isso acontece.
Um recurso pode ser um pino, um registrador ou um temporizador. Dois escritores podem parecer funcionar isoladamente, mas disputar o mesmo hardware ao longo da execução.
Dica
Neste caso-base, a divisão compatível mantém o Timer0 para os serviços do núcleo Arduino, usa o Timer1 somente para a sinalização temporal em CTC e reserva o Timer2 para o PWM no D3. Um PWM esperado em D9 ou D10 não é compatível com essa configuração do Timer1.

O mesmo Timer1 não deve ser, ao mesmo tempo, reconfigurado para CTC e esperado como fonte do PWM padrão em D9 ou D10.
Use uma tabela curta para tornar concorrências visíveis. Inclua tanto chamadas da API quanto escritas diretas em registradores: elas podem controlar o mesmo hardware.
Inventário de exemplo para investigar uma perda de PWM
| Recurso | Função esperada | Quem escreve | Momento |
|---|---|---|---|
| Timer0 | Base de tempo do núcleo | Nenhum trecho do projeto | Preservado |
| Timer1 | CTC para sinalização | configurarTimer1CTC() | setup |
| D3 / Timer2 | PWM do LED | analogWrite(3, nivel) | setup ou loop |
| D3 | Não deve ser digital | digitalWrite(3, LOW) | loop suspeito |
| D9 / Timer1 | Sem uso neste caso | analogWrite(9, nivel) | setup suspeito |
Atenção
Compare a configuração logo após setup() com a configuração após a rotina suspeita. Se um valor ou comportamento muda nesse intervalo, você encontrou um escritor a investigar. Trocar apenas a ordem das chamadas não resolve: se os dois trechos continuam executando, o último continua sobrescrevendo o anterior.
Este trecho reúne duas disputas. A primeira é de temporizador: após colocar o Timer1 em CTC, o programa espera PWM padrão no D9, que depende do Timer1. A segunda é de pino: o digitalWrite() repetido toma o controle digital do D3, que deveria permanecer sob PWM do Timer2.
Trecho para inspecionar; não o use como versão corrigida.
void setup() {
configurarTimer1CTC(); // Timer1: sinalização temporal
analogWrite(9, 128); // conflito: D9 usa Timer1
analogWrite(3, 128); // PWM pretendido no Timer2
}
void loop() {
digitalWrite(3, LOW); // conflito: substitui o comando PWM do D3
}Dica
A correção mínima é atribuir uma responsabilidade exclusiva: mantenha o Timer1 em CTC, use o PWM no D3 e remova qualquer digitalWrite() ou escrita de registrador que commande D3. Não altere o Timer0 para tentar compensar o problema.
Complete a chamada que mantém o PWM no D3 sem disputar o Timer1 nem alterar o Timer0.
void setup() {
configurarTimer1CTC(); // Timer1: sinalização temporal
(3, 128); // D3: PWM pelo Timer2
}
void loop() {
// Nenhum digitalWrite(3, ...) aqui.
// Timer0 permanece sem reconfiguração.
}
Passo 7 de 8
Audite acessos entre ISR e loop, reconstrua intercalações vulneráveis e escolha uma proteção mínima conforme o tipo de dado.
Uma variável é compartilhada quando a ISR e o loop() a leem ou escrevem. Antes de corrigir, faça uma auditoria curta: quem escreve, quem lê, qual é a largura do dado e qual operação precisa ser indivisível.
No Uno R3, uma leitura de 16 bits pode envolver mais de uma operação do processador. Também é composta a sequência “testar uma flag e depois limpá-la”. volatile mantém os acessos visíveis ao compilador, mas não impede uma ISR de ocorrer entre essas partes.
Use este inventário para decidir o que precisa de proteção.
| Variável | ISR | loop() | Risco principal |
|---|---|---|---|
| ticks (uint16_t) | incrementa | lê | leitura formada por partes |
| pendente (bool) | define true | consulta e limpa | ocorrência perdida |
| atendimentos (uint16_t) | incrementa | copia e zera | quantidade incompleta sem proteção |

A sequência, e não a aparência ocasional do LED, evidencia a leitura incoerente.
Trecho para analisar; não é necessário executá-lo agora.
volatile uint16_t ticks = 0;
ISR(TIMER1_COMPA_vect) {
ticks++;
}
void usarTicks() {
uint16_t copia = ticks; // pode ser interrompida entre bytes
processar(copia);
}Ordene a intercalação que explica uma cópia impossível de ticks. Considere que o valor inicial é 0x01FF.
Nem toda falha compartilhada é uma leitura de vários bytes:
loop() vê pendente, mas a ISR pode definir a flag novamente antes de o loop() limpá-la. A transferência “copiar e limpar” deve ser indivisível.A seção crítica deve conter somente a cópia ou transferência. Decisão, cálculos e comandos de saída ficam depois dela.
Uma transferência protegida consome a pendência sem apagar uma nova ocorrência que chegue no meio da operação.
volatile bool pendente = false;
bool retirarPendencia() {
bool houve;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
houve = pendente;
pendente = false;
}
return houve;
}A ISR pode registrar várias comparações antes de o loop() atendê-las. O programa precisa tratar cada atendimento registrado separadamente. Qual representação é mais adequada?
Complete a proteção da cópia. Ela restaura o estado de interrupções que já existia antes do bloco, em vez de supor que elas estavam habilitadas. A proteção é curta; processar() continua fora dela.
Preencha o modo do bloco atômico para obter um instantâneo coerente sem alterar indevidamente o estado anterior das interrupções.
#include <util/atomic.h>
volatile uint16_t ticks = 0;
void usarTicks() {
uint16_t copia;
ATOMIC_BLOCK() {
copia = ticks;
}
processar(copia);
}
Passo 8 de 8
Aplique uma correção localizada em uma variante reproduzível e confirme, pela mesma sequência de testes, o comportamento do botão, da sinalização temporal e do PWM.
Use uma cópia do caso-base, mantendo a versão conhecida sem alterações. Nesta variante, a gravação é confirmada pela IDE e, após reset, D13 alterna visualmente e D3 começa em brilho baixo.
Ao pressionar D2 e manter o botão pressionado, D3 não muda. Ao soltar D2, porém, D3 muda de brilho. D13 continua alternando durante toda a sequência.
Classifique primeiro: como a compilação e a gravação foram confirmadas, a evidência aponta para comportamento em execução. A continuidade de D13 também torna menos provável atribuir o sintoma ao Timer1. Antes de editar, reproduza a mesma sequência e registre exatamente em qual ação D3 muda.

A ordem das ações é evidência: compare pressionamento, manutenção e soltura sem atribuir a causa antes de examinar o código.
Registre sua hipótese inicial em uma ou duas frases: qual etapa falhou, qual observação a sustenta e que parte do comportamento merece auditoria? Não nomeie uma correção ainda.
Escreva pelo menos 50 caracteres (0/50).
Crie uma cópia do sketch de referência e substitua seu conteúdo por esta variante completa. Ela é intencionalmente defeituosa, mas compila e pode ser gravada no Uno R3. Use a montagem já conhecida: botão entre D2 e GND e LED externo com resistor em D3. Não altere nada antes de executar a sequência da tela anterior e conferir o comportamento.
#include <avr/interrupt.h>
#include <util/atomic.h>
const uint8_t PINO_BOTAO = 2;
const uint8_t PINO_PWM = 3;
volatile uint16_t ticks = 0;
bool leituraAnterior = HIGH;
bool botaoEstavel = HIGH;
unsigned long mudouEm = 0;
const unsigned long DEBOUNCE_MS = 30;
bool brilhoAlto = false;
void configurarTimer1() {
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31249;
TIFR1 = _BV(OCF1A);
TIMSK1 = _BV(OCIE1A);
TCCR1B = _BV(WGM12) | _BV(CS12);
}
ISR(TIMER1_COMPA_vect) {
PINB = _BV(PB5);
ticks++;
}
void setup() {
pinMode(PINO_BOTAO, INPUT_PULLUP);
pinMode(PINO_PWM, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
analogWrite(PINO_PWM, 40);
configurarTimer1();
}
void loop() {
bool leitura = digitalRead(PINO_BOTAO);
unsigned long agora = millis();
if (leitura != leituraAnterior) {
leituraAnterior = leitura;
mudouEm = agora;
}
if ((agora - mudouEm >= DEBOUNCE_MS) &&
(leitura != botaoEstavel)) {
botaoEstavel = leitura;
if (botaoEstavel == HIGH) {
brilhoAlto = !brilhoAlto;
analogWrite(PINO_PWM, brilhoAlto ? 180 : 40);
}
}
uint16_t copiaTicks;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
copiaTicks = ticks;
}
(void)copiaTicks;
}
Após reset e cerca de 3 segundos: D13 alterna visualmente. D3 permanece em brilho baixo. Durante pressionamento estável de D2: D13 continua alternando visualmente. D3 permanece no brilho anterior. Após soltura estável de D2: D13 continua alternando visualmente. D3 muda de brilho.
A saída é uma sequência de observações visuais esperadas para esta variante com falha. O instante exato em que D13 está alto ou baixo depende da fase do Timer1; a inspeção visual não mede sua precisão nem a frequência do PWM.
Após reproduzir o sintoma, localize a decisão feita logo depois de o novo estado estável ser aceito. Complete a condição mínima que faz a troca de brilho ocorrer no pressionamento, e não na soltura.
if ((agora - mudouEm >= DEBOUNCE_MS) &&
(leitura != botaoEstavel)) {
botaoEstavel = leitura;
if () {
brilhoAlto = !brilhoAlto;
analogWrite(PINO_PWM, brilhoAlto ? 180 : 40);
}
}Salve a alteração mínima, compile e grave novamente. Só compare a versão corrigida depois da confirmação de gravação da IDE. Repita a sequência idêntica: reset; aguarde alguns intervalos; pressione D2; mantenha pressionado; solte; aguarde novamente.
Preencha a matriz no seu registro local. “D13 alternou visualmente” e “D3 pareceu manter brilho” são observações. “O intervalo é preciso” e “o PWM tem certa frequência” não são conclusões verificadas apenas olhando LEDs.
Registre o antes e o depois com a mesma sequência de ações. Inclua funções que não eram o sintoma principal.
| Função | Esperado após correção | Antes | Depois |
|---|---|---|---|
| D2 → PWM em D3 | Muda no pressionamento estável | Não mudou ao pressionar; mudou ao soltar | Anote |
| D13 pelo Timer1 | Continua alternando visualmente | Anote | Anote |
| PWM em D3 após soltura | Mantém o brilho escolhido | Mudou na soltura | Anote |
| Compilação e gravação | IDE confirma ambas | Anote | Anote |
Produza um relato curto da sua prática local. Inclua: a evidência que classificou a etapa; o comportamento reproduzido antes da alteração; a causa localizada; a única mudança aplicada; e os resultados antes e depois para D2/D3, D13 e a permanência do brilho em D3 após a soltura. Termine com uma conclusão que a inspeção visual ainda não permite afirmar.
Escreva pelo menos 120 caracteres (0/120).
Resumo
Parabéns! Você concluiu: Diagnóstico de firmware temporizado
Você concluiu este nível!
Agora você vai iniciar: Aquisição de dados e interfaces
Conversão analógico-digital: referência e quantizaçãoAo concluir, o aluno será capaz de relacionar referência, faixa de entrada e número de bits aos códigos de um ADC, estimando tensões sem confundir resolução com exatidão.Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks