Ficha 02 · Arduino intermédio
Exercício 1 · Servo controlado por potenciómetro
Servo no pino 9. Potenciómetro em A0. A posição angular do servo (0-180°) acompanha o potenciómetro.
Resposta:
#include <Servo.h>
Servo servo;
const int POT = A0;
void setup() {
servo.attach(9);
}
void loop() {
int raw = analogRead(POT);
int ang = map(raw, 0, 1023, 0, 180);
servo.write(ang);
delay(15);
}
Servos SG90 funcionam directo do 5V do Arduino. Para servos maiores, usa fonte externa.
Exercício 2 · Distância com HC-SR04
Sensor HC-SR04 (Trig pino 9, Echo pino 10). Lê distância e imprime no Serial Monitor.
Resposta:
const int TRIG = 9;
const int ECHO = 10;
void setup() {
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
Serial.begin(9600);
}
float medirCm() {
digitalWrite(TRIG, LOW);
delayMicroseconds(2);
digitalWrite(TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
long dur = pulseIn(ECHO, HIGH, 30000); // timeout 30ms
if (dur == 0) return -1;
return dur * 0.0343 / 2;
}
void loop() {
float d = medirCm();
if (d < 0) {
Serial.println("Sem leitura");
} else {
Serial.print(d, 1);
Serial.println(" cm");
}
delay(200);
}
Exercício 3 · Alarme de proximidade
Combina HC-SR04 (Trig=9, Echo=10), buzzer no pino 11 e LED no pino 12: - > 30cm: nada. - 10-30cm: LED on, buzzer pisca devagar. - < 10cm: LED + buzzer constantes (alarme).
Resposta:
const int TRIG = 9, ECHO = 10, BUZZER = 11, LED = 12;
void setup() {
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(BUZZER, OUTPUT);
pinMode(LED, OUTPUT);
Serial.begin(9600);
}
float medirCm() {
digitalWrite(TRIG, LOW);
delayMicroseconds(2);
digitalWrite(TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
long dur = pulseIn(ECHO, HIGH, 30000);
return dur > 0 ? dur * 0.0343 / 2 : 999;
}
void loop() {
float d = medirCm();
Serial.print(d, 1);
Serial.println(" cm");
if (d > 30) {
digitalWrite(LED, LOW);
noTone(BUZZER);
} else if (d > 10) {
digitalWrite(LED, HIGH);
tone(BUZZER, 1000);
delay(100);
noTone(BUZZER);
delay(300);
} else {
digitalWrite(LED, HIGH);
tone(BUZZER, 2000); // contínuo, freq mais alta
}
}
tone(pin, freq) gera onda quadrada no pin. noTone(pin) desliga.
Exercício 4 · OLED + temperatura DHT22
Liga DHT22 (pino 2) e OLED I2C. Mostra no OLED temperatura e humidade em tempo real.
Resposta:
# Library Manager (Sketch → Include Library → Manage Libraries)
# Procura: "DHT sensor library" (Adafruit)
# Procura: "Adafruit SSD1306"
# Procura: "Adafruit GFX"
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define DHT_PIN 2
DHT dht(DHT_PIN, DHT22);
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
void setup() {
Serial.begin(9600);
dht.begin();
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
oled.clearDisplay();
oled.setTextColor(SSD1306_WHITE);
oled.setTextSize(2);
oled.setCursor(0, 0);
oled.print(t, 1);
oled.print((char)247); // ° simbolo
oled.println("C");
oled.setCursor(0, 30);
oled.print(h, 1);
oled.println(" %");
oled.display();
Serial.print(t); Serial.print("C, "); Serial.print(h); Serial.println("%");
delay(2000);
}
Exercício 5 · LCD I2C com contador
LCD 16x2 I2C. Mostra "Tempo activo:" na linha 1 e segundos desde arranque na linha 2.
Resposta:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Tempo activo:");
}
void loop() {
unsigned long s = millis() / 1000;
unsigned long h = s / 3600;
unsigned long m = (s % 3600) / 60;
unsigned long sec = s % 60;
lcd.setCursor(0, 1);
char buf[17];
sprintf(buf, "%02lu:%02lu:%02lu ", h, m, sec);
lcd.print(buf);
delay(500);
}
Se endereço 0x27 não funcionar, tenta 0x3F. Em última instância, corre i2c_scanner.
Exercício 6 · Serial control LEDs
3 LEDs (pinos 8, 9, 10). Via Serial Monitor podes escrever comandos como R1, R0, G1, B1 para ligar/desligar vermelho, verde, azul.
Resposta:
const int R = 8, G = 9, B = 10;
void setup() {
pinMode(R, OUTPUT);
pinMode(G, OUTPUT);
pinMode(B, OUTPUT);
Serial.begin(9600);
Serial.println("Comandos: R0,R1,G0,G1,B0,B1");
}
void loop() {
if (Serial.available() >= 2) {
char cor = Serial.read();
char val = Serial.read();
int pin;
if (cor == 'R') pin = R;
else if (cor == 'G') pin = G;
else if (cor == 'B') pin = B;
else return;
digitalWrite(pin, val == '1' ? HIGH : LOW);
Serial.print(cor);
Serial.print(" → ");
Serial.println(val);
}
}
No Serial Monitor: escreve R1 e enter. LED vermelho acende. R0 apaga.
Exercício 7 · Multi-tarefa com millis()
Sistema que faz simultaneamente (sem delay() longo):
- LED no pino 8 pisca a cada 500ms.
- Outro LED no pino 9 pisca a cada 1200ms.
- A cada 2s imprime no Serial Monitor o valor de A0.
Resposta:
const int LED1 = 8, LED2 = 9;
unsigned long t1 = 0, t2 = 0, t3 = 0;
bool led1 = false, led2 = false;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
Serial.begin(9600);
}
void loop() {
unsigned long now = millis();
if (now - t1 >= 500) {
t1 = now;
led1 = !led1;
digitalWrite(LED1, led1);
}
if (now - t2 >= 1200) {
t2 = now;
led2 = !led2;
digitalWrite(LED2, led2);
}
if (now - t3 >= 2000) {
t3 = now;
Serial.print("A0 = ");
Serial.println(analogRead(A0));
}
}
Comparar com versão delay() (bloqueante): impossível com 3 timings diferentes.
Exercício 8 · Mini-projecto: smart light
Combina: - LDR em A0 (mede luz ambiente). - LED em pino 9 (PWM). - Comportamento: LED acende automaticamente ao escurecer; brilho inversamente proporcional à luz ambiente (mais escuro = mais brilho).
Adiciona um botão (pino 2 com INPUT_PULLUP) para fazer override on/off.
Resposta:
const int LDR = A0;
const int LED = 9;
const int BTN = 2;
enum Modo {AUTO, ON, OFF};
Modo modo = AUTO;
int lastBtn = HIGH;
unsigned long lastChange = 0;
void setup() {
pinMode(LED, OUTPUT);
pinMode(BTN, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
// Detectar click do botão (debounced)
int btn = digitalRead(BTN);
if (btn != lastBtn && millis() - lastChange > 50) {
lastChange = millis();
lastBtn = btn;
if (btn == LOW) {
// Cicla AUTO → ON → OFF → AUTO
modo = (Modo)((modo + 1) % 3);
Serial.print("Modo: ");
Serial.println(modo == AUTO ? "AUTO" : modo == ON ? "ON" : "OFF");
}
}
// Comportamento
switch (modo) {
case ON:
analogWrite(LED, 255);
break;
case OFF:
analogWrite(LED, 0);
break;
case AUTO: {
int luz = analogRead(LDR); // 0-1023
int brilho = map(luz, 0, 700, 255, 0);
brilho = constrain(brilho, 0, 255);
analogWrite(LED, brilho);
break;
}
}
}
Comportamento esperado: - AUTO (default): escuro → LED brilhante. Luz forte → LED desligado. - ON: LED 100% sempre. - OFF: LED desligado sempre. - Click cicla pelos 3 modos.