A ponte: o mesmo programa nas duas linguagens — Arduino e IoT — semana 1 do 1o trimestre
Semana 1 de 13· 1o trimestre · 01/02 a 30/04
A ponte: o mesmo programa nas duas linguagens
O ESP32, a IDE e a traducao do que o aluno já faz em JavaScript para C++.
Aula 1 — O que e o ESP32 e o que ele tem a mais que o Arduino Uno
Objetivos
- Identificar as peças do kit que fazem cada etapa do curso: protoboard, jumpers, resistores, MB102 e a placa.
- Comparar o ESP32 com o Arduino Uno em processador, memória e rede, e dizer por que a escolha muda o curso.
- Explicar para a turma o que e WiFi integrado e por que isso e o motivo de o curso existir.
- Ler a pinagem da sua placa DevKit e apontar no desenho onde comeca e onde termina a alimentacao.
Material
- 1 ESP32 DevKit V1 por aluno, com o cabo USB
- 1 protoboard de 830 pontos por aluno
- 1 jogo de jumpers (macho-macho, macho-femea e femea-femea) por aluno
- 1 módulo de alimentacao MB102 por dupla
- 2 a 5 LEDs e 2 a 5 resistores de 330 por aluno
- Lista do kit impressa, uma por aluno
Conceitos
O que e um microcontrolador
Um microcontrolador e um computador inteiro em um chip: processador, memória do programa, memória de trabalho e pinos de entrada e saída. Não tem sistema operacional, não tem disco, não tem tela e não gerencia mais de uma coisa por vez. O que ele faz e o que você escreve nele.
O microcontrolador executa o seu programa de cima para baixo, sem parar, voltando para o início quando chega no fim. Isso e o loop, e e a unica coisa que ele faz a vida inteira.
ESP32 contra Arduino Uno
| Caracteristica | Arduino Uno | ESP32 DevKit V1 |
|---|---|---|
| Processador | 8 bits, AVR | 32 bits, dois núcleos |
| Memória do programa | 2 KB | 4 MB |
| Memória de trabalho | 2 KB | 320 KB |
| Rede | nenhuma | WiFi e Bluetooth integrados |
| Entrada analogica | 6 pinos | 18 pinos |
| Tensão de sinal | 5 V | 3,3 V |
O ponto que importa para o ano inteiro e o terceiro: o WiFi esta na placa. Não precisa comprar módulo, não precisa_library, não precisa ligar nada. Isso e o que permite que, no ultimo dia, o dado do sensor da sua bancada chegue num navegador de outro computador.
O ponto que mais gera erro e o ultimo: o sinal do ESP32 e 3,3 V. Tudo que a placa manda para fora e 3,3 V. Por isso existe o conversor de nivel lógico no kit.
O que esta em uma placa DevKit
Uma placa DevKit e três coisas juntas: o módulo ESP32-WROOM-32 (o que faz o trabalho), o conversor USB para serial (o que permite gravar o programa pelo cabo) e os pinos quebrados em duas fileiras para ease de usar com protoboard.
A fileira de pinos de um lado e alimentacao: 3V3, 5V, GND, e alguns pinos de uso geral. A do outro lado são os pinos de entrada e saída, numerados de 0 a 36, com alguns reservados.
Atividade
Montagem: nenhuma. Não ligue nada nesta aula. E a unica do ano em que a bancada fica sem circuito.
- Pegue sua placa e localize, anotando no caderno: o conector USB, a botao de
BOOT, a botao deRESETe a antena. - Na fileira de pinos, circule com a caneta o pino
3V3e o pinoGND. Escreva ao lado de cada um para que lado da protoboard ele aponta. - Preencha a tabela do seu caderno: quantos pinos de saída digital a placa tem, segundo o desenho que você fez.
- Marque no desenho os dois pinos que você não pode usar: justifique o motivo em uma frase.
Nota: 8 pontos. Critério de fim: o desenho tem os quatro pontos localizados e a tabela preenchida. Não precisa compilar nada nesta aula.
Resolucao
A resposta do professor para o item 4 depende da placa, e por isso o gabarito e a discussao, não um número. O professor circula e pergunta o que o aluno respondeu.
O código de hoje não manipula hardware nenhum: ele pede a placa que se descreva. Serve para o professor mostrar que a Serial funciona e que o programa roda antes de qualquer circuito existir.
#include <Arduino.h> const int PINOS[] = {2, 4, 5, 12, 13, 14, 18, 19}; const int TOTAL_DE_PINOS = 8; void setup() { Serial.begin(115200); Serial.println(); Serial.println("ESP32 DevKit V1 — dia 1, aula 1"); Serial.print("Frequencia do clock: "); Serial.print(getCPUFreqMHz()); Serial.println(" MHz"); Serial.print("Cores: "); Serial.println(ESP.getChipCores()); } void loop() { for (int i = 0; i < TOTAL_DE_PINOS; i++) { Serial.print(" GPIO"); if (PINOS[i] < 10) { Serial.print("0"); } Serial.print(PINOS[i]); Serial.println(" — saida digital"); } Serial.println(); Serial.println("O ESP32 ja traz WiFi e Bluetooth."); delay(3000); }
Por que assim e não de outro jeito. O for imprime a lista inteira de pinos em dez linhas de código. A alternativa seria escrever oito Serial.print na mao, e o aluno aprenderia que a lista de pinos e algo que se escreve repetido — o que e falso, e o contraria a aula 4, onde for vira ferramenta de trabalho.
O delay(3000) no fim existe para o programa não encher a tela a 60 vezes por segundo. E a ultima vez que o curso usa delay para esperar: no dia 3 o professor mostra o que acontece quando o aluno precisa que o programa responda enquanto espera.
Criterios de correcao
| Critério | Pontos |
|---|---|
Conector USB, BOOT, RESET e antena localizados no desenho | 3 pontos |
3V3 e GND circulados e com a direcao anotada | 2 pontos |
| Tabela de pinos de saída preenchida | 2 pontos |
| Os dois pinos proibidos marcados e a justificativa coerente | 1 ponto |
Erros comuns
| Erro | Como aparece | Correcao |
|---|---|---|
Circular 3V3 e 5V como se fossem o mesmo pino | O aluno diz "3 volts e 5 volts e a mesma coisa, so que mais" | "3V3 e saída de 3,3 V e 5V e saída de 5 V. Guarde a 5V para alimentar LED e relé; sinal do ESP32 e sempre 3,3 V." |
| Contar pinos contando os de alimentacao | Tabela com 20 pinos de saída quando o DevKit tem menos | "Conte so os pinos numerados, sem GND, sem 3V3, sem 5V." |
| Achar que a antena e um conector de WiFi que precisa ser encaixada | O aluno aponta para a antena e pergunta "onde entra o cabo" | "A antena já esta soldada. E a parte que faz a comunicacao, não um conector." |
| Ficar touching a placa enquanto fala do circuito | Não e erro tecnico, e perda de tempo: e a aula sem circuito | "Guardem a placa na caixa. Ela volta na aula 2, e ai sim a gente liga." |
| Dizer que o ESP32 e um computador | O aluno explica para o colega que "ele roda Windows" | "Ele roda um programa, não varios. Não tem sistema operacional. Tudo que ele faz esta no seu código." |
Desafio extra
O ESP32 tem dois núcleos e três interfaces de rede. Pesquise e escreva em cinco linhas: o que são os dois núcleos, e o que muda para quem escreve o programa se o processador pode executar duas coisas ao mesmo tempo. A resposta e a mesma para o professor: na programacao Arduino você não aproveita esse paralelismo, e por isso ele não muda o que você escreve hoje.
>A resolucao, compilada
// Prova de que o portao compila sketch de verdade para o ESP32. // Aula 1 do 1o trimestre: o ESP32 conta os proprios pinos e diz na serial. #include <Arduino.h> // Pinos que o ESP32 DevKit V1 expoe como saida comum. Nao ha LED embutido em // varios kits, entao a aula conta os pinos em vez de depender do LED. const int PINOS[] = {2, 4, 5, 12, 13, 14, 18, 19}; const int TOTAL_DE_PINOS = 8; void setup() { Serial.begin(115200); // Tempo de espera pelo monitor serial: sem isso, o professor ve a tela // vazia em dois dos primeiros cliques e acha que a placa nao gravou. Serial.println(); Serial.println("ESP32 DevKit V1 — dia 1, aula 1"); Serial.println("-----------------------------------"); Serial.print("Frequencia do clock: "); // Nome exato da funcao: getCpuFrequencyMhz, com "Cpu" maiusculo e "Mhz" // junto. Escrever getCPUFreqMHz compila em nenhuma plataforma — o portao // do material e o quePEGOU esse erro. Serial.print(getCpuFrequencyMhz()); Serial.println(" MHz"); Serial.print("Cores: "); Serial.println(ESP.getChipCores()); Serial.println(); Serial.println("Pinos de saida disponiveis neste kit:"); } void loop() { // Um pino por linha, com o numero e o nome logico. E a lista que o aluno // vai usar nas 12 semanas seguintes. for (int i = 0; i < TOTAL_DE_PINOS; i++) { Serial.print(" GPIO"); if (PINOS[i] < 10) { Serial.print("0"); } Serial.print(PINOS[i]); Serial.print(" — saida digital"); Serial.println(); } Serial.println(); Serial.println("O ESP32 ja traz WiFi e Bluetooth. Nao precisa de modulo extra."); // A placa repete a cada 3 segundos enquanto o professor explica o que e // cada peca do kit. delay e o unico lugar aceitavel na aula 1: a aula 3 // mostra por que isso nao pode continuar. delay(3000); Serial.println("-----------------------------------"); }
Saída real do compilador para esp32:esp32:esp32
Sketch uses 269728 bytes (20%) of program storage space. Maximum is 1310720 bytes.
Global variables use 22116 bytes (6%) of dynamic memory, leaving 305564 bytes for local variables. Maximum is 327680 bytes.
Aula 2 — Instalar a IDE, gravar o primeiro blink e ler o serial
Objetivos
- Instalar a Arduino IDE 2.x, selecionar a placa certa e gravar um programa sem erro.
- Abrir o monitor serial na velocidade correta e explicar por que 115200 e obrigatorio.
- Usar
pinMode,digitalWriteedelaypara piscar um LED e não transformar o programa em um ponto parado. - Ler um erro de gravação e dizer o que ele significa antes de chamar o professor.
Material
- 1 ESP32 DevKit V1 por aluno, com o cabo USB
- Computador com a Arduino IDE 2.x instalada antes da aula
- 2 a 5 LEDs de 3,3 V e 2 a 5 resistores de 330 por aluno
- 1 protoboard de 830 pontos e 1 jumper femea-femea por aluno
- 1 módulo MB102 por dupla
Conceitos
As três coisas que a IDE faz
Quando o professor aperta o botao de gravar, três processos acontecem e o aluno precisa saber distinguir:
- Compilar: o código C++ vira código de maquina para o processador Xtensa. Se esta etapa falha, o erro tem o nome do arquivo e o número da linha.
- Gravar: o código de maquina e enviado pela porta serial e gravado na memória da placa. Se esta etapa falha, o erro e de conexão, e não de código.
- Executar: a placa reinicia e roda o programa. Se não aparece nada no serial, pode ser velocidade errada, ou o programa não imprime nada.
O aluno precisa dessa distincao porque o "erro" que ele ve depende de qual das três falhou, e o que se faz em cada caso e completamente diferente.
pinMode antes de digitalWrite
pinMode(PIN_LED, OUTPUT); // declara o pino como saida digitalWrite(PIN_LED, HIGH); // manda nivel alto
O pino de um microcontrolador comeca sempre como entrada. digitalWrite em um pino que foi declarado como entrada não da erro de compilacao e não faz nada: o sinal vai para dentro da placa em vez de sair. E o defeito mais comum da aula, e a causa número um de "o LED não acende".
A velocidade do monitor serial
Serial.begin(115200) diz: "vou falar a 115200 bits por segundo". O monitor serial precisa da mesma velocidade, senao o que chega e lixo — e o aluno conclui que o programa esta errado quando o programa esta certo.
Se o monitor mostrar caracteres estranhos como ÿÿó ou ááá, não e o código. E a velocidade. Troque 115200 por 9600 no monitor e veja se muda.
Atividade
Montagem:
- Resistor de 330 entre o
GPIO2e um lado do LED. - Outro lado do LED na trilha
+(5 V) da protoboard. - Fio jumper femea-femea levando o
GPIO2ao resistor.
O lado longo do LED e o anodo: ele vai para o positivo. Se o lado curto ir para o positivo, o LED não acende — e o aluno costuma trocar os lados.
Nota: 10 pontos. Critério de fim: o LED pisca a cada meio segundo, e o monitor serial mostra a contagem de voltas subindo.
- Selecione em Ferramentas > Placa a placa
ESP32 DevKit Module. - Em Ferramentas > Porta, escolha a porta que apareceu. Se aparecerem varias, use a que some quando você desconecta o cabo.
- Grave o código da resolucao.
- Monte o circuito do enunciado e confirme que o LED pisca.
- Troque
INTERVALOde 500 para 150, grave de novo e descreva a diferença em uma frase. - No monitor serial, anote quantas voltas aparecem em 10 segundos. O número que você calcula e o número que a placa mostra? Explique a diferença.
Resolucao
#include <Arduino.h> // GPIO2 e o LED embutido na maioria dos DevKit. Se o seu kit nao acender, // e porque o LED esta em outro pino: troque a constante e grave de novo. const int PIN_LED = 2; // Intervalo em milissegundos. Declarar o tempo como constante e o que permite // mudar o ritmo do sem mexer na logica. const int INTERVALO = 500; int voltas = 0; void setup() { // OUTPUT tem que vir ANTES do primeiro digitalWrite. Esquecido, o pino fica // como entrada e o LED nao acende — sem erro de compilacao. pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("Monitor serial aberto a 115200 baud."); Serial.println("Aperte o botao RESET se a tela estiver vazia."); Serial.println(); Serial.println("Pino | voltas | tempo"); } void loop() { voltas++; digitalWrite(PIN_LED, HIGH); // led aceso delay(INTERVALO); digitalWrite(PIN_LED, LOW); // led apagado delay(INTERVALO); Serial.print(PIN_LED); Serial.print(" | "); Serial.print(voltas); Serial.print(" | "); Serial.print(voltas * INTERVALO * 2); Serial.println(" ms"); }
Por que assim e não de outro jeito. O pinMode vem antes de qualquer digitalWrite, no setup. Se o aluno escreve o digitalWrite primeiro e so depois declara a saída, o programa funciona na maioria das vezes — o que e pior. Depende da ordem em que o processador executou, e o defeito reaparece quando o aluno mexer no código por outro motivo. Esse e o tipo de bug que ele vai levar para o projeto final.
A variável voltas existe por um motivo pedagogico, não funcional: sem ela, o pisca-pisca e invisivel no serial, e o aluno não tem como provar que o programa esta rodando. Com ela, o professor olha a tela e sabe que o loop esta girando mesmo com o LED coberto pela mao.
O calculo voltas * INTERVALO * 2 existe para responder o item 6 da atividade: o tempo real e o dobro do intervalo, porque o LED fica aceso INTERVALO e apagado INTERVALO. O aluno que calcula voltas * INTERVALO esqueceu o segundo delay.
Criterios de correcao
| Critério | Pontos |
|---|---|
| Placa e porta selecionadas, programa gravado sem erro | 2 pontos |
pinMode declarado no setup antes de qualquer digitalWrite | 3 pontos |
| Resistor de 330 em serie com o LED e lado longo do LED no positivo | 2 pontos |
| Monitor serial em 115200, com a contagem de voltas subindo | 2 pontos |
| Item 6 respondido: o dobro do intervalo esta explicado | 1 ponto |
Erros comuns
| Erro | Como aparece | Correcao |
|---|---|---|
Esquecer o pinMode(..., OUTPUT) | "Meu código esta certo e o LED não acende" | "digitalWrite em pino declarado como entrada não da erro, so não funciona. Ponha o pinMode no setup." |
| Placa selecionada como Arduino Uno | Erro de compilacao com nomes de pin que so existem no Uno | "Em Ferramentas > Placa, escolha ESP32 DevKit Module. A lista e longa: e a unica com ESP32 escrito." |
| Não aparece nada no monitor | Tela vazia, placa piscando | "Aperte o botao RESET. O programa comeca a rodar de novo e o Serial.println do setup repete." |
| Caracteres estranhos no monitor | þÿÇöÿÇö ou @@@ | "Não mexa no código. Troque a velocidade do monitor para 115200 — e o Serial.begin do seu programa que manda." |
| Resistor depois do LED, ou nenhum resistor | LED muito fraco, ou LED que durou dois minutos | "O resistor limita a corrente. Sem ele, o LED pede mais corrente do que o pino entrega, e ele queima." |
| Cabecar USB frouxo | "Ele grava e depois para" | "Encaixe de novo, com firmeza. Cabo solto não e comum, mas e comum quando o aluno mexe com a placa enquanto grava." |
| Medir voltas por 10 segundos e vir num número estranho | Item 6 com resposta errada | "Conte quantas linhas completas apareceram. A ultima linha pode ter saido pela metade." |
Desafio extra
Faca o LED piscar duas vezes: rapido e lento, sem mudar o intervalo constante. Depois faca o contrario: um unico intervalo que muda de valor a cada dez voltas. Em ambos os casos, escreva qual das duas formas deixa o código mais facil de ler, e defenda a sua escolha.
A resolucao, compilada
// Aula 2 do 1o trimestre: o primeiro blink e a leitura do monitor serial. // // Este e o codigo que o professor projeta, digita junto com a turma e grava na // placa. Depois de gravar, TODA aula do ano passa a usar monitor serial: o // professor nao tem osciloscopio, e o serial e o instrumento de aula. #include <Arduino.h> // GPIO2 e o LED embutido na maioria dos DevKit. Se o seu kit nao acender, // e porque o LED esta em outro pino: troque a constante e grave de novo. const int PIN_LED = 2; // Intervalo em milissegundos. Declarar o tempo como constante e o que permite // mudar o ritmo do sem mexer na logica. const int INTERVALO = 500; // Quantas vezes o ciclo ja rodou. Serve para o professor mostrar que o programa // esta vivo mesmo quando o olho nao percebe o pisca-pisca. int voltas = 0; void setup() { // OUTPUT tem que vir ANTES do primeiro digitalWrite. Esquecido, o pino fica // como entrada e o LED nao acende — sem erro de compilacao. pinMode(PIN_LED, OUTPUT); Serial.begin(115200); Serial.println(); Serial.println("Monitor serial aberto a 115200 baud."); Serial.println("Aperte o botao RESET se a tela estiver vazia."); Serial.println(); Serial.println("Pino | voltas | tempo"); } void loop() { voltas++; digitalWrite(PIN_LED, HIGH); // led aceso delay(INTERVALO); digitalWrite(PIN_LED, LOW); // led apagado delay(INTERVALO); // O monitor mostra o estado do programa a cada ciclo completo. Serial.print(PIN_LED); Serial.print(" | "); Serial.print(voltas); Serial.print(" | "); Serial.print(voltas * INTERVALO * 2); Serial.println(" ms"); }
Saída real do compilador para esp32:esp32:esp32
Sketch uses 272164 bytes (20%) of program storage space. Maximum is 1310720 bytes.
Global variables use 22116 bytes (6%) of dynamic memory, leaving 305564 bytes for local variables. Maximum is 327680 bytes.
