Início›Sensor+Motor
⬤ Motor DC · Avançado

📡 Motor Controlado por Sensor

⏱️ 35 min 🧩 Sensor → Motor · Realimentação · Paragem de emergência · LCD

Nesta página

🚧 Sensor de Obstáculos → Motor

ℹ️
A combinação sensor→motor cria um sistema de malha fechada: o sensor mede o estado real do ambiente e o motor actua para o alterar. É a base de robótica autónoma e automação industrial.
ex_motor_sensor.ino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <AFMotor.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);
AF_DCMotor motor(1);

#define SENSOR_PIN 5    // Sensor IR — LOW = obstáculo
#define VEL_NORMAL 180

void setup() {
  lcd.init(); lcd.backlight();
  pinMode(SENSOR_PIN, INPUT);
  motor.setSpeed(VEL_NORMAL);
  motor.run(FORWARD);
  lcd.setCursor(0,0); lcd.print("Motor + Sensor IR   ");
}

void loop() {
  bool obst = (digitalRead(SENSOR_PIN) == LOW);

  if (obst) {
    // Obstáculo: para, recua 0.5s, vira direita 0.5s
    motor.run(BRAKE);
    lcd.setCursor(0,1); lcd.print("OBSTACULO! BRAKE    ");
    lcd.setCursor(0,2); lcd.print("A desviar...        ");
    lcd.noBacklight(); delay(150);
    lcd.backlight();   delay(150);  // pisca como alerta
    motor.run(BACKWARD); delay(500);
    motor.run(RELEASE);
    delay(300);
  } else {
    motor.setSpeed(VEL_NORMAL);
    motor.run(FORWARD);
    lcd.setCursor(0,1); lcd.print("A CORRER FORWARD    ");
    lcd.setCursor(0,2); lcd.print("Vel: 180  Livre     ");
  }
}

📏 Controlo Proporcional — Velocidade por Distância

💡
Controlo proporcional: a velocidade do motor é proporcional ao erro (diferença entre valor desejado e valor medido). Quanto maior o erro, maior a velocidade de correcção. É o 'P' do controlador PID.
ex_motor_prop.ino
// Controlo proporcional com LDR — simula sensor de distância
// Setpoint: LDR a 500. Motor ajusta velocidade para manter esse valor.
#define LDR_PIN    A0
#define SETPOINT   500   // Valor-alvo de luminosidade
#define KP         0.4   // Ganho proporcional
#define VEL_MIN    40
#define VEL_MAX    220

void loop() {
  int   ldr  = analogRead(LDR_PIN);
  int   erro = SETPOINT - ldr;       // positivo: muito escuro
  int   vel  = (int)(KP * abs(erro));
  vel = constrain(vel, VEL_MIN, VEL_MAX);

  if(abs(erro) < 20) {      // zona morta — não actua
    motor.run(RELEASE);
    lcd.setCursor(0,1); lcd.print("Zona morta — OK     ");
  } else if(erro > 0) {
    motor.setSpeed(vel); motor.run(FORWARD);
    lcd.setCursor(0,1); lcd.print("FORWARD vel:");lcd.print(vel);lcd.print("  ");
  } else {
    motor.setSpeed(vel); motor.run(BACKWARD);
    lcd.setCursor(0,1); lcd.print("BACKWARD vel:");lcd.print(vel);lcd.print(" ");
  }

  lcd.setCursor(0,2); lcd.print("LDR:");lcd.print(ldr);
  lcd.print(" Err:");lcd.print(erro);lcd.print("   ");
  delay(80);
}

🔴 Sistema de Paragem de Emergência

ex_emergencia.ino
#define BTN_EMG 6   // INPUT_PULLUP — pressionar = emergência
bool emergencia = false;

void verificarEmergencia() {
  if(digitalRead(BTN_EMG) == LOW || emergencia) {
    motor.run(BRAKE);
    emergencia = true;
    lcd.setCursor(0,3); lcd.print("** EMERGENCIA!! **  ");
    lcd.noBacklight(); delay(200);
    lcd.backlight();   delay(200);
    // Loop infinito — só reset do Arduino liberta
  }
}

void loop() {
  verificarEmergencia();   // SEMPRE a primeira instrução do loop

  // ... código normal do motor ...
}

📊 Introdução ao Controlo PID

ComponenteSiglaO que fazEfeito
ProporcionalPActua proporcional ao erro actualCorrecção rápida mas pode oscilar
IntegralIActua sobre o erro acumulado ao longo do tempoElimina erro estacionário
DerivativoDActua sobre a taxa de variação do erroAmorte as oscilações
pid_basico.ino
// PID simples — exemplo educativo
float Kp=0.4, Ki=0.05, Kd=0.1;
float erroAnt=0, integral=0;

int pid(int setpoint, int medicao) {
  float erro      = setpoint - medicao;
  integral       += erro;
  float derivada  = erro - erroAnt;
  erroAnt         = erro;
  float saida     = Kp*erro + Ki*integral + Kd*derivada;
  return constrain((int)saida, -255, 255);
}

void loop() {
  int ldr = analogRead(A0);
  int u   = pid(500, ldr);         // saída: negativo=BWD, positivo=FWD
  motor.setSpeed(abs(u));
  motor.run(u > 0 ? FORWARD : BACKWARD);
  lcd.setCursor(0,1); lcd.print("LDR:");lcd.print(ldr);lcd.print(" u:");lcd.print(u);lcd.print("   ");
  delay(50);
}

🏆 Para ir mais longe

PR.FT9_5 · LCD 20×4 · L293D Motor Driver · Arduino UNO Rev3 · Início · led.dge.medu.pt