Have you ever wondered how your smartphone magically knows when to flip the screen from portrait to landscape? Or how fitness trackers know when you’re walking, running, or just standing still? The secret behind these smart features is a tiny but powerful device called an accelerometer.
Accelerometers are built into most of today’s gadgets and are responsible for detecting motion, tilt, and orientation. One popular and affordable example is the ADXL335 module—a compact, low-power, and low-cost sensor used in countless electronics projects to measure acceleration in three directions (X, Y, and Z).
In this tutorial, we’re going to explore the ADXL335 accelerometer module in depth. You’ll learn what it is, how it works, and most importantly, how to hook it up to an Arduino so you can start building your own motion-sensing projects. Whether you’re creating a tilt-sensing robot, a basic step counter, or just want to understand how movement detection works, this guide is the perfect place to start.
Let’s get started!
How Does an Accelerometer Work?
To understand how accelerometers work, imagine a small, transparent cube with a ball suspended in its center by springs connected to each inner wall — front, back, left, right, top, and bottom.

When the cube isn’t moving, the ball stays perfectly centered. But as soon as the cube moves or accelerates in any direction, the ball lags slightly behind due to inertia (the tendency of objects to resist changes in motion). This lag stretches some springs more than others, and by measuring how much tension is in each spring, you can figure out the direction and strength of the force being applied.
Accelerometers often express the strength of this force in terms of g-force — like 1g, 2g, or 3g. So before we go further, let’s talk about what exactly “1g” means.
When we say “1g,” we’re referring to the acceleration due to gravity on Earth’s surface — about 9.8 m/s². Even when your phone is just sitting still on a table, it still senses a force of 1g pulling straight down due to gravity. It’s important to know that accelerometers don’t distinguish between gravitational acceleration and acceleration from actual movement — they simply detect the total acceleration in all directions.
Going back to our example, imagine the cube floating in outer space, in zero gravity. The ball would just float motionless in the center. Since there’s no gravity or motion, the springs wouldn’t stretch, and the accelerometer would register 0g on all three axes — X, Y, and Z.

Now, if you suddenly moved the cube quickly to the left, the ball would lag behind and push against the right-side spring. The accelerometer would then sense a force to the right, which means the box is accelerating to the left. In this case, you’d see 1g of acceleration on the X-axis, even though there’s still no gravity — it’s purely from motion.

Let’s see what happens when we place that cube on Earth. If you place the cube on a table and leave it there, gravity pulls the ball downward, stretching the bottom spring. There’s no motion, but the force of gravity alone causes the sensor to read 1g on the Z-axis. The X and Y axes would still read 0g, because there’s no force acting in those directions.

Things get interesting when you tilt the box. Imagine tilting it so it’s leaning at a 45-degree between the Z-axis and the X-axis. Gravity still pulls straight down toward Earth, but because the cube is tilted, that pull is now divided between the Z and X directions. The accelerometer senses this and shows about 0.71g on both axes. The value of 0.71 isn’t random – it’s the cosine of 45 degrees times 1g. The ball is effectively pulling equally on two springs now, so both the X and Z sensors register force.

While this box-and-ball model isn’t exactly how real accelerometers are built, it helps us understand why accelerometers measure forces in g’s, why they read 1g in the Z direction when sitting still, and what readings you might see when the device is held at different angles.
In the real world, accelerometers are built using Micro-Electro-Mechanical Systems (MEMS) technology. So, let’s explore how a MEMS accelerometer works.
How Does a MEMS Accelerometer Work?
A MEMS (Micro-Electro-Mechanical System) accelerometer is essentially a microscopic mechanical system fabricated directly onto a silicon chip.
At its core is a small mass, often called the “proof mass.” This mass is suspended between fixed plates by flexible beams or springs. Both the proof mass and the fixed plates are designed to work together as parts of a capacitor.


