Fundamentos · 12 min de leitura

Bloco se na programação em blocos: botão e LED no Arduino com if/else

Bloco se na programação em blocos com botão e LED no Arduino: leitura de pinos, if/else, =, ≠, <, >, ifs aninhados, liga/desliga, debounce e luz noturna com LDR.

O bloco se da programação em blocos permite que o programa escolha um de dois caminhos com base em uma pergunta: “O botão está pressionado? Se sim, acenda o LED; se não, apague.” No C++ do Arduino essa estrutura se chama if/else, e o bloco “se … fazer … senão” do BlueGrays é o equivalente exato dela. Neste post você vai usar um projeto de botão e LED no Arduino para aprender a configurar um pino como entrada e a lê-lo e, depois, o bloco se, os operadores de comparação, as condições aninhadas e como combinar duas condições com “e”, bloco a bloco e linha a linha.

Este post é a parte 3 da série Dos blocos ao código. Na parte anterior, escrevemos o primeiro programa e fizemos um LED piscar com blocos; na próxima, vamos tratar de laços e variáveis.

Até agora nossos programas sempre faziam a mesma coisa: o LED acendia, esperava, apagava e esperava de novo. Eles nunca prestavam atenção no mundo lá fora. Com as condições, a placa passa a tomar decisões olhando para um botão, um sensor de luz ou uma distância que ela mede, e é aí que começa a verdadeira diversão da programação de robótica. Todos os exemplos daqui vêm de projetos em blocos grátis, então você pode abrir os blocos e o código deles na página de programação em blocos ou no app e acompanhar o texto lado a lado.

Entrada e saída: em que sentido o pino trabalha?

Os pinos digitais do Arduino fazem um de dois trabalhos. Um pino configurado como saída fornece 5 V (HIGH) ou 0 V (LOW); é assim que você aciona um LED, um buzzer ou um relé. Um pino configurado como entrada não fornece nada e só “escuta” a tensão que chega nele: no Arduino Uno, ele lê qualquer coisa acima de cerca de 3 V como HIGH e qualquer coisa abaixo de 1,5 V como LOW. Nos blocos, você faz essa escolha na seção de configuração: o bloco “configurar pino 13 como ENTRADA” vira pinMode(13, INPUT); em C++, e “configurar pino 7 como SAÍDA” vira pinMode(7, OUTPUT);. Para ler o pino, você usa o bloco “ler pino 13”. Ele tem uma aparência diferente dos outros: não é um comando que você empilha, e sim um bloco de valor de cantos arredondados que se encaixa em um espaço dentro de outro bloco. O equivalente dele em C++ é digitalRead(13), que retorna HIGH ou LOW (nos blocos, ALTO ou BAIXO). Como no Arduino HIGH vale 1 e LOW vale 0, você também pode guardar o resultado em uma variável, como se fosse um número. Resumindo: blocos de comando fazem algo, blocos de valor dão um resultado, e o encaixe de condição do bloco se só pode ser preenchido com um resultado desse tipo.

BlocoEquivalente em C++O que faz
configurar pino 13 como ENTRADApinMode(13, INPUT);Coloca o pino em modo de escuta (uma vez, no setup)
configurar pino 7 como SAÍDApinMode(7, OUTPUT);Permite que o pino forneça tensão
ler pino 13digitalRead(13)Retorna HIGH (1) ou LOW (0)
escrever ALTO no pino 7digitalWrite(7, HIGH);Coloca 5 V no pino e o LED acende
ler analógico A0analogRead(A0)Retorna um número de 0 a 1023
se … fazer … senãoif (…) { … } else { … }Executa um de dois caminhos conforme a condição

Circuito: botão no 13, LED no 7, resistor de pull-down obrigatório

No projeto Controle de LED com botão (momentâneo), o botão fica no D13 e o LED no D7. Uma perna do botão vai ao 5V e a outra ao D13, e um resistor de pull-down de 10 kΩ fica entre o D13 e o GND. Com o botão solto, o resistor puxa o pino para o GND e ele lê LOW. Quando você pressiona, o 5V chega direto ao pino e ele lê HIGH. Como o resistor é grande, só cerca de meio miliampère passa do 5V para o GND enquanto o botão está pressionado. A perna longa do LED se liga ao D7 por um resistor de 220 Ω e a perna curta vai ao GND.

