Ever wondered how your smartphone knows up from down! It’s one of the coolest features of today’s smartphones. They all got a tiny device called Accelerometer built into the circuitry which can sense when you tilt it from side to side. That’s how your smartphone automatically figures out when to switch the screen layout from portrait to landscape.

Accelerometers are widely used in cost sensitive, low power, motion and tilt sensing applications like Mobile devices, Gaming systems, Disk drive protection, Image stabilization and Sports & health devices.

Let’s take a closer look at what they are, what they do, and how they work.

What is Acceleration?

The brilliant scientist Isaac Newton in his second law of motion defined acceleration by relating it to mass and force.

If you have a certain force (say, the power in your leg as you kick it outward) and you apply it to a mass (a soccer ball), you’ll make the mass accelerate (the ball will shoot off into the air).

Force = Mass x Acceleration

Acceleration = Force / Mass

In other words, acceleration is the amount of force we need to move each unit of mass.

How Accelerometer Works?

To know how accelerometers work, it is often useful to imagine a ball inside a 3D cube.

Accelerometer Working Illustration - Weightless State

Suppose, the cube is in outer-space where everything is in weightless state, the ball will simply float in the middle of the cube.

Now let’s imagine each wall represents particular axis.

If we suddenly move the box to the left with acceleration 1g(A single G-force 1g is equivalent to gravitational acceleration 9.8 m/s2), no doubt the ball will hit the wall X. If we measure the force that the ball applies to the wall X, we can get an output value of 1g on the X axis.

Accelerometer Working Illustration - Sudden Movement

Let’s see what happens if we put that cube on Earth. The ball will simply fall on the wall Z and will apply a force of 1g, as shown in the picture below:

Accelerometer Working Illustration - Gravitation Force

In this case the box isn’t moving but we still get a reading of 1g on the Z axis. This is because the gravitational force is pulling the ball down with force 1g.

The accelerometer measures the static acceleration of gravity in tilt-sensing applications as well as dynamic acceleration resulting from motion, shock, or vibration.

How MEMS Accelerometer Works?

MEMS(Micro Electro Mechanical Systems) accelerometer consists of a micro-machined structure built on top of a silicon wafer.

ADXL335 MEMS Accelerometer Internal Working

This structure is suspended by polysilicon springs. It allows the structure to deflect at the time when the acceleration is applied on the particular axis.

Due to deflection the capacitance between fixed plates and plates attached to the suspended structure is changed. This change in capacitance is proportional to the acceleration on that axis.

The sensor processes this change in capacitance and converts it into an analog output voltage.

Hardware Overview of ADXL335 Accelerometer

At the heart of the module is a small, low power triple axis MEMS accelerometer from Analog Devices with extremely low noise – ADXL335. The sensor has a full sensing range of ±3 g. It can measure the static acceleration due to gravity in tilt-sensing applications, as well as dynamic acceleration resulting from motion, shock, or vibration.

ADXL335 Accelerometer Module Hardware Overview

The sensor works on power between 1.8V to 3.6VDC (3.3V optimal), and typically consumes just 350µA of current. However, an on-board 3.3V regulator makes it a perfect choice for interfacing with 5V microcontrollers such as the Arduino.

This breadboard friendly board breaks out every pin of the ADXL335 to a 6-pin, 0.1″ pitch header. This includes 3 analog outputs for X, Y and Z axis measurements, 2 supply pins and a self-test pin which allows you to check the functioning of the sensor in the final application.

The analog outputs are Ratiometric, meaning 0g measurement output is nominally equal to half of the 3.3V supply voltage (1.65V), -3g is at 0v and 3g is at 3.3V with full scaling in between.

Here are the complete specifications of ADXL335 Accelerometer IC.

ADXL335 Accelerometer IC Specifications
Operating Voltage 1.8V – 3.6V
Operating Current 350μA (typical)
Sensing Range ±3g (Full Scale)
Temperature Range −40 to +85°C
Sensing axis 3 axis
Sensitivity 270 to 330mV/g (Ratiometric)
Shock Resistance Up to 10,000g
Dimension 4mm x 4mm x 1.45mm

