Recently I am working with two accelerometers: BMA020 and BMA180. I will try to explain my problem using BMA020 as example because it is less accurate therefore problem is more visible. When I hold my Acc in neutral position I get correct average result: -1G. Now I turn my Acc upside down but this time my average result is +0,91G. The same problem occurs for other axis. For BMA180 problem is less visible (-1G in normal position and +0.98G upside down). Do you know why accelerometer behaves like this ?
You have to calibrate the accelerometer to compensate for this. Usually, calibrating an accelerometer consists of finding a scaling factor and an offset vector. So the calibrated measurement vector Z can be written as:
Z = aX + B, where a is the scaling factor, B the offset vector and X is the 'raw' measurement vector.
If you mount the accelerometer on a device, the accelerometer axis system should be aligned with the device body axis system. If this is not the case, for example if the pcb is rotated or upside down, the calibrated measurement Z should be converted to the body axis system using a rotation matrix. You can combine the rotation matrix with the scaling factor a, so you get:
Z = AX + B.
A is now a 3x3 matrix. Z is the calibrated measurent in the device body axis system. The values of the 3x3 matrix A and the 3-element vector B are found by putting the device in a number of known, fixed orientations, so you know Z. By measuring X, you get a set of linear equations that you can solve to find A and B.
Hope this helps.
This behavior is usually specified in the datasheet. For example, in table 1 of the datasheet of the BMA020 accelerometer you have the entry "Sensitivity". Probably you are operating your sensor with a 2g range. If your sensor has a temperature of 25°C, according to the datasheet the raw output of your sensor is typically 256 LSB if it is exposed to a acceleration of 1.0 g. As specified in the datasheet, this is only the typical value. Each manufactured sensor is a little bit different and thus the "min" and "max" columns define other possible values, depending on your specific sensor.
In your question you talk about measurements in g units and not in LSB. Thus, the code operating your accelerometer already converts the raw measurements to g units. The conversion algorithm can range from very simple algorithms to very sophisticated algorithms. An ideal conversion algorithm would incorporate all errors your sensor makes due to production variations and due to the current operation conditions. To compensate for the production variations this conversion algorithm should make use of calibration values which you found for your specific accelerometer or which are known from factory calibration (expensive sensors). Additionally, if you look at your datasheet again, you see that the sensitivity of your accelerometer depends on the operation temperature. Thus, if the defined error due to temperature change is too high for your application, you need to add an temperature sensor and your conversion algorithm should use the temperature to correct for this error too. There are also additional error sources defined in the datasheet and the algorithm for converting your raw measurements to g units can get very sophisticated.
Thus, the reason why your sensors don't output 1 g is simply that you're using some conversion algorithm to get from the raw sensor readings to g units and this algorithm probably neither uses any calibrated values specific to your sensor nor does it incorporate the current environment conditions.