Friday, May 1, 2015

Sciborg Follow the Line

I must admit that this project was the hardest but also the most fun to do. In this exercise, we were asked to use a sensor, which detects the brightness of the material in front of it, to follow a white line on a brown cardboard. 

The first thing we did was to understand how the sensor works.
This code allows us to see the reading from the sensor. Having the red LED on is very helpful in terms of understanding what part of the board the sensor is detecting. We thus did some testing with the sensor and found the reading of each region. We then attempted to write our first code.
Note there is a typo in the second while() statement, it should be while (currentMills > 40500)

Our first attempt actually does not include the second "while()" statement. It makes the car go straight when it reads white, which has a value smaller than 550. It also makes the car turn right when it reads off white. We quickly realized that the code only worked before the Sciborg hit a left turn toward the end of the course. It would turn in a circle, then continue with the course. We soon realized that this became the biggest challenge of the project. 

Our first try to fix the problem was to time Sciborg. We figured that it would hit the left turn after about 20 seconds, so we added the second "while()" in our code after it moves along the course for 20 seconds. The second while() makes the Sciborg turn left when it reads off white. Note that we also added a 20 second delay at the beginning so we would have time to bring the Sciborg to the course and would be able to know when it starts exactly. However, this code requires too much precision with timing and fails very quickly.

Then it was clear that we would need to write something that would allow the Sciborg to turn left and right at any time. This would require out code to include both left turn and right turn at some point. Our next try was to ask the Sciborg to move straight when it's on white, turn right when it's half off white, and turn left when it's completely off white.

We've learned very early that the Sciborg does not actually go straight. This means that when it is asked to go straight. This results in that the Sciborg goes off course very easily when it reaches white. We were hoping that the code would compensate that by asking the Sciborg to turn back. Ideally, the Sciborg would turn right first when it reads partially off white (570 < value < 620). If it were indeed on the left side of the course, it would go back to the white. If it were on the right side of the course, it would read completely off white (value > 620), it would realize that it is not turning toward the correct direction and turn to the left, which brings the Sciborg back to the line. This became very troublesome along the course. Because the real world is not the ideal world, the Sciborg cannot make such sharp turns. Regardless how much we try to straighten up the front wheel or to make it looser, it would get stuck and stagger. This was clearly a dead end, so we decided to try another approach.

(*Note that at this point, we switched the orientation of the car. So a positive power makes the wheel goes forward.)

This new idea was to do a sweeping motion. One of the problems with the previous code was that if the Sciborg detects partially off white, it may spend so little time on that region that the sensor wouldn't have time to read and turn. As a result, we only wanted two ranges in the new code. The idea is that when the Sciborg is more than half off white, it will start to turn to the left for a bit and then to the right. If at any point the Sciborg hits white, it will go straight. In fact, our initial idea was to let the Sciborg do a small sweep followed by a big sweep, which is supposed to help the Sciborg at the turn. I could not figure out how to include two different intervals in this code and thus had to only do small sweeps. We also modified the speed, hoping that with more power, the Sciborg could overcome the friction that made it stumble. 

This, again, failed sadly. First of all, I realized that it was not the most helpful to use intervals. The initial idea was that using intervals would avoid delay, which would prevent the Sciborg from noticing its reaching white. However, since the interval is equal, the Sciborg would turn right and come back to the original position, as opposed to turning to the left and check if there is white on the left. Another problem was to set what startMillis is. We wanted it to be the reading at the moment the sensor detects off-white. This command did not work. Now that I look back, I realized that in the screenshot, "startMillis = millis();" should be in the while (value > 585) condition, as opposed to before. We made the change later and forgot to take the screenshot. Perhaps, changing that would have solved the problem with setting startMillis. However, the turning time was still a problem. In addition, the Sciborg still could not turn very smoothly.

At this point, we were pretty frustrated. It seems like Light_Sensor_Follow2 was the code that makes the most sense. The only probably we had was, well, reality. "Why can't the Sciborg go straight!" We screamed. Then we thought, wait a second, what if we just don't let it go straight then. And voila, we have a new brilliant idea.
The idea was to make the Sciborg turn right when it's more than half on white (value < 590) and turn left when it's more than half off white (value > 590). Note that the Sciborg must be placed on the right of the line for this code to work. Essentially, our Sciborg was following the edge of the line, as opposed to the center of the line. Now, since we do not have a go straight command, we must make sure that there is a velocity vector in the forward direction. The sharpness of the turn is only controlled by the difference between the power of the two wheels, so we just added some positive integer to both wheels. Another problem we encountered was that the Sciborg cannot make the first right turn because it is a relatively sharp turn. We changed the value and the delay in the code, but it did not work until we realized that all we had to do was to let the left turn and right turns of the Sciborg greater that the turn on the line. By switching the angle of the turn, our Sciborg followed the line beautifully. (Granted it does look like it's spasming a little, but it moves forward relatively quickly.)

Our next task was to use proportional control. Here is the code.


The gains of the two wheels are slightly different, because they have different powers (in reality). We calculated the gain with the following equation for m1:
  560*k+b=-40
  620*k+b=220
Note that 590 is the mid point between the value range, so that when the value hits 590, it would change the direction in which the Sciborg moves. We also needed the "b" in the equation, because the domain and range of the function do not start at 0. Similar equation goes for m2 with change on the right side of the equation based on our bang-bang control.

(*Unfortunately, we lost our video, but since we had to move forward with our final project, we did not have time to re-film this.)



3 comments:

  1. I love how detailed your blog post was! It really clearly led me through your thinking process!

    ReplyDelete
  2. I really like that you explained all you different ideas and why they did or did not work.

    ReplyDelete
  3. I really like your line following code. It was really simple and very effective at the same time

    ReplyDelete