# ADXL 335 accelerometer MEGA 2560 help

Hey all,

I'm new to the forum and very new to electronics and microcontrollers. This is my first project and unfortunately its been a big one. Payload to put in a rocket, being launched Saturday. Time to ask for some help! haha.

First thing is first, is the accelerometer. I want it to output g forces, so that later we can detect events that occurred. Here is the code:

``````int xAxisPin = 2;
int yAxisPin = 3;
int zAxisPin = 4;

float xVal;
float yVal;
float zVal;

void setup() {

Serial.begin(9600);
pinMode(xAxisPin,INPUT);
pinMode(yAxisPin,INPUT);
pinMode(zAxisPin,INPUT);

}

void loop() {

// Multiply by 5 volts

xVal = xVal*5/1023;
yVal = yVal*5/1023;
zVal = zVal*5/1023;

Serial.print("X Val:  ");
Serial.print(xVal, DEC);

Serial.print("  Y Val:  ");
Serial.print(yVal, DEC);

Serial.print("  Z Val:  ");
Serial.print(zVal, DEC);
Serial.println();

delay(1000);
}
``````

I'm using this breakout board:

Everything is wired up correctly I am sure of that. I also am aware that all I did was find the voltage difference (correct terms? its 5 am, who cares), hopefully. So I need to convert it to g's but I'm very confused as to how.

Any help would be much appreciated, don't be afraid to talk down to me, if my code is bad etc. I am new so I'm aware I'm not doing much right. Thanks for your time!

The maximum (measuring) rating for this device is only +/- 3.6 - a rocket will do way more than that initially, won't it?

To convert to g, you need to offset the zero g reading (which is half the supply voltage usually), and divide by the sensitivity, which depends on the supply voltage, but is 300mV per g with a 3V supply.
So, if you measure 600mV, you know you're accelerating at 2g.

Concentrate on getting one axis working (Z is my favourite because the test equipment is free) and then scale to the other axes.

You don't need to set pinMode for an analogue input, because it's an...input.

``````Serial.print(yVal, DEC);
``````

It isn't realistic to print "float" values to ten decimal places.

Isn't the rocket going to have its performance slugged a bit by the trailing USB cable?

Initially yes, but we have two accelerometers, one that is +/- 250 g in one direction and another that is +/- 3g in 3 directions. The one-D accelerometer is being used to measure initial accelerations. Its also being used so that when a certain amount of g's occur, like 4 I think I have it set to, the data starts recording and records for 10 minutes.

You don't need to set pinMode for an analogue input, because it's an...input.

It isn't realistic to print "float" values to ten decimal places.

I am bad with deciding what to declare my variables as, is there something else that would be more appropriate so I wouldn't be working with as much memory and therefore hogging memory? Otherwise I'll just print it to two decimal places.

Isn't the rocket going to have its performance slugged a bit by the trailing USB cable?

A USB module that utilizes the serial port is being used to record the data, somewhat successfully. Its had its problems but I believe its in working condition now. So all the data records to a USB drive that can be taken out and looked at immediately after launch.

Thanks for the advice, I'll start working on it when I get back from campus, I appreciate it.

I am bad with deciding what to declare my variables as, is there something else that would be more appropriate so I wouldn't be working with as much memory and therefore hogging memory? Otherwise I'll just print it to two decimal places

The amount of memory is immaterial; a float occupies four bytes and that's that.
However, if you only want it to print to 2 decimal places, use `Serial.print(yVal, 2);` or, if you insist `Serial.print(yVal, BIN);`

(The USB cable bit? I was kidding)

Hmmm I see.

And yeah I knew you were kidding just figured you might have been curious about data storage haha

interesting project!!

so what are you using to store the data exactly??

Alrighty. I thought I had it coded correctly by now, but I'm not getting the results I want. When it is oriented with the z-axis down and the xy plane horizontal, I get 1 g in the z direction and 0 in the x and y directions. As expected.

However when I orient it with x facing up and down, it gives me:

X Val: -1.5809711456 Y Val: 0.1459760665 Z Val: 0.7161939144

Here's the code right now:

``````int xAxisPin = 2;
int yAxisPin = 3;
int zAxisPin = 4;

float input_voltage = 5;
const float sensor_power_supply = 3;
float zero_g_bias = 1.5;

float x_voltage;
float y_voltage;
float z_voltage;

float xVal;
float yVal;
float zVal;

void setup() {

Serial.begin(9600);

}

