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

Linha Baseada em Inteligência Artificial (IA) Seguindo o Robô

Componentes e suprimentos

Arduino Nano
× 1
Transceptor mestre de RF sem fio Bluetooth sem fio
× 1
Módulo sensor infravermelho infravermelho da Amazon Web Services Luz fotoelétrica refletiva
× 1
Sony Continuous Rotation Servo
× 1
Bateria Android de 4,8 Volts
× 1

Aplicativos e serviços online

Arduino IDE

Sobre este projeto


Depois de desenvolver o Pick &Place Robot baseado em Arduino, a ideia era desenvolver uma linha baseada em IA Inteligente Artificial seguindo o robô. Desenvolver uma linha simples seguindo o robô foi bom para o iniciante, exatamente o que precisava para adicionar algum tipo de sensores infravermelhos em vez de servo motores em meu projeto recente. "A ideia era testar minhas habilidades em nível avançado ".

Embora tenha sido uma tarefa difícil, algum tipo de pesquisa online me ajudou muito.









Por que há uma necessidade de linha baseada em IA seguindo o robô?


Quando se trata de AI é a tecnologia recente que tem o potencial de mudar o ambiente mundial, portanto, a vida humana efetiva. Um sonho que pode se tornar realidade ao colocar inteligência em nossos robôs para entender problemas da vida real e resolvê-los de acordo, esse sonho só pode se tornar realidade por meio de Inteligência Artificial é por isso que todo mundo está falando sobre isso.
  • Pode ser usado na linha de montagem / produção.
  • Ônibus de coleta de passageiros.

Embora meu protótipo de robô possa ser um pouco inteligente, é apenas o começo para mover meus projetos em direção à IA. Portanto, aqui tentarei explicar o desenvolvimento passo a passo da linha seguindo o robô usando Inteligência Artificial em uma linguagem bastante simples. Devido à falta de recursos, não vou construir um robô, mas posso explicar muito bem como você pode construí-lo fazendo algum tipo de pesquisa. Vou tentar fornecer códigos precisos que funcionarão em seu IDE Arduino, para que você pode desenvolver seu primeiro robô de IA com bastante facilidade.

Você pode me apoiar no Patreon daqui :http://bit.ly/31NfQ6A

"Você pode encontrar os aparelhos com taxas mais baixas nos EUA na descrição deste vídeo, basta clicar em vídeo . "

Agora vamos ao projeto "Um robô que segue uma linha baseado em IA!".

USO DE SENSORES DE INFRAVERMELHO

Nosso projeto inclui 7 sensores infravermelhos, conforme mostrado no diagrama.
  • 5 para controle PID
  • 1 para detecção à esquerda
  • outro para detecção do lado direito.

Função de 5 sensores de controle PID :Estes 5 sensores serão usados ​​para gerar saída digital alta ou baixa (1, 0), respectivamente.

O sensor centralizado em relação à linha preta, apenas esse sensor produzirá ALTO (1). O resultado similarmente possível desse sensor poderia ser:-
  • 10.000
  • 11.000
  • 01000
  • 01100
  • 00100
  • 00110
  • 00010
  • 00011
  • 00001
  • 00000
  • 11111

Agora vêm outros dois sensores para resultados possíveis à esquerda e à direita são

Sensor da extrema esquerda:saída analógica alta ou baixa

Sensor da extrema esquerda:saída analógica alta ou baixa

Para armazenar o valor de 5 sensores permite criar uma variável de array.
  no LFSensor [5] ={1,1,1,1,1};  

Para armazenar o valor dos sensores esquerdo e direito, usaremos números inteiros
  int farleft_sensor =0;  

Como sabemos, temos 5 sensores que podem ser usados ​​para armazenar o caminho esquerdo e o caminho direito é percorrido pelo robô em uma matriz. assim
  LFSensor [0] =digitalRead (lineFollowSensor0); 
LFSensor [1] =digitalRead (lineFollowSensor1);
LFSensor [2] =digitalRead (lineFollowSensor2);
LFSensor [ 3] =digitalRead (lineFollowSensor3);
LFSensor [4] =digitalRead (lineFollowSensor4);
farRightSensor =analogRead (farRightSensorPin);
farLeftSensor =analogRead (farLeftSensorPin);