When the accelerometer moves or experiences acceleration in a certain direction, the proof mass tries to stay in place because of inertia, while the rest of the device moves around it. This movement changes the distance between the proof mass and the fixed plates. Since capacitance depends directly on the distance between plates, the value of the capacitance changes accordingly.
On-chip circuitry detects this change in capacitance and converts it into an electrical signal. The circuitry then calculates exactly how much acceleration has occurred based on the change.
ADXL335 Module Hardware Overview
At the heart of this module is the ADXL335, a small, low-power, and low-noise 3-axis MEMS accelerometer made by Analog Devices. This sensor can detect both static acceleration (due to gravity when the sensor is still) and dynamic acceleration (caused by movement, shaking, or sudden impacts).

The module is designed to be breadboard-friendly and brings out all the pins of the ADXL335 to a 6-pin header with 0.1-inch spacing. These pins include three analog outputs for measuring acceleration along the X, Y, and Z axes, two power supply pins, and one self-test pin.
Power
The ADXL335 works with voltages from 1.8V to 3.6V DC, with 3.3V being the typical operating voltage. Fortunately, the module includes a built-in 3.3V voltage regulator, which makes it easy to use with 5V microcontrollers like the Arduino.
The sensor is very energy-efficient, using only about 350 μA during normal operation—that’s much less power than a small LED!
Measurement Range
The ADXL335 can measure acceleration in a range of ±3g. This means it can detect acceleration up to 3 times the force of gravity in any direction. If the sensor experiences more than 3g, it won’t break, but the reading will max out at 3g.
The sensor is surprisingly tough and can survive extreme acceleration up to 10,000g. However, exposing it to anything higher than that could damage it permanently.
Ratiometric Output
The output of the ADXL335 is “ratiometric,” which means the voltage it outputs changes in direct proportion to the acceleration it detects.
- When there is no acceleration (0g), the output voltage is typically around half of 3.3V supply (~1.65V).
- If it detects -3g, the voltage drops to 0V
- If it detects +3g, the voltage rises to 3.3V
- The voltage smoothly scales between these values depending on the amount of acceleration.
Technical Specifications
Here are the 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 information, please refer to the datasheet below.
ADXL335 Accelerometer Pinout
Before we get into the hookup and example code, let’s take a look at its Pinout.

VCC supplies power to the module. You should connect it to the 5V output pin on your Arduino board.
X-Out outputs an analog voltage proportional to acceleration along the X axis.
Y-Out outputs an analog voltage proportional to acceleration along the Y axis.
Z-Out outputs analog voltage proportional to acceleration along the Z axis.
GND is the ground pin.
ST(Self-Test) pin is used to check if the sensor is working properly in your project. We’ll talk more about how to use this feature at the end of the tutorial.
Wiring an ADXL335 Accelerometer to an Arduino
Now that we understand how the ADXL335 accelerometer works, let’s move on to connecting it to an Arduino.
The wiring is fairly simple. Start by placing the accelerometer on a breadboard. Then, connect the VCC pin of the accelerometer to the 5V pin on the Arduino and GND pin to the ground.
Now, connect the X-Out, Y-Out, and Z-Out pins to the Arduino’s analog input pins A0, A1, and A2, respectively.
To get more accurate readings from the accelerometer, we need to change the Arduino’s analog reference voltage (AREF). You can do this by connecting the Arduino’s 3.3V pin to its AREF pin. This tells the Arduino to use 3.3V as the reference for reading analog signals, which better matches the ADXL335’s output range.
Here’s a quick reference table for the pin connections:
| ADXL335 Module | Arduino | |
| VCC | 5V | |
| GND | GND | |
| X-Out | A0 | |
| Y-Out | A1 | |
| Z-Out | A2 |
Please refer to the image below to see the proper wiring setup.

Arduino Example Code – Reading the ADXL335 accelerometer
Here’s a simple sketch that reads and displays the output from the ADXL335 accelerometer on each axis (X, Y, and Z).
Before we break down how the code works, go ahead and upload it to your Arduino.
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;
}Once the code is uploaded to your Arduino, open the serial monitor and set the baud rate to 9600 bps. Now, you can see how the accelerometer responds when you move it in different directions.