void loop() {

xVal = (x_voltage - zero_g_bias) * 1000 / 300;
xVal = xVal - 3;

yVal = (y_voltage - zero_g_bias) * 1000 / 300;
yVal = yVal - 3;

zVal = (z_voltage - zero_g_bias) * 1000 / 300;
zVal = zVal - 3;

Serial.print("X Val:  ");
Serial.print(xVal, BIN);

Serial.print("  Y Val:  ");
Serial.print(yVal, BIN);

Serial.print("  Z Val:  ");
Serial.print(zVal, BIN);
Serial.println();

delay(1000);
}
``````

I have it wired to 5V on the arduino and its properly grounded. What else could be wrong?

If the accelerometer supply is 3V, why don't you use the 3.3V for Aref?

Val: -1.5809711456 Y Val: 0.1459760665 Z Val: 0.7161939144

``````Serial.print(xVal, BIN);
``````

Huh?

(I was joking about using BIN too - it's the default)

Oh no, my noobness is showing.

Didn't know bin was default, googled it and saw it was to two dec. places to I used it. Whoops haha, now I know. Is it always the default for the print function?

uhhhh I've never used Aref before..am I supposed to have something wired up to it?

also:

Val: -1.5809711456 Y Val: 0.1459760665 Z Val: 0.7161939144

I switched it to bin like right after that. Sorry I stayed up all night and my brain is pretty scattered :/.

What does this `xVal = xVal - 3;` do?

If the acceleration was maxed out, it would give me 6 g's. I wanted to make it so that the max acceleration was 3 g's and that it would tell me -3 g's if it were maxed the opposite direction. This is correct no?

This is correct no?

This is incorrect, yes.
It is maxed-out, it will simply read close to the supply voltage, or close to zero.

Oh man sorry I didn't notice this post earlier

interesting project!!

so what are you using to store the data exactly??

I guess I should describe the project in full. I plan on releasing all the code that was made (some was used from others and I need to find who to reference as well).

The project is to design a payload for a rocket that will go 5280 feet in the air. The payload consists of two accelerometers, a humidity sensor, a temperature/pressure sensor, an irradiance sensor, a uv sensor, a gps locator, a transmitter, cameras to record the flight, and a usb module to record the data.

The usb module is:

http://www.dontronics-shop.com/ftdi-vdip1-mcu-to-usb-host-controller-development-module.html

That has been the bane of our existence. I think if we loosen the screws on the board it'll help. We bought a new one though since the first one was damaged in a failed launch. Hopefully that helps. Also lost the irradiance sensor, and bought a new one but it isn't right :/. Then the photodetector has been giving me fits but I just bought a multimeter today so I'll see if I can get that worked out.

Thanks again for all your help AWOL, I fixed the the 1-D accelerometer because of your help, and the 3-D accelerometer is well on its way. I have learned an increeeeeeedible amount from this project and I hope I can continue to learn.

Does anyone have any suggestions for books to buy?

Does anyone have any suggestions for books to buy?

Based on the nature of your questions...

Arduino Cookbook

Alright. I give. The rocket launch got delayed for other reasons, but my accelerometers are still off. I have tried to figure it out on my own but at this point am incapable, I have been awake for 53 hours straight and my brain is fried.

The code for my 1-D accelerometer is as follows:

``````// 1-D Accelerometer Variables
float G_force = 0;
float Calib_Diff;
float Accel;
int AccelPin = A1;
float val = 0;
const float arduino_voltage_1D = 5;
const float zero_g_bias = 0;

void setup() {
Serial.begin(9600);
//Use Accelerometer to detect liftoff
AutoCalib_250();
Serial.println("250-G Accelerometer Calibrated");
//startRecording();
}

void loop() {

Accel = Accel + Calib_Diff;
Accel = (arduino_voltage_1D - zero_g_bias_1D)*Accel/1023;
Accel = Accel*1000/10;
Accel = 250 - Accel;

delay(100);
}

// A function made so the Arduino knows when to start recording data

void startRecording() {

while (G_force <= abs(.5)){
Accel = Accel + Calib_Diff;
Accel = (arduino_voltage_1D - zero_g_bias_1D)*Accel/1023;
Accel = Accel*1000/10;
Accel = 250 - Accel;

delay(100);// record every 1/10th of a second

}
}

//Auto-Calibrate the 250-G Accelerometer
void AutoCalib_250() {
int Time_init = millis();

float SensorAvg = 0;
int CurrSense = 0;

float i = 1;

while (millis()-Time_init < 5000) {
SensorAvg = SensorAvg+CurrSense;
i = i + 1.00;
}

SensorAvg = SensorAvg/i;
Calib_Diff = 512.00 - SensorAvg;

}
``````

I tried basing my 3-D accelerometer off of this, but if its incorrect then that's my problem. So is there anything wrong with this, and if so what is?

I wired it to 5V.

This is currently my 3-D accelerometer code:

``````int xAxisPin = 2;
int yAxisPin = 3;
int zAxisPin = 4;

const float input_voltage_3D = 5;
const float sensor_power_supply_3D = 3;
const float zero_g_bias_3D = 0;

float x_voltage;
float y_voltage;
float z_voltage;

float xVal;
float yVal;
float zVal;

void setup() {

Serial.begin(9600);

}

void loop() {

x_voltage = (sensor_power_supply_3D - zero_g_bias_3D)*x_voltage/614;
xVal = x_voltage * 1000 / 500;

y_voltage = (sensor_power_supply_3D - zero_g_bias_3D)*y_voltage/614;
yVal = y_voltage * 1000 / 500;

z_voltage = (sensor_power_supply_3D - zero_g_bias_3D)*z_voltage/614;
zVal = z_voltage * 1000 / 500;

Serial.print("X Val:  ");
Serial.print(xVal);

Serial.print("  Y Val:  ");
Serial.print(yVal);

Serial.print("  Z Val:  ");
Serial.print(zVal);
Serial.println();

delay(1000);
}
``````

Supply voltage is 3V (tested it with multimeter)

Yeah so I don't even know. Like I said my brain is fried. I'm frustrated.

What needs to be changed in those two?

Oh and on a bright note, the UV sensor, which was the one I was having the most troubles with, appears to be working now :).

