Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Линия на основе искусственного интеллекта (ИИ), следующая за роботом

Компоненты и расходные материалы

Arduino Nano
× 1
Ведущее устройство видимого беспроводного радиочастотного приемопередатчика Bluetooth
× 1
Модуль инфракрасного датчика Amazon Web Services, отражающий фотоэлектрический свет
× 1
Сервопривод непрерывного вращения Sony
× 1
Батарея Android 4,8 В
× 1

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

После разработки робота Pick &Place на базе Arduino возникла идея разработать линию следующего робота на основе искусственного интеллекта. Разработка простого робота, следующего за линией, была хороша для новичка, как раз то, что ему нужно было добавить какие-то инфракрасные датчики вместо серводвигателей в моем недавнем проекте. "Идея заключалась в том, чтобы проверить мои навыки на продвинутый уровень ".

Хотя это была сложная задача, мне очень помогло какое-то онлайн-исследование.

Зачем нужен робот, следующий за линией искусственного интеллекта?

Что касается AI это новейшая технология, которая может изменить мировую среду, таким образом, сделать человеческую жизнь более эффективной. Мечта, которая может стать реальностью, если дать нашим роботам разум, чтобы понять реальные проблемы и решить их соответствующим образом, эта мечта может стать реальностью только с помощью Искусственный интеллект вот почему все об этом говорят.

  • Его можно использовать на сборочной / производственной линии.
  • Пассажирские автобусы-пикапы.

Хотя мой прототип робота может быть немного интеллектуальным, это только начало для меня, когда я двигаю свои проекты в сторону ИИ . Таким образом, здесь я попытаюсь объяснить пошаговое развитие робота, следующего за линией, с использованием искусственного интеллекта, на достаточно простом языке. Из-за нехватки ресурсов я не буду создавать робота, но я могу очень хорошо объяснить, как вы можете его построить, выполнив какое-то исследование. Я постараюсь предоставить точные коды, которые будут работать в вашей Arduino IDE, чтобы вы можете довольно легко разработать своего первого робота с искусственным интеллектом.

Отсюда вы можете поддержать меня на Patreon :http://bit.ly/31NfQ6A

"Вы можете найти самые дешевые тарифы в США в описании этого видео, просто нажмите на видео . "

А теперь перейдем к проекту «Робот, отслеживающий линию на основе искусственного интеллекта!» .

ИСПОЛЬЗОВАНИЕ ИНФРАКРАСНЫХ ДАТЧИКОВ

Наш Проект включает 7 инфракрасных датчиков, как показано на схеме.

  • 5 для ПИД-регулирования
  • 1 для обнаружения слева
  • еще один для обнаружения правой стороны.

Роль 5 датчиков ПИД-регулирования :Эти 5 датчиков будут использоваться для генерации цифрового выходного сигнала высокого или низкого (1, 0) соответственно.

Датчик, центрированный по отношению к черной линии, только этот датчик будет выдавать ВЫСОКИЙ (1). Аналогичным возможным результатом для этого датчика может быть:-

  • 10000
  • 11000
  • 01000
  • 01100
  • 00100
  • 00110
  • 00010
  • 00011
  • 00001
  • 00000
  • 11111

Теперь перейдем к двум другим датчикам для левого и правого возможных результатов:

Крайний левый датчик:аналоговый выход высокий или низкий

Крайний левый датчик:аналоговый выход высокий или низкий

Для хранения значения 5 датчиков создадим переменную массива.

  в LFSensor [5] ={1,1,1,1,1};  

Для хранения значений левого и правого датчиков мы будем использовать целое число

  int farleft_sensor =0;  

Как мы знаем, у нас есть 5 датчиков, которые можно использовать для хранения левого и правого пути, взятого роботом в массиве. Итак

  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);

ПРАВИЛО ЛЕВОГО ЛАБИРИНТА:

смотреть это видео, чтобы понять правило левой руки в лабиринте

Короче говоря, Правило левой руки можно описать как:

  • Положите левую руку на стену.
  • Иди вперед.
  • На каждом перекрестке и по всему лабиринту держите левую руку на стене слева от вас.
  • В конце концов вы доберетесь до конца лабиринта. Возможно, вы не пойдете самым коротким и прямым путем, но вы доберетесь туда.

Итак, главное здесь - определить перекрестки , определяя, какой курс выбрать, основываясь на приведенных выше правилах. В частности, в нашем 2D-лабиринте мы можем найти 8 различных типов пересечений (см. Первое изображение выше):

Глядя на картинку, мы можем понять, что возможные действия на перекрестках:

На " Кресте "

  • Перейти влево или
  • Перейти вправо или
  • Двигайтесь прямо
  • На " Кресте "Идите налево или направо или прямо

В " T ":

  • Перейти влево или
  • Перейти вправо
  • На " T ":Перейти влево или вправо

На " Только справа " ":

  • Перейти вправо
  • В " Только справа " ":Перейти вправо

В " Только слева " ":

  • Перейти влево
  • В " Только слева " ":Перейти влево

На " Прямо или налево ":

  • Перейти влево или
  • Двигайтесь прямо
  • В " Прямо или налево ":Налево или прямо.

На " Прямо или вправо ":

  • Перейти вправо или
  • Двигайтесь прямо
  • В " Прямо или вправо ":Идите вправо или прямо

В " тупике ":

  • Вернуться ("разворот")
  • В " тупике ":Вернуться (" Развернуть ")

В " Конец лабиринта" ":

  • Остановить
  • В " Конец лабиринта" ":Стоп

Но, применяя «Правило левой руки», каждое действие будет сведено к одному варианту:

  • У «креста»:идите налево.
  • На букву «Т»:налево.
  • "Только справа":переходите вправо.
  • "Только слева":идите налево.
  • Прямо или налево:идите налево.
  • Прямо или направо:идите прямо.
  • В "тупике":возвращайтесь ("разворачивайтесь")
  • В «конце лабиринта»:стоп.

Мы почти на месте! «Успокойся!»

Когда робот достигает «тупика» или «конца лабиринта», их легко идентифицировать, потому что в них не существует неоднозначных ситуаций (мы уже реализовали эти действия для робота-следящего за линией, помните?). Проблема в том, когда робот находит «ЛИНИЮ», например, потому что линия может быть «Крестиком» (1) или «Т» (2). Также, когда он достигает «ПОВОРОТА ВЛЕВО или ВПРАВО», это может быть простой поворот (варианты 3 или 4) или варианты движения прямо (5 или 6). Чтобы точно определить, какой тип пересечения представляет собой робот, необходимо предпринять дополнительный шаг:робот должен пробежать «лишний дюйм» и посмотреть, что будет дальше (см. Вторую картинку выше в качестве примера).

Итак, с точки зрения потока, возможные действия теперь можно описать как:

В "МЕРТВОЙ КОНЦЕ":

  • Вернуться ("разворот")
  • В "ТЕРМИЧЕСКОМ КОНЦЕ":возвращайтесь ("разворачивайтесь")

На «ЛИНИИ»:

  • Увеличьте длину на дюйм
  • Если есть линия:это "Крест" ==> ПЕРЕЙДИТЕ ВЛЕВО.
  • Если строки нет:это буква "T" ==> ПЕРЕЙДИТЕ ВЛЕВО
  • Если есть другая линия:это «Конец лабиринта» ==> СТОП.
  • На "ЛИНИИ": пробегите лишний дюйм Если есть линия:это «Крест» ==> Перейти к LEFTI, если нет линии:это «T» ==> Перейти к LEFTI, если есть другая линия:это «Конец лабиринта» ==> СТОП

На «ПОВОРОТ НАПРАВО»:

  • Увеличьте длину на дюйм
  • если есть линия:это прямая или правая ==> Иди ПРЯМО
  • Если линии нет:это только вправо ==> Перейти ВПРАВО
  • При "ПОВОРОТЕ ВПРАВО": Пробежка лишний дюйм если есть линия:это прямая или правая ==> идите прямо, если нет линии:она только правая ==> идите вправо

На «ЛЕВОМ ПОВОРОТЕ»:

  • Увеличьте длину на дюйм
  • если есть линия:это прямая или ЛЕВАЯ ==> Перейти в ЛЕВУЮ
  • Если строки нет:это только ЛЕВЫЙ ==> Перейти в ЛЕВЫЙ
  • При "левом повороте": пробегите лишний дюйм . если есть линия:это прямая или ЛЕВАЯ ==> Перейти в ЛЕВОЕсли нет линии:только ЛЕВАЯ ==> Перейти в ЛЕВУЮ

Обратите внимание, что на самом деле в случае «ЛЕВОГО ПОВОРОТА» вы можете пропустить тест, потому что вы все равно выберете ВЛЕВО. Я оставил объяснение более общим только для ясности. На реальном коде я пропущу этот тест.

Вот некоторые проблемы, которые могут возникнуть при создании этого проекта.

Связанная тема

РЕШЕНИЕ ПРОБЛЕМЫ ДРАЙВЕРА Arduino