REGRA DO LABIRINTO PARA A MÃO ESQUERDA:

assistir este vídeo para entender a regra da mão esquerda do labirinto

Em suma, a Regra da mão esquerda pode ser descrito como:
  • Coloque sua mão esquerda na parede.
  • Comece a andar para frente
  • Em cada cruzamento e em todo o labirinto, mantenha sua mão esquerda tocando a parede à sua esquerda.
  • Eventualmente, você chegará ao fim do labirinto. Você provavelmente não irá pelo caminho mais curto e direto, mas chegará lá.

Portanto, a chave aqui é identificar os cruzamentos , definindo o curso a seguir com base nas regras acima. Especificamente, em nosso tipo de labirinto 2D, podemos encontrar 8 tipos diferentes de interseções (veja a primeira imagem acima):

Olhando a foto, podemos perceber que as possíveis ações nos cruzamentos são:

Em um " Cross "
  • Vá para a esquerda ou
  • Vá para a direita ou
  • Siga em frente
  • Em uma " Cruz "Vá para a esquerda, ou vá para a direita ou vá direto

Em um " T ":
  • Vá para a esquerda ou
  • Vá para a direita
  • Em um " T ":Vá para a esquerda ou vá para a direita

Em um " direito apenas ":
  • Vá para a direita
  • Em um " direito apenas ":Vá para a direita

Em um " Somente à esquerda ":
  • Vá para a esquerda
  • Em um " Somente à esquerda ":Vá para a esquerda

Na " reta ou esquerda ":
  • Vá para a esquerda ou
  • Siga em frente
  • Na " reta ou esquerda ":Vá para a esquerda ou siga em frente

Na " reta ou direita ":
  • Vá para a direita ou
  • Siga em frente
  • Na " reta ou direita ":Vá para a direita ou siga em frente

Em um " beco sem saída ":
  • Voltar ("U turn")
  • Em um " beco sem saída ":Voltar (" volta em U ")

No " Fim do Labirinto ":
  • Pare
  • No " Fim do Labirinto ":Pare

Mas, aplicando a "Regra da Mão Esquerda", as ações serão reduzidas a uma opção cada:
  • Em uma "cruz":vá para a esquerda
  • Em um "T":vá para a esquerda
  • Em um "direito apenas":vá para a direita
  • Em um "lado esquerdo apenas":vá para a esquerda
  • Em uma "reta ou esquerda":vá para a esquerda
  • Na "reta ou na direita":vá direto
  • Em um "beco sem saída":volte ("volta em U")
  • No "Fim do labirinto":Pare

Estamos quase lá! "Fique calmo!"

Quando o robô chega a um "Beco Sem Saída" ou "Fim de um Labirinto", é fácil identificá-los, pois não existem situações ambíguas (já implementamos essas ações no Robô Seguidor de Linha, lembra?). O problema é quando o robô encontra uma "LINHA", por exemplo, porque uma linha pode ser uma "Cruz" (1) ou um "T" (2). Além disso, quando se atinge uma "VIRAGEM PARA A ESQUERDA ou PARA A DIREITA", essas podem ser uma curva simples (opções 3 ou 4) ou opções para seguir em frente (5 ou 6). Para descobrir exatamente que tipo de interseção é o robô, um passo adicional deve ser dado:o robô deve correr um "centímetro a mais" e ver o que vem a seguir (veja a segunda foto acima, como exemplo).

Portanto, em termos de fluxo, as ações possíveis agora podem ser descritas como:

Em um "DEAD END":
  • Voltar ("U turn")
  • Em um "DEAD END":Voltar ("U turn")

Em uma "LINHA":
  • Corra um centímetro a mais
  • Se houver uma linha:é uma "Cruz" ==> Vá para a ESQUERDA
  • Se não houver linha:é um "T" ==> Vá para a ESQUERDA
  • Se houver outra linha:é o "Fim do labirinto" ==> PARAR
  • Em uma "LINHA": Corra uma polegada extra Se houver uma linha:É uma "Cruz" ==> Vá para LEFTIf não houver linha:é um "T" ==> Vá para LEFTIf houver outra linha:é o "Fim do Labirinto" ==> PARAR

