Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Robô Omni-Direcional para Rastreamento de Pessoas

Componentes e suprimentos

Módulo da placa do controlador do motor de passo duplo L298N
Driver de motor duplo com capacidade de até 2A para acionar os motores
× 2
LM2596 Regulador de redução de tensão ajustável com comutação DC DC
Para reduzir os 12 V da bateria para um trilho de 5 V
× 1
Alarme Lipo a bordo Bateria Checker Low Voltage Detector RC Plane Quadcopter
Usado para soar quando a voltagem do lipo está ficando baixa para garantir que não se quebre durante o uso.
× 1
Motor com eixo dentado 24 RPM DC 12 V 4 mm
Três por três rodas
× 3
Arduino Nano R3
Controlador de motor
× 1
Câmera da Web Microsoft LifeCam HD-3000
Para detectar o rosto das pessoas, você pode usar uma câmera mais barata, mas esta é a que eu tinha no escritório .
× 1
Fios de jumpers (genérico)
Muitos fios de ligação para gerenciamento de energia e uso de sinal
× 10
Criador Ci20
Como poderíamos esquecer o cérebro da operação, o Ci20!
× 1
Bateria lipo 3Cell 11,1V
Exemplo para comprar no ebay em anexo.
× 1

Ferramentas e máquinas necessárias

Impressora 3D (genérica)
Ferro de soldar (genérico)

Aplicativos e serviços online

OpenCV

Sobre este projeto





Submissão inicial


Minha inscrição inicial para a competição "Hackster Terminate the Competition" foi criar um robô que buscava humanos, mas ao contrário daqueles no universo Exterminador, ele não saiu por aí matando pessoas, em vez disso, usou seus poderes para o bem.

Este robô omnidirecional irá encontrar você, detectá-lo, localizá-lo e cumprimentá-lo!

Um requisito que especifiquei para mim mesmo é que eu asseguraria que ele pudesse ser feito sem ter que construir nenhum dos componentes eletrônicos você mesmo. Cada parte dentro deste robô pode ser comprada no eBay, conectada usando tutoriais disponíveis gratuitamente e eles devem funcionar. A caixa poderá ser impressa em 3D para que você mesmo possa imprimi-la ou fazer com que seja feita em hubs 3D. Acho que este projeto atende a essa meta e agora irei guiá-lo pelas etapas de construção de seu próprio Hunter Flatterer Robot





Como tudo funciona!


Portanto, vamos começar com um diagrama do sistema que mostra todas as partes do robô e como elas se conectam. Faremos referência a isso durante a compilação e verificaremos à medida que avançamos.

Não se assuste muito com este diagrama se você nunca usou motores antes. Basicamente, ele se resume a quatro partes principais:
  • O lado esquerdo trata de retirar a bateria e verificar se as tensões estão corretas para o sistema.
  • A parte inteligente acabou no ci20
  • O Arduino é usado para dizer aos motores o que fazer

As próximas quatro seções espelharão essa lista e o guiarão na configuração de cada parte.





Lidando com Eletrickery


Então você tem uma bateria, o que vem a seguir?

O diagrama acima mostra como conectar todos os componentes para alimentação, se você seguir a fiação no esquema, esta é a representação da vida real.





Conectando o Arduino ao L298N


Eu poderia explicar isso, mas é melhor apenas seguir o tutorial que fiz:http://www.instructables.com/id/Arduino-Modules-L298N-Dual-H-Bridge-Motor-Controll.

Agora que você conectou tudo, tem luzes azuis piscando em todos os lugares e nenhuma fumaça azul, então você está pronto para continuar. Vamos fazer esse bad boy funcionar.





Impressão 3D de um caso para você


Quando projetei isso, decidi que queria que duas coisas acontecessem, fosse legal e exibisse o Ci20 da melhor forma possível. Quer dizer, esse é o objetivo da competição, certo?

