Massive sensor noise/problems?

So I'm building a 9DOF sensor unit to use in a performance art oriented setup with it being strapped to a performers wrist. (this is the project Takahashi's Shellfish Concern - Live @ The Noise Upstairs - YouTube)

The main board is an ArduIMU board (ArduIMU+ V2 (Flat) - DEV-09956 - SparkFun Electronics) which has onboard 3axis accel(ADXL335) and 3axis gyro (LY530/LPR530) and I've also added a 3axis magnetometer(HMC5883L) which is being read through the I2C bus.

The approach I'm taking, since I'm going to be using Max/MSP to handle all the actual data mapping and everything, is to have the ArduIMU just spit out raw sensor values over serial (XBee send/receive pair using a call/response type setup) and all the numbers will be calibrated/filtered/etc.. in Max/MSP.

The main problem I'm having is that the raw sensor values seem to be incredibly noisy. You can see this short little video here:

http://rodrigoconstanzo.com/sensors/sensors.MOV

My Accel X and Magnetometer axis' seem to just jump from 0 to 250 or so, and just go back and forth. That doesn't seem quite right. It should also be noted that I get radically different numbers sometimes when turning the sensor unit on (sometimes its other axis' that do that "jump from zero" stuff).

Now as far as treating the numbers I'm using this wonderful guide here (http://arduino.cc/forum/index.php/topic,58048.0.html), and then just applying the same ideas but to Max/MSP. (ie for my calibration code I'm taking the mean of the idle value, then subtracting the sensor value from that, and dividing by 102.3 (basically this accVal = (accAdc-accZero)/102.3 ).

I eventually want to do something like this MARG filtering (An efficient orientation filter for MARG sensor arrays (real-time demonstration) - YouTube) but with the raw values being what they are, it's mucking up all the number crunching down the line.

Here is the Arduino code

#include <Wire.h> //I2C Arduino Library
#define address 0x1E //0011110b, I2C 7bit address of HMC5883

#define aX A0
#define aY A1
#define aZ A2
#define gX A6
#define gY A7
#define gZ A3

// define sensor variables
int AccX;
int AccY;
int AccZ;
int GyroX;
int GyroY;
int GyroZ;

int inByte = 0;         // incoming serial byte

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(57600);
  Wire.begin();
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();
  establishContact();  // send a byte to establish contact until receiver responds 
}

void loop()
{
  
    int x,y,z; //triple axis data for magnetometer

  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
    //Read data from each axis of magnetometer, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    inByte = Serial.read();
    
    AccX = analogRead(aX);
    AccY = analogRead(aY);
    AccZ = analogRead(aZ);
    GyroX = analogRead(gX);
    GyroY = analogRead(gY);
    GyroZ = analogRead(gZ);
    
    Serial.write(AccX);
    Serial.write(AccY);
    Serial.write(AccZ);
    Serial.write(GyroX);
    Serial.write(GyroY);
    Serial.write(GyroZ);
    Serial.write(x);
    Serial.write(y);
    Serial.write(z);
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.write('A');   // send a capital A
    delay(300);
  }
}

So is there any reason why I should be getting this kind of sensor behavior? And more importantly, what can I do about it?

Yup, just restarted the system and both my Accel X and Y axis' are doing the "jump from 0 to 250" thing.

If you read the documentation for Serial.write() you will achieve enlightenment.

Your video is upside down :slight_smile:

For some reason it plays right side up for me, though others have mentioned the same problem. Weird.

The original code I had was based on serial.print(val, BYTE), but I literally just changed whatever Arduino 1.0 complained about to the newer versions.

