<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gen2 &#8211; chillibasket</title>
	<atom:link href="https://wired.chillibasket.com/tag/gen2/feed/" rel="self" type="application/rss+xml" />
	<link>https://wired.chillibasket.com</link>
	<description>A Robotics and Technology Blog</description>
	<lastBuildDate>Thu, 03 Mar 2022 20:57:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wired.chillibasket.com/wp-content/uploads/2015/03/4e9d6895b4e9e70456edbdb2b46312aa1-550c5afcv1_site_icon-32x32.png</url>
	<title>Gen2 &#8211; chillibasket</title>
	<link>https://wired.chillibasket.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>The PID Controller</title>
		<link>https://wired.chillibasket.com/2015/03/pid-controller/</link>
					<comments>https://wired.chillibasket.com/2015/03/pid-controller/#comments</comments>
		
		<dc:creator><![CDATA[Simon Bluett]]></dc:creator>
		<pubDate>Mon, 16 Mar 2015 13:51:50 +0000</pubDate>
				<category><![CDATA[Self-balancing]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Galileo]]></category>
		<category><![CDATA[Gen2]]></category>
		<category><![CDATA[Gyroscope]]></category>
		<category><![CDATA[MPU6050]]></category>
		<category><![CDATA[Stabilisation]]></category>
		<guid isPermaLink="false">http://wired.chillibasket.com/?p=254</guid>

					<description><![CDATA[The most important element of any robot is the controller. The control algorithm determines how the robot should react to different sensor inputs, allowing it to intelligently adapt to and interact with its environment. Especially for a self-balancing robot, the control program is vital as it interprets the motion sensor data and decides how much [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1024" height="384" src="https://wired.chillibasket.com/wp-content/uploads/2015/03/Self-balancing-Part-4-1024x384.jpg" alt="" class="wp-image-267" srcset="https://wired.chillibasket.com/wp-content/uploads/2015/03/Self-balancing-Part-4-1024x384.jpg 1024w, https://wired.chillibasket.com/wp-content/uploads/2015/03/Self-balancing-Part-4-300x113.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2015/03/Self-balancing-Part-4.jpg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">The most important element of any robot is the controller. The control algorithm determines how the robot should react to different sensor inputs, allowing it to intelligently adapt to and interact with its environment. Especially for a self-balancing robot, the control program is vital as it interprets the motion sensor data and decides how much the motors need to be moved in order for the robot to remain stable and upright. The most common controller used for stabilisation systems is the PID controller. So let&#8217;s look at how it works&#8230;</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">The PID Controller</h2>



<p class="wp-block-paragraph">PID stands for <strong>P</strong>roportional, <strong>I</strong>ntegral and <strong>D</strong>erivative, referring to the mathematical equations used to calculate the output of the controller. This is perhaps the most common type of controller used in industry, as it is able to control relatively complex systems even though the calculations are actually quite straightforward (making it easy to program and fast to compute). Mathematically, the PID controller can be described by the following formula:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>u(t)=K_pe(t) + K_i\int_{0}^{t}e(t)dt +K_d\frac{de(t)}{dt}</pre></div>



<p class="wp-block-paragraph">In this formula, the output of the controller <em>u(t)</em> is determined by the sum of three different elements, each dependent on the error <em>e(t)</em>. The error simply is the difference between the target value and the current value (measured by the sensor). Now let&#8217;s quickly look at what each of the terms in the equation is doing for our robot&#8230;</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>K_pe(t)</pre></div>



<p class="wp-block-paragraph">This is the proportional component, which takes the current error value and multiplies it by a constant number (<em>Kp</em>). For our self-balancing robot, this simply takes in the current angle of the robot and makes the motors move in the same direction as the robot is falling. The further the robot falls off target, the faster the motors move. If the P-component is used on its own, the robot might stabilise for a while, but the system will tend to overshoot, oscillate and ultimately fall over.</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>K_i\int_0^te(t)dt</pre></div>



<p class="wp-block-paragraph">The integral component is used to accumulate any errors over time, and multiplies this accumulated value by a constant number (<em>Ki</em>). For example if the robot tends to fall over to one side, it knows that it needs to move in the opposite direction in order to keep on target and to prevent&nbsp;drifting left or right.</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>K_d\frac{de(t)}{dt}</pre></div>



<p class="wp-block-paragraph">Finally, the derivative component is responsible for dampening any oscillations and ensures that the robot does not overshoot the target value. Each time the controller is called, this term calculates the change in the error value and multiplies it by a constant number (<em>Kd</em>). Often this is simplified to calculate only the change in the current sensor value, rather than the change in error. If the target position remains constant, this gives the same result. This simplification helps to prevent sudden jumps in the output value which happen when the target position it changed.</p>



<p class="wp-block-paragraph">Summing all three of these terms together then gives us an output value which we can send to the motor of the self-balancing robot. However, before the controller can successfully balance the robot, the three constants (<em>Kp</em>), (<em>Ki</em>) and (<em>Kd</em>) need to be tuned to suit our specific application. By increasing or decreasing the values of these constants, we control how much each of the three components of the controller contributes to the output of the system. </p>



<p class="wp-block-paragraph">The formula I used above is called the &#8220;Independent&#8221; PID equation. If you read up on the PID controller online, you may also see the formula for the algorithm expressed in a different format (known as the &#8220;Dependent&#8221; PID equation):</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true"><pre>u(t) = K_ce(t)+\frac{K_c}{T_i}\int_0^te(t)dt + K_cT_d\frac{de(t)}{dt}</pre></div>



<p class="wp-block-paragraph">The term (<em>Kc</em>) is known as controller gain, (<em>Ti</em>) the integral time and (<em>Td</em>) the derivative time. This format can be useful when using some automated tuning techniques, however the final result is the same.</p>



<figure class="wp-block-image"><img decoding="async" width="900" height="432" src="https://wired.chillibasket.com/wp-content/uploads/2015/03/pid-diagram-e1443473603418.jpg" alt="" class="wp-image-312"/><figcaption>Diagram of PID controller being used on a self-balancing robot.</figcaption></figure>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Implementing the Controller</h2>



<p class="wp-block-paragraph">Now that we know the basic theory, we can start to write this in code. The basic layout of the function is shown below. The controller can be used by calling the &#8220;pid&#8221; function at regular intervals, providing the target position and the current position (as recorded by the sensor) as parameters of the function. The function then outputs the calculated result of the controller. Tuning of the controller can be done by changing the values of the (<em>Kp</em>), (<em>Ki</em>) and (<em>Kd</em>) variables at the top of the code.</p>



<pre class="wp-block-code line-numbers language-cpp"><code class="" data-line="">// Declare variables
float Kp = 7;          // (P)roportional Tuning Parameter
float Ki = 6;          // (I)ntegral Tuning Parameter        
float Kd = 3;          // (D)erivative Tuning Parameter       
float iTerm = 0;       // Used to accumulate error (integral)
float lastTime = 0;    // Records the time the function was last called
float maxPID = 255;    // The maximum value that can be output
float oldValue = 0;    // The last sensor value

/**
 * PID Controller
 * @param  (target)  The target position/value we are aiming for
 * @param  (current) The current value, as recorded by the sensor
 * @return The output of the controller
 */
float pid(float target, float current) {
	// Calculate the time since function was last called
	float thisTime = millis();
	float dT = thisTime - lastTime;
	lastTime = thisTime;

	// Calculate error between target and current values
	float error = target - current;

	// Calculate the integral term
	iTerm += error * dT; 

	// Calculate the derivative term (using the simplification)
	float dTerm = (oldValue - current) / dT;

	// Set old variable to equal new ones
	oldValue = current;

	// Multiply each term by its constant, and add it all up
	float result = (error * Kp) + (iTerm * Ki) + (dTerm * Kd);

	// Limit PID value to maximum values
	if (result &gt; maxPID) result = maxPID;
	else if (result &lt; -maxPID) result = -maxPID;

	return result;
}</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="underline-heading wp-block-heading">What does this program do?</h4>



<p class="wp-block-paragraph">First of all, the algorithm calculates the time since the last loop was called, using the &#8220;millis()&#8221; function. The error is then calculated; this is the difference between the current value (the angle recorded by the sensor), and the target value (the angle of  0 degrees we are aiming to reach).</p>



<p class="wp-block-paragraph">The PID values are then calculated and summed up to give an output for the motors. The output is then constrained to ±255 as this is the maximum PWM value that can be output to the motors of the self-balancing robot.</p>



<p class="wp-block-paragraph">Although this program is almost complete, I found that my robot only worked well once I included a timing function. This is a system that ensures the PID controller function is called at regular intervals. In my self-balancing robot, I set the loop time to be 10ms (meaning the function is run 100 times per second). Here is the timer code and a sample loop function:</p>



<pre class="wp-block-code line-numbers language-cpp"><code class="" data-line="">// Any variables for the PID controller go here!
float targetValue = 0;

// Variables for Time Keeper function:
#define LOOP_TIME 10          // Time in ms (10ms = 100Hz)
unsigned long timerValue = 0;

/******** SETUP ************/
void setup() {
	// Put all of your setup code here
	timerValue = millis();
}

/******* MAIN LOOP *********/
void loop() {
	// Only run the controller once the time interval has passed
	if (millis() - timerValue &gt; LOOP_TIME) {
		timerValue = millis();

		// Replace getAngle() with your sensor data reading
		float currentValue = getAngle();

		// Run the PID controller
		float motorOutput = pid(targetValue, currentValue);

		// Replace moveMotors() with your desired output
		moveMotors(motorOutput);
	}
}

/****** PID CONTROLLER *****/
float pid(float target, float current) {          

	// PID code from above goes in here!
	return result;
}</code></pre>



<p class="wp-block-paragraph">Unfortunately this is not the end of the story! Although the PID controller code is complete, suitable&nbsp;PID constants still need to be found to tune the controller for your specific robot. These constants depend on things such as weight, motor speed and the shape of the robot, and therefore they can vary significantly from robot to robot. Here is a quick explanation of how you should go about calibrating your PID values:</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h4 class="underline-heading wp-block-heading">Calibrating your PID Controller</h4>



<ol class="wp-block-list"><li>Create some way in which you can change the PID constant of your robot while it is running.&nbsp;One option is to&nbsp;use a potentiometer or some other analogue input to be able to increase or decrease the PID constant. I personally used the USB connection and the serial monitor to send new PID values. This is important as you can then see straight away how well the new PID values are working, and you won&#8217;t have to re-upload the code hundreds of times!</li><li><strong>Set all PID constants to zero.</strong> This is as good a place to start as any&#8230;</li><li><strong>Slowly increase the P-constant value.</strong> While you are doing this, hold the robot to make sure it doesn&#8217;t fall over and smash into a million pieces! You should increase the P-constant until the robot responds quickly to any tilting, and then <em>just</em> makes the robot overshoot in the other direction.</li><li><strong>Now increase the I-constant.</strong> This component is a bit tricky to get right. You should keep this relatively low, as it can accumulate errors very quickly. In theory, the robot should be able to stabilise with only the P and I constants set, but will oscillate a lot and ultimately fall over.</li><li><strong>Raise&nbsp;the D-constant. A lot.&nbsp;</strong>The derivative components works against any motion, so it helps to dampen any oscillations and reduce overshooting. I found that this constant has to be set significantly higher than the other two (x10 to x100 more) in order to have any effect. All the same, don&#8217;t set it too high, as it will reduce the robot&#8217;s ability to react to external forces (aka. being pushed around).</li><li><strong>Spend many fruitless hours slightly modifying the PID values.</strong> This is probably the longest part of the procedure, as there isn&#8217;t much of a method to it. You just have to increase and decrease the values until you reach that perfect sweet-spot for your robot!</li></ol>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<hr>



<p class="wp-block-paragraph">Please leave a comment below if you have any questions or suggestions. </p>



<div class="wp-block-buttons aligncenter is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-outline is-style-outline--1"><a class="wp-block-button__link no-border-radius" href="https://wired.chillibasket.com/2015/10/putting-it-all-together/"><em>Part 5:</em> Putting it all together</a></div>
</div>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-cyan-bluish-gray-color has-text-color wp-block-paragraph"><em><strong>Updated: </strong>23rd May 2019 &#8211; Reformatted post and improved the code snippets. </em></p>



<p class="has-cyan-bluish-gray-color has-text-color wp-block-paragraph"><em><strong>Updated: </strong>1st June 2020 &#8211; Add PID equations and improved the descriptions.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://wired.chillibasket.com/2015/03/pid-controller/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>Calibrating &#038; Optimising the MPU6050</title>
		<link>https://wired.chillibasket.com/2015/01/calibrating-mpu6050/</link>
					<comments>https://wired.chillibasket.com/2015/01/calibrating-mpu6050/#comments</comments>
		
		<dc:creator><![CDATA[Simon Bluett]]></dc:creator>
		<pubDate>Wed, 21 Jan 2015 17:15:52 +0000</pubDate>
				<category><![CDATA[Self-balancing]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Galileo]]></category>
		<category><![CDATA[Gen2]]></category>
		<category><![CDATA[Gyroscope]]></category>
		<category><![CDATA[MPU6050]]></category>
		<category><![CDATA[Stabilisation]]></category>
		<guid isPermaLink="false">http://wired.chillibasket.com/?p=190</guid>

					<description><![CDATA[In this part of the tutorial I will cover how to get the most performance out of&#160;the MPU-6050 Accelerometer and Gyroscope module, using the &#8220;Motion Apps&#8221; library. This library is really amazing as the author reverse engineered how to use the Digital Motion Processor (DMP) integrated within the MPU-6050. This allows all the complicated sensor [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="1024" height="384" src="https://wired.chillibasket.com/wp-content/uploads/2015/01/Self-balancing-Part-3-1024x384.jpg" alt="" class="wp-image-240" srcset="https://wired.chillibasket.com/wp-content/uploads/2015/01/Self-balancing-Part-3-1024x384.jpg 1024w, https://wired.chillibasket.com/wp-content/uploads/2015/01/Self-balancing-Part-3-300x113.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2015/01/Self-balancing-Part-3.jpg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<p class="wp-block-paragraph">In this part of the tutorial I will cover how to get the most performance out of&nbsp;the MPU-6050 Accelerometer and Gyroscope module, using the &#8220;Motion Apps&#8221; library. This library is really amazing as the author reverse engineered how to use the Digital Motion Processor (DMP) integrated within the MPU-6050. This allows all the complicated sensor processing and fusion to be done using the DMP instead of by the micro-controller! I have found that reading the sensor through the Motion Apps Library is faster than doing the calculations manually, and the readings tend to be significantly&nbsp;more accurate.</p>



<div style="height:80px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">1. Analysing the Output</h2>



<p class="wp-block-paragraph">Here is the&nbsp;code that I used to get the yaw, pitch and roll sensor data. It is based on the &#8220;Teapot&#8221; example sketch which comes with the MPU-6050 Motion Apps library. To use this sketch, you will need to have the &#8220;<a href="https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050">MPU6050</a>&#8221; and the &#8220;<a href="https://github.com/jrowberg/i2cdevlib">I2Cdev</a>&#8221; libraries installed.</p>



<pre class="wp-block-code code-600 line-numbers language-cpp"><code class="" data-line="">// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class 
// using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg &lt;jeff@rowberg.net&gt;

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include &quot;I2Cdev.h&quot;

#include &quot;MPU6050_6Axis_MotionApps20.h&quot;

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include &quot;Wire.h&quot;
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // &lt;-- use for AD0 high

/* =========================================================================
   NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
   depends on the MPU-6050&#039;s INT pin being connected to the Arduino&#039;s
   external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
   digital I/O pin 2.

   For the Galileo Gen1/2 Boards, there is no INT pin support. Therefore
   the INT pin does not need to be connected, but you should work on getting
   the timing of the program right, so that there is no buffer overflow.
 * ========================================================================= */

/* =========================================================================
   NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
   when using Serial.write(buf, len). The Teapot output uses this method.
   The solution requires a modification to the Arduino USBAPI.h file, which
   is fortunately simple, but annoying. This will be fixed in the next IDE
   release. For more info, see these links:

   http:&#047;&#047;arduino.cc/forum/index.php/topic,109987.0.html
   http://code.google.com/p/arduino/issues/detail?id=958
 * ========================================================================= */


#define OUTPUT_READABLE_YAWPITCHROLL

// Unccomment if you are using an Arduino-Style Board
// #define ARDUINO_BOARD

// Uncomment if you are using a Galileo Gen1 / 2 Board
#define GALILEO_BOARD

#define LED_PIN 13      // (Galileo/Arduino is 13)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer&#091;64]; // FIFO storage buffer

// orientation/motion vars
VectorFloat gravity;    // &#091;x, y, z]            gravity vector
Quaternion q;           // &#091;w, x, y, z]         quaternion container
float euler&#091;3];         // &#091;psi, theta, phi]    Euler angle container
float ypr&#091;3];           // &#091;yaw, pitch, roll]   yaw/pitch/roll container and gravity vector



// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

// This function is not required when using the Galileo 
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}



// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
    // join I2C bus (I2Cdev library doesn&#039;t do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    Serial.begin(115200);
    while (!Serial);

    // initialize device
    Serial.println(F(&quot;Initializing I2C devices...&quot;));
    mpu.initialize();

    // verify connection
    Serial.println(F(&quot;Testing device connections...&quot;));
    Serial.println(F(&quot;MPU6050 connection &quot;));
    Serial.print(mpu.testConnection() ? F(&quot;successful&quot;) : F(&quot;failed&quot;));

    // wait for ready
    Serial.println(F(&quot;\nSend any character to begin DMP programming and demo: &quot;));
    while (Serial.available() &amp;&amp; Serial.read()); // empty buffer
    while (!Serial.available());                 // wait for data
    while (Serial.available() &amp;&amp; Serial.read()); // empty buffer again

    // load and configure the DMP
    Serial.println(F(&quot;Initializing DMP...&quot;));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        // turn on the DMP, now that it&#039;s ready
        Serial.println(F(&quot;Enabling DMP...&quot;));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        Serial.println(F(&quot;Enabling interrupt detection (Arduino external interrupt 0)...&quot;));
        attachInterrupt(0, dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it&#039;s okay to use it
        Serial.println(F(&quot;DMP ready! Waiting for first interrupt...&quot;));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        // ERROR!
        // 1 = initial memory load failed
        // 2 = DMP configuration updates failed
        // (if it&#039;s going to break, usually the code will be 1)
        Serial.print(F(&quot;DMP Initialization failed (code &quot;));
        Serial.print(devStatus);
        Serial.println(F(&quot;)&quot;));
    }

    // configure LED for output
    pinMode(LED_PIN, OUTPUT);
}



// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
    // if programming failed, don&#039;t try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available

    #ifdef ARDUINO_BOARD
        while (!mpuInterrupt &amp;&amp; fifoCount &lt; packetSize) {
        }
    #endif

    #ifdef GALILEO_BOARD
        delay(10);
    #endif

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus &amp; 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F(&quot;FIFO overflow!&quot;));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus &amp; 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount &lt; packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is &gt; 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;


        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&amp;q, fifoBuffer);
            mpu.dmpGetGravity(&amp;gravity, &amp;q);
            mpu.dmpGetYawPitchRoll(ypr, &amp;q, &amp;gravity);
            Serial.print(&quot;ypr\t&quot;);
            Serial.print(ypr&#091;0] * 180/M_PI);
            Serial.print(&quot;\t&quot;);
            Serial.print(ypr&#091;1] * 180/M_PI);
            Serial.print(&quot;\t&quot;);
            Serial.println(ypr&#091;2] * 180/M_PI);
        #endif

        // blink LED to indicate activity
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
    }
}</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">After completing several trials, I noticed that the accelerometer-gyroscope module and the Motion Apps library seem to have some type of auto-calibration feature, which requires a couple of seconds to complete. Here is a graph of the orientation output I got directly after initiating the sensor:</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><a href="https://wired.chillibasket.com/wp-content/uploads/2014/10/Calibrating-MPU6050.png"><img loading="lazy" decoding="async" src="http://wired.chillibasket.com/wp-content/uploads/2014/10/Calibrating-MPU6050.png" alt="Output from the MPU-6050, using Motion Apps" class="wp-image-191" width="453" height="380" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/10/Calibrating-MPU6050.png 906w, https://wired.chillibasket.com/wp-content/uploads/2014/10/Calibrating-MPU6050-300x251.png 300w" sizes="auto, (max-width: 453px) 100vw, 453px" /></a><figcaption>Output from the MPU-6050, using Motion Apps</figcaption></figure></div>



<p class="wp-block-paragraph">There is a large variation in the values as the sensor starts up, especially in the yaw data. This sensor drift stops after around 13 seconds, probably due to the completion of an integrated auto-calibration process. I repeated this test a number of times and it seems that the sensor can on some occasions take up to 40 seconds to complete its calibration. Therefore we should take this delay into account in our program&#8230; If we want to use the yaw data, the robot should wait for around 40 seconds before beginning to use the sensor and starting the main&nbsp;program. If only the pitch and roll data is used in a non-critical control system (no quadcopters!), we probably could get away with not waiting for the sensor to settle. </p>



<div style="height:80px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">2. Calibrating the Sensor</h2>



<p class="wp-block-paragraph">Just like most sensors, the MPU-6050 needs to be calibrated before it is used for the first time. What we want to do is remove the zero-error; this refers to when the sensor records a small angle even though it is totally level. This error can be removed by applying an offset to the raw accelerometer and gyroscope sensor readings. The offset needs to be adjusted until the gyroscope readings are zero (no rotation) and the accelerometer records the acceleration due to gravity pointing directly downwards. Fortunately I found a program that can calibrate the MPU-6050 for us! The original calibration sketch can be found on the <a rel="noreferrer noopener" href="https://www.i2cdevlib.com/forums/topic/96-arduino-sketch-to-automatically-calculate-mpu6050-offsets/" target="_blank">I2Cdev library forum</a>. To use&nbsp;the program, first make sure that the MPU-6050 is correctly wired up to the Arduino (or equivalent). Then upload the sketch and open up the serial monitor in the Arduino IDE, setting the baud rate to 115200. To start calibration, place the accel-gyro module in a flat and level position and send any character in the serial monitor. The program will make an average of a few hundred readings and display the offsets required to remove zero error.</p>



<pre class="wp-block-code code-600 line-numbers language-cpp"><code class="" data-line="">// Arduino sketch that returns calibration offsets for MPU6050 
//   Version 1.1  (31th January 2014)
// Done by Luis Ródenas &lt;luisrodenaslorda@gmail.com&gt;
// Based on the I2Cdev library and previous work by Jeff Rowberg &lt;jeff@rowberg.net&gt;
// Updates (of the library) should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib

// These offsets were meant to calibrate MPU6050&#039;s internal DMP, but can be also useful for reading sensors. 
// The effect of temperature has not been taken into account so I can&#039;t promise that it will work if you 
// calibrate indoors and then use it outdoors. Best is to calibrate and use at the same room temperature.

/* ==========  LICENSE  ==================================
 I2Cdev device library code is placed under the MIT license
 Copyright (c) 2011 Jeff Rowberg
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the &quot;Software&quot;), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 =========================================================
 */

// I2Cdev and MPU6050 must be installed as libraries
#include &quot;I2Cdev.h&quot;
#include &quot;MPU6050.h&quot;
#include &quot;Wire.h&quot;

///////////////////////////////////   CONFIGURATION   /////////////////////////////
//Change this 3 variables if you want to fine tune the skecth to your needs.
int buffersize=1000;     //Amount of readings used to average, make it higher to get more precision but sketch will be slower  (default:1000)
int acel_deadzone=8;     //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge  (default:8)
int giro_deadzone=1;     //Giro error allowed, make it lower to get more precision, but sketch may not converge  (default:1)

// default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
//MPU6050 accelgyro;
MPU6050 accelgyro(0x68); // &lt;-- use for AD0 high

int16_t ax, ay, az,gx, gy, gz;

int mean_ax,mean_ay,mean_az,mean_gx,mean_gy,mean_gz,state=0;
int ax_offset,ay_offset,az_offset,gx_offset,gy_offset,gz_offset;

///////////////////////////////////   SETUP   ////////////////////////////////////
void setup() {
  // join I2C bus (I2Cdev library doesn&#039;t do this automatically)
  Wire.begin();

  // initialize serial communication
  Serial.begin(115200);

  // initialize device
  accelgyro.initialize();

  // wait for ready
  while (Serial.available() &amp;&amp; Serial.read()); // empty buffer
  while (!Serial.available()){
    Serial.println(F(&quot;Send any character to start sketch.\n&quot;));
    delay(1500);
  }                
  while (Serial.available() &amp;&amp; Serial.read()); // empty buffer again

  // start message
  Serial.println(&quot;\nMPU6050 Calibration Sketch&quot;);
  delay(2000);
  Serial.println(&quot;\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon&#039;t touch it until you see a finish message.\n&quot;);
  delay(3000);
  // verify connection
  Serial.println(accelgyro.testConnection() ? &quot;MPU6050 connection successful&quot; : &quot;MPU6050 connection failed&quot;);
  delay(1000);
  // reset offsets
  accelgyro.setXAccelOffset(0);
  accelgyro.setYAccelOffset(0);
  accelgyro.setZAccelOffset(0);
  accelgyro.setXGyroOffset(0);
  accelgyro.setYGyroOffset(0);
  accelgyro.setZGyroOffset(0);
}

///////////////////////////////////   LOOP   ////////////////////////////////////
void loop() {
  if (state==0){
    Serial.println(&quot;\nReading sensors for first time...&quot;);
    meansensors();
    state++;
    delay(1000);
  }

  if (state==1) {
    Serial.println(&quot;\nCalculating offsets...&quot;);
    calibration();
    state++;
    delay(1000);
  }

  if (state==2) {
    meansensors();
    Serial.println(&quot;\nFINISHED!&quot;);
    Serial.print(&quot;\nSensor readings with offsets:\t&quot;);
    Serial.print(mean_ax); 
    Serial.print(&quot;\t&quot;);
    Serial.print(mean_ay); 
    Serial.print(&quot;\t&quot;);
    Serial.print(mean_az); 
    Serial.print(&quot;\t&quot;);
    Serial.print(mean_gx); 
    Serial.print(&quot;\t&quot;);
    Serial.print(mean_gy); 
    Serial.print(&quot;\t&quot;);
    Serial.println(mean_gz);
    Serial.print(&quot;Your offsets:\t&quot;);
    Serial.print(ax_offset); 
    Serial.print(&quot;\t&quot;);
    Serial.print(ay_offset); 
    Serial.print(&quot;\t&quot;);
    Serial.print(az_offset); 
    Serial.print(&quot;\t&quot;);
    Serial.print(gx_offset); 
    Serial.print(&quot;\t&quot;);
    Serial.print(gy_offset); 
    Serial.print(&quot;\t&quot;);
    Serial.println(gz_offset); 
    Serial.println(&quot;\nData is printed as: acelX acelY acelZ giroX giroY giroZ&quot;);
    Serial.println(&quot;Check that your sensor readings are close to 0 0 16384 0 0 0&quot;);
    Serial.println(&quot;If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)&quot;);
    while (1);
  }
}

///////////////////////////////////   FUNCTIONS   ////////////////////////////////////
void meansensors(){
  long i=0,buff_ax=0,buff_ay=0,buff_az=0,buff_gx=0,buff_gy=0,buff_gz=0;

  while (i&lt;(buffersize+101)){
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&amp;ax, &amp;ay, &amp;az, &amp;gx, &amp;gy, &amp;gz);
    
    if (i&gt;100 &amp;&amp; i&lt;=(buffersize+100)){ //First 100 measures are discarded
      buff_ax=buff_ax+ax;
      buff_ay=buff_ay+ay;
      buff_az=buff_az+az;
      buff_gx=buff_gx+gx;
      buff_gy=buff_gy+gy;
      buff_gz=buff_gz+gz;
    }
    if (i==(buffersize+100)){
      mean_ax=buff_ax/buffersize;
      mean_ay=buff_ay/buffersize;
      mean_az=buff_az/buffersize;
      mean_gx=buff_gx/buffersize;
      mean_gy=buff_gy/buffersize;
      mean_gz=buff_gz/buffersize;
    }
    i++;
    delay(2); //Needed so we don&#039;t get repeated measures
  }
}

