Self-Balancing Bot without PID
Self Balancing robot is one awesome form of the subject Control Systems. It relies on the topic "Feedback Controller".It always feels awesome to work on these projects and to calibrate your bot according to your needs. Although calibration my bot took less time than to work with PIDs which can take ages and ages also. Auto-Tune PID is also available to manipulate your bot but still, hard work deserves more reward and peace.
In this project, I haven't used PID control to control the motion of bot. That doesn't mean that my bot is unstable or it will wobble around here and there. It is indeed stable and can recover from sudden jerks and movements too. I am not using the enable pins of L293D IC which is used to control the motors using PWM signal I am using here a soft coded PWM signal and decoding part of Arduino to determine the speed of the motor with the respect to the angle. Also, I coded a virtual encoder that can help my bot to return to its original place from where it started drifting.
This project is a complete do it yourself project. I've only used foam tape, hot glue gun, some rulers, etc. I've converted the micro servo into continuous rotation Servo since it has high torque but also one should note that it has less speed so better use large wheels in order to cover more distance.
I am using here
Two continuous micro servo 9g
GY-521 Accelerometer + Gyroscope
Arduino Pro Mini
0.1 uF Ceramic Capacitors
10 uF Electrolytic Capacitors
Do remember that electrolytic capacitors have polarity and ceramics do not. Ceramic capacitors are being used here to nullify motor noise. Electrolytic capacitors are being used for appropriate filtering of power fed into L293D IC.
Some concepts of GY-521 - Gyroscope never measure the actual angle of the tilt it actually measures the rate of tilting. Similarly, the accelerometer measures the acceleration in a particular direction basically GY-521 has 3 Axis accelerometer it can measure in X Y and Z-Axis. The gyroscope present on GY-521 can measure and X, Y, and Z gyro rate. We can either use Kalman filter or the complementary filter to nullify the peaks and valleys obtained from GY-521. The complementary filter is easy as it is just a one-line code as compared to Kalman filter. However, I got results that were more or less equal for both more filters.
I named my bot 'Po'. Yes, I love Kung Fu Panda.
Po works within 5 regions on each signed axis i.e 5 on the positive angle tilt and 5 on the negative angle tilt.
Within the first region (0, 0.8) and (-0.8, 0) degree, no power is supplied to the motor since the bot is perfectly stable.
Within the second region (0.8, - 2) and (-2, -0.8) degree, servos run @ 30% duty cycle.
Within the third region (2, 7) and (-7, -2) degrees, servos run @ 60% duty cycle.
Within the third region (7, 15) and (-15, -7) degrees, servos run @ 80% duty cycle.
Within the third region (15, 25) and (-25, -15) degrees, servos run @ 100% duty cycle.
Both the servos were attached using a ruler and foam tape like this.
A vertical section is added to the horizontal servo support. This vertical support will carry the circuit board.
Here is the circuit of the connection.
I am uploading my sketches using HC 05 Bluetooth. Better prefer a bluetooth module with a STATE pin present on it. Serial Monitor also works using bluetooth.
Currently I am working on an another way of controlling the bot using an equation of the damped parabola. I will upload its results soon. To increase smoothness we will have to increase the regions and change motor duty cycle. Then we can map the duty cycle to the angle of Po to get an equation. Sounds a tough job but is far better than trial and error of PID setting if you ask me.
Another approach I am thinking about is using state space. I have used servos here because plastic DC motors have a backlash error that will always make an error of 0.5 degrees which will keep your bot vibrating at the single point.
I have used an approach to change the balance angle in this bot as it moves. Whenever forward() is instantiated, a counter named "f" is incremented. Similarly, a counter "b" is incremented whenever backward() instantiated. A separate counter is run inside the main loop which checks "f" and "b" after every 1200 cycle. If "f" is greater than "b" setpoint is decreased by 0.05 degrees. If "b" is greater than "f" then setpoint is increased by 0.05 degrees. Then it will reset the main loop counter along with "f" and "b" too. Th basic problem of self-balancing bots without encoder is that they don't return back from where it started. Although Po won't return to its exact point of location, it will return to its nearest point as long as both motors rotate at the same rate which rarely happens with L293D IC.
A point of note - Better use L298 or L293 IC as both have the greater amount of current supply than L293D IC. Also, use a 0.1nF ceramic capacitor across the motor terminals in order to nullify the reverse current spikes. Whenever your motor power stops, it will still rotate due to inertia and will act as a generator of better say back EMF. This sudden drop is the spike and will keep resetting your Arduino, Bluetooth or even Gyro. In my case, it always resets the bluetooth module.
Here is the code for Po.