смотреть это видео, чтобы решить проблему с драйвером Arduino:


Код

  • Робот-лабиринт_Solve_2
  • Функции
  • Общие функции.
  • сенсорные функции
  • RobotDefines.h
  • MotorFuntions
RoBot_Maze_Solve_2 C / C ++
 / * --------------------------------------------- --------------------- 7 датчиков Smart Robot - Maze Solver и Line Follower с программируемым ПИД-регулятором через BT ==> Базовое движение на основе Nano Mouse Robot, разработанного Майкл Бэкус (http://www.akrobotnerd.com/) ==> Следуйте за строкой на основе http://samvrit.tk/tutorials/pid-control-arduino-line-follower-robot/?ckattempt=1==> ПРЕДОСТАВЛЯЕТСЯ Патрику МакКейбу за путь решения кода, посетите patrickmccabemakes.com !! Марсело Хосе Роваи - 23 апреля 2016 г. - Посетите:http://mjrobot.org---------------- -------------------------------------------------- - * / # include  #include "robotDefines.h" String command; String device; // BT Module # include  SoftwareSerial BT1 (10, 11); // El pin 10 es Rx y el pin 11 es Tx // ----------------------------------- ---------- void setup () {Serial.begin (9600); BT1.begin (9600); pinMode (ledPin, ВЫХОД); pinMode (buttonPin, INPUT_PULLUP); // линия следит за датчиками pinMode (lineFollowSensor0, INPUT); pinMode (lineFollowSensor1, ВХОД); pinMode (lineFollowSensor2, ВХОД); pinMode (lineFollowSensor3, ВХОД); pinMode (lineFollowSensor4, ВХОД); // сервоприводы leftServo.attach (5); rightServo.attach (3); BT1.print («проверить константы PID для отправки роботу»); Serial.print («проверить константы PID для отправки роботу»); BT1.println ('\ п'); в то время как (digitalRead (buttonPin) &&! режим) {checkBTcmd (); // проверяем, получена ли команда от пульта дистанционного управления BT manualCmd (); команда =""; } checkPIDvalues ​​(); режим =ОСТАНОВЛЕН; статус =0; // 1-й проход} void loop () {ledBlink (1); BT1.println («Начать первый проход»); Serial.println («Начать первый проход»); readLFSsensors (); mazeSolve (); // Первый проход для решения лабиринта ledBlink (2); BT1.println («Завершить первый проход»); Serial.println («Завершить первый проход»); в то время как (digitalRead (buttonPin) &&! режим) {checkBTcmd (); // проверяем, получена ли команда от пульта дистанционного управления BT manualCmd (); команда =""; } BT1.println («Запуск 2-го прохода»); Serial.println («Запуск 2-го прохода»); pathIndex =0; статус =0; mazeOptimization (); // как можно быстрее запустить лабиринт ledBlink (3); BT1.println («Завершить 2-й проход»); Serial.println («Завершить 2-й проход»); в то время как (digitalRead (buttonPin) &&! режим) {checkBTcmd (); // проверяем, получена ли команда от пульта дистанционного управления BT manualCmd (); команда =""; } режим =ОСТАНОВЛЕН; статус =0; // 1-й проход pathIndex =0; pathLength =0;} 
Функции C / C ++
 void mazeSolve (void) {в то время как (! статус) {readLFSsensors (); переключатель (режим) {case NO_LINE:motorStop (); goAndTurn (СЛЕВА, 180); recIntersection ('B'); ломать; case CONT_LINE:runExtraInch (); readLFSsensors (); если (режим! =CONT_LINE) {goAndTurn (LEFT, 90); recIntersection ('L');} // или это буква "Т" или "Крест"). В обоих случаях переходит к LEFT else mazeEnd (); ломать; case RIGHT_TURN:runExtraInch (); readLFSsensors (); если (режим ==NO_LINE) {goAndTurn (ВПРАВО, 90); recIntersection ('R');} else recIntersection ('S'); ломать; case LEFT_TURN:goAndTurn (LEFT, 90); recIntersection ('L'); ломать; case FOLLOWING_LINE:followingLine (); ломать; }}} // --------------------------------------------- void recIntersection (char direction) {path [pathLength] =direction; // Сохраняем пересечение в переменной пути. pathLength ++; simpleifyPath (); // Упростим изученный путь.} // ---------------------------------------- ------ void mazeEnd (void) {motorStop (); BT1.print ("Конец ==> Путь:"); для (int я =0; я "); Serial.println (длина пути); статус =1; mode =STOPPED;} // ------------------------------------------- --- void followingLine (void) {// readLFSsensors (); CalculPID (); motorPIDcontrol (); } // ----------------------------------------------- ------------------------------------------- // Упрощение пути. Стратегия заключается в том, что всякий раз, когда мы встречаем // последовательность xBx, мы можем упростить ее, вырезав тупик. Например, // например, LBL -> S, потому что одиночный S обходит тупик, // представленный LBL .void simpleifyPath () {// упрощает путь только в том случае, если предпоследний поворот был 'B' if ( pathLength <3 || путь [pathLength-2]! ='B') return; int totalAngle =0; int i; for (i =1; i <=3; i ++) {switch (path [pathLength-i]) {case 'R':totalAngle + =90; ломать; case 'L':totalAngle + =270; ломать; case 'B':totalAngle + =180; ломать; }} // Получаем угол в виде числа от 0 до 360 градусов. totalAngle =totalAngle% 360; // Заменить все эти повороты одним. переключатель (totalAngle) {case 0:path [pathLength - 3] ='S'; ломать; case 90:путь [pathLength - 3] ='R'; ломать; case 180:путь [pathLength - 3] ='B'; ломать; case 270:путь [pathLength - 3] ='L'; ломать; } // Теперь путь на два шага короче. pathLength - =2; } // ----------------------------------------------- ----------------------------------------------- Пустой лабиринтОптимизация ( void) {в то время как (! статус) {readLFSsensors (); переключатель (режим) {case FOLLOWING_LINE:followingLine (); ломать; case CONT_LINE:if (pathIndex> =pathLength) mazeEnd (); иначе {mazeTurn (путь [pathIndex]); pathIndex ++;} перерыв; case LEFT_TURN:if (pathIndex> =pathLength) mazeEnd (); иначе {mazeTurn (путь [pathIndex]); pathIndex ++;} перерыв; case RIGHT_TURN:if (pathIndex> =pathLength) mazeEnd (); иначе {mazeTurn (путь [pathIndex]); pathIndex ++;} перерыв; }}} // --------------------------------------------- -------- void mazeTurn (char dir) {switch (dir) {case 'L':// Повернуть налево goAndTurn (LEFT, 90); ломать; case 'R':// Повернуть направо goAndTurn (RIGHT, 90); ломать; case 'B':// Повернуть назад goAndTurn (RIGHT, 800); ломать; case 'S':// Прямо runExtraInch (); ломать; }} 
Общие функции. C / C ++
 void ledBlink (int times) {for (int i =0; i  0) {Serial.print ("Команда получена от BT ==>"); Serial.println (устройство); команда =устройство; устройство =""; // Сбрасываем переменную BT1.flush (); }} // ---------------------------------------------- -------------------------- void manualCmd () {переключатель (команда [0]) {case 'g':mode =FOLLOWING_LINE; ломать; case 's':motorStop (); // выключаем оба мотора break; case 'f':motorForward (); ломать; case 'r':motorTurn (ВПРАВО, 30); motorStop (); ломать; case 'l':motorTurn (ЛЕВЫЙ, 30); motorStop (); ломать; case 'b':motorBackward (); ломать; case 'p':Kp =команда [2]; ломать; case 'i':Ki =команда [2]; ломать; case 'd':Kd =команда [2]; ломать; }} // ---------------------------------------------- -------------------------- void sendBTdata (int data) // отправляем данные в BT {digitalWrite (ledPin, HIGH); BT1.print («Данные с Arduino»); BT1.print (данные); BT1.print ("хх"); BT1.println ('\ п'); digitalWrite (ledPin, LOW);} // ---------------------------------------- ---------------- void calculatePID () {P =error; I =I + ошибка; D =ошибка-предыдущая ошибка; Значение PID =(Kp * P) + (Ki * I) + (Kd * D); previousError =error;} // ------------------------------------------- ------------- void checkPIDvalues ​​() {BT1.print ("PID:"); BT1.print (КП); BT1.print ("-"); BT1.print (Ki); BT1.print ("-"); BT1.println (Кд); Serial.print ("PID:"); Серийный принт (КП); Serial.print ("-"); Серийный принт (Ki); Serial.print ("-"); Serial.println (Кд); } // ----------------------------------------------- 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 ==>"); Серийный принт (LFS0); Serial.print (""); Серийный принт (LFS1); Serial.print (""); Серийный принт (LFS2); Serial.print (""); Серийный принт (LFS3); Serial.print (""); Серийный принт (LFS4); Serial.print ("==>"); Serial.print ("P:"); Серийный принт (P); Serial.print ("I:"); Серийный принт (I); Serial.print ("D:"); Серийный принт (D); Serial.print ("PID:"); Serial.println (PIDvalue);} 
sensorFuntions C / C ++
 // --------------------------------------------- ---------------- / * считывание значений линейных датчиков Sensor Array Error Value 0 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 Робот обнаружил непрерывную линию - проверьте, есть ли пересечение или конец of maze0 0 0 0 0 0 Робот не нашел линии:поверните на 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 )) {mode =CONT_LINE; error =0;} else if ((LFSensor [0] ==0) &&(farRightSensor "); Serial.print (farRightSensor); Serial.print ("режим:"); Serial.print (режим); Serial.print ("ошибка:"); Serial.println (ошибка); } // ----------------------------------------------- ------------ void readLateralSensors (void) {} ​​
RobotDefines.h C / C ++
 int mode =0; # определить STOPPED 0 # определить FOLLOWING_LINE 1 # определить NO_LINE 2 # определить CONT_LINE 3 # определить POS_LINE 4 # определить RIGHT_TURN 5 # определить 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 левее "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; // Аналоговый вывод A0const int farLeftSensorPin =1; // Аналоговый вывод A0const int THRESHOLD =150; int farRightSensor =0; int farLeftSensor =0; int LFSensor [5] ={0, 0, 0, 0, 0}; // Поплавок ПИД-регулятора 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; // ------------------------------------------------ - // Определения и переменные фазы 2 лабиринта (оптимизация) unsigned char dir; // Переменная пути будет хранить путь, который прошел робот:// 'L' для левого // 'R' для правого // 'S' для прямого (идущего прямо через перекресток) // 'B' для обратного (Разворот) char path [100] =""; беззнаковый char pathLength =0; // длина пути int pathIndex =0; unsigned int status =0; // решение =0; достичь конца =1 
MotorFuntions C / C ++
 void motorStop () {leftServo.writeMicroseconds (1500); rightServo.writeMicroseconds (1500); delay (200);} // ------------------------------------------ --- void motorForward () {leftServo.writeMicroseconds (1500 - (мощность + прил.)); rightServo.writeMicroseconds (1500 + мощность);} // -------------------------------------- ------- void motorBackward () {leftServo.writeMicroseconds (1500 + мощность); rightServo.writeMicroseconds (1500 - мощность);} // -------------------------------------- ------- void motorFwTime (беззнаковое целое время) {motorForward (); Время задержки); motorStop ();} // ------------------------------------------- --void motorBwTime (целое время без знака) {motorBackward (); Время задержки); motorStop ();} // ------------------------------------------- ----- void motorTurn (int direction, int градусов) {leftServo.writeMicroseconds (1500 - (iniMotorPower + adj) * направление); rightServo.writeMicroseconds (1500 - iniMotorPower * direction); задержка (round (adjTurn * градусов + 20)); motorStop ();} // ------------------------------------------- -------- void motorPIDcontrol () {int leftMotorSpeed ​​=1500 - (iniMotorPower + adj) - значение PID; int rightMotorSpeed ​​=1500 + iniMotorPower - значение PID; // Скорость двигателя не должна превышать максимальное значение PWM constrain (leftMotorSpeed, 1000, 2000); ограничение (rightMotorSpeed, 1000, 2000); leftServo.writeMicroseconds (leftMotorSpeed); rightServo.writeMicroseconds (rightMotorSpeed); //Serial.print (PIDvalue); //Serial.print ("==> Влево, вправо:"); //Serial.print (leftMotorSpeed); //Serial.print (""); //Serial.println (rightMotorSpeed);} // -------------------------------------- ------------- void runExtraInch (void) {motorPIDcontrol (); задержка (extraInch); motorStop ();} // ------------------------------------------- -------- void goAndTurn (целое направление, целое число градусов) {motorPIDcontrol (); задержка (adjGoAndTurn); motorTurn (направление, градусы);} 

Схема


Производственный процесс

  1. Робот, избегающий стен на базе Raspberry Pi - FabLab NerveCentre
  2. Мобильный робот с функцией обхода препятствий на основе обзора
  3. «Художественный» робот в NPE
  4. Автоматизация:переработка линии роботов
  5. Bosch добавляет искусственный интеллект в Индустрию 4.0
  6. Расширенная линия робота SCARA
  7. Искусственный интеллект - вымысел или вымысел?
  8. Искусственный интеллект помогает роботу распознавать объекты на ощупь
  9. Роботы с искусственным интеллектом
  10. Преимущества и недостатки искусственного интеллекта