I had a read through this (http://arduino.cc/en/Serial/Write) and don't feel any more enlightened. I thought maybe for a moment that I wasn't converting the data format in Max, but running it through a symbol to number object, nothing changes.

Can you elaborate?

You are sending 16 and 10 bit values down an 8 bit pipe - you are losing the top bits.

Aha!

So my accel/gyro are 10bit and the magnetometer is 16bit? I'm guessing the onboard Arduino ADC is the 10bit and the i2c is 16bit input?

So how do I get that data into Max if not using Serial.write?

Looking through an older version of my code I noticed I was using this:

  Serial.write(highByte(z));
  Serial.write(lowByte(z));

Instead of just using Serial.print

Should I be doing that? (splitting each sensor into two bytes)
Or maybe using Serial.println and sending it as ASCII?

I think I started using bytes when I wanted to get the message sent as small as possible (for minimal latency).

That's exactly what you should do. On the other end you'll need to recombine those two bytes into an int. you should be able to find easilly find some sample code that does the lowbyte/write and then on the read recombines.

Perfect.

Now just need to figure out how to fuse the bytes together in Max.

Does it matter what order I send the bytes in?

  Serial.write(highByte(z));
  Serial.write(lowByte(z));

or

  Serial.write(lowByte(z));
  Serial.write(highByte(z));

Finally got it working. For people searching for the similar problem in the future, here is the Max code that merges the bytes.

----------begin_max5_patcher----------
828.3oc6XstSaCCE92sOEQQZ+Yqqy2iyDBo8bflPtMFvrboJwkwFh284KMsz
aotrR.jnRMwI1Ge9Ne9bN1m7vvAwSptW1DG88nKhFL3ggCF3dk8ECV77f3Bw
8SyEMtgEWLOWqZxUYx53Q99mIzSuQUd8k0xoZ+bQ.iAihvb2MHD6twGCh9Yq
LRwulVkWU6GOXLIkCvoi1YK3SDbpnLSYtH4sRBPIDJzMdRBf5jjBfoL3djjr
Tm3TDjYGOyLb.21BXlBNecImIpEERsr9RYoXRtzJOXQekyKTk4RsicfapJZq
pnbBFRrJfuBtXHNAutpppUxRsPqpJ2PKUy0spA0plpRclPK1opSZUMOwpaqB
QNMZaAITPJeO7CtURTpkFcPEBSXTaqDyLfXa.ZGzz+YlzKYb7Hy+kc2H0FNx
3EsbEacwUYNOqpI29UDIdSzvZkJAa+4VivTTpiLS3bDltG6.0JYq0ZrHi+DB
YagoLNqk7sB93vg1KiBLN3p7JyhxgCAnta9qHv+iS0UlU6F0ecCDhF2sqwVK
IF7Jz10kIhxqi2I2iiehlJMfy00OpUh73mACUJ+sYZamSs7dGwD+sHFkhoiO
L0g7TGYKpaM5AcLzCra5YmzBrWnkubP9.4ylx4iou77gpbOrA3zxFSqJJLI7
1hNxq5fOfXOg.89IftcPNp3Gv1lLj2Ol7MpNLYVuZwI8hK+YmEwOrWOcQdz9
HKv975gzSLgLuXRmmeB5WngouQ18vRLcs2Aum4Gx6K5g0KwSexDrvBvoxSdj
W0HJTuvHmed.YXfj2BYXNs7QfmN8czgSOwNLGSYrnOph8ipXOlpXwuWJhcOo
M+bnkn4qHgRecqPiDVpAmnw4pxM+fWNyy990Yplp40Sa0daAxQqrwLYiVUtz
I+hUeAimLnaTYYx0BBxTM1nOG7A6bMKX7.CAO39COfPvCr2vCOD3XwLrWfis
HhvvS+POr.fyFX9E06AE.d5ufKRHryaJzfN.ZJTYypLm+bQ1ORp86HAgL+ga
V8zJ0b5b8C.9r9ySK.zv6MzDzlJnmIb764IlM6NYcyh4zgDy4.t0erU1H2ip
R+itYLtVdmpc7zg1Y6wg+CvmzqdZ
-----------end_max5_patcher-----------

I also ended up with a weird problem in my parsing code (in Max) that meant the bytes were not coming in the correct order (which breaks everything). Once that was sorted everything came in nice and smooth. So satisfying to see that steady stream just rolling on in.

Actually it turns out that my 12-bit sensor data isn't making it in correctly (my magnetometer).

Actually it's all working perfectly for the 10bit sensors (accel/gyro). I'm wondering if the bytes are getting split and then recombined incorrectly.

Here's the relevant Arduino code:

Wire.requestFrom(address, 6);
if(6<=Wire.available()){
x = Wire.read()<<8; //X msb
x |= Wire.read(); //X lsb
z = Wire.read()<<8; //Z msb
z |= Wire.read(); //Z lsb
y = Wire.read()<<8; //Y msb
y |= Wire.read(); //Y lsb

So it's reading and splitting into a high byte and a low byte already.
Then I'm sending that out:

// Magnetometer X
Serial.write(highByte(MagX));
Serial.write(lowByte(MagX));
// Magnetometer Y
Serial.write(highByte(MagY));
Serial.write(lowByte(MagY));
// Magnetometer Z
Serial.write(highByte(MagZ));
Serial.write(lowByte(MagZ));

Now the values I'm getting inside Max are kind of hovering around 250 for each byte (low and high), so the sensor values I'm getting are in the 60000 range, now this being a 12bit sensor I should be getting no more than 4095 max.

Any thoughts on what can be happening between the value being read and sent out of the Arduino?

When you only show two pieces of code that don't appear to have the error in it makes it very difficult to guess what he problem is - try posting ALL the code!

Are you sure you're reading the values in the same order you are writing them?

I've tried switching the order that they are combined in in Max and that doesn't make a difference. I've not tried mixing up the code in Arduino but from what it looks like to me the Wire library is making a single int out of the values coming in over i2c and then I'm splitting that into two bytes. There's no 'wrong way' around for it since it's all getting boiled down to an int.

Here's the complete code

// i2c Arduino Library
#include <Wire.h> 

// 0011110b, i2c 7bit address of HMC5883
#define address 0x1E 

// Define sensor variables
int AccX;
int AccY;
int AccZ;
int GyroX;
int GyroY;
int GyroZ;
int SW1 = 9;
int SW2 = 10;

#define aX A0
#define aY A1
#define aZ A2
#define gX A6
#define gY A7
#define gZ A3

// Incoming serial byte
int inByte = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  // Start serial port at 57600 bps:
  Serial.begin(57600);
  
  // Set incoming switch mode
  pinMode(SW1,INPUT);
  pinMode(SW2,INPUT);
  
  // Start i2c communication
  Wire.begin();
  
  // Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();
  
  // Send a byte to establish contact until receiver responds 
  establishContact();  
}

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  // Define variables for magnetometer
  int MagX,MagY,MagZ; 

  // Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
  // If we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    inByte = Serial.read();
    
    AccX = analogRead(aX);
    AccY = analogRead(aY);
    AccZ = analogRead(aZ);
    GyroX = analogRead(gX);
    GyroY = analogRead(gY);
    GyroZ = analogRead(gZ);
    
  // Read data from each axis of magnetometer, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    MagX = Wire.read()<<8; // X msb
    MagX |= Wire.read(); // X lsb
    MagZ = Wire.read()<<8; // Z msb
    MagZ |= Wire.read(); // Z lsb
    MagY = Wire.read()<<8; // Y msb
    MagY |= Wire.read(); // Y lsb
  }
  
  // Send sensor data out
  
  // Accelerometer X  
  Serial.write(highByte(AccX));
  Serial.write(lowByte(AccX));
  
  // Accelerometer Y
  Serial.write(highByte(AccY));
  Serial.write(lowByte(AccY));
  
  // Accelerometer Z
  Serial.write(highByte(AccZ));
  Serial.write(lowByte(AccZ));
  
  // Gyroscope X
  Serial.write(highByte(GyroX));
  Serial.write(lowByte(GyroX));
  
  // Gyroscope Y
  Serial.write(highByte(GyroY));
  Serial.write(lowByte(GyroY));
  
  // Gyroscope Z
  Serial.write(highByte(GyroZ));
  Serial.write(lowByte(GyroZ));
  
  // Magnetometer X
  Serial.write(highByte(MagX));
  Serial.write(lowByte(MagX));
  
  // Magnetometer Y
  Serial.write(highByte(MagY));
  Serial.write(lowByte(MagY));
  
  // Magnetometer Z
  Serial.write(highByte(MagZ));
  Serial.write(lowByte(MagZ));
  
  // Switch 1
  Serial.write(digitalRead(SW1));
  
  // Switch 2
  Serial.write(digitalRead(SW2));
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.write('A');   // send a capital A
    delay(300);
  }
}

