C++: variáveis e tipos — Arduino e IoT — semana 2 do 1o trimestre

Informatica · Conteudo · publicado em 02/10/2026
Semana 2 · C++: variáveis e tipos — Material de Apoio Arduino

Semana 2 de 13· 1o trimestre · 01/02 a 30/04

C++: variáveis e tipos

A mesma lógica do primeiro trimestre de JavaScript, agora com tipo declarado.

Aula 1 — Declarar variável com tipo: o que o JavaScript não exige

Objetivos

  • Declarar variável com tipo em C++ e dizer o que muda em relação ao let do JavaScript.
  • Escolher o tipo certo para cada valor do kit e justificar a escolha pelo sizeof de cada tipo.
  • Declarar pino, tempo e valor de circuito como const no topo do arquivo.
  • Reproduzir no monitor serial o estouro do int de 32 bits e explicar por que ele não gera erro.

Material

  • 1 ESP32 DevKit V1 por aluno, com o cabo USB
  • 1 protoboard de 830 pontos e 1 jogo de jumpers por aluno
  • 2 a 5 LEDs de 3,3 V e 2 a 5 resistores de 330 Ω por aluno
  • 1 módulo de alimentação MB102 por dupla
  • Lista dos tipos do ESP32 impressa, uma por aluno

Conceitos

O tipo vem antes do nome

Em JavaScript, let x = 5 cria uma variável cujo tipo é deduzido do valor, e que aceita qualquer coisa depois. Em C++ a forma é int x = 5: o tipo vem antes do nome, e o compilador passa a recusar tudo que não couber nele.

O ganho é que o erro aparece antes de gravar. int x = "texto" não compila. Em JavaScript isso rodaria e o defeito apareceria três semanas depois, em outra linha, sem relação com a linha que causou.

Os tipos do dia a dia

TipoTamanhoFaixaPara que serve no kit
bool1 bytetrue e falsese o botão está apertado
char1 byteum caractereo texto de uma letra
int4 bytes-2147483648 a 2147483647pino, tempo, contador, leitura do ADC
long8 bytesvalores muito maiorestempo acumulado de programa
unsigned int4 bytes0 a 4294967295contador que nunca fica negativo
float4 bytescom casas decimaistensão em volts

Todos os inteiros do ESP32 têm 32 bits, mesmo em int. É o dobro do int do Arduino Uno, e ainda assim o limite cabe na conversão de sensor do dia.

const é o que segura o circuito

const int PINO_LED = 2;    // tipo, const, nome, valor
const int RESISTOR_OHMS = 330;

Declarar o pino como const no topo do arquivo resolve três problemas de uma vez: o professor sabe onde olhar quando o LED não acende, o compilador recusa um valor novo no meio do programa, e o número do pino não se repete em cinco linhas diferentes.

O estouro que não avisa

Quando um int chega em 2147483647 e recebe mais um, ele não dá erro: sai pelo valor mais negativo, -2147483648. O programa continua rodando com o número errado. Em JavaScript o mesmo número simplesmente continua crescendo, e é por isso que a checagem de limite entra no dia de hoje e não no projeto final.

Atividade

Montagem:

  • Resistor de 330 Ω entre o GPIO2 e um lado do LED.
  • O outro lado do LED na trilha + da protoboard.
  • Jumper macho-fêmea levando o GPIO2 ao resistor.

O lado longo do LED é o anodo e vai para o positivo. Invertido, o LED não acende — e não dá erro.

  1. No topo do seu sketch, antes de qualquer função, declare com const o pino do LED, o valor do resistor e o tempo do intervalo. Os três com tipo declarado.
  2. Grave a resolução e confirme que o LED pisca e que o monitor serial mostra a contagem subindo.
  3. Rode sizeof em bool, char, int, long, float e unsigned int, e anote os seis números na mesma ordem da tabela do caderno.
  4. Imprima 2147483647 + 1 no monitor serial e explique em uma frase por que a placa não acusou erro.
  5. Troque o tipo do seu contador de voltas de int para unsigned int e diga o que muda para um contador que só sobe.
  6. Escreva a linha que calcula quantos elementos tem um vetor de inteiros sem contar à mão, e justifique o sizeof que aparece no denominador.

Nota: 10 pontos. Critério de fim: o monitor serial mostra os seis tamanhos de tipo, a linha do estouro e a contagem de voltas subindo.

Resolucao