For more details, please refer below datasheet.

ADXL335 Accelerometer Pinout

Before diving into hookup and example code, let’s first take a look at its Pinout.

ADXL335 Accelerometer Module Pinout

VCC pin provides power for the accelerometer which can be connected to 5V on the Arduino.

X-Out pin outputs analog voltage proportional to acceleration exerted on X axis.

Y-Out pin outputs analog voltage proportional to acceleration exerted on Y axis.

Z-Out pin outputs analog voltage proportional to acceleration exerted on Z axis.

GND pin is connected to GND on Arduino

ST(Self-Test) pin controls the self-test feature. This feature is discussed in detail at the end.

Wiring ADXL335 Accelerometer to Arduino UNO

Now that we have a complete understanding of how ADXL335 accelerometer works, we can begin hooking it up to our Arduino.

Connections are pretty easy. Start by placing the accelerometer on to your breadboard. Connect VCC pin to the 5V pin on the Arduino and connect GND pin to the Ground pin on the Arduino. Also connect X, Y and Z output to the analog pins A0, A1 and A2 on Arduino.

For accurate results, we need to change the analog reference(AREF) voltage of the Arduino. This can be done by connecting the 3.3V pin on Arduino to the AREF pin.

When you’re done you should have something that looks similar to the illustration shown below.

Wiring ADXL335 Accelerometer Module to Arduino UNO
Wiring ADXL335 Accelerometer Module to Arduino UNO

So now that we’ve hooked up our accelerometer, it’s time to write some code and test it out.

Arduino Code – Reading ADXL335 accelerometer

The sketch is pretty simple. it merely displays the calibrated sensor output on each axis on the serial interface. Try the sketch out, before we begin its detailed breakdown.

const int xInput = A0;
const int yInput = A1;
const int zInput = A2;

// initialize minimum and maximum Raw Ranges for each axis
int RawMin = 0;
int RawMax = 1023;

// Take multiple samples to reduce noise
const int sampleSize = 10;

void setup() 
{
	analogReference(EXTERNAL);
	Serial.begin(9600);
}

void loop() 
{
	//Read raw values
	int xRaw = ReadAxis(xInput);
	int yRaw = ReadAxis(yInput);
	int zRaw = ReadAxis(zInput);

	// Convert raw values to 'milli-Gs"
	long xScaled = map(xRaw, RawMin, RawMax, -3000, 3000);
	long yScaled = map(yRaw, RawMin, RawMax, -3000, 3000);
	long zScaled = map(zRaw, RawMin, RawMax, -3000, 3000);

	// re-scale to fractional Gs
	float xAccel = xScaled / 1000.0;
	float yAccel = yScaled / 1000.0;
	float zAccel = zScaled / 1000.0;

	Serial.print("X, Y, Z  :: ");
	Serial.print(xRaw);
	Serial.print(", ");
	Serial.print(yRaw);
	Serial.print(", ");
	Serial.print(zRaw);
	Serial.print(" :: ");
	Serial.print(xAccel,0);
	Serial.print("G, ");
	Serial.print(yAccel,0);
	Serial.print("G, ");
	Serial.print(zAccel,0);
	Serial.println("G");

	delay(200);
}

// Take samples and return the average
int ReadAxis(int axisPin)
{
	long reading = 0;
	analogRead(axisPin);
	delay(1);
	for (int i = 0; i < sampleSize; i++)
	{
	reading += analogRead(axisPin);
	}
	return reading/sampleSize;
}

The sketch starts by declaring Arduino’s analog input pins to which sensor’s X, Y and Z output pins are connected.

Next, we define the minimum and maximum values the Arduino is going provide. As the Arduino board contains 10-bit analog to digital converter, it will map sensor’s output voltages between 0 and 3.3 volts into integer values between 0 and 1023. That’s why RawMin is set to 0 and RawMax is set to 1023.

The variable sampleSize tells the Arduino to take 10 samples of each conversion to get more precise results.

const int xInput = A0;
const int yInput = A1;
const int zInput = A2;

// initialize minimum and maximum Raw Ranges for each axis
int RawMin = 0;
int RawMax = 1023;