PeçaLiga-se aPino do Arduino Uno
Botão, perna 1Direto5V
Botão, perna 2 (diagonal)DiretoD13
Resistor de 10 kΩ (pull-down)Entre D13 e GNDD13 – GND
Perna longa do LED (ânodo)Por um resistor de 220 ΩD7
Perna curta do LED (cátodo)DiretoGND
Se você pular o resistor de pull-down, o D13 fica ligado a nada enquanto o botão está solto; isso se chama entrada flutuante. O pino capta ruído elétrico, digitalRead() retorna valores HIGH e LOW aleatórios e o LED tremula sem você tocar em nada, ou até acende quando sua mão chega perto. Nos botões de quatro pernas, as duas pernas do mesmo lado já estão ligadas por dentro, então use pernas na diagonal. Para mais detalhes, veja como ligar um botão no Arduino e resistores de pull-up e pull-down.

O bloco se e o if/else: acender o LED enquanto o botão está pressionado

A versão em blocos do projeto tem duas seções. Em “configuração (uma vez)”, o pino 13 é configurado como ENTRADA e o pino 7 como SAÍDA. Em “repetir para sempre”, há um único bloco grande: se … fazer … senão. O encaixe hexagonal de condição dele guarda a comparação “ler pino 13 = ALTO”. Se a condição for verdadeira, roda o bloco “escrever ALTO no pino 7” do ramo “fazer”; se for falsa, roda o bloco “escrever BAIXO no pino 7” do ramo “senão”.

Bloco se na programação em blocos: blocos do projeto Controle de LED com botão (momentâneo)
O pino 13 é ENTRADA e o pino 7 é SAÍDA; se o pino 13 lê ALTO, o LED acende; caso contrário, apaga.
C++ (Arduino IDE)
1void setup() {
2  pinMode(13, INPUT);    // Buton girişi (harici pull-down) / Button input (external pull-down)
3  pinMode(7, OUTPUT);    // LED çıkışı / LED output
4}
5
6void loop() {
7  if (digitalRead(13) == HIGH) {   // Buton basılı mı? / Is the button pressed?
8    digitalWrite(7, HIGH);         // Basılı: LED yanar / Pressed: LED on
9  } else {
10    digitalWrite(7, LOW);          // Bırakıldı: LED söner / Released: LED off
11  }
12}
13

Coloque o código ao lado dos blocos e a correspondência fica evidente. A palavra if corresponde ao “se” do bloco, a condição digitalRead(13) == HIGH entre parênteses corresponde ao encaixe de condição, o primeiro par de chaves corresponde ao ramo “fazer”, e o else com suas chaves corresponde ao ramo “senão”. Cada bloco que você coloca em um ramo vira uma linha dentro das chaves correspondentes no código. Como o loop() roda dezenas de milhares de vezes por segundo, a placa lê o botão sem parar; no instante em que você tira o dedo, a condição fica falsa no ciclo seguinte e o LED apaga. É por isso que o projeto é “momentâneo” (Push, no nome em inglês): o LED só fica aceso enquanto você segura o botão. O ramo “senão” é opcional; um bloco se só com o ramo “fazer” vira um if sem else. Mas, se você remover o ramo “senão” aqui, o LED nunca mais apaga depois de aceso, porque não sobra nenhuma linha para desligá-lo. Pensar nos dois ramos em toda condição é um bom hábito.

Blocos de comparação: =, ≠, < e >

Símbolo no blocoC++SignificadoExemplo dos projetos
===igual adigitalRead(13) == HIGH (LED com botão momentâneo)
≠!=diferente debutton != lastButton (LED liga/desliga com botão)
<<menor quevalue < 50 (luz noturna com LDR)
>>maior quedistance > minDistance (distância com HC-SR04)
O sinal “=” de um bloco de comparação é escrito == em C++. Um único sinal de igual em C++ não é uma comparação, e sim uma atribuição. Se você escrever if (button = 1), o compilador não impede: button recebe 1, o resultado é diferente de zero e, por isso, a condição é verdadeira em todo ciclo e o LED acende sem nunca olhar para o botão. Com blocos você não comete esse erro, porque a atribuição (“definir … como …”) e a comparação são blocos separados. Mas, quando você passa para o código, esse é o erro mais comum de todos.