// Aula 1 do dia 2: declarar variável com tipo.
//
// O aluno chega do JavaScript, onde `let x = 5` já basta e todo número é do
// mesmo tipo. Aqui o tipo vem ANTES do nome. Isso não é burocracia: é o que
// impede a placa de fazer conta com o número errado sem avisar.

#include <Arduino.h>

// ---- Constantes do kit: tipo, nome e valor, nessa ordem ----
// `const` declara que o valor não muda depois. O tipo antes do nome é a
// novidade do dia, e `const` é o que impede alguém de trocar o pino no meio
// do programa sem perceber.
const int PINO_LED = 2;
const int RESISTOR_OHMS = 330;
const float TENSAO_ALIMENTACAO = 3.3;

// Sufixo `L` no final do número diz: "isto é long". Sem o sufixo, `500` é int.
const long INTERVALO_MS = 500;

// Sufixo `U` diz: "isto é unsigned", ou seja, não aceita número negativo.
// `TABELA_CORES` é o lugar onde o tipo faz serviço: cada elemento ocupa
// exatamente 4 bytes, então dá para perguntar ao sizeof quantos há.
const unsigned int TABELA_CORES[] = {0, 32, 64, 96, 128, 160, 192, 224, 255};

// ---- Variáveis que mudam de valor enquanto o programa roda ----
int voltas = 0;
float tensaoLida = 0.0;
bool ledLigado = false;
char inicial = 'E';

