ARDUİNO İLE LABİRENT ÇÖZEN ROBOT YAPIMI

ARDUİNO İLE LABİRENT ÇÖZEN ROBOT YAPIMI

Çizgi labirent çözen zumo robot kiti yapımından bahsedeceğiz , pololu firması tarafından geliştirilip üretilen zumo robot kiti ve zumo shield ile birçok robot projesi yapabilmektesiniz.Bu yazımızda labirent çözen yapımını göstereceğiz.

Zumo robot kitini aldığınızda kit içerisinden kurulum kılavuzu çıkmaktadır kılavuza göre kurulumu gerçekleştirebilirsiniz. Kit ile beraber DC motor göndermiyorlar siz redüktörlü mikro dc motor almanız gerekmektedir.

Malzeme Listesi

  • Zumo Robot Kiti
  • Redüktörlü mikro dc motor
  • Zumo Shield
  • Zumo QTR Çizgi Sensörü
  • Arduino UNO

Aşağıda zumo robotun parçaları mevcuttur.

Projenin çalışma videosu

Robotu kurduğunuzda aşağıdaki gibi görünmektedir. Zumo shiled tamamen demonte halde gönderiliyor evinizde lehim yapmak için ekipmanınızın olması gerekiyor.Aksi halde robotu kurmazsınız.

Proje için gerekli arduino kütüphanesi linki : https://github.com/pololu/zumo-shield