Em uma "VIRAGEM À DIREITA":
  • Corra um centímetro a mais
  • se houver uma linha:é uma reta ou direita ==> Vá EM LINHA RETA
  • Se não houver linha:é um direito apenas ==> Vá para a DIREITA
  • Em uma "VIRAGEM PARA A DIREITA": Corra uma polegada extra se houver uma linha:é uma reta ou direita ==> vá em linha retaSe não houver uma linha:é uma reta apenas ==> vá para a direita

Em uma "VIRAGEM PARA A ESQUERDA":
  • Corra um centímetro a mais
  • se houver uma linha:é uma reta ou ESQUERDA ==> Vá para a ESQUERDA
  • Se não houver linha:é apenas ESQUERDA ==> Vá para ESQUERDA
  • Em uma "VIRAGEM PARA A ESQUERDA": Corra um centímetro extra se houver uma linha:É uma reta ou ESQUERDA ==> Vá para a ESQUERDA; se não houver uma linha:é uma ESQUERDA apenas ==> Vá para a ESQUERDA

Observe que, na verdade, no caso de uma "VIRAGEM PARA A ESQUERDA", você pode pular o teste, porque você fará para a ESQUERDA de qualquer maneira. Deixei a explicação mais genérica apenas para maior clareza. No código real, vou pular este teste.

Aqui estão alguns problemas que podem surgir ao fazer este projeto.

Tópico Relacionado

RESOLUÇÃO DE PROBLEMAS DO DRIVER Arduino

assistir este vídeo para resolver o problema do driver do Arduino:



Código

  • RoBot_Maze_Solve_2
  • Funções
  • Funções gerais.
  • sensorFuntions
  • RobotDefines.h
  • MotorFuntions