void setup() {
  // OUTPUT antes de qualquer digitalWrite. Sem isso o LED não acende e não
  // dá erro — é o defeito número um do curso inteiro.
  pinMode(PINO_LED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("=== dia 2, aula 1: variável com tipo ===");
  Serial.println();

  // sizeof devolve quantos BYTES cada tipo ocupa na memória do ESP32.
  // É a pergunta que responde "por que importa o tipo": tipos diferentes
  // ocupam espaço diferente.
  Serial.println("Tamanho de cada tipo, em bytes:");
  Serial.print("  bool              ");
  Serial.println(sizeof(bool));
  Serial.print("  char              ");
  Serial.println(sizeof(char));
  Serial.print("  int               ");
  Serial.println(sizeof(int));
  Serial.print("  long              ");
  Serial.println(sizeof(long));
  Serial.print("  float             ");
  Serial.println(sizeof(float));
  Serial.print("  unsigned int      ");
  Serial.println(sizeof(unsigned int));
  Serial.println();

  // int tem 32 bits: vai de -2147483648 até 2147483647. Este é o limite.
  const int MAIOR_INT = 2147483647;
  Serial.print("Maior int: ");
  Serial.println(MAIOR_INT);
  Serial.println();

  // A soma abaixo ESTOURA o int. Não é erro de compilação e não trava a
  // placa: o número simplesmente dá a volta e sai pelo valor mais negativo.
  // Este é o defeito que o tipo declarado evita em JavaScript, onde o número
  // cresce e ninguém percebe.
  Serial.print("Maior int + 1 = ");
  Serial.println(MAIOR_INT + 1);
  Serial.println("  (estourou: o int não cabe mais e deu a volta)");
  Serial.println();

  // sizeof de um vetor devolve o tamanho INTEIRO do vetor, não a quantidade de
  // elementos. Dividir pelo sizeof de um elemento dá a contagem.
  Serial.print("Elementos na tabela de cores: ");
  Serial.println(sizeof(TABELA_CORES) / sizeof(TABELA_CORES[0]));

  Serial.println();
  Serial.print("Resistor do LED: ");
  Serial.print(RESISTOR_OHMS);
  Serial.print(" ohms, alimentado por ");
  Serial.print(TENSAO_ALIMENTACAO);
  Serial.println(" V");
  Serial.print("Inicial do projeto: ");
  Serial.println(inicial);
}

void loop() {
  voltas++;

  // O tipo do PINO_LED é int, e HIGH é uma constante do núcleo. O compilador
  // aceita os dois juntos porque os dois cabem em int.
  digitalWrite(PINO_LED, voltas % 2 == 0 ? HIGH : LOW);

  Serial.print("volta ");
  Serial.print(voltas);
  Serial.print("  |  intervalo ");
  Serial.print(INTERVALO_MS);
  Serial.println(" ms");

  // delay é aceitável aqui: esta aula ainda não tem nada concorrente para
  // responder. O dia 3, aula 2 mostra o que acontece quando aparece.
  delay(INTERVALO_MS);
}

Por que assim e não de outro jeito. Os seis sizeof estão no setup, e não no loop: o tamanho de um tipo não muda enquanto o programa roda, e repetir a conta a cada volta só polui o serial com um número que a turma já leu.

O MAIOR_INT + 1 está ali de propósito. O professor deixa o monitor rodando e pergunta o que o aluno acha que vai aparecer. A resposta é -2147483648, e a discussão que vem é a mais importante da aula: em C++ o limite é conhecido na hora de compilar, e é por isso que int dura mais que o número do JavaScript.

A tabela de cores é declarada com sizeof em vez de uma constante com o tamanho. Hard-code o 9 e, quando alguém acrescentar um nível, o programa passa a fazer conta com o número velho sem reclamar — exatamente o defeito que o sizeof evita.

Criterios de correcao

CritérioPontos
Pino, resistor e intervalo declarados com const e tipo, no topo do arquivo3 pontos
pinMode(..., OUTPUT) no setup antes de qualquer digitalWrite2 pontos
Os seis tamanhos de tipo impressos e anotados na ordem da tabela3 pontos
Estouro do int impresso e explicado sem chamar de "erro"2 pontos

Erros comuns

ErroComo apareceCorrecao
Declarar o pino dentro do loopconst int pino = 2; aparece entre as linhas do pisca-pisca"Constante de peca vai no topo do arquivo, antes do setup. No loop não tem constante nenhuma."
Achar que const int x = 5; impede x de mudarAluno escreve const e depois tenta x = 6, leva erro de compilacao"const proibe a mudanca na variável. Se precisa mudar, declara sem const e ai você olha para o código e ve a mudanca."
Citar PI como nome de constanteAluno escreve const float PI = 3.14159; e a gravação falha"O núcleo do ESP32 já tem um PI definido, e os dois se atropelam. Use VALOR_PI."
Escrever int 5 = valor"Por que o compilador não aceitou o 5 no lugar do nome""A ordem e tipo, depois nome. int valor, nunca int 5."
Acreditar que o estouro do int avisa o professorItem 4 respondido como "deu erro""Não deu erro nenhum. O número deu a volta e saiu negativo. E exatamente por isso que o limite se verifica antes."
Usar int para o tempo todoint agora = millis(); e a conta falha depois de alguns dias rodando"O millis devolve unsigned long. Se você guardar em int, o contador estoura em cerca de 24 dias de programa ligado."

Desafio extra

Declare uma constante para cada resistor que existe no seu kit e escreva uma função que imprima, para cada uma, qual é a corrente que passa pelo LED com sinal de 3,3 V. Depois explique no caderno por que a corrente cai quando o resistor sobe de 220 Ω para 1 kΩ, e qual dos dois valores você usaria se o LED estivesse esquentando.

>

A resolucao, compilada

// Aula 1 do dia 2: declarar variável com tipo.
//
// O aluno chega do JavaScript, onde `let x = 5` já basta e todo número é do
// mesmo tipo. Aqui o tipo vem ANTES do nome. Isso não é burocracia: é o que
// impede a placa de fazer conta com o número errado sem avisar.

#include <Arduino.h>

// ---- Constantes do kit: tipo, nome e valor, nessa ordem ----
// `const` declara que o valor não muda depois. O tipo antes do nome é a
// novidade do dia, e `const` é o que impede alguém de trocar o pino no meio
// do programa sem perceber.
const int PINO_LED = 2;
const int RESISTOR_OHMS = 330;
const float TENSAO_ALIMENTACAO = 3.3;

// Sufixo `L` no final do número diz: "isto é long". Sem o sufixo, `500` é int.
const long INTERVALO_MS = 500;

// Sufixo `U` diz: "isto é unsigned", ou seja, não aceita número negativo.
// `TABELA_CORES` é o lugar onde o tipo faz serviço: cada elemento ocupa
// exatamente 4 bytes, então dá para perguntar ao sizeof quantos há.
const unsigned int TABELA_CORES[] = {0, 32, 64, 96, 128, 160, 192, 224, 255};

// ---- Variáveis que mudam de valor enquanto o programa roda ----
int voltas = 0;
float tensaoLida = 0.0;
bool ledLigado = false;
char inicial = 'E';

void setup() {
  // OUTPUT antes de qualquer digitalWrite. Sem isso o LED não acende e não
  // dá erro — é o defeito número um do curso inteiro.
  pinMode(PINO_LED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("=== dia 2, aula 1: variável com tipo ===");
  Serial.println();

  // sizeof devolve quantos BYTES cada tipo ocupa na memória do ESP32.
  // É a pergunta que responde "por que importa o tipo": tipos diferentes
  // ocupam espaço diferente.
  Serial.println("Tamanho de cada tipo, em bytes:");
  Serial.print("  bool              ");
  Serial.println(sizeof(bool));
  Serial.print("  char              ");
  Serial.println(sizeof(char));
  Serial.print("  int               ");
  Serial.println(sizeof(int));
  Serial.print("  long              ");
  Serial.println(sizeof(long));
  Serial.print("  float             ");
  Serial.println(sizeof(float));
  Serial.print("  unsigned int      ");
  Serial.println(sizeof(unsigned int));
  Serial.println();

  // int tem 32 bits: vai de -2147483648 até 2147483647. Este é o limite.
  const int MAIOR_INT = 2147483647;
  Serial.print("Maior int: ");
  Serial.println(MAIOR_INT);
  Serial.println();

  // A soma abaixo ESTOURA o int. Não é erro de compilação e não trava a
  // placa: o número simplesmente dá a volta e sai pelo valor mais negativo.
  // Este é o defeito que o tipo declarado evita em JavaScript, onde o número
  // cresce e ninguém percebe.
  Serial.print("Maior int + 1 = ");
  Serial.println(MAIOR_INT + 1);
  Serial.println("  (estourou: o int não cabe mais e deu a volta)");
  Serial.println();

  // sizeof de um vetor devolve o tamanho INTEIRO do vetor, não a quantidade de
  // elementos. Dividir pelo sizeof de um elemento dá a contagem.
  Serial.print("Elementos na tabela de cores: ");
  Serial.println(sizeof(TABELA_CORES) / sizeof(TABELA_CORES[0]));

  Serial.println();
  Serial.print("Resistor do LED: ");
  Serial.print(RESISTOR_OHMS);
  Serial.print(" ohms, alimentado por ");
  Serial.print(TENSAO_ALIMENTACAO);
  Serial.println(" V");
  Serial.print("Inicial do projeto: ");
  Serial.println(inicial);
}

void loop() {
  voltas++;

  // O tipo do PINO_LED é int, e HIGH é uma constante do núcleo. O compilador
  // aceita os dois juntos porque os dois cabem em int.
  digitalWrite(PINO_LED, voltas % 2 == 0 ? HIGH : LOW);

  Serial.print("volta ");
  Serial.print(voltas);
  Serial.print("  |  intervalo ");
  Serial.print(INTERVALO_MS);
  Serial.println(" ms");

  // delay é aceitável aqui: esta aula ainda não tem nada concorrente para
  // responder. O dia 3, aula 2 mostra o que acontece quando aparece.
  delay(INTERVALO_MS);
}

Sem saída de compilação gravada. Rode python3 validar.py -t 1 dia02 aula1.

Aula 2 — Operacoes, comparacao e a armadilha da divisão

Objetivos

  • Prever o resultado de uma divisão entre inteiros e de uma divisão com casa decimal.
  • Usar o operador de resto para decidir uma ação sem contador paralelo.
  • Diferenciar o sinal de igual simples do comparador de igualdade e dizer o que o compilador faz com o erro.
  • Combinar comparadores com &&, || e ! para montar uma condição que a turma consiga ler em voz alta.

Material

  • 1 ESP32 DevKit V1 por aluno, com o cabo USB
  • 1 protoboard de 830 pontos e 1 jogo de jumpers por aluno
  • 2 a 5 LEDs de 3,3 V e 2 a 5 resistores de 330 Ω por aluno
  • 1 módulo de alimentação MB102 por dupla
  • Folha com as duas colunas de divisão inteira e de divisão real impressa, uma por dupla

Conceitos

A armadilha da divisão

Em C++, dois inteiros divididos dão um inteiro, e o resto é descartado sem aviso:

5 / 2      // 2, e o 0,5 foi embora
5 % 2      // 1, o resto
5 / 2.0    // 2.5, porque o 2.0 é float

O jeito mais curto de entender: um dos dois lados precisa ser float. Não precisa ser o primeiro nem o segundo, e não precisa ser o resultado — leitura * 3.3 / 4095 funciona porque o 3.3 já é float.

Onde isso vira defeito de verdade é na conversão de sensor. 2048 * 3 / 4095 dá 1 volt; o valor certo é 1,65 volt. Com o potenciômetro no meio da escala, o programa lê metade da tensão que existe ali, e o número errado sai no monitor com cara de número certo.

Igual simples e igualdade

tensao = 1.65;    // atribui: o 1.65 vai para a variavel
tensao == 1.65;   // pergunta: os dois sao iguais?

O sinal de igual sozinho não compila. O compilador entende que 1.65 é um valor, e uma função que devolve valor precisa de um nome que receba o valor — e a mensagem de erro mostra essa checagem. Esse erro é o mais barato que o aluno vai ter na semana, porque ele para o programa na hora.

Comparadores e operadores lógicos

OperadorNomeO que faz
== !=igualdade e diferençacompara dois valores
< <= > >=ordemcompara dois valores
&&eas duas condições precisam ser verdadeiras
`\\`oupelo menos uma das duas precisa ser verdadeira
!negaçãoinverte verdadeiro e falso

O || tem um comportamento que o aluno vai perder se ninguém mostrar: quando o lado esquerdo já é verdadeiro, o lado direito nem é avaliado. Isso se chama curto-circuito, e é o que permite escrever contador > 0 && TABELA[contador - 1] != -1 sem o programa tentar ler uma posição que não existe.

Atribuição composta e incremento

voltas += 1 é voltas = voltas + 1. voltas++ soma um depois de usar o valor, e ++voltas soma antes. Entre dois valores isso importa; sozinho, em uma linha que só soma um, dá para ser preguiçoso e escrever do jeito mais curto.

Atividade

Montagem:

  • Resistor de 330 Ω entre o GPIO2 e um lado do LED.
  • O outro lado do LED na trilha + da protoboard.
  • Jumper macho-fêmea levando o GPIO2 ao resistor.

O lado longo do LED é o anodo e vai para o positivo.

  1. Grave a resolução e confirme que o LED acende a cada três voltas e que o serial imprime as duas formas de divisão.
  2. No monitor serial, anote o valor de 5 / 2 e de 5 / 2.0 e explique em uma frase por que os dois são diferentes.
  3. Corrija a conversão de tensão do sketch trocando o 3 inteiro por 3.3, grave de novo e anote a nova voltagem lida.
  4. Escreva uma condição que seja verdadeira somente quando a tensão estiver entre 0 e 3,3 V, usando os três operadores lógicos. Diga qual deles é o do "e".
  5. Troque o if (voltas % 3 == 0) por uma condição escrita com ||, que acenda o LED na primeira e na terceira volta de cada grupo de cinco. Explique por que % não serve nesse caso.
  6. Escreva, sem executar, uma linha que divida dois inteiros e não perca o resto. Diga qual é a palavra que faz isso acontecer.

Nota: 10 pontos. Critério de fim: o serial mostra a divisão inteira e a real lado a lado, e o LED acende exatamente uma vez a cada três voltas.

Resolucao

// Aula 2 do dia 2: operações, comparação e a armadilha da divisão.
//
// A divisão inteira é o defeito mais silencioso desta transição: o programa
// compila, roda e devolve um número errado sem nunca reclamar. Este sketch
// imprime as duas versões lado a lado para o professor mostrar a diferença.

#include <Arduino.h>

const int PINO_LED = 2;
const float TENSAO_REFERENCIA = 3.3;
const int LEITURA_MAXIMA_ADC = 4095;   // ADC do ESP32 tem 12 bits: 2^12 = 4096
const int INTERVALO_MS = 800;

// Dois números escolhidos para a divisão não fechar. Se dividissem certo, a
// armadilha não apareceria na aula.
const int LIDO_ADC = 2048;
const int TENS_INTEIROS = 5;

int voltas = 0;

void setup() {
  pinMode(PINO_LED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("=== dia 2, aula 2: operações e divisão ===");
  Serial.println();
  Serial.println("Divisão inteira: o resto é descartado, sem aviso.");
  Serial.print("  5 / 2       = ");
  Serial.println(TENS_INTEIROS / 2);
  Serial.print("  5 % 2       = ");
  Serial.println(TENS_INTEIROS % 2);
  Serial.print("  5 / 2.0     = ");
  Serial.println(TENS_INTEIROS / 2.0);
  Serial.println("  (o mesmo 5, com o mesmo 2, e três respostas diferentes)");
  Serial.println();

  // A divisão inteira SOME o resto ANTES de multiplicar. Numa conversão de
  // sensor, isso vira erro de quase 1 V: 2048 * 3.3 / 4095 dá 1 volt, e o
  // valor certo é 1.65.
  int voltsInteiros = LIDO_ADC * 3 / LEITURA_MAXIMA_ADC;
  float voltsReais = LIDO_ADC * 3.3 / LEITURA_MAXIMA_ADC;
  Serial.println("Conversão de leitura do ADC:");
  Serial.print("  modo inteiro  (cru * 3 / 4095)   = ");
  Serial.println(voltsInteiros);
  Serial.print("  modo correto  (cru * 3.3 / 4095) = ");
  Serial.println(voltsReais);
  Serial.println();

  // Comparação devolve true ou false, que em C++ valem 1 e 0. `=` atribui,
  // `==` compara. Confundir os dois é o erro de digitação mais caro.
  Serial.println("Comparação:");
  Serial.print("  7 == 7  -> ");
  Serial.println(7 == 7);
  Serial.print("  7 = 7   -> ");
  Serial.println("  (o sinal de igual sozinho nem compila: ele pede um nome)");
  Serial.println();

  // Operadores lógicos. && é "e", || é "ou", ! é "nega".
  bool acimaDoLimite = (voltsReais > 1.6);
  bool dentroDaFaixa = (voltsReais >= 0.0 && voltsReais <= TENSAO_REFERENCIA);
  Serial.print("acima de 1.6 V? ");
  Serial.println(acimaDoLimite);
  Serial.print("dentro de 0 a 3.3 V? ");
  Serial.println(dentroDaFaixa);
}

void loop() {
  voltas++;

  // O operador % devolve o resto. Ele serve para decidir a ação sem precisar
  // de um contador separado: uma ação a cada 3 voltas.
  if (voltas % 3 == 0) {
    digitalWrite(PINO_LED, HIGH);
  } else {
    digitalWrite(PINO_LED, LOW);
  }

  Serial.print("volta ");
  Serial.print(voltas);
  Serial.print("  |  resto por 3 = ");
  Serial.println(voltas % 3);

  delay(INTERVALO_MS);
}

Por que assim e não de outro jeito. As duas divisões estão impressas no setup, lado a lado e com o resto embaixo, porque o ponto da aula é a comparação direta: o mesmo 5 e o mesmo 2, e a única diferença é um .0 no segundo.

A conversão de tensão aparece nas duas formas de propósito. O valor de 2048 não é real de um sensor: é um número para a conta fechar errado na frente da turma. O aluno vê 1 volt e 1,65 volt na mesma tela e a conclusão fica sem precisar de discurso.

O if do loop usa % 3 em vez de um contador paralelo. Com um contador paralelo seriam duas variáveis que precisam concordar; com o resto, a decisão sai da própria contagem e não existe estado para ficar inconsistente.

O Serial.println(" (o sinal de igual sozinho nem compila: ele pede um nome)") no setup é texto de aluno: o compilador não aceitaria aquela linha como código. Ela existe para o professor apontar que o aluno vai ver esse erro hoje, e reconhecer o texto quando aparecer.

Criterios de correcao

CritérioPontos
Sketch gravado com o LED acendendo a cada três voltas2 pontos
Divisão inteira, resto e divisão real impressos e comentados3 pontos
Conversão corrigida para 3.3 e nova voltagem anotada3 pontos
Item 4 com os três operadores lógicos e o nome do "e"2 pontos

Erros comuns

ErroComo apareceCorrecao
Perder o resto sem perceberItem 6 respondido com 5 / 2"Para não perder o resto se usa o operador módulo, o sinal de porcento. 5 % 2 devolve 1."
Dividir dois inteiros esperando decimalleitura * 3 / 4095 e o professor lê 1 volt"Um dos lados tem que ser float. Ponha o 3.3: e assim que o número real entra na conta."
Comparar com um igual soAluno escreveu tensao = 1.65; dentro do if"Você não perguntou nada, você ordenou. Troque por dois iguais."
Usar & em vez de &&Condição que nunca entra, sem erro"Com um & so, o C++ compara os dois lados como número. E o operador de e lógica tem dois sinais: &&."
Chamar ` de "ou" e escrever or`Sketch não compila"Em C++ não existe palavra or. O operador e `\\`, dois sinais de barra."
Confundir >= com =>Erro de compilacao apontando para a seta">= e maior ou igual. => não existe em C++."
Escolher float para contar voltasContador que para em 16777215"Contador e int. float guarda número com casas decimais e o espaco vai embora com a precisao."

Desafio extra

O operador % serve para decidir ação por ciclo. Escreva uma condição que acenda o LED quando o número da volta for par ou múltiplo de 5, usando os dois operadores juntos, e depois explique por que o número 10 acenderia nessa regra e o número 4 não. Em seguida, faça o mesmo com um contador de 1 a 20 impresso no serial, marcando na tela os números que acenderiam.

>

A resolucao, compilada

// Aula 2 do dia 2: operações, comparação e a armadilha da divisão.
//
// A divisão inteira é o defeito mais silencioso desta transição: o programa
// compila, roda e devolve um número errado sem nunca reclamar. Este sketch
// imprime as duas versões lado a lado para o professor mostrar a diferença.

#include <Arduino.h>

const int PINO_LED = 2;
const float TENSAO_REFERENCIA = 3.3;
const int LEITURA_MAXIMA_ADC = 4095;   // ADC do ESP32 tem 12 bits: 2^12 = 4096
const int INTERVALO_MS = 800;

// Dois números escolhidos para a divisão não fechar. Se dividissem certo, a
// armadilha não apareceria na aula.
const int LIDO_ADC = 2048;
const int TENS_INTEIROS = 5;

int voltas = 0;

void setup() {
  pinMode(PINO_LED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("=== dia 2, aula 2: operações e divisão ===");
  Serial.println();
  Serial.println("Divisão inteira: o resto é descartado, sem aviso.");
  Serial.print("  5 / 2       = ");
  Serial.println(TENS_INTEIROS / 2);
  Serial.print("  5 % 2       = ");
  Serial.println(TENS_INTEIROS % 2);
  Serial.print("  5 / 2.0     = ");
  Serial.println(TENS_INTEIROS / 2.0);
  Serial.println("  (o mesmo 5, com o mesmo 2, e três respostas diferentes)");
  Serial.println();

  // A divisão inteira SOME o resto ANTES de multiplicar. Numa conversão de
  // sensor, isso vira erro de quase 1 V: 2048 * 3.3 / 4095 dá 1 volt, e o
  // valor certo é 1.65.
  int voltsInteiros = LIDO_ADC * 3 / LEITURA_MAXIMA_ADC;
  float voltsReais = LIDO_ADC * 3.3 / LEITURA_MAXIMA_ADC;
  Serial.println("Conversão de leitura do ADC:");
  Serial.print("  modo inteiro  (cru * 3 / 4095)   = ");
  Serial.println(voltsInteiros);
  Serial.print("  modo correto  (cru * 3.3 / 4095) = ");
  Serial.println(voltsReais);
  Serial.println();

  // Comparação devolve true ou false, que em C++ valem 1 e 0. `=` atribui,
  // `==` compara. Confundir os dois é o erro de digitação mais caro.
  Serial.println("Comparação:");
  Serial.print("  7 == 7  -> ");
  Serial.println(7 == 7);
  Serial.print("  7 = 7   -> ");
  Serial.println("  (o sinal de igual sozinho nem compila: ele pede um nome)");
  Serial.println();

  // Operadores lógicos. && é "e", || é "ou", ! é "nega".
  bool acimaDoLimite = (voltsReais > 1.6);
  bool dentroDaFaixa = (voltsReais >= 0.0 && voltsReais <= TENSAO_REFERENCIA);
  Serial.print("acima de 1.6 V? ");
  Serial.println(acimaDoLimite);
  Serial.print("dentro de 0 a 3.3 V? ");
  Serial.println(dentroDaFaixa);
}

void loop() {
  voltas++;

  // O operador % devolve o resto. Ele serve para decidir a ação sem precisar
  // de um contador separado: uma ação a cada 3 voltas.
  if (voltas % 3 == 0) {
    digitalWrite(PINO_LED, HIGH);
  } else {
    digitalWrite(PINO_LED, LOW);
  }

  Serial.print("volta ");
  Serial.print(voltas);
  Serial.print("  |  resto por 3 = ");
  Serial.println(voltas % 3);

  delay(INTERVALO_MS);
}

Sem saída de compilação gravada. Rode python3 validar.py -t 1 dia02 aula2.