void calibration(){
  ax_offset=-mean_ax/8;
  ay_offset=-mean_ay/8;
  az_offset=(16384-mean_az)/8;

  gx_offset=-mean_gx/4;
  gy_offset=-mean_gy/4;
  gz_offset=-mean_gz/4;
  while (1){
    int ready=0;
    accelgyro.setXAccelOffset(ax_offset);
    accelgyro.setYAccelOffset(ay_offset);
    accelgyro.setZAccelOffset(az_offset);

    accelgyro.setXGyroOffset(gx_offset);
    accelgyro.setYGyroOffset(gy_offset);
    accelgyro.setZGyroOffset(gz_offset);

    meansensors();
    Serial.println(&quot;...&quot;);

    if (abs(mean_ax)&lt;=acel_deadzone) ready++;
    else ax_offset=ax_offset-mean_ax/acel_deadzone;

    if (abs(mean_ay)&lt;=acel_deadzone) ready++;
    else ay_offset=ay_offset-mean_ay/acel_deadzone;

    if (abs(16384-mean_az)&lt;=acel_deadzone) ready++;
    else az_offset=az_offset+(16384-mean_az)/acel_deadzone;

    if (abs(mean_gx)&lt;=giro_deadzone) ready++;
    else gx_offset=gx_offset-mean_gx/(giro_deadzone+1);

    if (abs(mean_gy)&lt;=giro_deadzone) ready++;
    else gy_offset=gy_offset-mean_gy/(giro_deadzone+1);

    if (abs(mean_gz)&lt;=giro_deadzone) ready++;
    else gz_offset=gz_offset-mean_gz/(giro_deadzone+1);

    if (ready==6) break;
  }
}</code></pre>