Liga/desliga com um botão: ifs aninhados e uma variável de estado

No projeto momentâneo, o LED só ficava aceso enquanto você segurava o botão. Se você quer que ele se comporte como um interruptor de luz de verdade, “aperte uma vez para ligar, aperte de novo para desligar”, o programa precisa lembrar duas coisas: se o LED está aceso agora e o que o botão leu no ciclo anterior. O projeto Ligar e desligar um LED com botão declara dois inteiros para isso na seção “variáveis globais (no topo)”: ledState (0 = apagado, 1 = aceso) e lastButton (a leitura anterior). O circuito é o mesmo de antes: botão no D13 com pull-down externo e LED no D7.

Blocos do projeto Ligar e desligar um LED com botão: se aninhado, a comparação ≠ e o bloco “não”
O se de fora detecta uma mudança no estado do botão, e o se de dentro confere se é um aperto; “não ledState” inverte o estado do LED.
C++ (Arduino IDE)
1int ledState = 0;     // LED durumu: 0 = sönük, 1 = yanık / LED state: 0 = off, 1 = on
2int lastButton = 0;   // Butonun önceki okuması / Previous button reading
3
4void setup() {
5  pinMode(13, INPUT);   // Buton girişi (harici pull-down) / Button input (external pull-down)
6  pinMode(7, OUTPUT);   // LED çıkışı / LED output
7}
8
9void loop() {
10  int button = digitalRead(13);   // Butonu oku / Read the button
11  if (button != lastButton) {     // Buton durumu değişti / Button state changed
12    if (button == 1) {            // Yalnız basış anında (LOW -> HIGH) / Only at the press (LOW -> HIGH)
13      ledState = !ledState;       // Durumu ters çevir / Flip the state
14      digitalWrite(7, ledState);
15    }
16    delay(50);                    // Sıçramayı atlamak için kısa bekleme / Short wait to skip the bounce
17    lastButton = button;          // Bu okumayı sakla / Store this reading
18  }
19}
20
BlocoLinha em C++Função
declarar inteiro (int) ledState = 0int ledState = 0;Guarda o estado do LED
declarar inteiro (int) lastButton = 0int lastButton = 0;Guarda a leitura anterior do botão
definir button como ler pino 13int button = digitalRead(13);Lê o estado atual do botão
se button ≠ lastButtonif (button != lastButton) {Entra se o estado do botão mudou
se button = 1if (button == 1) {Entra se a mudança for um aperto (de 0 para 1)
definir ledState como não ledStateledState = !ledState;Transforma 0 em 1 e 1 em 0
escrever ledState no pino 7digitalWrite(7, ledState);Coloca o LED no novo estado
aguardar 50 msdelay(50);Ignora o repique dos contatos
definir lastButton como buttonlastButton = button;Guarda esta leitura para o próximo ciclo

O coração do programa é o par de blocos se aninhados. A condição de fora, button ≠ lastButton, só é verdadeira no ciclo em que o estado do botão muda; nos milhares de ciclos em que você segura o botão ou nem encosta nele, nada acontece. Uma mudança pode ir em dois sentidos: um aperto (de 0 para 1) ou uma soltura (de 1 para 0). A condição de dentro, button = 1, escolhe só o aperto. Assim, o LED muda uma vez a cada aperto e não muda nada ao soltar. No código, ifs aninhados aparecem como chaves dentro de chaves. Nos blocos, o se de dentro fica no ramo “fazer” do de fora, então você vê de relance qual linha depende de qual condição.

O bloco não ledState é escrito !ledState em C++. O ponto de exclamação dá o oposto lógico: o oposto de 0 é 1, e o oposto de qualquer número diferente de zero é 0. Atribuir a ledState o seu próprio oposto inverte o estado a cada aperto. O bloco seguinte, “escrever ledState no pino 7”, é a linha digitalWrite(7, ledState); como HIGH vale 1 e LOW vale 0, o valor da variável pode ser escrito direto no pino. Por fim, lastButton recebe a leitura deste ciclo para que a comparação do próximo ciclo saia correta. Se você esquecer essa atribuição, lastButton fica em 0; enquanto você segura o botão, a condição de fora é verdadeira em todo ciclo e o LED pisca rapidamente.

O bloco aguardar 50 ms não é enfeite: é uma técnica simples de debounce. Os contatos metálicos de um botão abrem e fecham por alguns milissegundos enquanto se fecham; a placa lê tão rápido que pode tomar um aperto por vários, deixando o LED aceso ou apagado ao acaso. Esperar 50 ms depois de uma mudança dá tempo para o repique acabar. Enquanto o delay() espera, a placa não consegue fazer mais nada; para temporizar sem parar o programa, veja millis() e delay().

Condição analógica: luz noturna com LDR

As condições não servem só para HIGH e LOW. No projeto Luz noturna com LDR, o bloco “definir value como ler analógico A0” transforma a tensão no A0, onde o LDR está ligado, em um número entre 0 e 1023; em C++, essa é a linha value = analogRead(A0);. Em seguida, o bloco se verifica value < 50. Se o valor estiver abaixo de 50, o ambiente conta como escuro e o LED no D13 acende; caso contrário, apaga. A estrutura é a mesma do projeto momentâneo; só muda a comparação no encaixe de condição.

Blocos do projeto Luz noturna com LDR: ler analógico A0 e a condição value < 50
Uma leitura analógica dá um número de 0 a 1023; se value for menor que 50, o LED acende; caso contrário, apaga.
C++ (Arduino IDE)
1int value;   // Işık okuması (0-1023) / Light reading (0-1023)
2
3void setup() {
4  pinMode(13, OUTPUT);   // LED çıkışı / LED output
5}
6
7void loop() {
8  value = analogRead(A0);   // Işık seviyesini oku / Read the light level
9
10  // Eşik 50: altı karanlık sayılır, hassasiyeti bu sayıyla ayarla
11  // Threshold 50: anything below counts as dark. Tune the sensitivity with this number
12  if (value < 50) {
13    digitalWrite(13, HIGH);   // Karanlık: LED yanar / Dark: LED on
14  } else {
15    digitalWrite(13, LOW);    // Aydınlık: LED söner / Bright: LED off
16  }
17}
18

Dependendo do seu LDR e do resistor do circuito, um limite de 50 pode ser baixo ou alto demais para o seu cômodo. Para achar o número certo, use primeiro o projeto Medição da intensidade da luz com LDR para ver os valores de claro e escuro no Monitor Serial e depois coloque o limite entre eles. Se o valor ficar oscilando bem em volta do limite, o LED pode tremular; usar dois limites separados, um para ligar e outro para desligar, resolve isso de um jeito elegante. Você encontra como um LDR funciona no post sensor de luz LDR.

Combinando condições: o bloco “e” e o &&

Às vezes uma condição só não basta. No projeto Medição de distância com HC-SR04 (Monitor Serial), a distância medida só é exibida no Monitor Serial se estiver entre 3 cm e 100 cm. Nos blocos, duas comparações são unidas lado a lado com um bloco e: “distance > minDistance e distance < maxDistance”. Em C++, essa linha vira if (distance > minDistance && distance < maxDistance). O operador && torna o resultado verdadeiro só se os dois lados forem verdadeiros; se pelo menos um for falso, a condição é falsa. Assim, valores sem sentido fora do alcance do sensor nunca chegam à tela. Em C++, “ou” se escreve || e basta uma condição verdadeira. Você pode testar as tabelas-verdade de AND, OR e NOT na ferramenta Portas lógicas.

As mesmas condições no ESP32: pull-up interno e lógica invertida

O projeto Controle de LED com botão no ESP32 (momentâneo) usa o mesmo bloco se em um ESP32, com duas diferenças. O LED fica no GPIO 5, o botão no GPIO 4, e o pino do botão recebe a opção “ENTRADA (PULLUP)” no bloco “configurar pino … como …”. Em C++, isso é pinMode(BUTTON_PIN, INPUT_PULLUP);: um resistor dentro do chip puxa o pino para HIGH, então nenhum resistor externo é necessário. Desta vez o botão vai ao GND, por isso o pino lê LOW quando pressionado, e a condição vira “ler pino BUTTON_PIN = BAIXO”. O projeto Controle de LED com botão no ESP32 (alternância) faz o liga/desliga com o bloco “milissegundos desde o início”, ou seja, millis(), em vez de uma espera de 50 ms, e de novo une duas condições com um bloco “e”. Os pinos do ESP32 trabalham com 3,3 V; não ligue o botão ao 5 V.

Erros comuns e soluções

ErroSintomaSolução
Sem resistor de pull-downO LED tremula sozinho e acende quando a mão chega pertoColoque 10 kΩ entre D13 e GND, ou use INPUT_PULLUP e inverta a lógica
Igual simples na condição: if (button = 1)O LED fica sempre aceso e ignora o botãoUse == para comparações
Ponto e vírgula no fim da linha do ifO código entre chaves roda em todo ciclo, independentemente da condiçãoApague o ; depois de if (…)
Usar pernas do botão do mesmo ladoO pino lê sempre HIGH ou sempre LOWUse pernas na diagonal
lastButton não atualizado ou falta de espera no liga/desligaO LED pisca enquanto o botão está pressionado ou fica num estado aleatórioAdicione lastButton = button e a espera de 50 ms
Tratar HIGH como pressionado com INPUT_PULLUPO LED funciona ao contrário e acende ao soltarCom o pull-up interno, LOW significa pressionado
Limite do LDR inadequado para o cômodoO LED nunca acende ou fica sempre acesoObserve o valor no Monitor Serial e escolha um novo limite

Abrindo blocos e código lado a lado no app

Todos os projetos deste post estão entre os projetos em blocos grátis do app BlueGrays. Ative a chave Ver em blocos na seção de código de um projeto e o código é substituído pelo mesmo programa em blocos; toque na imagem para abri-la em tela cheia. A aba Entenda os blocos explica o programa passo a passo: cada passo mostra só os blocos daquele passo e o que eles fazem, para que você acompanhe os blocos se aninhados um de cada vez. Os exemplos de if/else e digitalRead do Guia de código também aparecem em blocos. Os blocos não são carregados diretamente na placa e, por enquanto, você não pode montar seus próprios programas arrumando blocos; você sempre copia o código C++ real do projeto para o Arduino IDE e o carrega. Se quiser revisar o que aprendeu, as Perguntas do dia trazem 5 perguntas por dia, em níveis de A1 a C2.

Agora que você conhece as condições, o próximo passo é lidar com repetições e contadores: na parte de laços e variáveis, você vai ver como “repetir para sempre” se relaciona com o loop() e como o bloco de contagem se relaciona com um laço for. Até lá, você pode ver o esquema do circuito e o código dos projetos de LED com botão momentâneo, luz noturna com LDR e botão no ESP32 no app BlueGrays, passar para a visualização em blocos com Ver em blocos e para a explicação passo a passo com Entenda os blocos.

Perguntas frequentes

Para que serve o bloco se na programação em blocos?

O bloco se permite que o programa tome uma decisão: se a condição for verdadeira, rodam os blocos do ramo “fazer”; se for falsa, rodam os do ramo “senão”. Nos projetos com Arduino, ele costuma ser usado para verificar se um botão está pressionado ou se o valor de um sensor passou de um limite. O equivalente em C++ é a estrutura if/else.

Qual é a diferença entre if e else no Arduino?

O if executa o código entre as chaves dele quando a condição entre parênteses é verdadeira. O else é opcional e guarda o código que roda só quando a condição é falsa. Sem else, nada acontece quando a condição é falsa e o programa segue para a próxima linha.

Qual é a diferença entre = e == no Arduino?

Um sinal de igual simples (=) atribui um valor a uma variável, enquanto o sinal de igual duplo (==) compara dois valores. Escrever if (x = 1) atribui 1 a x e deixa a condição sempre verdadeira; a forma correta é if (x == 1). Nos blocos, o sinal “=” de um bloco de comparação vira == no código.

Por que o LED do meu Arduino acende sem eu apertar o botão?

O mais provável é que o pino do botão esteja flutuando, ou seja, sem resistor de pull-down ou pull-up. Aí o pino lê o ruído em volta e parece HIGH ou LOW ao acaso. Coloque um resistor de 10 kΩ entre o pino e o GND, ou use pinMode(pin, INPUT_PULLUP) e ligue o botão ao GND.

Como ligar e desligar um LED com um botão no Arduino?

Guarde o estado do LED em uma variável (ledState) e a leitura anterior do botão em outra (lastButton). Quando o estado do botão mudar e o novo estado for pressionado, inverta o estado com ledState = !ledState e escreva-o no LED com digitalWrite. Acrescente uma espera curta, como 50 ms, para ignorar o repique dos contatos; o projeto Ligar e desligar um LED com botão faz exatamente isso.

Posso carregar os blocos do BlueGrays no meu Arduino?

Não, os blocos não são carregados diretamente na placa. Eles correspondem um a um ao código real do projeto e servem para ajudar você a entender o programa. Você sempre copia o código C++ do projeto para o Arduino IDE e o carrega na placa.

Ver todos os projetos
Controle de LED com botão (momentâneo)
#9Iniciante

Controle de LED com botão (momentâneo)

É como uma campainha: a luz fica acesa enquanto você pressiona o botão e apaga quando você solta. O Arduino monitora o botão continuamente; enquanto ele está pressionado, o LED fica aceso e apaga assi

4.8(113)
229
Ligar e desligar um LED com botão
#10Iniciante

Ligar e desligar um LED com botão

Pressione o botão uma vez para acender a luz e outra vez para apagar, como o interruptor do seu quarto. O Arduino detecta cada toque e inverte o estado do LED, aguardando um breve instante para que as

4.8(100)
167
Luz noturna com LDR
#12Iniciante

Luz noturna com LDR

Uma pequena luz noturna que acende sozinha quando escurece e apaga ao amanhecer. Um sensor de luz mede a luminosidade do quarto, e o Arduino acende o LED quando está escuro o suficiente e apaga quando

4.8(102)
205
Medição de distância com HC-SR04 (Monitor Serial)
#27Iniciante

Medição de distância com HC-SR04 (Monitor Serial)

O sensor HC-SR04 funciona como um morcego que se orienta no escuro: emite um som que você não consegue ouvir, escuta o eco e mede a distância até o objeto à sua frente. O Arduino escreve essa distânci

4.6(46)
71
Controle de LED com botão no ESP32 (momentâneo)
#104Iniciante

Controle de LED com botão no ESP32 (momentâneo)

O LED acende enquanto o botão está pressionado e apaga ao soltá-lo. Mostra como usar o pino de entrada digital e o resistor pull-up interno do ESP32. O modo INPUT_PULLUP dispensa um resistor externo.

4.6(36)
55
Controle de LED com botão no ESP32 (alternância)
#105Iniciante

Controle de LED com botão no ESP32 (alternância)

Cada vez que o botão é pressionado, o estado do LED muda: se estiver aceso, apaga; se estiver apagado, acende. É o padrão clássico de alternância. Com debounce, eliminamos o ruído mecânico dos contatos do botão para garantir uma única mudança a cada pressionamento.

4.6(39)
57
Medição da intensidade da luz com LDR
#11Iniciante

Medição da intensidade da luz com LDR

Quer ver a luminosidade do seu quarto em números? O LDR, um pequeno componente sensível à luz, mede a luz ambiente, e o Arduino exibe o valor na tela do computador a cada meio segundo. Cubra o sensor

4.6(81)
139
LED piscante
#1Iniciante

LED piscante

O primeiro contato com a eletrônica: acender e apagar um único LED. O Arduino acende e apaga o LED em intervalos curtos, fazendo a luz piscar rapidamente. Você vê da forma mais simples como a placa co

4.6(188)
1127