// Take multiple samples to reduce noise
const int sampleSize = 10;

In setup function, we must set the analog reference to EXTERNAL, as we have connected 3.3V to the AREF pin on Arduino. This is done by calling analogReference(EXTERNAL).

You can read more about the function on Arduino’s official website. Except this, we initialize serial communications with the PC.

WARNING

If you fail call analogReference(EXTERNAL), you will short together the active reference voltage (internally generated) and the AREF pin, possibly damaging your Arduino.

analogReference(EXTERNAL);
Serial.begin(9600);

In setup function, we read analog outputs from the sensor every 200ms. Instead of calling analogRead() function, we are calling ReadAxis() custom function. This function merely takes 10 sample of ADC conversions and returns the average.

//Read raw values
int xRaw = ReadAxis(xInput);
int yRaw = ReadAxis(yInput);
int zRaw = ReadAxis(zInput);

Converting ADXL335 Output to Acceleration(g)

The following code snippet is the most important part of the program. It maps and converts the analog output voltages from the sensor to gravitational acceleration(G).

The IDE’s built-in map() function does the actual mapping. So, when we call map(xRaw, RawMin, RawMax, -3000, 3000), value of RawMin would get mapped to -3000, a value of RawMax to 3000 and values in-between to values in-between.

The values -3000 and 3000 are not arbitrary. They actually represents the gravitational acceleration (in milli-g which is 1/1000 of a g) measured by the sensor i.e. ±3g (-3000 milli-g to 3000 milli-g).

For example,

  • When the sensor outputs 0 volts on x-axis i.e. xRaw=0, the map() function will return -3000 representing -3g.
  • When the sensor outputs 3.3 volts on x-axis i.e. xRaw=1023, the map() function will return 3000 representing +3g.
  • When the sensor outputs 1.65 volts on x-axis i.e. xRaw=511, the map() function will return 0 representing 0g.

The term Ratiometric will make more sense now as the output voltage increases linearly with acceleration over the range.

// Convert raw values to 'milli-Gs"
long xScaled = map(xRaw, RawMin, RawMax, -3000, 3000);
long yScaled = map(yRaw, RawMin, RawMax, -3000, 3000);
long zScaled = map(zRaw, RawMin, RawMax, -3000, 3000);

Finally, the sensor’s output is scaled down to fractional Gs by dividing it by 1000 and displayed on the serial monitor.

// re-scale to fractional Gs
float xAccel = xScaled / 1000.0;
float yAccel = yScaled / 1000.0;
float zAccel = zScaled / 1000.0;

Serial.print("X, Y, Z  :: ");
Serial.print(xRaw);
Serial.print(", ");
Serial.print(yRaw);
Serial.print(", ");
Serial.print(zRaw);
Serial.print(" :: ");
Serial.print(xAccel,0);
Serial.print("G, ");
Serial.print(yAccel,0);
Serial.print("G, ");
Serial.print(zAccel,0);
Serial.println("G");

Following image shows the accelerometer output on serial monitor at different positions.

ADXL335 Accelerometer Output on +X axis
ADXL335 Accelerometer Output on -Y axis
ADXL335 Accelerometer Output on -X axis
ADXL335 Accelerometer Output on +Y axis
ADXL335 Accelerometer Output on -Z axis
ADXL335 Accelerometer Output on +Z axis

ADXL335 Self Test Feature

The ADXL335 Accelerometer has a self-test feature which allows you to check the functioning of the sensor in the final application.

ADXL335 Module SelfTest Pin

ST(self-test) pin on the module controls this feature.

When ST pin is connected to 3.3V, an electrostatic force is exerted on the accelerometer beam internally. The resulting movement of the beam allows the user to test if the accelerometer is functional.

The typical change in output is

  • −1.08 g (−325 mV) on the X-axis
  • +1.08 g (+325 mV) on the Y-axis
  • +1.83 g (+550 mV) on the Z-axis

This ST pin can be left open-circuit or connected to GND in normal use.

WARNING

Exposing the ST pin to voltages greater than 3.6V may damage the accelerometer permanently.