I'm trying to build a stand alone logging unit to log accelerometer output. I bought the ADXL335-BB analog triple-axis accelerometer. I am getting some strange results and hope someone can help me understand my readings.
When I am running a simple script reading the values from each axis via A1-A3 I do get different readings when I connect to an Arduino Uno or Ardulog Data Logger V3.
I am using VCC = 3v in both cases. In rest position on the Arduino Uno I do get x = 277, y=332, z=336. On the ArduLog I get x = 420, y = 490, z = 504. When I move the accelerometer these values will change. Why the difference in absolute readings? Is this due to differences in the microcontroller?
To log read data onto a micro SD I used the RTC_DS1307 RTC example sketch with required libraries (see attachments). I made some changes to the original sketch to read the analog data. Strangely enough the X and Y values seem to be consistent with the values from the previous sketch, but the Z values can only take one of two values; 256 or 512. I tried swapping physical pins, changed order of x, y, z in the code but whatever I do the Z value remains the same two readings. I suspect it is something in the code I do not understand. I tried placing the analogRead statements just past the "// Read current date/time" comment about 3/4 down. That resulted in no readings at all.
Any ideas will be much appreciated!
int x, y, z;
int i;
int noiseresolution;
// Accelerometer characteristics
// 3.3 Vs -> 3.3/1023 = 0.03225806 V/Integer = 3.225806 mV/Integer
// Sensitivity: 0.306 V/g = 306 mV/g
// Sensitivity in g: 3.225806 (mV/Integer) / 306 (mV/g) = 0.010541 g/Integer
void setup()
{
Serial.begin(9600); // sets the serial port to 9600
// Print headers
Serial.print("x,");
Serial.print(" ");
Serial.print("y,");
Serial.print(" ");
Serial.print("z,");
Serial.println(" ");
}
void loop()
{
// Read average values over 40 samples
x = 0.00;
y = 0.00;
z = 0.00;
for (i=0; i<40; i++)
{
x = x + analogRead(1); // read analog input pin 5
y = y + analogRead(2); // read analog input pin 4
z = z + analogRead(3); // read analog input pin 3
}
x = x/40;
y = y/40;
z = z/40;
// Raw smoothed (rolling average) sensor values
// Serial.print(x);
// Serial.print(" ");
// Serial.print(y);
// Serial.print(" ");
// Serial.print(z);
// Establish ranges
// Align axis with gravity field - Axis-by-axis
// Two other axis will be perpendicular to gravity field
// and expereince 0.5 g-forces
// +1 g-force X-value = 399
// 0.5 g-force X-value = 333
// -1 g-force X-value = 266
// +1 g-force Y-value = 399
// 0.5 g-force Y-value = 329
// -1 g-force Y-value = 264
// +1 g-force Z-value = 411
// 0.5 g-force Z-value = 338 - 345
// -1 g-force Z-value = 278
//0.5 g-force X-value = 333
// x = (333 - x) ;
// x = x * 149 ;
//0.5 g-force Y-value = 329
// y = (329 - y) ;
// y = y * 149 ;
// 0.5 g-force Z-value: 344
// z = (344 - z) ;
// z = (z * 149);
// Calculated g-force
//Serial.print(" ");
Serial.print(x);
Serial.print(" ");
Serial.print(y);
Serial.print(" ");
Serial.println(z);
}
What do you mean with which one do you have? Are you referring to the board? UEB Arduino ATmega328P CH340G UNO R3.
I'm not sure I follow your comment on analogref. On the Arduino Uno I do have the choice between 5V and 3.3V or are you referring to the ADC reference voltage to convert analogue to Digital?
Yes - the ADXL335 is embedded in boards with Additional components that will influence some capabilities such as 0.1uF capacitors which set the bandwidth of each axis to 50Hz.
Yes on the UNO you can use in your code analogReference() to define the settings. Basically the range on your uno will be 0-5V by default whereas on the other board it’s 0-3.3V (sampled on 10 bits) so the sampled value does not denote the same voltage
After changing the analog reference, the first few readings from analogRead() may not be accurate. So wait a bit
Thanks J-M-L! I tried using the 3.3v on the AREF pin and the values on the Arduino Uno now came close to those on ArduLog indeed.
Do you have any idea why the z-value is either 256 or 512 when I use the RTC sketch as attached in my original post? It is suspicious I get 1/2 and 1/4 of the 1024 values, suggesting I'm only reading 1.65 or 0.825V, but the results from a simple analogRead script suggests this is not a hardware issue.
Well one issue you might have is that x,y,z are int and on a uno int are on 16 bits, signed - so max is +32767
When you do your average 40 times (in my opinion it’s useless and reading 2 different analog input very quickly can actually lead to wrong reading) if the value is close to the max then you overflow your int
OK found the bug with help from Mike from Hobbytronics. I was running the code on IDE 1.8.2. I found that by declaring the variable assigned to the 3rd AnalogRead (in my case z) to float instead of int the sketch would work. Because of memory I don't like doing that and tried IDE 1.6.0. This resolved the problem as all variables can now be declared as int. I don't know if the bug is present in other IDE versions but at least you could always fall back to the 1.6.0 version if and when necessary.
Read my answer #5 - I think this is the real issue. Try with unsigned long instead of int in you sum 40 Times a value close to 1000 you will overflow your int - that is 100% guaranteed and it’s not an IDE issue
Just for clarity, the 40 consecutive readings only happen in my test sketch (ADXL335_READ) not in the problem sketch (ardulog_rtc_analogue_read).
I'm confident the ADXL335_READ does confirm analogRead works fine on both IDE 1.8.2 and 1.6.0 at the default read frequency (default settings on ADC). My readings are between 400 and 500 each. 40*500=20,000 < 32,767 for int.
I tested on both Arduino Uno and ArduLog and the readings are sensible. I converted raw readings to g-force and the readings make sense.
Problems happened in the other sketch that I could run on the ArduLog only. Changing IDE from 1.8.2 to 1.6.0 did resolve the issue with the ardulog_rtc_analogue_read sketch. So I think the problem is with the IDE.