And the MAX code that reads the packet? You are configuring the serial as 8N1 ?

I've not configured the serial in Max at all, it's just a generic serial object [serial a 57600]

----------begin_max5_patcher----------
4233.3oc6ck0iiabD94Y9UzQH4onc.6CdY3WVi7PdIAAw.9EaiETRbjnWJRA
RpY1cM7+8zGjTjT7nnFINMcjCxrhGhppu5nqp6pZ96O9vhUwewOcA56P+L5g
G98Ge3A4oDm3g7ieXwduurNzKUdaKx7+R1piYYwQKVpt7gD+T+nLurf3nOk3
uNS83H3mLVhvtOQswFtrkHl6SLrCiXKOqA5Wy+9q1FGsNNLNQ88Ldxlgw1VK
4ehe6TLS7IaSKGKp3SNkew3iYg9YYe8fu5atXwR0+OHhSCE2kffkTdPTPVfW
Xv27WT4Rwu3mT62WQ1U+yIJMNYieRMZ0XY8+TduOGGkkJ9s32HV7jJY1WZ7H
HV7+ydYGexs7IdvKa8tfnsUvXriwSlbZzR7qa57joiqqqUC7sp7QRM4mOXiD
VhW8ae.WfHIwGi13KufQIMevKwauelexm7i7VEJYo57yHDfUwSA9CC4iNtOH
hKrSqx.q1VGGWV4OM+YTrdK5.JYZCFnWoZDGLjOr+oe3K9YAq8P+a+ikOPNo
pTLkzJsgp1XTzj3r3D+wiOJ9yxK1D8EujRp94fPtnb.iWrqoPhwLbqYByUwL
rvtNtuES3pLJGoNbLae7lZJUizv9G8iRiSR+SiUMkHIQoQsEoznlve.XCCG5
XrrITm+ew1tgZvU2vtPKEqMF5G26Gcrf71IMN9NggRg1QbVrvHpju9XB22ma
ocR71KRx1gKCa1ShuOyrlGC9odxk5ZJNMoJfGj4uOOviE+P3Q+r33rce3+7O
93G9wuFsVXruT7mSW5ewg+8km+X5pTeA67gOx31DLueZQ2wEHPlbOHmtKujj
3Wqpt2gsMezhs0rtZabXWWw3vLao7ka4JXYSRCVtKyU9CLKoo1UEaXKValv.
LfgaClatQZ0Nogv+4fu7oBpkbMrgeVvA0tUbYzds8oQY0VhADHNhZwfdWX1E
YlH0ujr1kZd+bXLmjVzkVM+xdR85UdQaWz9PTjJN5OebFtooImEDllL9XRtF
tFbFyz3IKGL0toA6IExR8w9T9ZUkHiaxFss9MVSHJcQ0dnTDMGBI0fPpEwl0
MDZeGBaABMFiVnycH7bHTjQHbHDeGCaCCsFikLAeGCaACG0.JDxcLrELjLJL
z5NF1BFNpgTH2GVtELrwPJhj7vcigT5rACi7ekSwKZNeRGPpTKWLP9jW5+bd
tniPrHman7DMsrexrmA2scWzFZSGIxhIUIG0rU7PIh9fXBE8ewOIsdVs7DfN
bnxoenxWQHF9MUFUVKKOUPj5TFkmJw+kfhuuo5jbg6iEWr.SLUfBwwUhJFtx
+01nR1XhjQCiW+4Z4NykrG7iBhZlWd4k23+r2wvrO0t3o90e1aseme4Vg4GV
rMIXSbjfHp8MEmt3mimvpojqLqxLx6Hx6PKe4TNebLckWh.5xM5HEWLKNNr9
kJkVbKEunf8dY7TnUDKOZ7hKFr+PR9zKUdNkM8tz0Iwgg0dTpq7RKWYCWft1
+0fMY6pMMjhqvu8fCEhfEkXzlfs9oY0OWl21z5mo1xXUUSqpKfZmugq.o4Qw
iq84ftD96xzL2pTsvWDyh+V66Uw9zr5OWMKTi5WnpsXkqrNd+d+h47q3zROf
4FJWHTv+EWUt.A85.r1XK83HqKDyQrjUKQVVRDyTNYSU8lc1DggWT6A14vKc
NDS+N95ZXk4Gvx88MJfkbGXAAr1LiQArlt2AVP.qkCcbZrF2AVX.KQsNhf0X
ctCrf.VSK2wAryaerEQaT4GqLgoUAQdIeEk9ZfHAgTTTbFZcbTDGq72f7xPY
67Q6ia98CC32Q7QUHLzKevNFUJAXxr.bYxDjb5VPvrWbsAZiIBnWG56kf9VH
ZaR7wCKtXHC6HcJPoxHVcnCo6xLmsPFmoi2yUP2hBie8G9ZlOxKZCZWv1cxC
3NChQdnz.w7NfdwKrbkCOWEkb43ssDhYlTUd6RMUJqa.Gq03cs4MoNb+2Gz0
6aI5KaowsonLjTEiT+psjtszIWHLhmFX76+djyTfjDIFRMGDIclqH4MUgzx0
ZTJjX7cEx9QRvJj20GaCEwNiSejcWerejDp9H15tBYaIIwLFkBI8t9X+.IX+
i2cP1FLxTgdCOBx6NHG.IAqPZdWgrsEMxYbozbWeb.fDp9n8c0w1PQiwkPiy
c0w9ARvwOZbWerEXjPFYBM2Cfb.jDrB4cGjsNStliKgF7cOjCfjfCfb1lg8w
nCdq+Lx.1+CxZW99+OucAOSsRc1VpUNE2ij2c7qFxO4mrwKxqm0F8ZtfHpm6
BXJ7pxSb35CiR.w1MVlmIn.w.wsEi2.laYyYtsHbOvbq0rlayy0BL2ZOm41h
Y5.L25Lm41hIZDL25Nm41ho4GJ2xLl0bq637RwvyYtsXMtAysy5wacLGmWJF
cVyst3Qws15J2t2OM0aqeq4M7sPY8dMhtRXrUAlpNjrrTEmjr1j5ov4Hy1IW
4PvAejogwsCJI1pBpSUJh1ClL6rc59xPqPPTLkkW6xSJwukotxT0XW4EbKYv
4bwcgVWhx8nmhptk9z8dgUd2X8FfTaEJRwvzWsu9yFHoIEdpyBqidc1ggc0k
gM95s0sgczwgc00g057vFceHwU48TggpHrnh5qsJV1d+GBnGDgzGhC1Kh.6G
wd5IQX8k3.8l3f8m3.8n3f8oXW8pX+8qX+8rX+8sXu8tXW8uX68vX68wXSc4
lNYN65CVZzM73De3XnmnpnUtdPuFjsSVu9pdfFcHNICsdWLm+SEmOBsNLN0G
sk+kZ9T6pZoGvAUmAvSKlYPQbIlsUyz8UVf858eX2U8UC00FIn9nAuUA1YiN
TWd0Fr2ejLWH3ql9NhkxJW4jq4HD8lSQuiTbQvO98G9S3jiuzlXXgvxqif.S
yWjIR2Q+z4dvvsQPPd+EDeKDEj4mfvSsb.aiUqdAD4Pshd5OkxgLjARNdKR0
aRCKOxWDI0fzKy6oo1VVo2jiKKkvBnXhcSG1f89KlRkv8yHdzx9QaP+szIYL
jBWWprLvXGHBCmaprPCFCI0ODk36sYPQPQJzWSuWLb20sPu0tv7z6Uys0Cn5
5cGPDo6Ibr2Ic7b7yneE0FWs0IfbdfbE5dp0HEH1wlwX2YSgcmY3fehJ9Oqw
hNlixIYmSqsdiN4UFjg4H.Fq2Afo97eHRBdfT3k7p395G0RiOlrtvRKenQz4
r+F+zrfnxYN5mOkKFBe1MuKXylymUF0DUjJlBjMWdhtWJaIr0AyW31AAsjun
ifuHrYCewFCeIrHmI7EscSl14q4iZnHITvhKJc9vWBKFxsRMbevlCw7blRKV
fO1SXwquCw6z.013fJTvZGPT0zHUsuL511jU9NiWPUusMmW5AiZXwYDeQuU7
US8a0dIpq8I8Wwm0H0W4.+PUeI2J025w5swWLcJ9Qq+5mV6sdWN4h90GaaQC
Wj58h+lOwIOdDteR7N+HX0wLUrhstpmcsRduokAr80cpqUoB5hFFFuxKLeUb
KuuEMI5ddBvVhyFqy1imKjtwkjib0v9q3aVcjPH46ES3hcwp9KIGrsduihbV
4LT809iW4aymUke5za9mMkexu7SOW9oskeZW4mBJ+zuU9oOWWZ.5UCzkH2vX
0KhOUw.LbIpXWqXCC8V4GtNLX8maVjJCsOwErMJlSFs8UuJE9BcZJ7k7Ea1C
YZaY.pEXdSUqkU0peQsWn0uzho0UTTedrrLucNqTEQDyPVw3ThzBnGmUty0Z
dSLi8XPU61U.NopEXjNnV40ue3HS1dx2o2CmxhJQVMIonWEkWR1wjH+Mn3H4
F0W7yOeK1O9LXpz0T6GeTyg1O9rXy28Lxc9q+bJ543DIR6ktNHPsQGxAWzur
3i+xBTVLZk+1fHD+AEDcbsLb5mPnO9rXM1yEVhKt+XTf5pnfTzduM9K4OU9G
WIptMT5tiYonMwuF8zMXi9jpDWD0frDUs112N8oEcttMJZbSaEbUodSMrO42
t2ct1Yaqf+W9v.9seq6xCpkzlZa.DImsaBNBGz7ruucY9jCk4uDOLYCtcJq2
6DNYwaEuHaFktWOJXmhFX.TgdU1joeOUwt8MogpeW.nhYLmCXcf.+uFQrVnc
hUyVwvaizNZcHq810KVlnvaddoJETlxNOeVD5YiQfZdK1XDlFDsXSLGQLFrc
WtFF8461DtChoWvDpoKXpvr2.XlpWkLVy6YPUI5yFLiUZ2NToZv7S02znHa5
ga2HS1lUl1Wp6fch4rcejlGNRRLBaLrN5ae98x0KArIMo2aVp8kc++02aSQq
5DDc3XFZ0wmelmztng49JGnQ6CBCCR44eGsI8VLUJJW.37YRwcv2rA58qRhq
v6AthWuCNvZMcrst9hfaXr.TJLFi60hG11RSwCP6LAtViaGEAaeq2tXN8Zi7
rRS7DBz1pxWAGNe03IMWf8tpWuyqtu1WF91WB9dEailnEqV5UlpaTGEj7IAh
vjqFhMt7n5+pS.ux.xqhzbqWXEuiBHvDMCHQ2rNWxkHp.tnVjxidWjOX.rpn
26uDVkPkucMIV4SgDqkiT9mnX2xilXXfbysHwNL8vhjZdyYUpkf4XpzxbUqN
a0CHXqhdXzL+nIFDZQY9JCBEJyp8URroYKGolSfRcA6IGFbu4iC4H4MVdWKo
lKo5GQTsTeQORV+n7has.gHSNB4.DgnVZS3ERcaXRUm2jTkXRUEnoc4QSsYL
PNUeh8yBHE6pMTrITP1jdgZSlxgDoTU9pD6xilXsISywD02kLlPNuoJf.psZ
S5o1Q49+xuS4QSMJ.M1Wli9niRARyVuMAmUtTAWdzTKbfxnsnKq8BGYFfuEo
iJ3JUzmxilZoiAznEv5izAHI2RTEvDNlVpf7USAUdjC3o2uFy4ZON1DPyP0m
r0FRVldIjLqH5SHNTnY+S0GupTn9ZLsmezLA+lBkT7JNPVD3mNZpmjECnyuf
FYE.0HPeHYoODS.zri1L2xRR1Bx.t5EJigPyVDMinsgPzXMinYPHZCMingXE
ZpYdNvTHDsilQzDHDslYHZCbR5zHezXHCeS0LZFhSZhyLzIMwVuPZPQwZoW.
sCDZ1TunYWHzrt44.jxAYFF0gtQyPRvRyB8m.Zg4lggbfslgA2g0LWGfnYcK
nCHg9iw5EQCwaGVixwB5jWSzHWGfWcdMZXEnqOOViBhF5R3Pzmxff.dkMzHb
ldsWcul0MmqZckcqsNltS+5XRfVU05yJkQLt0BmJKqbYaDz3HU0MVJ3l9JXA
b0vqOS4IFZf7jKs5.x2SrbUKFjR3HOZpK0Z3Ua4kt7WVNJlSUdo4aERhilZV
EbYSRzntx.7X+1jKUUTo7k+tlO+UJ06PgpfsgFy.0PiDPfqbccRqh.tRy0Hm
xfKgX8IB.LXyWMpSv.WqkZjYH3vf0HbFZA9vzHaPnQzdsxP5TCZ169IbwdI7
P6iv47Vq6evc0b28tuAe9dFba6Wv.1qfGXeBtml9dn8G3N1afUfr7u4vb8df
UBUmof76O1QKDTytpyQSpEW84pDmqNjSeKGMAQpmjduTjwjPQpeKqAnHmNnG
7MhdrGfdrmX54zJb2UQlvlXIly.DDahQngzoq+ZpXJDYCPPjoVGhLDAYMwDD
cHBhLwDDaHBBOwDj4PNpmP+hfG2fbAdgTiz13MytfTZ7lXuwaf8lu404Os+3
w+G.GtSLj
-----------end_max5_patcher-----------

