Milestone 1
Autonomous Control Test (Line Sensing)
After assembling the robot, we worked on code for line sensing, allowing the robot to maintain a straight path following the direction of a white line. An important first step was to calibrate the motors to move at the same speed by adjusting the setting of the potentiometers. This enabled the robot to move in a straight line when no turn or drift-recovery command was executed. Our line sensing algorithm implemented the readings from the three line sensors mounted on the robot, using the differences between the readings and a set of thresholds as part of conditional statements to decide an action.
We decided that our threshold value for the difference between the white and dark surfaces would be 200 after trying various values. We saved the current time using millis(). We checked if the right line sensor was reading a value more than 200 lower than the left line sensor. This would indicate that the right line sensor is now reading white and the robot is drifting left, so we slowed the right motor for 50 ms to move to the right. After the 50 ms, the conditions were checked again. We followed the same procedure for a drift in the other direction. If no drifting is detected, the robot continues forward at full speed.
Initially, we ran into errors where the robot was either overcorrecting in a jittery manner or simply swaying off the path of the white line. After some time was spent debugging, the robot was able to successfully follow the white line across the whole grid with little error correction.
Below is a sample of our code that enables the robot to follow the line, correcting its path when it sways either direction.
now = millis(); if((right_line < (left_line - 200)) || (right_line < (mid_line - 200))){ // drifted LEFT -> slow the RIGHT motor left_drift_flag = true; servo_R.write(SLOWER_RIGHT); while(millis() < (now + 50)); } else if((left_line < (right_line - 200)) || (right_line < (mid_line - 200))){ // drifted RIGHT -> slow the LEFT motor right_drift_flag = true; servo_L .write(SLOWER_LEFT); while(millis() < (now + 50)); } else { // no adjustment needed servo_L.write(FORWARD_LEFT); servo_R.write(FORWARD_RIGHT); left_drift_flag = false; right_drift_flag = false; }
Autonomous Control Test (Figure 8)
The next step in developing our robot was to make it move along the grid in a figure eight pattern. We implemented two turn functions that allow the robot to rotate in either direction in order to start following the line perpendicular to its original path. Either of these functions were triggered when an intersection was reached. These functions in combination with our line sensing algorithm allowed us to develop code for traveling in a figure eight.
The code shown below is used to set an intersection flag to be set in order to make a turn. This flag determines if a turn should be made before it is decided what kind of turn should be made. The values of 500 and 300 are thresholds we determined experimentally were best for detecting an intersection on the grid.
if(abs(left_line - right_line) < 500 && left_line < 300 && right_line < 300) { intersection_flag = true; } else { intersection_flag = false; }
The next sample of code is the logic used to make the robot traverse the grid in a figure eight pattern. We used a turn counter to check how many turns have been made, performing the left turns sequentially before performing the right turns. The turns are made by stopping one servo completely while powering the other servo. For turning left, the left wheel servo would be stopped, and for turning right, the right wheel servo would be stopped.
now = millis(); if(intersection_flag == true && turn_count < 4) { // left turns servo_L.write(STOPPED); while(millis() < now + 400 || right_line > 200) { left_line = analogRead(LINE_L_PIN); right_line = analogRead(LINE_R_PIN); } servo_L.write(FORWARD_LEFT); turn_count++; } else if(intersection_flag == true && turn_count > 3 && turn_count < 8) { // right turns servo_R.write(STOPPED); while(millis() < now + 400 || left_line > 200) { left_line = analogRead(LINE_L_PIN); right_line = analogRead(LINE_R_PIN); } servo_R.write(FORWARD_RIGHT); turn_count++; }
**NOTE**: The robot spinning at the end of the video was done on purpose as a celebration of the completion of the figure eight. It is not an error in our code.