Multiple Sensor Noise

Hello,

Another newbie here. Thanks for your kindness and understanding with your responses.

I'm in the early stages of developing an open-source nano-sat tracking and communications station. We've decided to incorporate Arduino in our eventual design and are in the early stages of proofing our concept with OTS consumer electronics components. I just completed another slightly similar project using Arduino as the primary controller and have some understanding of and experience with interfacing Arduino with sensors, but in this project, as you might understand, fine accuracy will be quite important for locating and tracking satellites.

At this point I'm attempting to merely understand the calibration and raw sensor values coming off a MAG3110 magnetometer and MMA7361 accelerometer. They are mounted to the same breadboard on opposing sides (maintaining the same NED orientation). Because the MAG3110 operates only in 3.3V (for VCC, SDA and SCL for I2C), I have the SCL and SDA lines running through bi-directional level shifters. I noted that there was some noise and bad readings from the accelerometer when the two were mounted to the breadboard, so I backed off and tested the accelerometer component on its own and then tested the raw readings from Arduino with the breadboard connected and feeding input into the analog inputs from an external power supply.

When the breadboard is connected to Arduino (5V to high side of breadboard, 3.3V to low side of breadboard and GND) and I feed voltage from an external PS to the Arduino analog inputs, the Arduino output values differ by anywhere from 5-14, or .02V - .07V. (ie. connecting PS to A0, Arduino reads 3.3V as 687; connecting 5V, 3.3V, GND to to breadboard and PS to A0, Arduino reads 3.3V as 701). There is no linear relationship between voltages and errors, so a simple correction in the code does not appear possible.

I understand it's not a huge difference, but it may make a big difference when we're talking minutes and seconds of sky.

Any ideas? I'm wondering more generally how multiple devices affect Arduino analog inputs (and/or if some resistance/capacitance is required to clean up the readings)? I do see that input on one analog input affects the output values on other unconnected analog inputs (via Serial Monitor).

Also, I know I've seen this in other forums, but if you can remind me: the accelerometer ranges in output from .85-2.45V or 1.6V in range. That's only 327 possible Arduino values. To me, that sounds like .5 degree of resolution (also ~4% potential error as it stands right now). Is there any way to get finer resolution from this sensor and controller? I should mention I'm working with Arduino Uno.

Thanks so much for reading and for any support you may provide.

~J

Fritzing file attached.

Code (borrowed, thank you):

/* Magnetometer and Accelerometer Combined

analog 0: accelerometer z-axis
analog 1: accelerometer y-axis
analog 2: accelerometer x-axis

analog 4: magnetometer SDA (with bi-directional filtering)
alalog 5: magnetometer SCL (with bi-directional filtering)

both sensors' VCC to 3.3V
both sensors' GND to Arduino GND

*/

#include <Wire.h>

#define MAG_ADDR 0x0E

const int xpin = A2; // x-axis of the accelerometer
const int ypin = A1; // y-axis
const int zpin = A0; // z-axis (only on 3-axis models)

void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
config(); // turn the MAG3110 on
}

void loop()
{
print_values();
delay(50);
}

void config(void)
{
Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x11); // cntrl register2
Wire.write(0x80); // send 0x80, enable auto resets
Wire.endTransmission(); // stop transmitting

delay(15);

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x10); // cntrl register1
Wire.write(1); // send 0x01, active mode
Wire.endTransmission(); // stop transmitting
}

void print_values(void)
{
//Serial.print ("Magnetometer Readings: ");
//Serial.print ("Bx=");
Serial.print (readx());
Serial.print (",");
//Serial.print ("By=");
Serial.print (ready());
Serial.print (",");
//Serial.print ("Bz=");
Serial.print (readz());
Serial.print(",");
//Serial.print ("\t");
//Serial.print ("\t");
//Serial.print ("Accelerometer Readings: ");
//Serial.print("Gx=");
Serial.print(analogRead(xpin));
Serial.print(",");
//Serial.print("\t");
//Serial.print("Gy=");
Serial.print(analogRead(ypin));
Serial.print(",");
//Serial.print("\t");
//Serial.print("Gz=");
Serial.print(analogRead(zpin));
Serial.println();
//Serial.println();

}

int readx(void)
{
int xl, xh; //define the MSB and LSB

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x01); // x MSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
xh = Wire.read(); // receive the byte
}

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x02); // x LSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
xl = Wire.read(); // receive the byte
}

int xout = (xl|(xh << 8)); //concatenate the MSB and LSB
return xout;
}

int ready(void)
{
int yl, yh; //define the MSB and LSB

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x03); // y MSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
yh = Wire.read(); // receive the byte
}

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x04); // y LSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
yl = Wire.read(); // receive the byte
}

int yout = (yl|(yh << 8)); //concatenate the MSB and LSB
return yout;
}

int readz(void)
{
int zl, zh; //define the MSB and LSB

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x05); // z MSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
zh = Wire.read(); // receive the byte
}

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(0x06); // z LSB reg
Wire.endTransmission(); // stop transmitting

delayMicroseconds(2); //needs at least 1.3us free time between start and stop

Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire.available()) // slave may send less than requested
{
zl = Wire.read(); // receive the byte
}

int zout = (zl|(zh << 8)); //concatenate the MSB and LSB
return zout;
}

Nanosat Ground Station.fzz (10.2 KB)

Quick point - if measuring 3V3 sensors use 3V3 on the AREF pin and call analogReference(EXTERNAL) early in setup().

Make sure you are not measuring IR losses across your wiring by mistake - route sensor ground and supply wires separately from those carrying significant current (such as the ATmega or output loads). Remember breadboard connections being mechanical can have much higher resistances than soldered connections - tarnished and dirty contacts might be affecting things.

Decouple each chip/sensor as appropriate. If all your analog sensors have an output impedance of 10k or less you shouldn't need to worry about analog crosstalk.

Sometimes breadboarded circuits can misbehave due to the lack of a ground-plane - signal crosstalk or RFI might be an issue. Keep wiring short if possible. Provide voltage regulation close to chips using it.

Consider connecting AREF to a voltage reference chip rather than simply the supply voltage (which will be noisey).