Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

Componentes y materiales

Controlador motor dual paso a paso L298N (hasta 2 A) × 2
Regulador ajustable LM2596 DC-DC Step Down (12 V → 5 V) × 1
Alarma LiPo / detector baja tensión × 1
Motor DC 12 V 24 RPM eje 4 mm con reductor × 3
Arduino Nano R3 (control motor) × 1
Cámara web Microsoft LifeCam HD-3000 (detección facial) × 1
Cables jumper (gestión alimentación y señales) × 10
Creator Ci20 (cerebro del robot) × 1
Batería LiPo 11.1 V 3 celdas × 1

Herramientas necesarias

Aplicaciones y servicios online

Sobre el proyecto

Presentación inicial

Mi propuesta para el concurso "Hackster Terminate the competition" era un robot que busca humanos, pero no para eliminarlos (como en Terminator), sino para hacer el bien. Este robot omnidireccional te encuentra, te detecta, se acerca y ¡te hace un cumplido!

Requisito autoimpuesto: todo debe ser comprable en eBay, conectable con tutoriales públicos y sin fabricar electrónica propia. El chasis es imprimible en 3D (tú o 3D Hubs). Creo que se cumple.

Cómo funciona

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

Cuatro bloques principales:

  1. Gestión de energía: batería → voltajes correctos.
  2. Procesamiento inteligente: Ci20.
  3. Control de motores: Arduino.

Gestión de energía ("Electrickery")

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

El diagrama muestra la conexión real de todos los componentes de potencia.

Conexión Arduino a L298N

Sigue este tutorial: Instructables L298N. Si no hay humo azul, todo bien.

Chasis impreso en 3D

Diseñado para verse bien y lucir el Ci20. Totalmente imprimible (tapa, base, ruedas). Archivos en PARTES PERSONALIZADAS. Necesitas tornillo M4 para fijar motores.

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

La magia del Ci20

El Ci20 usa OpenCV para detectar caras y envía comandos serie al Arduino para mover los motores.

Paso 1: Instalar OpenCV — Sigue este tutorial para instalar OpenCV en el Ci20 paso a paso.

Paso 2: Compilar y ejecutar

g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o binary main.cpp \
-lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video \
-lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib \
-lopencv_legacy -lopencv_stitching

Archivo fuente: FaceTracking.cpp → binario FaceTracking.

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

Ci20 + Arduino: Magia conjunta

Flashea el Arduino con el código adjunto, conéctalo por USB al Ci20 y ejecuta FaceTracker. Verás la imagen de la webcam; si pones tu cara en el centro, el robot avanza.

¿Terminado?

Por falta de tiempo no añadí más funciones. Reto para quien llegue aquí:

Código

Sketch Arduino - Principal Arduino

Recibe comandos de movimiento del Ci20 por serie y acciona los 3 motores omnidireccionales.

// Motor 1
int dir1PinA = 3; int dir2PinA = 2; int speedPinA = 9; // PWM
// Motor 2
int dir1PinB = 4; int dir2PinB = 5; int speedPinB = 8; // PWM
// Motor 3
int dir1PinC = 6; int dir2PinC = 7; int speedPinC = 10; // PWM
int x = 0, y = 0, dominantUltrasonic = 0;
bool moveMotor = false;
int startTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(dir1PinA, OUTPUT); pinMode(dir2PinA, OUTPUT); pinMode(speedPinA, OUTPUT);
  pinMode(dir1PinB, OUTPUT); pinMode(dir2PinB, OUTPUT); pinMode(speedPinB, OUTPUT);
  pinMode(dir1PinC, OUTPUT); pinMode(dir2PinC, OUTPUT); pinMode(speedPinC, OUTPUT);
  startTime = millis();
}
String rpiString;
void loop() {
  readDataFromRPi();
  delay(30);
}
void readDataFromRPi() {
  while (Serial.available()) {
    delay(3);
    if (Serial.available() > 0) {
      char c = Serial.read();
      rpiString += c;
      if (c == 'n') break;
    }
  }
  if (rpiString.length() > 0) {
    Serial.println(rpiString);
    String isRotate = getValue(rpiString, ' ', 0);
    String xval = getValue(rpiString, ' ', 1);
    String yval = getValue(rpiString, ' ', 2);
    x = xval.toInt(); y = yval.toInt();
    startTime = millis();
    if (isRotate == "r") rotate(x);
    else driveInDirection(x, y);
    rpiString = "";
  }
}
String getValue(String data, char separator, int index) {
  int found = 0; int strIndex[] = {0, -1}; int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
Sketch Arduino - ControlMotor Arduino

Incluir en el mismo proyecto. Implementa cinemática omnidireccional (3 ruedas a 120°).

void driveInDirection(float newX, float newY) {
  delay(20);
  float x = newX, y = newY;
  float theta = atan2(y, x);
  float mag = sqrt(x*x + y*y);
  float vx = mag * cos(theta), vy = mag * sin(theta);
  float w1 = -vx;
  float w2 = 0.5 * vx - sqrt(3)/2 * vy;
  float w3 = 0.5 * vx + sqrt(3)/2 * vy;
  float wSet[] = {w1, w2, w3};
  float largestValue = 0;
  for (int i = 0; i < 3; i++) if (abs(wSet[i]) > largestValue) largestValue = abs(wSet[i]);
  float speedCoef = 147.0 / largestValue;
  w1 *= speedCoef; w2 *= speedCoef; w3 *= speedCoef;
  if (x == 0 && y == 0) { w1 = w2 = w3 = 0; }
  w1 = constrain(w1, -150, 150); w2 = constrain(w2, -150, 150); w3 = constrain(w3, -150, 150);
  boolean w1_ccw = w1 < 0, w2_ccw = w2 < 0, w3_ccw = w3 < 0;
  byte w1_speed = map(abs(w1), 0, 150, 0, 255);
  byte w2_speed = map(abs(w2), 0, 150, 0, 255);
  byte w3_speed = map(abs(w3), 0, 150, 0, 255);
  analogWrite(speedPinA, w1_speed); analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed);
  digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw);
  digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw);
  digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw);
}
void rotate(float milliseconds) {
  float w1 = 255, w2 = 255, w3 = 255;
  boolean w1_ccw = false, w2_ccw = false, w3_ccw = false;
  byte w1_speed = map(abs(w1), 0, 150, 0, 255);
  byte w2_speed = map(abs(w2), 0, 150, 0, 255);
  byte w3_speed = map(abs(w3), 0, 150, 0, 255);
  analogWrite(speedPinA, w1_speed); analogWrite(speedPinB, w2_speed); analogWrite(speedPinC, w3_speed);
  digitalWrite(dir1PinA, !w1_ccw); digitalWrite(dir2PinA, w1_ccw);
  digitalWrite(dir1PinB, !w2_ccw); digitalWrite(dir2PinB, w2_ccw);
  digitalWrite(dir1PinC, w3_ccw); digitalWrite(dir2PinC, !w3_ccw);
  delay(milliseconds);
  analogWrite(speedPinA, 0); analogWrite(speedPinB, 0); analogWrite(speedPinC, 0);
}
FaceTracking C++ para Ci20 C/C++