RoBot_Maze_Solve_2 C / C ++
 / * --------------------------------------------- --------------------- 7 sensores Smart Robot - Maze Solver e Line Follower com controlador PID programável via BT ==> Movimento básico baseado em Nano Mouse Robot, desenvolvido por Michael Backus (http://www.akrobotnerd.com/) ==> Linha de seguimento baseada em http://samvrit.tk/tutorials/pid-control-arduino-line-follower-robot/?ckattempt=1==> CRÉDITO a Patrick McCabe pelo caminho Solving Code, visite patrickmccabemakes.com !! Marcelo Jose Rovai - 23 de abril de 2016 - Visite:http://mjrobot.org---------------- -------------------------------------------------- - * / # include  #include "robotDefines.h" Comando String; Dispositivo String; // Módulo BT # include  SoftwareSerial BT1 (10, 11); // El pin 10 es Rx y el pin 11 es Tx // ----------------------------------- ---------- configuração vazia () {Serial.begin (9600); BT1.begin (9600); pinMode (ledPin, OUTPUT); pinMode (buttonPin, INPUT_PULLUP); // sensores de seguimento de linha pinMode (lineFollowSensor0, INPUT); pinMode (lineFollowSensor1, INPUT); pinMode (lineFollowSensor2, INPUT); pinMode (lineFollowSensor3, INPUT); pinMode (lineFollowSensor4, INPUT); // servos leftServo.attach (5); rightServo.attach (3); BT1.print ("verificar as constantes PID a serem enviadas ao Robot"); Serial.print ("verificar as constantes PID a serem enviadas ao Robot"); BT1.println ('\ n'); while (digitalRead (buttonPin) &&! modo) {checkBTcmd (); // verifica se um comando é recebido do controle remoto BT manualCmd (); comando =""; } checkPIDvalues ​​(); modo =PARADO; status =0; // 1ª passagem} void loop () {ledBlink (1); BT1.println ("Iniciar primeira passagem"); Serial.println ("Start First Pass"); readLFSsensors (); mazeSolve (); // Primeira passagem para resolver o labirinto ledBlink (2); BT1.println ("Fim da primeira passagem"); Serial.println ("Fim da primeira passagem"); while (digitalRead (buttonPin) &&! modo) {checkBTcmd (); // verifica se um comando é recebido do controle remoto BT manualCmd (); comando =""; } BT1.println ("Iniciando a 2ª passagem"); Serial.println ("Iniciando a 2ª passagem"); pathIndex =0; status =0; mazeOptimization (); // executa o labirinto o mais rápido possível ledBlink (3); BT1.println ("Fim da 2ª passagem"); Serial.println ("Fim da 2ª passagem"); while (digitalRead (buttonPin) &&! modo) {checkBTcmd (); // verifica se um comando é recebido do controle remoto BT manualCmd (); comando =""; } modo =PARADO; status =0; // 1ª passagem pathIndex =0; pathLength =0;} 
Funções C / C ++
 void mazeSolve (void) {while (! status) {readLFSsensors (); switch (modo) {case NO_LINE:motorStop (); goAndTurn (LEFT, 180); recIntersecção ('B'); pausa; case CONT_LINE:runExtraInch (); readLFSsensors (); if (modo! =CONT_LINE) {goAndTurn (LEFT, 90); recIntersection ('L');} // ou é um "T" ou "Cruz"). Em ambos os casos, vai para LEFT else mazeEnd (); pausa; case RIGHT_TURN:runExtraInch (); readLFSsensors (); if (modo ==NO_LINE) {goAndTurn (RIGHT, 90); recIntersection ('R');} else recIntersection ('S'); pausa; case LEFT_TURN:goAndTurn (LEFT, 90); recIntersecção ('L'); pausa; case FOLLOWING_LINE:followingLine (); pausa; }}} // --------------------------------------------- void recIntersection (char direction) {path [pathLength] =direction; // Armazena a interseção na variável de caminho. pathLength ++; simplifyPath (); // Simplifique o caminho aprendido.} // ---------------------------------------- ------ vazio mazeEnd (vazio) {motorStop (); BT1.print ("Fim ==> Caminho:"); para (int i =0; i "); Serial.println (pathLength); status =1; mode =STOPPED;} // ------------------------------------------- --- void followingLine (void) {// readLFSsensors (); calcule PID (); motorPIDcontrol (); } // ----------------------------------------------- ------------------------------------------- // Simplificação do caminho. A estratégia é que sempre que encontrarmos uma // sequência xBx, podemos simplificá-la cortando o beco sem saída. Por // exemplo, LBL -> S, porque um único S ignora o beco sem saída // representado por LBL.void simplifyPath () {// apenas simplifica o caminho se a penúltima curva for um 'B' if ( pathLength <3 || path [pathLength-2]! ='B') return; int totalAngle =0; int i; para (i =1; i <=3; i ++) {switch (path [pathLength-i]) {case 'R':totalAngle + =90; pausa; caso 'L':totalAngle + =270; pausa; caso 'B':totalAngle + =180; pausa; }} // Obtenha o ângulo como um número entre 0 e 360 ​​graus. totalAngle =totalAngle% 360; // Substitua todas essas curvas por uma única. switch (totalAngle) {case 0:path [pathLength - 3] ='S'; pausa; caso 90:caminho [pathLength - 3] ='R'; pausa; caso 180:caminho [pathLength - 3] ='B'; pausa; caso 270:caminho [pathLength - 3] ='L'; pausa; } // O caminho agora é duas etapas mais curto. pathLength - =2; } // ----------------------------------------------- ----------------------------------------------- void mazeOptimization ( void) {while (! status) {readLFSsensors (); switch (modo) {case FOLLOWING_LINE:followingLine (); pausa; case CONT_LINE:if (pathIndex> =pathLength) mazeEnd (); else {mazeTurn (path [pathIndex]); pathIndex ++;} break; case LEFT_TURN:if (pathIndex> =pathLength) mazeEnd (); else {mazeTurn (path [pathIndex]); pathIndex ++;} break; case RIGHT_TURN:if (pathIndex> =pathLength) mazeEnd (); else {mazeTurn (path [pathIndex]); pathIndex ++;} break; }}} // --------------------------------------------- -------- void mazeTurn (char dir) {switch (dir) {case 'L':// Vire à esquerda goAndTurn (LEFT, 90); pausa; case 'R':// Vire à direita goAndTurn (RIGHT, 90); pausa; case 'B':// Voltar goAndTurn (RIGHT, 800); pausa; case 'S':// Vá direto runExtraInch (); pausa; }} 
Funções Gerais. C / C ++
 void ledBlink (int times) {for (int i =0; i  0) {Serial.print ("Comando recebido de BT ==>"); Serial.println (dispositivo); comando =dispositivo; dispositivo =""; // Reinicializa a variável BT1.flush (); }} // ---------------------------------------------- -------------------------- void manualCmd () {switch (command [0]) {case 'g':mode =FOLLOWING_LINE; pausa; case 's':motorStop (); // desligue ambos os motores break; caso 'f':motorForward (); pausa; caso 'r':motorTurn (DIREITO, 30); motorStop (); pausa; caso 'l':motorTurn (LEFT, 30); motorStop (); pausa; caso 'b':motorBackward (); pausa; caso 'p':Kp =comando [2]; pausa; caso 'i':Ki =comando [2]; pausa; caso 'd':Kd =comando [2]; pausa; }} // ---------------------------------------------- -------------------------- void sendBTdata (int data) // enviar dados para BT {digitalWrite (ledPin, HIGH); BT1.print ("Dados do Arduino"); BT1.print (dados); BT1.print ("xx"); BT1.println ('\ n'); digitalWrite (ledPin, LOW);} // ---------------------------------------- ---------------- void calculPID () {P =erro; I =I + erro; D =erro anteriorError; Valor PID =(Kp * P) + (Ki * I) + (Kd * D); previousError =error;} // ------------------------------------------- ------------- void checkPIDvalues ​​() {BT1.print ("PID:"); BT1.print (Kp); BT1.print ("-"); BT1.print (Ki); BT1.print ("-"); BT1.println (Kd); Serial.print ("PID:"); Serial.print (Kp); Serial.print ("-"); Serial.print (Ki); Serial.print ("-"); Serial.println (Kd); } // ----------------------------------------------- void testLineFollowSensors () {int LFS0 =digitalRead (lineFollowSensor0); int LFS1 =digitalRead (lineFollowSensor1); int LFS2 =digitalRead (lineFollowSensor2); int LFS3 =digitalRead (lineFollowSensor3); int LFS4 =digitalRead (lineFollowSensor4); Serial.print ("LFS:L 0 1 2 3 4 R ==>"); Serial.print (LFS0); Serial.print (""); Serial.print (LFS1); Serial.print (""); Serial.print (LFS2); Serial.print (""); Serial.print (LFS3); Serial.print (""); Serial.print (LFS4); Serial.print ("==>"); Serial.print ("P:"); Serial.print (P); Serial.print ("I:"); Serial.print (I); Serial.print ("D:"); Serial.print (D); Serial.print ("PID:"); Serial.println (PIDvalue);} 
sensorFuntions C / C ++
 // --------------------------------------------- ---------------- / * ler os valores dos sensores da linha Sensor Array Error Value0 0 0 0 1 4 0 0 0 1 1 3 0 0 0 1 0 2 0 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 -1 0 1 0 0 0 -2 1 1 0 0 0 -3 1 0 0 0 0 -4 1 1 1 1 1 0 Robô encontrou linha contínua - teste se uma interseção ou final de maze0 0 0 0 0 0 O robô não encontrou nenhuma linha:gire 180o * / void readLFSsensors () {LFSensor [0] =digitalRead (lineFollowSensor0); LFSensor [1] =digitalRead (lineFollowSensor1); LFSensor [2] =digitalRead (lineFollowSensor2); LFSensor [3] =digitalRead (lineFollowSensor3); LFSensor [4] =digitalRead (lineFollowSensor4); farRightSensor =analogRead (farRightSensorPin); farLeftSensor =analogRead (farLeftSensorPin); if ((LFSensor [0] ==1) &&(LFSensor [1] ==1) &&(LFSensor [2] ==1) &&(LFSensor [3] ==1) &&(LFSensor [4] ==1 )) {modo =CONT_LINE; erro =0;} else if ((LFSensor [0] ==0) &&(farRightSensor "); Serial.print (farRightSensor); Serial.print ("modo:"); Serial.print (modo); Serial.print ("erro:"); Serial.println (erro); } // ----------------------------------------------- ------------ void readLateralSensors (void) {} ​​
RobotDefines.h C / C ++
 int mode =0; # define STOPPED 0 # define FOLLOWING_LINE 1 # define NO_LINE 2 # define CONT_LINE 3 # define POS_LINE 4 # define RIGHT_TURN 5 # define LEFT_TURN 6const int power =250; const int iniMotorPower =250; const int adj =0; float adjTurn =8; int extraInch =200; int adjGoAndTurn =800; const int ledPin =13; const int buttonPin =9; // LFSensor mais à esquerda é "0" const int lineFollowSensor0 =12; const int lineFollowSensor1 =18; const int lineFollowSensor2 =17; const int lineFollowSensor3 =16; const int lineFollowSensor4 =19; const int farRightSensorPin =0; // Pino analógico A0const int farLeftSensorPin =1; // Pino analógico A0const int THRESHOLD =150; int farRightSensor =0; int farLeftSensor =0; int LFSensor [5] ={0, 0, 0, 0, 0}; // controlador PIDfloat Kp =50; float Ki =0; float Kd =0; float error =0, P =0, I =0, D =0, PIDvalue =0; float previousError =0, previousI =0; #define RIGHT 1 # define LEFT -1Servo leftServo; Servo rightServo; // ------------------------------------------------ - // Definições e variáveis ​​específicas da Fase 2 do Labirinto (otimização) unsigned char dir; // A variável de caminho armazenará o caminho que o robô percorreu:// 'L' para esquerda // 'R' para direita // 'S' para linha reta (indo direto por uma interseção) // 'B' para costas (U-turn) char path [100] =""; unsigned char pathLength =0; // o comprimento do pathint pathIndex =0; unsigned int status =0; // resolvendo =0; alcance final =1 
MotorFuntions C / C ++
 void motorStop () {leftServo.writeMicroseconds (1500); rightServo.writeMicroseconds (1500); atraso (200);} // ------------------------------------------ --- void motorForward () {leftServo.writeMicroseconds (1500 - (power + adj)); rightServo.writeMicroseconds (1500 + potência);} // -------------------------------------- ------- void motorBackward () {leftServo.writeMicroseconds (1500 + potência); rightServo.writeMicroseconds (1500 - potência);} // -------------------------------------- ------- void motorFwTime (tempo int sem sinal) {motorForward (); tempo de atraso); motorStop ();} // ------------------------------------------- --void motorBwTime (tempo int sem sinal) {motorBackward (); tempo de atraso); motorStop ();} // ------------------------------------------- ----- vazio motorTurn (direção int, graus int) {leftServo.writeMicroseconds (1500 - (iniMotorPower + adj) * direção); rightServo.writeMicroseconds (1500 - direção iniMotorPower *); atraso (redondo (ajusteTurn * graus + 20)); motorStop ();} // ------------------------------------------- -------- void motorPIDcontrol () {int leftMotorSpeed ​​=1500 - (iniMotorPower + adj) - PIDvalue; int rightMotorSpeed ​​=1500 + iniMotorPower - valor PID; // A velocidade do motor não deve exceder a restrição do valor máximo de PWM (leftMotorSpeed, 1000, 2000); constrain (rightMotorSpeed, 1000, 2000); leftServo.writeMicroseconds (leftMotorSpeed); rightServo.writeMicroseconds (rightMotorSpeed); //Serial.print (PIDvalue); //Serial.print ("==> Esquerda, Direita:"); //Serial.print (leftMotorSpeed); //Serial.print (""); //Serial.println (rightMotorSpeed);} // -------------------------------------- ------------- void runExtraInch (void) {motorPIDcontrol (); atraso (extraInch); motorStop ();} // ------------------------------------------- -------- void goAndTurn (direção interna, graus internos) {motorPIDcontrol (); atraso (adjGoAndTurn); motorTurn (direção, graus);} 

Esquemas


Processo de manufatura

  1. Robô evitando parede baseado em Raspberry Pi - FabLab NerveCentre
  2. Um robô móvel com prevenção de obstáculos baseada na visão
  3. Robô ‘Artístico’ na NPE
  4. Automação:Linha do robô redesenhada
  5. Bosch adiciona inteligência artificial à indústria 4.0
  6. Linha do robô SCARA expandida
  7. Inteligência artificial é ficção ou moda passageira?
  8. Inteligência Artificial Ajuda o Robô a Reconhecer Objetos pelo Toque
  9. Robôs de Inteligência Artificial
  10. Vantagens e desvantagens da inteligência artificial