<p class="wp-block-paragraph">If all goes well, the sketch should output the accelerometer and gyroscope offsets through the serial monitor. It may take up to a minute for the sketch to converge on the correct offsets. If the sensor is accidentality moved during calibration, it could take even longer to complete.</p>



<p class="wp-block-paragraph">To use the calibration values, all you have to do is plug them into the initialisation code at the start of any sketch in which you use the MPU-6050! Please note that the required offsets vary significantly from sensor to sensor, so you have to repeat the calibration program above for each MPU-6050 sensor you are using. That concludes the basic calibration of the MPU-6050; the sensor should now be more than accurate enough for most applications, such as self-balancing robots and quad-copters.</p>



<div class="wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-fe48e5de wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-outline is-style-outline--2"><a class="wp-block-button__link" href="https://wired.chillibasket.com/2015/03/pid-controller/"><em>Part 4:</em> The PID Controller</a></div>
</div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph"><strong> <span class="has-inline-color has-cyan-bluish-gray-color"><em>Updated:</em></span></strong><span class="has-inline-color has-cyan-bluish-gray-color"><em> 23rd May 2019 – Reformatted post</em></span></p>



<p class="wp-block-paragraph"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-cyan-bluish-gray-color"><em><strong>Updated</strong>: 26th May 2020 <em>–</em> Improved the descriptions and reformatted post</em></mark></p>
]]></content:encoded>
					
					<wfw:commentRss>https://wired.chillibasket.com/2015/01/calibrating-mpu6050/feed/</wfw:commentRss>
			<slash:comments>62</slash:comments>
		
		
			</item>
		<item>
		<title>Batteries &#038; Micro-Controllers</title>
		<link>https://wired.chillibasket.com/2014/12/micro-controller-batteries/</link>
					<comments>https://wired.chillibasket.com/2014/12/micro-controller-batteries/#comments</comments>
		
		<dc:creator><![CDATA[Simon Bluett]]></dc:creator>
		<pubDate>Tue, 16 Dec 2014 21:12:28 +0000</pubDate>
				<category><![CDATA[Galileo]]></category>
		<category><![CDATA[Techniques]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Battery]]></category>
		<category><![CDATA[Gen2]]></category>
		<category><![CDATA[Measurement]]></category>
		<category><![CDATA[Power]]></category>
		<category><![CDATA[Voltage]]></category>
		<guid isPermaLink="false">http://wired.chillibasket.com/?p=203</guid>

					<description><![CDATA[How to connect a battery to the Arduino When working with sensitive circuits and micro-controllers, batteries can be a tricky thing to get right. It is not as simple as just buying a battery with the same voltage as what the micro-controller requires; the issue&#160;with batteries is that their voltage does&#160;not remain constant. The voltage [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter"><a href="https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-1.jpg"><img loading="lazy" decoding="async" width="1200" height="671" src="https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-1.jpg" alt="" class="wp-image-214" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-1.jpg 1200w, https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-1-300x167.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-1-1024x572.jpg 1024w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></a><figcaption>A lithium quad-copter battery, powering a Galileo Gen2 Board</figcaption></figure></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">How to connect a battery to the Arduino</h2>



<p class="wp-block-paragraph">When working with sensitive circuits and micro-controllers, batteries can be a tricky thing to get right. It is not as simple as just buying a battery with the same voltage as what the micro-controller requires; the issue&nbsp;with batteries is that their voltage does&nbsp;not remain constant. The voltage stated on the battery usually tells you the approximate voltage when it is at 50% charge. The voltage tends to be slightly higher when fully charged, and drops below this value as it is drained. Battery power level indicators work by analysing this voltage and then calculating how much power is left.</p>



<p class="wp-block-paragraph">Most Arduino compatible micro-controllers have several different ways in which they can be powered. Through the (1) USB jack, the (2) Power Jack, the (3) 5V Pin, and the (4) Vin Pin. Many Arduino&#8217;s also have a 3.3V pin, however this is only a voltage output and cannot be used to power the board. The voltage input (Vin) pin and power jack are both connected to the same power regulation circuitry, which can take in voltages between 7-12V and convert them into stable 5V used by the micro-controller. If you use the 5V pin to provide power, this regulation circuitry is bypassed and feeds the chip directly. This means that if the voltage provided to the 5V pin deviates by as little as ±0.1v, you could potentially fry the board. </p>



<p class="wp-block-paragraph">As the voltage of a battery varies with&nbsp;use, I would always connect it through the Vin pin or the power jack. This allows the power regulation circuitry to deal with any variances in the voltage and prevent the battery from frying the board. </p>



<p class="wp-block-paragraph">However, frying the board isn&#8217;t the only danger when using a battery! As the battery is drained and its voltage drops below the micro-controller&#8217;s minimum voltage requirement, a brown-out can occur. Brown-outs happen when the micro-controller partially shuts-down due to a power shortage. These usually cause the controller to restart, but they could also potentially damage the controller. Some batteries (especially LiPos) also are damaged if they are over-discharged and the voltage drops too low. This makes it important to monitor the voltage of the battery during use, so that we know when the battery level is too low and it needs to be recharged.</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Protecting your Battery from being Over-discharged</h2>



<p class="wp-block-paragraph">The best way to prevent a brown-out is to make sure that the voltage being supplied is always above the minimum required voltage for the controller. If the battery falls below this minimum voltage, the micro-controller should display a warning message, or switch itself off. A nice way of dealing with this is to make the micro-controller monitor its own power supply by using one of the analogue input pins. If the voltage of the battery is less than 5V, it can be connected directly into the analogue pin of an Arduino. Otherwise, we will have to use a potential divider circuit in order to reduce the voltage to a&nbsp;safe level.</p>



<p class="wp-block-paragraph">For my second version of the self-balancing robot, I am using a 11.1V lithium quad-copter battery to power a Galileo Gen2 Board and two 12V motors. As the voltage of the battery is greater than 5V, I used the following circuit in order to monitor the battery as it is being used:</p>



<div class="wp-block-dgwt-justified-gallery">
<a href='https://wired.chillibasket.com/3d-printed-wall-e/battery_level_circuit/'><img loading="lazy" decoding="async" width="300" height="227" src="https://wired.chillibasket.com/wp-content/uploads/2020/02/battery_level_circuit-300x227.jpg" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2020/02/battery_level_circuit-300x227.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2020/02/battery_level_circuit.jpg 500w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a>
<a href='https://wired.chillibasket.com/2014/12/micro-controller-batteries/testing-batteries-2/'><img loading="lazy" decoding="async" width="300" height="143" src="https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-2-300x143.jpg" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-2-300x143.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-2-1024x490.jpg 1024w, https://wired.chillibasket.com/wp-content/uploads/2014/12/Testing-Batteries-2.jpg 1200w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a>
</div>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">When two resistors are connected in series like this, with one end connected to a certain voltage and the other to ground, the voltage at the junction of the two resistors is determined by the ratio of the two resistances. The formula is as follows, where (Vin) is the input voltage, (R1) and (R2) the resistances of the first and second resistor, and (Vdiv) the voltage at the junction between both resistors:</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true">V_{div}=\frac{V_{in}R_2}{R_1+R_2}</div>



<p class="wp-block-paragraph">The ratio of the resistors should be chosen, so that the voltage at the junction (Vdiv) is below 5V when the battery is at its maximum voltage. Since the Arduino measures the lower voltage (Vdiv) at the junction of both resistors, this formula can be rearranged to calculate the voltage of the battery (Vin):</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true">V_{in}=V_{div}\frac{R_1+R_2}{R_2}=V_{div}\left(\frac{R_1}{R_2}+1\right)</div>



<p class="wp-block-paragraph">The code I use to monitor the battery percentage on the Arduino is shown below. The same formula is used on line 22 to calculate the actual battery voltage. For the 11.1V LiPo battery I used, the maximum voltage at full charge was 12.6V. The minimum voltage below which it should no longer be used was 10.2V.</p>



<pre class="wp-block-code line-numbers language-arduino"><code class="" data-line="">// Pin number of the analog input being used for the reading
#define ANALOG_PIN 2

// Values for the two resistors used in the potential divider
float resistorOne = 100000;
float resistorTwo = 47000;

float vRef = 5;               // Reference voltage - usually 5v or 3.3v
float maxVoltage = 12.6;      // The voltage of the battery when fully charged
float minVoltage = 10.2;      // Voltage below which battery isn&#039;t safe to use

void setup() {
    // Initialize serial communication
    Serial.begin(9600);
}

void loop() {
    // Calculate voltage at the analog pin
    float voltage = analogRead(ANALOG_PIN) * vRef / 1024.0;

    // Calculate the battery voltage
    voltage = voltage * (resistorOne / resistorTwo + 1);

    // Calculate the battery percentage
    float batteryPercentage = (voltage - minVoltage) / (maxVoltage - minVoltage) * 100;

    // Limit the percentage value to be between 0 to 100%
    if (batteryPercentage &gt; 100) batteryPercentage = 100;
    else if (batteryPercentage &lt; 0) batteryPercentage = 0;

    // Output the calculated values to the serial monitor
    Serial.print(voltage); Serial.print(&quot;V, &quot;);
    Serial.print(batteryPercentage); Serial.println(&quot;%&quot;);
    delay(1000);
}</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">
The serial output I got from the system then&nbsp;looked like this:

</p>



<pre class="wp-block-code language-none"><code class="" data-line="">11.07V, 36%
11.29V, 45%
11.29V, 45%
11.29V, 45%</code></pre>



<p class="wp-block-paragraph">In my test, the actual voltage of the battery according to the Lithium battery charger was 11.3V, so the value recorded by the micro-controller was relatively accurate. </p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<hr>



<p class="wp-block-paragraph">Here is a quick summary of the points I discussed above:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>1. Never connect a battery directly into the 5v or 3.3v pins of the micro-controller. These inputs require the voltage to be properly regulated.</p><p>2. Always ensure that the battery is within &nbsp;the controller&#8217;s specified voltage input range. For the Arduino Uno this is 7-12V.</p><p>3. Avoid brown-outs and battery over-discharge by monitoring the voltage of the battery and switching off the system if it drops below the minimum voltage.</p><p>4. When monitoring the voltage, take caution that the voltage being measured does not exceed the reference voltage (5V). Reduce the voltage by using a potential divider circuit.</p></blockquote>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-color has-cyan-bluish-gray-color wp-block-paragraph"><em><strong>Updated:</strong> 24th May 2019 – Reformatted post</em> </p>



<p class="has-text-color has-cyan-bluish-gray-color wp-block-paragraph"><em><strong>Updated:</strong> 28th May 2020 – Added extra detail about the potential divider circuit</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://wired.chillibasket.com/2014/12/micro-controller-batteries/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Accelerometer &#038; Gyroscope Sensors</title>
		<link>https://wired.chillibasket.com/2014/10/accel-gyro-sensors/</link>
					<comments>https://wired.chillibasket.com/2014/10/accel-gyro-sensors/#comments</comments>
		
		<dc:creator><![CDATA[Simon Bluett]]></dc:creator>
		<pubDate>Thu, 09 Oct 2014 13:02:20 +0000</pubDate>
				<category><![CDATA[Self-balancing]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Accelerometer]]></category>
		<category><![CDATA[Balancing]]></category>
		<category><![CDATA[Galileo]]></category>
		<category><![CDATA[Gen2]]></category>
		<category><![CDATA[Gyroscope]]></category>
		<category><![CDATA[MPU6050]]></category>
		<category><![CDATA[Stabilisation]]></category>
		<guid isPermaLink="false">http://wired.chillibasket.com/?p=109</guid>

					<description><![CDATA[If you haven&#8217;t already read the first part of this Self-balancing robot series, I would encourage you to do so now! The first section below deals with a little bit of theory behind the sensors, so if you want to get straight to the programming/building part, please feel free to skip to the second section&#8230; [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1200" height="450" src="https://wired.chillibasket.com/wp-content/uploads/2014/10/Self-balancing-Part-2.jpg" alt="Self-balancing Part 2" class="wp-image-125" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/10/Self-balancing-Part-2.jpg 1200w, https://wired.chillibasket.com/wp-content/uploads/2014/10/Self-balancing-Part-2-300x112.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/10/Self-balancing-Part-2-1024x384.jpg 1024w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure></div>



<p class="wp-block-paragraph">If you haven&#8217;t already read the first part of this Self-balancing robot series, I would encourage you to <a href="https://wired.chillibasket.com/2014/09/self-balancing-robot-part-1/">do so now</a>! The first section below deals with a little bit of theory behind the sensors, so if you want to get straight to the programming/building part, please feel free to skip to the second section&#8230;</p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Deciding which Gyroscope Module to Use</h2>



<p class="wp-block-paragraph">So you have decided to go ahead with the project and construct your own self-balancing robot? That&#8217;s great! Now we can start by looking at one of the most significant elements of this project; the sensor. Traditionally the sensor of preference for stabilisation&nbsp;is a gyroscope. Now-days gyroscopes are extremely small and very cheap to buy, so they are ideal for amateur electronics projects. Unfortunately these gyroscopes (both the cheap and the not-so-cheap versions) also come with their own problems. They are good for short-term and quick movements, but tend to drift over time as the error accumulates. They also record a lot of jitter and noise, which needs to be filtered by the micro-controller before the data can be used.</p>



<p class="wp-block-paragraph">To reduce this drifting effect of the gyroscope, it is possible to combine the sensor data with that from an accelerometer. The accelerometer is good at sensing slower and more prolonged movements, rather than the fast motion. Therefore if we take the best of both worlds and fuse the data together, we will be left with an extremely accurate picture of the motion&nbsp;of the robot.</p>



<p class="wp-block-paragraph">As a result I decided to use a combined accelerometer &amp; gyroscope breakout module (the MPU-6050), which is slightly more expensive than a simple gyro, but should lead to a superior stabilisation performance. <em>Note: the MPU-6050 comes with a library which does all of the sensor fusion calculations for you, so that definitely is a plus!</em></p>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Getting started with the Accel-Gyro Module</h2>



<p class="wp-block-paragraph">The MPU-6050 uses I<sup>2</sup>C to communicate with the micro-controller, so I started by connecting up the pins as shown in the schematics: the SDA line connects to the Analog pin 4, the SCL to Analog pin 5, power input to the 3.3v pin and the ground to the GND pin. If you are using one of the newer Arduinos, you could also connect the sensor to the dedicated SDA and SCL header pins.</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><a href="https://wired.chillibasket.com/wp-content/uploads/2014/10/AccelGyro-Schematic.jpg"><img loading="lazy" decoding="async" src="https://wired.chillibasket.com/wp-content/uploads/2014/10/AccelGyro-Schematic.jpg" alt="Schematic for wiring the accel-gyro to the Galileo. (Made using Fritzing)" class="wp-image-127" width="500" height="429" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/10/AccelGyro-Schematic.jpg 1000w, https://wired.chillibasket.com/wp-content/uploads/2014/10/AccelGyro-Schematic-300x257.jpg 300w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a><figcaption>Schematic for wiring the accel-gyro to the Galileo. (Made using Fritzing)</figcaption></figure></div>



<p class="wp-block-paragraph">As I am using an Intel Galileo Gen2 board, I did not use the interrupt pin. In general it is very bad practice to disregard the interrupts, as it might cause the buffer holding the sensor data to overflow, but for some reason the Galileo does not support normal interrupts! In order to get the sensor working correctly on the Galileo Board, I spent a lot of time on getting the timing right so that there is no overflow of incoming sensor data.For all other Arduino-compatible board, you should use the interrupt so that the micro-controller deals with new sensor data the moment that it is sent. (The interrupt pin is connected to Arduino digital pin 2)</p>



<p class="wp-block-paragraph">Now it is time to get some data from the accel-gyro module! To do this I simply used the sample code which came with the documentation of the MPU6050 in order to read the raw sensor data. For this sample to work, the <a href="https://github.com/jrowberg/i2cdevlib">I2Cdev</a>&nbsp;and the <a href="https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050">MPU6050</a>&nbsp;libraries need to be installed. Here is the code:</p>



<pre class="wp-block-code language-arduino line-numbers code-600"><code class="" data-line="">// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg &lt;jeff@rowberg.net&gt;
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include &quot;I2Cdev.h&quot;
#include &quot;MPU6050.h&quot;

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
	#include &quot;Wire.h&quot;
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // &lt;-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;

#define LED_PIN 13
bool blinkState = false;

void setup() {
	// join I2C bus (I2Cdev library doesn&#039;t do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
	Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
	Fastwire::setup(400, true);
#endif

	// initialize serial communication
	// it&#039;s really up to you depending on your project)
	Serial.begin(115200);

	// initialize device
	Serial.println(&quot;Initializing I2C devices...&quot;);
	accelgyro.initialize();

	// verify connection
	Serial.println(&quot;Testing device connections...&quot;);
	Serial.print(&quot;MPU Connection &quot;);
	Serial.println(accelgyro.testConnection() ? &quot;successful&quot; : &quot;failed&quot;);

	// configure Arduino LED
	pinMode(LED_PIN, OUTPUT);
}

void loop() {
	// read raw accel/gyro measurements from device
	accelgyro.getMotion6(&amp;ax, &amp;ay, &amp;az, &amp;gx, &amp;gy, &amp;gz);

	// display tab-separated accel/gyro x/y/z values
	Serial.print(&quot;a/g:\t&quot;);
	Serial.print(ax); Serial.print(&quot;\t&quot;);
	Serial.print(ay); Serial.print(&quot;\t&quot;);
	Serial.print(az); Serial.print(&quot;\t&quot;);
	Serial.print(gx); Serial.print(&quot;\t&quot;);
	Serial.print(gy); Serial.print(&quot;\t&quot;);
	Serial.println(gz);

	// blink LED to indicate activity
	blinkState = !blinkState;
	digitalWrite(LED_PIN, blinkState);
}</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">
The result I got on the Serial Monitor looked like this:

</p>



<pre class="wp-block-code language-none"><code class="" data-line="">Initializing I2C devices...
Testing device connections...
MPU Connection successful 
a/g:	-1428	14240	12120	-536	131	-149
a/g:	-1416	14196	11972	-505	110	-169
a/g:	-1484	14260	11948	-524	108	-147
a/g:	-1508	14220	11968	-513	87	-151
a/g:	-1540	14176	11920	-501	15	-164
a/g:	-1408	14212	11984	-523	27	-153
a/g:	-1472	14104	11888	-526	123	-137
a/g:	-1400	14236	11936	-514	136	-148
a/g:	-1512	14216	12008	-522	132	-142
a/g:	-1412	14172	11956	-520	127	-158
a/g:	-1456	14120	11936	-533	94	-166
a/g:	-1496	14124	11936	-529	97	-161
a/g:	-1496	14208	11996	-526	108	-177
a/g:	-1420	14236	11992	-505	104	-151
a/g:	-1540	14264	11984	-510	115	-171
a/g:	-1468	14300	12068	-504	51	-143
a/g:	-1508	14172	11868	-545	105	-137
a/g:	-1416	14244	11812	-523	69	-154
a/g:	-1472	14276	11956	-504	92	-146
a/g:	-1492	14192	12028	-517	143	-175</code></pre>



<p class="wp-block-paragraph">In this data we can see the readings from the accelerometer already divided into the x/y/z values, and the readings from the gyroscope are also divided into its x/y/z components. This is a great first step, but unfortunately this data is not very usable in its current form. We still have to fuse the accelerometer and gyroscope data together, and then filter it to remove all of the noise!</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-image wp-image-144 size-full"><figure class="aligncenter"><img loading="lazy" decoding="async" width="1200" height="657" src="https://wired.chillibasket.com/wp-content/uploads/2014/10/Accel-Gyro-Test-Setup.jpg" alt="The MPU6050 module connected to a Galileo Gen 2 Board" class="wp-image-144" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/10/Accel-Gyro-Test-Setup.jpg 1200w, https://wired.chillibasket.com/wp-content/uploads/2014/10/Accel-Gyro-Test-Setup-300x164.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/10/Accel-Gyro-Test-Setup-1024x560.jpg 1024w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /><figcaption>The MPU6050 module connected to a Galileo Gen 2 Board</figcaption></figure></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="underline-heading wp-block-heading">Manipulating the data</h2>



<p class="wp-block-paragraph">It is possible to calculate the tilt of the sensor manually through the use of a number of formulas, but fortunately (at least for the MPU-6050) there is a library to do this for us! As a matter of fact, the MPU-6050 has a built-in &#8220;Motion Processing Unit&#8221; (hence the initials) which can be used to process the sensor data, therefore minimising the load on the micro-processor. This library also automatically filters the data so that we get a clean and usable result straight away.</p>



<div class="wp-block-katex-display-block katex-eq" data-katex-display="true">tan^{-1} \frac{A_x}{A_y} = sin^{-1} \frac{A_x}{\sqrt{A^2_x + A^2_y}} = sin^{-1} \frac{A_x}{g}</div>



<p class="wp-block-paragraph">Above is the equation used to calculate the angle of inclination from the accelerometer data, where (<em>Ax</em>) and (<em>Ay</em>) are the x- and y- accelerometer values. If you want to find out about calculating the angles manually, please visit: <a href="http://www.kerrywong.com/2012/03/08/a-self-balancing-robot-i/">http://www.kerrywong.com/2012/03/08/a-self-balancing-robot-i/</a>. Kerry Wong does an awesome job at describing the whole system, so I would encourage you to check it out! He covers all of the main topics such as the calculations, sensor fusion and the Kalman filter.</p>



<p class="wp-block-paragraph">As regards the filtering, here is another great post which looks at the main advantages and disadvantages of using the a complimentary filter instead of the MPU6050 motion-apps library: <a href="http://www.geekmomprojects.com/mpu-6050-redux-dmp-data-fusion-vs-complementary-filter/">http://www.geekmomprojects.com/mpu-6050-redux-dmp-data-fusion-vs-complementary-filter/</a></p>



<hr class="wp-block-separator"/>



<div class="wp-block-buttons aligncenter is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-outline is-style-outline--3"><a class="wp-block-button__link no-border-radius" href="https://wired.chillibasket.com/2015/01/calibrating-mpu6050/"><em>Part 3:</em> Calibrating the MPU6050</a></div>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-text-color has-cyan-bluish-gray-color wp-block-paragraph"><em>Updated: 23rd May 2019 – Reformatted post</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://wired.chillibasket.com/2014/10/accel-gyro-sensors/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Introduction to Self-Balancing Robots</title>
		<link>https://wired.chillibasket.com/2014/09/balancing-robot-intro/</link>
					<comments>https://wired.chillibasket.com/2014/09/balancing-robot-intro/#comments</comments>
		
		<dc:creator><![CDATA[Simon Bluett]]></dc:creator>
		<pubDate>Sun, 07 Sep 2014 19:12:30 +0000</pubDate>
				<category><![CDATA[Self-balancing]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Balancing]]></category>
		<category><![CDATA[Galileo]]></category>
		<category><![CDATA[Gen2]]></category>
		<category><![CDATA[Introduction]]></category>
		<category><![CDATA[Stabilisation]]></category>
		<guid isPermaLink="false">http://wired.chillibasket.com/?p=65</guid>

					<description><![CDATA[Why build a self-balancing robot? The aim of a self-balancing robot is to balance itself on two wheels, being able to drive around without toppling over. Self-balancing robots use a &#8220;closed-loop feedback control&#8221; system; this means that real-time data from motion sensors is used to control the motors and quickly compensate for any tilting motion [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="384" src="https://wired.chillibasket.com/wp-content/uploads/2014/09/Self-balancing-Part-1-1024x384.jpg" alt="" class="wp-image-91" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/09/Self-balancing-Part-1-1024x384.jpg 1024w, https://wired.chillibasket.com/wp-content/uploads/2014/09/Self-balancing-Part-1-300x112.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/09/Self-balancing-Part-1.jpg 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Why build a self-balancing robot?</h2>



<p class="wp-block-paragraph">The aim of a self-balancing robot is to balance itself on two wheels, being able to drive around without toppling over. Self-balancing robots use a &#8220;closed-loop feedback control&#8221; system; this means that real-time data from motion sensors is used to control the motors and quickly compensate for any tilting motion in order to keep the robot upright. Similar self-balancing feedback control systems can be seen in many other applications. Some of the obvious examples include Segways, bipedal robots and space rockets (A few rockets have been lost due to a&nbsp;<a href="http://youtu.be/8_EnrVf9u8s?t=1m31s">faulty balancing system</a>).</p>



<p class="wp-block-paragraph">But what many people don&#8217;t realise is that often the same type of controller is also used in a large variety of other applications which aren&#8217;t related to balance. Proportional-integral-derivative (PID) controllers are used by elevators to control their motion and position, used by air-conditioning units to control the temperature within a room, and even used to control the operation of jet engines. Of course rockets use significantly more complex controllers than air-conditioners, but the underlying principle is still the same: how to adjust the system in order to get as close to the desired target value (be it temperature, angle, or position) as possible. That is why building a self-balancing robot is so educational;&nbsp;you can use the same control methods over and over again for other projects. And don&#8217;t forget, self-balancing robots are a fun toy to play with! Here is a video of my self-balancing in action:</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-rich is-provider-embed-handler wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe loading="lazy" src="https://www.youtube-nocookie.com/embed/yO_fyqfrPzQ?feature=oembed&amp;modestbranding=1&amp;showinfo=0&amp;rel=0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" width="560" height="315" frameborder="0"></iframe></div></figure>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">A Brief Overview</h2>



<p class="wp-block-paragraph">It takes several steps to build a self-balancing robot. The easiest part is the hardware, so that is always a good place to start. The robot requires two motors, a motor controller, a sensor to detect its current tilt angle, a micro-controller and some type of frame. Surprisingly enough due to the inertia of an&nbsp;<a href="http://en.wikipedia.org/wiki/Inverted_pendulum">inverted pendulum</a>, the robot actually finds it easier to stabilise if the frame is very tall with a lot of weight on top, instead of a small frame with a low centre of gravity!</p>



<p class="wp-block-paragraph">Once all of the physical components have been assembled, we can proceed to the tricky stuff; the software. As the system is inherently unstable and wants to topple over, the micro-controller needs to continuously monitor the current angle of the robot and be as fast and efficient as possible in order to retain its balance. While the loop time (refresh rate) should be short, it also needs to remain regular so that the control system can properly performs its calculations. For my robot I used a standard loop time of 10ms (100Hz). Therefore, the controller recalculates its response 100 times per second!</p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-image wp-image-27 size-full"><figure class="aligncenter is-resized"><img loading="lazy" decoding="async" src="https://wired.chillibasket.com/wp-content/uploads/2014/08/Title-Slider-2.jpg" alt="Title Slider 2" class="wp-image-27" width="600" height="225" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/08/Title-Slider-2.jpg 1200w, https://wired.chillibasket.com/wp-content/uploads/2014/08/Title-Slider-2-300x112.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2014/08/Title-Slider-2-1024x384.jpg 1024w" sizes="auto, (max-width: 600px) 100vw, 600px" /><figcaption>The motors of my self-balancing robot</figcaption></figure></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="striped-heading wp-block-heading">Required Components</h2>



<p class="wp-block-paragraph">Before we dive into how to make a self-balancing robot, we need to get our hardware together. Here is a list of the required component,&nbsp;with some links as reference:</p>



<ul class="wp-block-list"><li><strong>Essential:</strong></li><li>1 x <a href="https://store.arduino.cc/arduino-uno-rev3" target="_blank" rel="noreferrer noopener">Arduino-compatible Controller</a></li><li>1 x Power Supply/Battery</li><li>1 x <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://store.arduino.cc/arduino-motor-shield-rev3" target="_blank">Motor Controller</a></li><li>1 x <a href="https://www.adafruit.com/product/3886" target="_blank" rel="noreferrer noopener">Gyroscope/Accelerometer Module (Eg. MPU-6050)</a></li><li>2 x <a rel="noreferrer noopener" href="http://www.amazon.com/HOSSEN%C2%AE-120RPM-Powerful-Torque-Replacement/dp/B00B1KZ8UU/ref=sr_1_4?ie=UTF8&amp;qid=1409308057&amp;sr=8-4&amp;keywords=high+torque+gear+motors" target="_blank">High Torque Gearbox Motors</a></li><li><a href="https://www.sparkfun.com/products/11367" target="_blank" rel="noreferrer noopener">Colour-coded wires, preferably single core</a></li><li>Some type of frame!</li></ul>



<ul class="wp-block-list"><li><strong>Optional:</strong></li><li><a href="https://www.sparkfun.com/products/11992" target="_blank" rel="noreferrer noopener">Some buttons to control the robot</a></li><li><a href="https://www.sparkfun.com/products/16723" target="_blank" rel="noreferrer noopener">A on/off power switch</a></li><li>A number of colourful LEDs</li></ul>



<p class="wp-block-paragraph">The links above are for reference only! I recommend that you look around for the best deals before buying anything.</p>



<p class="wp-block-paragraph">I decided to use the Intel Galileo Gen2 Development Board (now discontinued) for my micro-controller as I still had a couple lying around, and it is compatible with the Arduino environment. In reality you could use any board (Eg. Uno, Mega, Red-board) to make your self-balancing robot. In all of my robots I used the MPU-6050 sensor, which contains both a gyroscope and an accelerometer. The benefit of using both of the sensors together is that their data can be fused, giving us much stabler and more accurate readings for angle.</p>



<p class="wp-block-paragraph">To create my frame I designed all of the components on the computer using SketchUp, and then sent them to be 3D printed. If you don&#8217;t have access a printer, an alternative would be to build your own frame out of scrap parts! I built my first self-balancing robot prototype out of lollipop sticks and glue, and I was surprised how well it worked! A frame design which I have commonly seen other people implement is to use a couple of plastic/wood rectangles as platforms, and to connect these using a long threaded bolt and some nuts (as shown in the diagram below). </p>



<div class="wp-block-dgwt-justified-gallery">
<a href='https://wired.chillibasket.com/2015/10/putting-it-all-together/balancerdiagram1/'><img loading="lazy" decoding="async" width="300" height="177" src="https://wired.chillibasket.com/wp-content/uploads/2015/10/BalancerDiagram1-300x177.jpg" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2015/10/BalancerDiagram1-300x177.jpg 300w, https://wired.chillibasket.com/wp-content/uploads/2015/10/BalancerDiagram1.jpg 700w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a>
<a href='https://wired.chillibasket.com/2015/10/putting-it-all-together/lollipop-balancer/'><img loading="lazy" decoding="async" width="210" height="300" src="https://wired.chillibasket.com/wp-content/uploads/2015/10/Lollipop-Balancer-210x300.jpg" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2015/10/Lollipop-Balancer-210x300.jpg 210w, https://wired.chillibasket.com/wp-content/uploads/2015/10/Lollipop-Balancer.jpg 699w" sizes="auto, (max-width: 210px) 100vw, 210px" /></a>
<a href='https://wired.chillibasket.com/?attachment_id=74'><img loading="lazy" decoding="async" width="210" height="300" src="https://wired.chillibasket.com/wp-content/uploads/2014/08/Screen-Shot-2014-07-16-at-16.51.55-2-210x300.png" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/08/Screen-Shot-2014-07-16-at-16.51.55-2-210x300.png 210w, https://wired.chillibasket.com/wp-content/uploads/2014/08/Screen-Shot-2014-07-16-at-16.51.55-2.png 500w" sizes="auto, (max-width: 210px) 100vw, 210px" /></a>
<a href='https://wired.chillibasket.com/?attachment_id=41'><img loading="lazy" decoding="async" width="223" height="300" src="https://wired.chillibasket.com/wp-content/uploads/2014/08/Balancing-Robot-1-223x300.jpg" class="attachment-medium size-medium" alt="" srcset="https://wired.chillibasket.com/wp-content/uploads/2014/08/Balancing-Robot-1-223x300.jpg 223w, https://wired.chillibasket.com/wp-content/uploads/2014/08/Balancing-Robot-1-762x1024.jpg 762w, https://wired.chillibasket.com/wp-content/uploads/2014/08/Balancing-Robot-1.jpg 893w" sizes="auto, (max-width: 223px) 100vw, 223px" /></a>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<hr>



<p class="wp-block-paragraph">Please leave a comment below if you have any questions or suggestions. In the next part of this tutorial I will cover the basics of how accelerometer and gyroscope sensors work, and how we can use them in our robot.</p>



<div class="wp-block-buttons aligncenter is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-outline is-style-outline--4"><a class="wp-block-button__link no-border-radius" href="https://wired.chillibasket.com/2014/10/accel-gyro-sensors/"><em>Part 2:</em> Accelerometer &amp; Gyroscope Sensors</a></div>
</div>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="has-cyan-bluish-gray-color has-text-color wp-block-paragraph"><em><strong>Updated:</strong> 23rd May 2019 – Reformatted post</em></p>



<p class="has-cyan-bluish-gray-color has-text-color wp-block-paragraph"><em><strong>Updated:</strong> 29th May 2020 – Updated the descriptions and reformatted post</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://wired.chillibasket.com/2014/09/balancing-robot-intro/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
	</channel>
</rss>