Are you sure the line
MagX = Wire.read()<<8; //X msb
is working as you expect. The byte needs to be cast to an int, is this done before the shift or after? If before the cast then the values you are getting will all be zero. Might be worth putting a debug line in to check the values read for MagX make sense (also MagY and Z)

Most of the wire code is from the example sketch for the HMC5883L.

I didn't know what the "MagX |=" meant in the context of the code (still don't) so I just took the variable the Wire library spit out and split it from there.

MagX |= is shorthand for MagX = MagX |

| is the bitwise-OR operator. The code's assembling 16 bit value by shifting and ORing 8 bit values together ?

My bitwise knowledge is pretty much nil, so I didn't know what to make of that.

It's a 12bit sensor, so I don't know if that impacts stuff. The readings I'm guessing for those bytes (both low and high are in the 250 range, though one of them sits at 0 for the most part), so something is definitely not write in terms of splitting into bytes (at the wire library level) and recombining them (at the arduino serial.write level) because what I'm getting on the computer isn't consistent with what should be happening.

Another thing is that when I originally wired it up I had the SDA and SCL wires mixed up (I got no data through at all) so I went back and rewired it. There is the possibility that it was right before and I had something else wrong? (Can i2c stuff work if the two data lines are backwards?)

Scratch that, I didn't have the data lines backwards, I had all 4 wires 'upsidedown', so that's why it didn't work at all (at first).