Em C, funções são blocos reutilizáveis com um tipo de retorno, um nome e parâmetros entre parênteses. O tipo void significa que a função não retorna nenhum valor.
A estrutura básica do Arduino é formada por dois blocos obrigatórios que carregam outras funções escritas em C/C++. Sem eles, nenhum programa funciona!
/* Exemplo: setup() abre a serial; loop() transmite "Hello World!" a cada 2 segundos. */ void setup() { Serial.begin(9600); // inicia porta serial em 9600 bps } void loop() { Serial.println("Hello World!"); // transmite frase delay(2000); // pausa 2 segundos }
Em C, funções são blocos reutilizáveis com um tipo de retorno, um nome e parâmetros entre parênteses. O tipo void significa que a função não retorna nenhum valor.
Toda função criada pelo programador deve ser declarada antes de ser chamada. Você pode declarar apenas o cabeçalho no início e escrever o corpo depois do loop().
Constantes são valores fixos que nunca mudam. No Arduino há 3 grupos, e cada par pode ser representado por 1 e 0 em binário:
HIGH = 5 volts no pino digital. LOW = 0 volt (terra). TRUE = qualquer valor diferente de zero. FALSE = sempre zero.
int i = 0; // variável GLOBAL — visível em todo o programa void ledOn(); // declaração prévia da função criada void setup() { pinMode(10, OUTPUT); } void loop() { for (i=0; i <= 255; i++) ledOn(); // aumenta brilho for (i=255; i >= 0; i--) ledOn(); // diminui brilho } void ledOn() { // usa 'i' que é global analogWrite(10, i); // brilho proporcional a i delay(10); }
Declarada antes do setup() → é Global (todo o programa a enxerga). Declarada dentro de uma função → é Local (só essa função a enxerga). Use globais só quando realmente necessário!
Matrizes são coleções de variáveis do mesmo tipo armazenadas em posições contíguas de memória. Cada posição é acessada por um índice — e o primeiro índice é sempre 0!
// Declaração com inicialização dos valores int nomeMatriz[] = { 16, 32, 64, 128, 255 }; // Declaração só com tamanho (sem valores iniciais) int notas[10]; // reserva 10 posições para inteiros // Escrevendo na 4ª posição (índice 3) nomeMatriz[3] = 200; // Lendo a 5ª posição (índice 4) e guardando em x int x = nomeMatriz[4]; // x = 255 // Percorrendo a matriz inteira com for for (int i = 0; i < 5; i++) { Serial.println(nomeMatriz[i]); }
Uma matriz com 5 elementos tem índices de 0 a 4. Acessar o índice 5 é um erro que causa comportamento imprevisível no Arduino. Cuidado sempre!
Matrizes são perfeitas para guardar sequências de notas musicais, padrões de LEDs, leituras de sensores ao longo do tempo, ou comandos em sequência para um servo motor.
O Arduino herda da linguagem C todos os operadores aritméticos e lógicos. Aqui estão os mais usados:
= é atribuição (guarda um valor). == é comparação (pergunta se são iguais). Usar = dentro de um if em vez de == é o erro número 1 dos iniciantes — e o compilador às vezes nem avisa!
No Monitor Serial, mostre o resultado de: x++ 10 vezes, depois x-- 10 vezes — e observe o padrão. Depois teste && e || combinando duas condições ao mesmo tempo.
O Arduino tem funções embutidas para controlar o tempo, gerar números aleatórios e fazer conversões de faixas. São essenciais para praticamente todo projeto!
| Função | Exemplo e Resultado | Observações |
|---|---|---|
| delay(ms) | delay(1000);Pausa de 1 segundo exato. |
Congela TUDO por esse período. Nenhuma outra função roda. Equivale ao HALT do Assembly. |
| delayMicroseconds(us) | delayMicroseconds(500);Pausa de 500 microssegundos. |
Para pausas muito curtas. Mesma limitação do delay(). |
| millis() | long t = millis();Guarda ms desde o boot. |
Não congela o programa! Reinicia após ~9 horas de uso contínuo. |
| random(min, max) | int v = random(100,400);Número entre 100 e 399. |
O parâmetro min é opcional (padrão = 0). O max nunca é incluído. |
| abs(x) | float v = abs(-3.14);Resultado: 3.14 |
Retorna o valor absoluto (sem sinal). |
| map(val,min1,max1,min2,max2) | int v = map(analogRead(A0), 0,1023, 0,255); |
Converte uma faixa de valores para outra. Pode inverter: map(x,1,100,100,1). |
A função map() é uma das mais poderosas: converte a leitura analógica (0–1023) para o brilho do LED (0–255), a posição de um sensor para ângulo de servo, temperatura em porcentagem... As possibilidades são infinitas!
unsigned long ultimoTempo = 0; int estado = LOW; void loop() { if (millis() - ultimoTempo >= 500) { // 500ms passaram? ultimoTempo = millis(); estado = (estado == LOW) ? HIGH : LOW; // inverte digitalWrite(13, estado); } // Aqui você pode fazer outras coisas enquanto o LED pisca! }
As estruturas de controle de fluxo, herdadas da linguagem C/C++, determinam quais instruções serão executadas e quantas vezes. São o núcleo da lógica de qualquer programa!
int temperatura = 35; if (temperatura > 40) { Serial.println("ALERTA: temperatura crítica!"); } else if (temperatura > 30) { Serial.println("Temperatura alta."); } else if (temperatura > 20) { Serial.println("Temperatura normal."); } else { Serial.println("Temperatura baixa."); }
// for (variável; condição; incremento) for (int i = 0; i <= 10; i++) { Serial.println(i); // imprime 0, 1, 2 ... 10 delay(1000); } // Também funciona de trás para frente! for (int i = 255; i >= 0; i--) { analogWrite(9, i); // LED apagando gradualmente delay(8); }
int modo = 2; switch (modo) { case 1: Serial.println("Modo 1: LED piscando devagar"); break; // ESSENCIAL! Sem break, cai no próximo case case 2: Serial.println("Modo 2: LED piscando rápido"); break; case 3: Serial.println("Modo 3: LED apagado"); break; default: // se nenhum case for verdadeiro Serial.println("Modo desconhecido!"); } // Operador ternário — if...else em uma linha só: // (condição) ? valor_se_verdadeiro : valor_se_falso int x = 8; int y = (x > 10) ? 15 : 20; // y = 20 (pois 8 não é > 10)
No switch...case, cada case precisa terminar com break;. Sem ele, o código "cai" no próximo case e continua executando — comportamento quase sempre indesejado!
O Arduino UNO possui 4 grupos de pinos, cada um com função e comandos específicos em C:
São 14 pinos (0 a 13) que operam em dois estados: HIGH (5V) ou LOW (0V). Antes de usar, é preciso configurar a direção com pinMode() dentro do setup().
Os pinos 3, 5, 6, 9, 10 e 11 são marcados com ~ na placa e suportam analogWrite() para simular tensão analógica via PWM (Modulação por Largura de Pulso). Valores de 0 a 255.
| Função | Exemplo e Resultado | Observações |
|---|---|---|
| pinMode(pino, modo) | pinMode(2, OUTPUT);Pino 2 configurado como saída. |
Sempre no setup(). Use INPUT ou OUTPUT. Existe também INPUT_PULLUP. |
| digitalRead(pino) | int chave = digitalRead(3);Guarda HIGH ou LOW em 'chave'. |
Pino deve estar configurado como INPUT com pinMode(). |
| digitalWrite(pino, val) | digitalWrite(2, HIGH);Coloca 5V no pino 2. |
Pino deve ser OUTPUT. Use LOW para colocar 0V. |
| analogWrite(pino, val) | analogWrite(10, 128);~2.5V no pino 10 (PWM). |
Só nos pinos PWM (~). Valor 0–255. Não precisa de pinMode(). |
| attachInterrupt(pino,fn,modo) | attachInterrupt(0, contador, RISING); |
Pino 0→digital 2, pino 1→digital 3. Modos: LOW, CHANGE, RISING, FALLING. |
| pulseIn(pino, val) | pulseIn(4, HIGH);Mede largura do pulso HIGH no pino 4. |
Retorna microssegundos. Terceiro parâmetro opcional: timeout em µs. |
void setup() { pinMode(2, OUTPUT); // LED no pino 2 como saída pinMode(3, INPUT); // Botão no pino 3 como entrada } void loop() { int chave = digitalRead(3); // lê estado do botão digitalWrite(2, chave); // passa estado para o LED } // Versão ultra-compacta (mesma coisa em 1 linha): // digitalWrite(2, digitalRead(3));
Monte 3 LEDs (vermelho=pino 11, amarelo=10, verde=9). Use analogWrite() para fazer um fade: o verde vai de 0 a 255 enquanto o vermelho vai de 255 a 0. Use map() para calcular um a partir do outro!
São 6 pinos (A0 a A5) dedicados à leitura de sinais analógicos — tensões que variam continuamente entre 0 e 5V. O conversor A/D de 10 bits transforma essa tensão em um número de 0 a 1023.
| Função | Exemplo e Resultado | Observações |
|---|---|---|
| analogRead(pino) | int sensor = analogRead(A0);Guarda 0–1023 em 'sensor'. |
Não precisa de pinMode()! Os pinos A0–A5 equivalem também a 14–19. |
void setup() { } // sem configuração necessária! void loop() { // Lê A5 (0–1023) e divide por 4 para ter 0–255 analogWrite(10, analogRead(A5) / 4); // Alternativa mais legível com map(): // int leitura = analogRead(A5); // int brilho = map(leitura, 0, 1023, 0, 255); // analogWrite(10, brilho); }
Os pinos A0–A5 podem ser usados como pinos digitais comuns! Basta usar pinMode(14, OUTPUT) — onde 14 corresponde a A0. Isso aumenta o Arduino de 14 para 20 pinos digitais!
A porta serial é o "chat" entre o Arduino e o computador. Pelo cabo USB, é possível enviar e receber dados em tempo real — visualizados no Monitor Serial da IDE do Arduino (Ctrl+Shift+M).
Quando a porta serial está habilitada com Serial.begin(), os pinos digitais 0 (RX) e 1 (TX) ficam ocupados e não podem ser usados para outros fins.
| Função | Exemplo e Resultado | Observações |
|---|---|---|
| Serial.begin(taxa) | Serial.begin(9600);Taxa de 9600 bits/segundo. |
Sempre no setup(). O computador deve usar a mesma taxa no Monitor Serial. |
| Serial.end() | Serial.end(); |
Libera os pinos 0 e 1 para uso geral. Também no setup(). |
| Serial.available() | int n = Serial.available();Nº de bytes no buffer. |
Retorna 0 se não há dados. Use para verificar antes de ler. |
| Serial.read() | int v = Serial.read();Lê 1 byte do buffer. |
Retorna -1 se não há dados. Consome o byte lido. |
| Serial.print(val, fmt) | Serial.print(3.14159, 3);Transmite: 3.142 |
fmt opcional: nº de decimais ou base (BIN, OCT, HEX, DEC). |
| Serial.println(val) | Serial.println("Olá!");Transmite com quebra de linha. |
Igual ao print(), mas acrescenta \r\n no final. Cada chamada fica em uma linha. |
void setup() { Serial.begin(9600); // abre serial em 9600 bps } void loop() { Serial.print("Bytes no buffer: "); Serial.println(Serial.available()); // mostra qtd disponível delay(1000); Serial.print("Primeiro byte: "); Serial.println(Serial.read()); // -1 se vazio delay(1000); } /* Abra o Monitor Serial e digite "ABCDE" + Send. available() mostrará 5 bytes disponíveis. read() mostrará 65 (código ASCII do 'A'). Os demais bytes saem em sequência. */
Serial.print('A', BIN) → 01000001 | Serial.print('A', HEX) → 41 | Serial.print('A', DEC) → 65 | Serial.print(3.14159, 2) → 3.14
A barra POWER fica ao lado dos pinos analógicos e fornece tensões reguladas para alimentar circuitos externos conectados ao Arduino.
O pino 5V pode fornecer no máximo 500mA (quando alimentado por USB). O pino 3.3V está limitado a 50mA. Exceder esses limites pode danificar permanentemente o Arduino!
Use o conector P4 (jack 2.1mm) ou o pino Vin para alimentar o Arduino com bateria ou fonte externa de 7 a 12V. O regulador interno converte para 5V automaticamente.
Você agora conhece a estrutura completa do Arduino: linguagem C/C++, variáveis, operadores, controle de fluxo, pinos digitais, analógicos, comunicação serial e alimentação.
Baseado na obra de João Alexandre da Silveira — www.revistadoarduino.com.br 📖