Code Explanation:
At the beginning of our sketch, we tell the Arduino which pins connect to the accelerometer. We’ve connected the X, Y, and Z outputs of the ADXL335 to pins A0, A1, and A2 on the Arduino. These pins will read data from the sensor.
const int xInput = A0;
const int yInput = A1;
const int zInput = A2;Next, we create two variables for the minimum and maximum values of the sensor’s raw readings: RawMin and RawMax. Since the Arduino has a 10-bit Analog-to-Digital Converter (ADC), it takes the voltage outputs from the ADXL335 (ranging from 0 to 3.3 volts) and converts them into whole numbers between 0 and 1023. That’s why we set RawMin to 0 and RawMax to 1023.
// initialize minimum and maximum Raw Ranges for each axis
int RawMin = 0;
int RawMax = 1023;To make our readings more stable and reduce noise (random fluctuations), the sketch takes multiple readings from each axis. We set the variable sampleSize to 10, which means the Arduino will take 10 samples per axis and average them for more accurate results.
// Take multiple samples to reduce noise
const int sampleSize = 10;In the setup section, we tell the Arduino to use an external voltage reference instead of the default by using the analogReference(EXTERNAL) function.
analogReference(EXTERNAL);Warning:
Since we’ve connected the Arduino’s 3.3V pin to the AREF pin, using analogReference(EXTERNAL) is absolutely necessary. If you forget this step, you could damage your Arduino by shorting together the internally generated active reference voltage and the AREF pin. You can learn more about the analogReference() function on Arduino’s official website if you’re interested.
In the loop() section, we read values from the X, Y, and Z pins every 200 ms. Instead of using analogRead() directly, we use a custom function called ReadAxis(), which takes 10 readings, adds them together, and returns the average. This helps filter out any random fluctuations in our readings.
//Read raw values
int xRaw = ReadAxis(xInput);
int yRaw = ReadAxis(yInput);
int zRaw = ReadAxis(zInput);Converting ADXL335 Output to Acceleration(g)
The following part of the code is the most important. It converts the analog output voltages from the sensor into gravitational acceleration (g), which is how we measure the force of gravity.
// 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);The conversion uses the Arduino’s built-in map() function. When we call map(xRaw, RawMin, RawMax, -3000, 3000), it maps the value of RawMin (0) to -3000, the value of RawMax (1023) to 3000, and any values in between to a number between -3000 and 3000.
For example:
- If the sensor outputs 0 volts on the x-axis (xRaw=0), the
map()function gives us -3000, which equals -3g. - If the sensor outputs 1.65 volts on the x-axis (xRaw=511), the
map()function gives us 0, which equals 0g. - If the sensor outputs 3.3 volts on the x-axis (xRaw=1023), the
map()function gives us 3000, which equals +3g.
This is what “ratiometric” means – the output voltage changes in direct proportion to acceleration across the entire range. When acceleration increases, voltage increases at the same rate.
The numbers -3000 and 3000 are not just random—they represent acceleration in milli-g, which means thousandths of a g. Since the ADXL335 can measure from -3g to +3g, that range is equal to -3000 milli-g to +3000 milli-g.
Finally, we divide the milli-g values by 1000 to convert them to regular g values (like 1.2g, -0.8g, etc.) and display these readings in 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");ADXL335 Self Test Feature
The ADXL335 accelerometer comes with a helpful self-test feature that allows you to check if your sensor is working properly. This feature works through a special pin called the ST (self-test) pin found on the module.

When you want to test your accelerometer, you simply connect the ST pin to 3.3V. This connection creates a small electrostatic force inside the chip, which moves the tiny mechanical beam inside the accelerometer. This movement simulates what happens when the sensor experiences actual acceleration, letting you verify if the sensor is responding correctly.
During a successful self-test, you should notice specific changes in the sensor’s output values:
- −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
After you’ve completed testing, remember that during normal operation of your project, the ST pin should either be left disconnected or connected to the ground (GND) pin.
Warning:
Be careful never to connect the ST pin to any voltage higher than 3.6V. Doing so could cause permanent damage to your accelerometer.