Sigue la guía en la historia. Usa cascade Haar para detección facial y envía comandos serie al Arduino.

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream> #include <stdio.h>
using namespace std; using namespace cv;
CascadeClassifier face_cascade;
String window_name = "Face Detection";
#include <termios.h> #include <fcntl.h> #include <unistd.h>

int sendSerial(char* message) {
  int fd = open("/dev/ttyUSB0", O_RDWR);
  if (fd == -1) { perror("dev/ttyUSB0"); return 1; }
  struct termios tios; tcgetattr(fd, &tios);
  tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0;
  cfsetspeed(&tios, B9600); tcsetattr(fd, TCSAFLUSH, &tios);
  usleep(1000); write(fd, message, strlen(message)); return 0;
}

void detectFaces(Mat frame) {
  vector<Rect> faces; Mat frame_gray;
  cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
  equalizeHist(frame_gray, frame_gray);
  face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(30,30));
  for (size_t i = 0; i < faces.size(); i++) {
    Point center(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2);
    ellipse(frame, center, Size(faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar(255,0,255), 4, 8, 0);
    if (center.x > frame.cols/3 && center.x < frame.cols/3*2) sendSerial("F 50 50");
    else sendSerial("0 0 ");
  }
  imshow(window_name, frame);
}

int main() {
  sendSerial("0 0 ");
  VideoCapture cap(0);
  cap.set(CV_CAP_PROP_FRAME_WIDTH, 480);
  cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
  Mat frame;
  if (!face_cascade.load("haarcascade_frontalface_default.xml")) { cout << "classifier"; return -1; }
  while (cap.read(frame)) {
    detectFaces(frame);
    if (waitKey(30) >= 0) break;
  }
  return 0;
}

Partes personalizadas y envolventes

Esquemáticos

Ver descripción detallada en la historia.

Robot Omnidireccional Diseñado para Seguimiento Seguro de Personas

Proceso de manufactura

  1. Seguimiento Avanzado de Pelotas de Ping‑Pong con Raspberry Pi y OpenCV
  2. Raspoulette: Sistema autónomo de puerta de gallinero alimentado por energía solar – Prototipo
  3. Robot DIY inspirado en Wall‑E con Raspberry Pi y caja de CD
  4. Robot Despertador Rodante: Sistema Inteligente y Móvil de Despertar con Raspberry Pi y Google Calendar
  5. Construye un Robot de Visión Artificial Controlado por Voz en Windows 10 IoT Core
  6. Robot ROS: Navegación Controlada por Terminal en Raspberry Pi
  7. Simple Pi Robot: Construye un Rover Autónomo 2‑WD con Raspberry Pi
  8. Kit de Robot de Navegación Interior Inteligente para Proyectos Arduino
  9. Entendiendo los Motores Lineales: De Energía Eléctrica a Movimiento Lineal Preciso
  10. Comprender los Robots de Bebidas: Tecnología, Automatización y su Papel en la Industria de Bebidas
  11. Motores servo: funcionamiento, tipos y por qué son importantes