Projenin kodları:

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6.  
  7. /* This example uses the Zumo Reflectance Sensor Array
  8.  * to navigate a black line maze with no loops. This program
  9.  * is based off the 3pi maze solving example which can be
  10.  * found here:
  11.  *
  12.  * http://www.pololu.com/docs/0J21/8.a
  13.  *
  14.  * The Zumo first calibrates the sensors to account
  15.  * for differences of the black line on white background.
  16.  * Calibration is accomplished in setup().
  17.  *
  18.  * In loop(), the function solveMaze() is called and navigates
  19.  * the Zumo until it finds the finish line which is defined as
  20.  * a large black area that is thick and wide enough to
  21.  * cover all six sensors at the same time.
  22.  *
  23.  * Once the Zumo reaches the finishing line, it will stop and
  24.  * wait for the user to place the Zumo back at the starting
  25.  * line. The Zumo can then follow the shortest path to the finish
  26.  * line.
  27.  *
  28.  * The macros SPEED, TURN_SPEED, ABOVE_LINE(), and LINE_THICKNESS
  29.  * might need to be adjusted on a case by case basis to give better
  30.  * line following results.
  31.  */
  32.  
  33. // SENSOR_THRESHOLD is a value to compare reflectance sensor
  34. // readings to to decide if the sensor is over a black line
  35. #define SENSOR_THRESHOLD 300
  36.  
  37. // ABOVE_LINE is a helper macro that takes returns
  38. // 1 if the sensor is over the line and 0 if otherwise
  39. #define ABOVE_LINE(sensor)((sensor) > SENSOR_THRESHOLD)
  40.  
  41. // Motor speed when turning. TURN_SPEED should always
  42. // have a positive value, otherwise the Zumo will turn
  43. // in the wrong direction.
  44. #define TURN_SPEED 200
  45.  
  46. // Motor speed when driving straight. SPEED should always
  47. // have a positive value, otherwise the Zumo will travel in the
  48. // wrong direction.
  49. #define SPEED 200
  50.  
  51. // Thickness of your line in inches
  52. #define LINE_THICKNESS .75
  53.  
  54. // When the motor speed of the zumo is set by
  55. // motors.setSpeeds(200,200), 200 is in ZUNITs/Second.
  56. // A ZUNIT is a fictitious measurement of distance
  57. // and only helps to approximate how far the Zumo has
  58. // traveled. Experimentally it was observed that for
  59. // every inch, there were approximately 17142 ZUNITs.
  60. // This value will differ depending on setup/battery
  61. // life and may be adjusted accordingly. This value
  62. // was found using a 75:1 HP Motors with batteries
  63. // partially discharged.
  64. #define INCHES_TO_ZUNITS 17142.0
  65.  
  66. // When the Zumo reaches the end of a segment it needs
  67. // to find out three things: if it has reached the finish line,
  68. // if there is a straight segment ahead of it, and which
  69. // segment to take. OVERSHOOT tells the Zumo how far it needs
  70. // to overshoot the segment to find out any of these things.
  71. #define OVERSHOOT(line_thickness)(((INCHES_TO_ZUNITS * (line_thickness)) / SPEED))
  72.  
  73. ZumoBuzzer buzzer;
  74. ZumoReflectanceSensorArray reflectanceSensors;
  75. ZumoMotors motors;
  76. Pushbutton button(ZUMO_BUTTON);
  77.  
  78. // path[] keeps a log of all the turns made
  79. // since starting the maze
  80. char path[100] = "";
  81. unsigned char path_length = 0; // the length of the path
  82.  
  83. void setup()
  84. {
  85.  
  86.   unsigned int sensors[6];
  87.   unsigned short count = 0;
  88.   unsigned short last_status = 0;
  89.   int turn_direction = 1; 
  90.  
  91.   buzzer.play(">g32>>c32");
  92.    
  93.   reflectanceSensors.init();
  94.    
  95.   delay(500);
  96.   pinMode(13, OUTPUT);
  97.   digitalWrite(13, HIGH);        // turn on LED to indicate we are in calibration mode
  98.     
  99.   button.waitForButton();
  100.    
  101.   // Calibrate the Zumo by sweeping it from left to right
  102.   for(int i = 0; i < 4; i ++)
  103.   {
  104.     // Zumo will turn clockwise if turn_direction = 1.
  105.     // If turn_direction = -1 Zumo will turn counter-clockwise.
  106.     turn_direction *= -1;
  107.      
  108.     // Turn direction.
  109.     motors.setSpeeds(turn_direction * TURN_SPEED, -1*turn_direction * TURN_SPEED);
  110.        
  111.     // This while loop monitors line position
  112.     // until the turn is complete.
  113.     while(count < 2)
  114.     {
  115.       reflectanceSensors.calibrate();
  116.       reflectanceSensors.readLine(sensors);
  117.       if(turn_direction < 0) { // If the right most sensor changes from (over white space -> over
  118.         // line or over line -> over white space) add 1 to count.
  119.         count += ABOVE_LINE(sensors[5]) ^ last_status;
  120.         last_status = ABOVE_LINE(sensors[5]);
  121.       }
  122.       else
  123.       {
  124.         // If the left most sensor changes from (over white space -> over
  125.         // line or over line -> over white space) add 1 to count.
  126.         count += ABOVE_LINE(sensors[0]) ^ last_status;
  127.         last_status = ABOVE_LINE(sensors[0]);    
  128.       }
  129.     }
  130.    
  131.     count = 0;
  132.     last_status = 0;
  133.   }
  134.    
  135.   // Turn left.
  136.   turn('L');
  137.    
  138.   motors.setSpeeds(0, 0);
  139.    
  140.   // Sound off buzzer to denote Zumo is finished calibrating
  141.   buzzer.play("L16 cdegreg4");
  142.    
  143.   // Turn off LED to indicate we are through with calibration
  144.   digitalWrite(13, LOW);
  145. }
  146.  
  147. void loop()
  148. {
  149.  
  150.   // solveMaze() explores every segment
  151.   // of the maze until it finds the finish
  152.   // line.
  153.   solveMaze();
  154.    
  155.   // Sound off buzzer to denote Zumo has solved the maze
  156.   buzzer.play(">>a32");
  157.    
  158.   // The maze has been solved. When the user
  159.   // places the Zumo at the starting line
  160.   // and pushes the Zumo button, the Zumo
  161.   // knows where the finish line is and
  162.   // will automatically navigate.
  163.   while(1)
  164.   {
  165.     button.waitForButton();
  166.     goToFinishLine();
  167.     // Sound off buzzer to denote Zumo is at the finish line.
  168.     buzzer.play(">>a32");
  169.   }
  170. }
  171.  
  172. // Turns according to the parameter dir, which should be
  173. // 'L' (left), 'R' (right), 'S' (straight), or 'B' (back).
  174. void turn(char dir)
  175. {
  176.  
  177.   // count and last_status help
  178.   // keep track of how much further
  179.   // the Zumo needs to turn.
  180.   unsigned short count = 0;
  181.   unsigned short last_status = 0;
  182.   unsigned int sensors[6];
  183.    
  184.   // dir tests for which direction to turn
  185.   switch(dir)
  186.   {
  187.    
  188.   // Since we're using the sensors to coordinate turns instead of timing them,
  189.   // we can treat a left turn the same as a direction reversal: they differ only
  190.   // in whether the zumo will turn 90 degrees or 180 degrees before seeing the
  191.   // line under the sensor. If 'B' is passed to the turn function when there is a
  192.   // left turn available, then the Zumo will turn onto the left segment.
  193.     case 'L':
  194.     case 'B':
  195.       // Turn left.
  196.       motors.setSpeeds(-TURN_SPEED, TURN_SPEED);
  197.        
  198.       // This while loop monitors line position
  199.       // until the turn is complete.
  200.       while(count < 2) { reflectanceSensors.readLine(sensors); // Increment count whenever the state of the sensor changes // (white->black and black->white) since the sensor should
  201.         // pass over 1 line while the robot is turning, the final
  202.         // count should be 2
  203.         count += ABOVE_LINE(sensors[1]) ^ last_status;
  204.         last_status = ABOVE_LINE(sensors[1]);
  205.       }
  206.      
  207.     break;
  208.      
  209.     case 'R':
  210.       // Turn right.
  211.       motors.setSpeeds(TURN_SPEED, -TURN_SPEED);
  212.        
  213.       // This while loop monitors line position
  214.       // until the turn is complete.
  215.       while(count < 2) { reflectanceSensors.readLine(sensors); count += ABOVE_LINE(sensors[4]) ^ last_status; last_status = ABOVE_LINE(sensors[4]); } break; case 'S': // Don't do anything! break; } } // This function decides which way to turn during the learning phase of // maze solving. It uses the variables found_left, found_straight, and // found_right, which indicate whether there is an exit in each of the // three directions, applying the "left hand on the wall" strategy. char selectTurn(unsigned char found_left, unsigned char found_straight, unsigned char found_right) { // Make a decision about how to turn. The following code // implements a left-hand-on-the-wall strategy, where we always // turn as far to the left as possible. if(found_left) return 'L'; else if(found_straight) return 'S'; else if(found_right) return 'R'; else return 'B'; } // The maze is broken down into segments. Once the Zumo decides // which segment to turn on, it will navigate until it finds another // intersection. followSegment() will then return after the // intersection is found. void followSegment() { unsigned int position; unsigned int sensors[6]; int offset_from_center; int power_difference; while(1) { // Get the position of the line. position = reflectanceSensors.readLine(sensors); // The offset_from_center should be 0 when we are on the line. offset_from_center = ((int)position) - 2500; // Compute the difference between the two motor power settings, // m1 - m2. If this is a positive number the robot will turn // to the left. If it is a negative number, the robot will // turn to the right, and the magnitude of the number determines // the sharpness of the turn. power_difference = offset_from_center / 3; // Compute the actual motor settings. We never set either motor // to a negative value. if(power_difference > SPEED)
  216.       power_difference = SPEED;
  217.     if(power_difference < -SPEED)
  218.       power_difference = -SPEED;
  219.       
  220.     if(power_difference < 0)
  221.       motors.setSpeeds(SPEED + power_difference, SPEED);
  222.     else
  223.       motors.setSpeeds(SPEED, SPEED - power_difference);
  224.       
  225.     // We use the inner four sensors (1, 2, 3, and 4) for
  226.     // determining whether there is a line straight ahead, and the
  227.     // sensors 0 and 5 for detecting lines going to the left and
  228.     // right.
  229.       
  230.     if(!ABOVE_LINE(sensors[0]) && !ABOVE_LINE(sensors[1]) && !ABOVE_LINE(sensors[2]) && !ABOVE_LINE(sensors[3]) && !ABOVE_LINE(sensors[4]) && !ABOVE_LINE(sensors[5]))
  231.     {
  232.       // There is no line visible ahead, and we didn't see any
  233.       // intersection.  Must be a dead end.           
  234.       return;
  235.     }
  236.     else if(ABOVE_LINE(sensors[0]) || ABOVE_LINE(sensors[5]))
  237.     {
  238.       // Found an intersection.
  239.       return;
  240.     }
  241.     
  242.   }
  243. }
  244.  
  245. // The solveMaze() function works by applying a "left hand on the wall" strategy:
  246. // the robot follows a segment until it reaches an intersection, where it takes the
  247. // leftmost fork available to it. It records each turn it makes, and as long as the
  248. // maze has no loops, this strategy will eventually lead it to the finish. Afterwards,
  249. // the recorded path is simplified by removing dead ends. More information can be
  250. // found in the 3pi maze solving example.
  251. void solveMaze()
  252. {
  253.     while(1)
  254.     {
  255.         // Navigate current line segment
  256.         followSegment();
  257.           
  258.         // These variables record whether the robot has seen a line to the
  259.         // left, straight ahead, and right, while examining the current
  260.         // intersection.
  261.         unsigned char found_left = 0;
  262.         unsigned char found_straight = 0;
  263.         unsigned char found_right = 0;
  264.           
  265.         // Now read the sensors and check the intersection type.
  266.         unsigned int sensors[6];
  267.         reflectanceSensors.readLine(sensors);
  268.           
  269.         // Check for left and right exits.
  270.         if(ABOVE_LINE(sensors[0]))
  271.             found_left = 1;
  272.         if(ABOVE_LINE(sensors[5]))
  273.             found_right = 1;
  274.              
  275.         // Drive straight a bit more, until we are
  276.         // approximately in the middle of intersection.
  277.         // This should help us better detect if we
  278.         // have left or right segments.
  279.         motors.setSpeeds(SPEED, SPEED);
  280.         delay(OVERSHOOT(LINE_THICKNESS)/2);
  281.          
  282.         reflectanceSensors.readLine(sensors);
  283.           
  284.         // Check for left and right exits.
  285.         if(ABOVE_LINE(sensors[0]))
  286.             found_left = 1;
  287.         if(ABOVE_LINE(sensors[5]))
  288.             found_right = 1;
  289.          
  290.         // After driving a little further, we
  291.         // should have passed the intersection
  292.         // and can check to see if we've hit the
  293.         // finish line or if there is a straight segment
  294.         // ahead.  
  295.         delay(OVERSHOOT(LINE_THICKNESS)/2);
  296.          
  297.         // Check for a straight exit.
  298.         reflectanceSensors.readLine(sensors);
  299.          
  300.         // Check again to see if left or right segment has been found
  301.         if(ABOVE_LINE(sensors[0]))
  302.             found_left = 1;
  303.         if(ABOVE_LINE(sensors[5]))
  304.             found_right = 1;
  305.          
  306.         if(ABOVE_LINE(sensors[1]) || ABOVE_LINE(sensors[2]) || ABOVE_LINE(sensors[3]) || ABOVE_LINE(sensors[4]))
  307.             found_straight = 1;
  308.           
  309.         // Check for the ending spot.
  310.         // If all four middle sensors are on dark black, we have
  311.         // solved the maze.
  312.         if(ABOVE_LINE(sensors[1]) && ABOVE_LINE(sensors[2]) && ABOVE_LINE(sensors[3]) && ABOVE_LINE(sensors[4]))
  313.         {
  314.           motors.setSpeeds(0,0);
  315.           break;
  316.         }
  317.           
  318.         // Intersection identification is complete.
  319.         unsigned char dir = selectTurn(found_left, found_straight, found_right);
  320.          
  321.         // Make the turn indicated by the path.
  322.         turn(dir);
  323.           
  324.         // Store the intersection in the path variable.
  325.         path[path_length] = dir;
  326.         path_length++;
  327.           
  328.         // You should check to make sure that the path_length does not
  329.         // exceed the bounds of the array.  We'll ignore that in this
  330.         // example.
  331.           
  332.         // Simplify the learned path.
  333.         simplifyPath();
  334.           
  335.     }
  336. }
  337.  
  338. // Now enter an infinite loop - we can re-run the maze as many
  339. // times as we want to.
  340. void goToFinishLine()
  341. {
  342.   unsigned int sensors[6];
  343.   int i = 0;
  344.  
  345.   // Turn around if the Zumo is facing the wrong direction.
  346.   if(path[0] == 'B')
  347.   {
  348.     turn('B');
  349.     i++;
  350.   }
  351.    
  352.   for(;i
  353.   {
  354.  
  355.     followSegment();
  356.                    
  357.     // Drive through the intersection.
  358.     motors.setSpeeds(SPEED, SPEED);
  359.     delay(OVERSHOOT(LINE_THICKNESS));
  360.                     
  361.     // Make a turn according to the instruction stored in
  362.     // path[i].
  363.     turn(path[i]);
  364.   }
  365.      
  366.   // Follow the last segment up to the finish.
  367.   followSegment();
  368.   
  369.   // The finish line has been reached.
  370.   // Return and wait for another button push to
  371.   // restart the maze.        
  372.   reflectanceSensors.readLine(sensors);
  373.   motors.setSpeeds(0,0);
  374.    
  375.   return;
  376. }
  377.  
  378.  
  379. // simplifyPath analyzes the path[] array and reduces all the
  380. // turns. For example: Right turn + Right turn = (1) Back turn.
  381. void simplifyPath()
  382. {
  383.    
  384.   // only simplify the path if the second-to-last turn was a 'B'
  385.   if(path_length < 3 || path[path_length - 2] != 'B')
  386.   return;
  387.     
  388.   int total_angle = 0;
  389.   int i;
  390.    
  391.   for(i = 1; i <= 3; i++)
  392.   {
  393.     switch(path[path_length - i])
  394.     {
  395.       case 'R':
  396.         total_angle += 90;
  397.         break;
  398.       case 'L':
  399.         total_angle += 270;
  400.         break;
  401.       case 'B':
  402.         total_angle += 180;
  403.         break;
  404.     }
  405.   }
  406.     
  407.   // Get the angle as a number between 0 and 360 degrees.
  408.   total_angle = total_angle % 360;
  409.     
  410.   // Replace all of those turns with a single one.
  411.   switch(total_angle)
  412.   {
  413.     case 0:
  414.       path[path_length - 3] = 'S';
  415.       break;
  416.     case 90:
  417.       path[path_length - 3] = 'R';
  418.       break;
  419.     case 180:
  420.       path[path_length - 3] = 'B';
  421.       break;
  422.     case 270:
  423.       path[path_length - 3] = 'L';
  424.       break;
  425.   }
  426.     
  427.   // The path is now two steps shorter.
  428.   path_length -= 2;
  429. }

Facebook Twitter Google+ LinkedIn Pinterest Addthis