Eu projetei este robô para ser totalmente imprimível em 3D e os designs estão todos disponíveis abaixo. Basicamente, neste ponto, vá e imprima você mesmo a parte superior, inferior e as rodas. Se você não tiver acesso a uma impressora 3D, pode acessar www.3dhubs.com para pedir a alguém que a imprima para você! Você pode conferir os designs abaixo

Aqui está uma bela renderização que fiz do design para ter certeza de que o ci20 iria caber e ficar no lugar de honra

Depois de imprimir tudo, você pode colar todas as peças conforme descrito acima (ou usar fita adesiva se não estiver se sentindo confiante. Você precisará de um parafuso M4 para prender os motores.





Fazendo o CI20 fazer mágica


O CI20 é o chefe, o cérebro da operação. Sem ele, o robô vai se debater. Então, o que isso faz?

Bem, o ci20 vai usar o OpenCV para detectar seu rosto e, em seguida, enviar comandos apropriados via serial para o Arduino para colocar os motores na direção certa.

Etapa 1:Instale o OpenCV

Como disse ao longo deste guia, não estava tentando reinventar o carrinho de maçãs. Estou tentando construir algo que você possa fazer em casa e estender com relativa facilidade. Portanto, para instalar o OpenCV, siga este tutorial:

Ele explica passo a passo como colocar o OpenCV em funcionamento.

Etapa 2:execute o código

O código do Face Tracking precisará ser compilado e executado, execute este comando no arquivo no Ci20.
  g ++ -I / usr / local / include / opencv -I / usr / local / include / opencv2 -L / usr / local / lib / -g -o binário main.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching  

O arquivo binário a ser criado:FaceTracking:main.cpp> Arquivo fonte:FaceTracking.cpp

Fácil, certo?





Ci20 e Arduino Magic


Após fazer o flash do Arduino com o código nos anexos abaixo. Conecte o Arduino à porta USB do CI20 e execute o FaceTracker criado recentemente. Você verá uma imagem da câmera aparecer (Oh sim, conecte a webcam) e se você enfiar o rosto no meio, as rodas do robô devem começar a fazê-lo avançar!





Trabalho concluído?


Agora, devido às limitações de tempo, não consegui fazer mais nada, então aqui está um desafio para qualquer pessoa que já tenha chegado até aqui. Existem duas coisas que você pode adicionar para tornar este bot super incrível:

Adicione um conjunto de alto-falantes e alguns arquivos de som para que, quando o rosto for grande o suficiente na tela, ele reproduza um arquivo de som para a pessoa
  • Se o robô não detectou um rosto em 1-2 minutos, faça-o girar no local. Você pode fazer isso enviando o comando "R XX" para o Arduino. Substitua XX pela quantidade de tempo que você deseja fazer a volta.

Código

  • Arduino Sketch - Principal
  • Arduino Sketch - MotorControl
  • FaceTracking C ++ para Ci20
Arduino Sketch - Principal Arduino
Este código do Arduino recebe o comando de drive do Ci20 via serial e garante que os motores sejam acionados da maneira correta para ir na direção certa.

Eu escrevi isso originalmente para um Raspberry Pi, mas funciona com o Ci20 também
 // Motor 1int dir1PinA =3; int dir2PinA =2; int speedPinA =9; // Precisa ser um pino PWM para ser capaz de controlar a velocidade do motor // Motor 2int dir1PinB =4; int dir2PinB =5; int speedPinB =8; // Precisa ser um pino PWM para ser capaz de controlar a velocidade do motor // Motor 3int dir1PinC =6; int dir2PinC =7; int speedPinC =10; // Precisa ser um pino PWM para ser capaz de controlar a velocidade do motorint x =0; int y =0; int dominanteUltrasonic =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 (); // Isso testa se recebemos um valor do RPi no último segundo. // Atua efetivamente como buffer para que não continue parando e iniciando porque o comando de movimentação não é contínuo // Também permite a parada se nada estiver vindo do RPi // int elapsedTime =millis () - startTime; // if (elapsedTime> 1000) // {// x =0; // y =0; // dominanteUltrasonic =0; // moveMotor =false; // startTime =millis (); // //} // Envie o X e Y para os motores // if (moveMotor ==true &&(x! =0 &&y! =0)) // {//Serial.println("MovingMotor "); // driveInDirection (x, y); //} // if (x ==0 &&y ==0) // {//Serial.println("ZeroMMotor "); // driveInDirection (x, y); //} // Isso pode ser apenas uma sobra do ultrassom - hesitante em remover delay (30);} void readDataFromRPi () {// Leitura de Rpi while (Serial.available ()) {delay (3); // demora para permitir que o buffer seja preenchido if (Serial.available ()> 0) {char c =Serial.read (); // obtém um byte do buffer serial rpiString + =c; // torna a string readString if (c =='n') {break; }}} // ENDWHILE // Se algo foi lido do RPi, coloque-o em x, y &domniantUltrasonic if (rpiString.length ()> 0) {Serial.println (rpiString); // veja o que foi recebido String isRotate =getValue (rpiString, '', 0); String xval =getValue (rpiString, '', 1); String yval =getValue (rpiString, '', 2); x =xval.toInt (); y =yval.toInt (); startTime =milis (); if (isRotate =="r") {rotate (x); } else {driveInDirection (x, y); } rpiString =""; } // ENDIF} String getValue (dados da string, separador de caracteres, índice interno) {int encontrado =0; int strIndex [] ={0, -1}; int maxIndex =data.length () - 1; for (int i =0; i <=maxIndex &&found <=index; i ++) {if (data.charAt (i) ==separador || i ==maxIndex) {found ++; strIndex [0] =strIndex [1] +1; strIndex [1] =(i ==maxIndex)? i + 1:i; }} retorno encontrado> índice? data.substring (strIndex [0], strIndex [1]):"";} 
Arduino Sketch - MotorControl Arduino
Isso vai com o arquivo ino principal e precisa ser incluído no mesmo arquivo de projeto
 / * * Código de controle do motor * * Esta classe incluirá o código para fazer o robô ir em qualquer direção * e girar em torno do ponto central. * / void driveInDirection (float newX, float newY) {delay (20); float x =newX; float y =newY; float teta =atan2 (y, x); float mag =sqrt ((x * x) + (y * y)); float vx =mag * cos (theta); float 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; // Obtém o maior valor w float wSet [] ={w1, w2, w3}; float maiorValue =0,0; para (int i =0; i <3; i ++) {if (abs (wSet [i])> maiorValor) {maiorValue =abs (wSet [i]); }} float speedCoef =(float) 147.0 / maiorValor; w1 =w1 * speedCoef; w2 =w2 * speedCoef; w3 =w3 * speedCoef; if (x ==0 &&y ==0) {w1 =0; w2 =0; w3 =0; } Serial.println (w1); Serial.println (w2); Serial.println (w3); w1 =restrição (w1, -150, 150); w2 =restrição (w2, -150, 150); w3 =constrangimento (w3, -150, 150); booleano w1_ccw =w1 <0? verdadeiro falso; booleano w2_ccw =w2 <0? verdadeiro falso; booleano w3_ccw =w3 <0? verdadeiro falso; byte w1_speed =(byte) map (abs (w1), 0, 150, 0, 255); byte w2_speed =mapa (byte) (abs (w2), 0, 150, 0, 255); byte w3_speed =(byte) map (abs (w3), 0, 150, 0, 255); printMotorSpeed ​​(w1_speed, 1); printMotorSpeed ​​(w2_speed, 2); printMotorSpeed ​​(w3_speed, 3); analogWrite (speedPinA, w1_speed); // Define a variável de velocidade via PWM analogWrite (speedPinB, w2_speed); analogWrite (speedPinC, w3_speed); // Define a variável de velocidade via PWM 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 milissegundos) {float w1 =255; float w2 =255; float w3 =255; booleano w1_ccw =w1 <0? verdadeiro falso; booleano w2_ccw =w2 <0? verdadeiro falso; booleano w3_ccw =w3 <0? verdadeiro falso; byte w1_speed =(byte) map (abs (w1), 0, 150, 0, 255); byte w2_speed =mapa (byte) (abs (w2), 0, 150, 0, 255); byte w3_speed =(byte) map (abs (w3), 0, 150, 0, 255); printMotorSpeed ​​(w1_speed, 1); printMotorSpeed ​​(w2_speed, 2); printMotorSpeed ​​(w3_speed, 3); analogWrite (speedPinA, w1_speed); // Define a variável de velocidade via PWM analogWrite (speedPinB, w2_speed); analogWrite (speedPinC, w3_speed); // Define a variável de velocidade via PWM digitalWrite (dir1PinA,! w1_ccw); digitalWrite (dir2PinA, w1_ccw); digitalWrite (dir1PinB,! w2_ccw); digitalWrite (dir2PinB, w2_ccw); digitalWrite (dir1PinC, w3_ccw); digitalWrite (dir2PinC,! w3_ccw); atraso (milissegundos); analogWrite (speedPinA, 0); // Define a variável de velocidade via PWM analogWrite (speedPinB, 0); analogWrite (speedPinC, 0); // Define a variável de velocidade via PWM} void printMotorSpeed ​​(byte motorSpeed, int motor) {Serial.print ("Motor"); Serial.print (motor); Serial.print (":"); Serial.println (motorSpeed); } 
FaceTracking C ++ para Ci20 C / C ++
Siga o guia na história
 #include "opencv2 / objdetect / objdetect.hpp" #include "opencv2 / highgui / highgui.hpp" #include "opencv2 / imgproc / imgproc.hpp" #include  #include  usando namespace std; usando namespace cv; CascadeClassifier face_cascade, eyes_cascade; String window_name ="Face Detection"; # include  #include  #include  #include #include  #include  #include  #include  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); // char msg [] ="50 50"; write (fd , mensagem, strlen (mensagem)); return 0;} / ** * Detecta faces e desenha uma elipse ao redor delas * / void detectFaces (Mat frame) {std ::vector  faces; Mat frame_gray; // Converter para escala de cinza cvtColor (frame, frame_gray, COLOR_BGR2GRAY); // Equalize o histograma equalizeHist (frame_gray, frame_gray); // Detecta faces face_cascade.detectMultiScale (frame_gray, faces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size (30,30)); // Itere sobre todas as faces para (size_t i =0; i  olhos; // Tenta detectar olhos, dentro de cada rosto // eyes_cascade.detectMultiScale (face, eyes, 1.1, 2, // 0 | CASCADE_SCALE_IMAGE, Size (50, 50)); // if (eyes.size ()> 0) // Desenhe a elipse ao redor da elipse do rosto (quadro, centro, Tamanho (faces [i] .width / 2, faces [i] .height / 2), 0, 0, 360 , Escalar (255, 0, 255), 4, 8, 0); if (center.x> frame.cols / 3 &¢er.x  =0) // pausa na pausa; } return 0;} 

Peças personalizadas e gabinetes

Esta é a base do robô omnidirecional, projetada por mim para encaixar todas as peças e ter uma tampa anexada. Esta é a tampa que mostra o Ci20 em toda a sua glória.
Rodas omnidirecionais
Este é o projeto original das rodas omnidirecionais. Usei metade disso com os aros e editei para incluir o arquivo CAD do eixo do motor em thingiverse.com Uma roda remixada do link thingiverse

Esquemas

Veja a melhor descrição na seção de história

Processo de manufatura

  1. Rastreamento Raspberry Pi Ball
  2. Protótipo da Raspoulette
  3. Robô da caixa de CD do Raspberry Pi
  4. Robô de alarme rotativo
  5. Abra o Robô CV
  6. Robô ROS
  7. Robô Pi Simples
  8. Robô para navegação interna supercool
  9. O que é um Motor Linear?
  10. O que é um robô de bebidas?