Partilhar: WhatsApp
aulify
UC UC02842 · T. Desenv. Software, T. Sist. Comp. Redes

Ficha 02 · Arduino intermédio

Servos, displays, comunicação, multi-tarefa
Versão · Aluno
Tempo · 45 minutos
Aluno(a)
Turma
Data

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.