Self-balancing two-wheeled robot
Duration of activity: 4 hours.
Participants: Nick Lauritsen, Jens Junge, and Allan Thomassen
The goal of this session was to build and program a two-wheeled robot that is able to balance.
The goal of this session was to build and program a two-wheeled robot that is able to balance.
To reach the goal we started out by building the robot that Brian Bagnall[Bagnall], proposes as a balancing two-wheeled robot, and using the code example as well.
The first problem we encountered was that the code example uses the Motors directly, which cause the JVM to throw an exception - a piece of code that didn't work was: line 20, Motor.B.regulateSpeed(false); or Line 61, Motor.B.setPower(power);
We handled this by using the Car class introduced in the very first lab session, and calling this instead. This didn't work well at all. One of the reasons that the robot didn't balance was, in our opinion, that the center of gravity was shifted a bit forward compared to the center of the robot. Therefore we extended to the robot with an "arm" with weights on. The robot didn't balance at all.
The result is seen in the video as "The First Attempt". Here is a .mov edition, and here is a .m4v edition.
The next thing we thought about was changing the balancing algorithm. This thought came from the fact the robot didn't seem aggressive enough, and therefore tilted in stead of getting back to the starting position - or close to this. The change made to the code was to add extra power to the motors. Here is a snapshot of the code:
"Original", power = 55 + ((power * 45) / 100); // NORMALIZE POWER
"New", power = 65 + ((power * 45) / 100); // NORMALIZE POWER
This attempt, which can be seen as "The Second Attempt" in the video, still didn't balance. It appeared that the robot was more eager to go backwards than forwards. This could e.g. be caused by the fact that the light intensity measurement isn't a linear function, but grows quadratic and therefore the reactions from the robot are different, and hence more aggressive in one direction as the other. To deal with this we experimented with changing the values of power to the motors such that the backward power (in the direction where the light sensor is placed) was eased in the hope that robot wouldn't tilt too much backwards. In the video this can be seen as "The Third Attempt". It is clear that robot is actually balancing for a while, a very short while, and then goes back to the unwanted behavior of overpowering the motors in the backwards direction.
After considering how we handle to problems so far, we realized that we needed to teach the robot how to balance. By this we mean that the robot needs to be aware of the environment, just like humans, in order to balance for a longer period of time. Otherwise the robot will blindly trust the calibration point and try to reach this state (even if it is wrong), or react in inappropriate ways if the surrounding lights changes just a bit, as we saw in lab 1 -- it is of course not possible to make the robot balance if the light settings change fast, e.g. by going from a white surface to a black, the robot simply cannot adapt to such a dramatic change.
The next, and last, phase of building a two-wheeled balancing robot is to make the robot evaluate the changes in light intensity in a way that the robot will automatically adjust the balancing point according to the light setting/measurements, and not quite precise calibration. This is done by counting how many times more the robot goes forwards or backwards compared to the other, e.g. if the goes forward 14 times, then goes backward 1 time, and goes forward again, the balancing point (value of light intensity that equals this point) needs to be shifted forward. This will make the robot aim to be in a state that is more upright than the previous. In theory this will also make the robot capable of adapting to small changes in the surface color or light settings.
The way we programmed this, was to introduce a counter, called "i", that counts how many times Car.forward() or Car.backward() is more than the other. Each time the loop is run, we check to see if the offset needs be edited. The indicator for a change is that the absolute value of "i" is greater than a predefined value, e.g. 100 (meaning that forward [or backward] has been called 100 more times than backward [or forward]). If this is true, we adjust the offset and reset the counter. Below is the complete control loop code.
The result can be see as "The Last Attempt" in the video. Unfortunately it is nothing to brag about, but it is clear that this a better path to a well-balanced robot.
It is questionable if it is possible to get robot to balance with a light sensor setup like the above described. A much better solution will be to use a gyrometer, as this is not affected very much by changes in light or the underlying surface. One thing we experimented with during the session was to the motors tachometers instead of speed, but the readings from the underlying framework was very odd, so we quickly discarded this way of solving the problem.
Ingen kommentarer:
Send en kommentar