Also if it appears as if I ignored your advice from earlier, I probably had it in my code but then started changing random things in the hope that it'd work. Bad plan haha.

Do you have any idea what that code is supposed to do? I can read it and see what it is doing -- but what do you want it to do....

For example the number 614 -- why is it in there?

Why is 3V in there -- the sensors read in bits -- not volts (after conversion)....

I presume you are using AREF -- based on the 614 -- but you don't say that.

Most people who write code without an algorithm end up with what you have -- code that does something as opposed to code that achieves a stated goal.

Maybe you should write out the algorithm instead of hacking....

Here's the code that I think should work and doesn't. I'll explain why I think it should work and you can tell me why I'm wrong. We'll focus on one direction.

``````int xAxisPin = 2;
int yAxisPin = 3;
int zAxisPin = 4;

const float input_voltage_3D = 5;
const float sensor_power_supply_3D = 3;
const float zero_g_bias_3D = 0;

float x_voltage;
float y_voltage;
float z_voltage;

float xVal;
float yVal;
float zVal;

void setup() {

Serial.begin(9600);

}

z_voltage = z_voltage*5/3;
// Serial.println(z_voltage);
z_voltage = (input_voltage_3D - zero_g_bias_3D)*z_voltage/1024;
z_voltage = z_voltage*1000;
zVal = map(z_voltage, 0, 5000, -3000, 3000);
zVal = zVal/1000;

Serial.println(zVal);
``````

Step 1: Read the pin. Should be a number between 0 and 614 because I am supplying it with 3V instead of 5V
Step 2: Convert it into 1024 bits of information
Step 3: Take the voltage times the bit. Should be a number between 0 and 5
Step 4: Multiply it by 1000 so I can use the map function, it only works with integers
Step 5: Map it to the correct amount of g force
Step 6: Divide it by 1000 to get the real number

Some Things.

First: The Mega2560 can use 3.3 V from itself as AREF. Apparently you don't want to do that. Why Not?

Second: why are you using a float to collect the integer value from the ADC? What is the point? When you read an ADC port when you use AREF a 3.3V signal should give you 1023 (0-1023). So maybe you are not using AREF as you claim.

Third: If you are going to save or send the data -- just send the integer. Do the math later on a PC -- unless you actually use the information on-board.

Fourth: It takes a lot more time to manipulate a float -- plus you lose accuracy every time you multiply or divide. The % of (Relative) error adds absolutely. Did you skip the physics, stats and engineering courses -- not to mention the labs? If you were not taught that complain to all the profs and lab tutors involved.

Fifth: Have actually read the specification sheet for the sensor?

Last but not least. Have you written a program that simply reads the sensors -- to see if you get expected values... They will be on the spec sheet. As I recall it is a 3G sensor. It should tell you the expected values.

More or less.... depends on the error in the sensor and whether the sensor is level.
460-563 for X and Y Z should be ????
If the Z out reads 512 when Zero G (on its edge) -- then what will the ADC read when the Z axis hows the normal on G on the output? Hint -- from 512 to 1023 is the range of numbers you will get for +1.5 G... so 1g is what amount of that 512? (0-512 for -1.5 G to 0 G)

And what you wrote was not an algorithm. It was a description of the lines of code. I can read code.

What should the code DO!!!!! What is the purpose of the code?

If you had written an algorithm you would have not trouble with such a trivial problem. However, you probably do not need to solve the problem at this stage -- just collect the data and analyze it later.