I am using 2 MAG3110 magnetometers for a project with the Arduino Due board. I can’t figure out a way to utilize the MAG3110 library with more than 1 sensor, so I am using the Wire library instead. I am aware that SDA/SCL and SDA1/SCL1 are Wire and Wire1, respectively. I cannot, however, figure out how to call each one to print the x, y, and z ouputs. It seems to always refer to the defaut SDA/SCL. This is the code I’m using, I’m sure it’s entirely wrong so I’d appreciate any help! I basically just edited a code I found to include both Wire and Wire1.
#include <Wire.h>
#define MAG1_ADDR 0x0E //7-bit address for the MAG3110, doesn't change
#define MAG2_ADDR 0x0E
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Wire1.begin();
Serial.begin(9600); // start serial for output
config(); // turn the MAG3110 on
}
void loop()
{
print_values();
delay(2000);
}
void config(void)
{
Wire.beginTransmission(MAG1_ADDR); // transmit to device 0x0E
Wire1.beginTransmission(MAG2_ADDR);
Wire.write(0x11); // cntrl register2
Wire1.write(0x11);
Wire.write(0x80); // write 0x80, enable auto resets
Wire1.write(0x80);
Wire.endTransmission(); // stop transmitting
Wire1.endTransmission();
delay(15);
Wire.beginTransmission(MAG1_ADDR); // transmit to device 0x0E
Wire1.beginTransmission(MAG2_ADDR);
Wire.write(0x10); // cntrl register1
Wire1.write(0x10);
Wire.write(1); // write 0x01, active mode
Wire1.write(1);
Wire.endTransmission(); // stop transmitting
Wire1.endTransmission();
}
float x = Wire.read();
void print_values(void)
{
Serial.print("x=");
Serial.print(read_x());
Serial.print(",");
Serial.print("y=");
Serial.print(read_y());
Serial.print(",");
Serial.print("z=");
Serial.println(read_z());
Serial.print("x1=");
Serial.print(read_x());
Serial.print(",");
Serial.print("y1=");
Serial.print(read_y());
Serial.print(",");
Serial.print("z1=");
Serial.println(read_z());
}
int mag_read_register(int reg)
{
int reg_val;
Wire.beginTransmission(MAG1_ADDR); // transmit to device 0x0E
Wire1.beginTransmission(MAG2_ADDR);
Wire.write(reg); // x MSB reg
Wire1.write(reg);
Wire.endTransmission(); // stop transmitting
Wire1.endTransmission();
delayMicroseconds(2); //needs at least 1.3us free time between start and stop
Wire.requestFrom(MAG1_ADDR, 1); // request 1 byte
Wire1.requestFrom(MAG2_ADDR, 1);
while(Wire.available()) // slave may write less than requested
{
reg_val = Wire.read(); // read the byte
}
return reg_val;
while(Wire1.available()) // slave may write less than requested
{
reg_val = Wire1.read(); // read the byte
}
return reg_val;
}
int mag_read_value(int msb_reg, int lsb_reg)
{
int val_low, val_high; //define the MSB and LSB
val_high = mag_read_register(msb_reg);
delayMicroseconds(2); //needs at least 1.3us free time between start and stop
val_low = mag_read_register(lsb_reg);
int out = (val_low|(val_high << 8)); //concatenate the MSB and LSB
return out;
}
int read_x(void)
{
return mag_read_value(0x01, 0x02);
}
int read_y(void)
{
return mag_read_value(0x03, 0x04);
}
int read_z(void)
{
return mag_read_value(0x05, 0x06);
}
Edit your post and put code tags around you code!
Provide a link to that library. I guess it’s easy to extend it to provide the I2C port. In your code you read the value but as you just doubled all the calls you cannot return the value the same way. So it’s best to use a class to access the chip and not functions as you do now.
Thank you for the help, I’m trying to follow your instructions but I’m still having problems. I’m attaching the source and header files as well as the code I’m trying to run.
The code will not compile after I edited the source and header files and I am getting this error: “‘MAG3110’ does not name a type”.
Also, I am still unsure how to print the x, y, and z on the SDA1/SCL1 sensor. The code only prints to the default SDA/SCL and not both.
#include <SparkFun_MAG3110.h>
MAG3110 mag = MAG3110(TwoWire &useWire); //Instantiate MAG3110
void setup() {
Serial.begin(9600);
mag.initialize(); //Initializes the mag sensor
mag.start(); //Puts the sensor in active mode
}
void loop() {
int x, y, z;
//Only read data when it's ready
if(mag.dataReady()) {
//Read the data
mag.readMag(&x, &y, &z);
Serial.print("X: ");
Serial.print(x);
Serial.print(", Y: ");
Serial.print(y);
Serial.print(", Z: ");
Serial.println(z);
Serial.println("--------");
}
}
Thanks for all of your help, the code compiles and seems to work! However, I still am only printing out one sensor output. How do I differentiate the Serial.print for each sensor?
Your mag_read_register function returns after it has read the first sensor. There's no way it can read the second sensor.
You'll have to modify the function so that it returns one or both values in global variables instead of as the value of the function.
Can you elaborate a little more on that? I’ve been struggling with this for about a week and can’t seem to find a whole lot of information on the Due I2C subject.
I had to give up on trying to edit the librariy and just went back to the original code that uses only Wire.h. I managed to get it to compile and display the info for both sensors. It seems to be working fine for the SDA1/SCL1 sensor (shockingly), but for the SDA/SCL sensor it only gives me one initial reading and remains constant. I tested the sensor with the code for singular sensor operation and it works, so I know it must be something in my dual code, but I have no idea what. Any suggestions?
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Wire1.begin();
Serial.begin(9600); // start serial for output
config(); // turn the MAG3110 on
}
void loop()
{
print_values();
delay(5000);
}
void config(void)
{
Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire1.beginTransmission(MAG_ADDR);
Wire.write(0x11); // cntrl register2
Wire1.write(0x11);
Wire.write(0x80); // write 0x80, enable auto resets
Wire1.write(0x80);
Wire.endTransmission(); // stop transmitting
Wire1.endTransmission();
delay(15);
Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire1.beginTransmission(MAG_ADDR);
Wire.write(0x10); // cntrl register1
Wire.write(0x10);
Wire.write(1); // write 0x01, active mode
Wire.write(1);
Wire.endTransmission(); // stop transmitting
Wire.endTransmission();
}
void print_values(void)
{
Serial.print("x=");
Serial.print(read_x());
Serial.print(",");
Serial.print("y=");
Serial.print(read_y());
Serial.print(",");
Serial.print("z=");
Serial.println(read_z());
Serial.print("x1=");
Serial.print(read_x1());
Serial.print(",");
Serial.print("y1=");
Serial.print(read_y1());
Serial.print(",");
Serial.print("z1=");
Serial.println(read_z1());
delay(1000);
}
int mag_read_register(int reg)
{
int reg_val;
Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire.write(reg); // 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 write less than requested
{
reg_val = Wire.read(); // read the byte
}
return reg_val;
}
int mag_read_value(int msb_reg, int lsb_reg)
{
int val_low, val_high; //define the MSB and LSB
val_high = mag_read_register(msb_reg);
delayMicroseconds(2); //needs at least 1.3us free time between start and stop
val_low = mag_read_register(lsb_reg);
int out = (val_low|(val_high << 8)); //concatenate the MSB and LSB
return out;
}
int read_x(void)
{
return mag_read_value(0x01, 0x02);
}
int read_y(void)
{
return mag_read_value(0x03, 0x04);
}
int read_z(void)
{
return mag_read_value(0x05, 0x06);
}
int mag_read_register1(int reg1)
{
int reg_val1;
Wire1.beginTransmission(MAG_ADDR); // transmit to device 0x0E
Wire1.write(reg1); // x MSB reg
Wire1.endTransmission(); // stop transmitting
delayMicroseconds(2); //needs at least 1.3us free time between start and stop
Wire1.requestFrom(MAG_ADDR, 1); // request 1 byte
while(Wire1.available()) // slave may write less than requested
{
reg_val1 = Wire1.read(); // read the byte
}
return reg_val1;
}
int mag_read_value1(int msb_reg1, int lsb_reg1)
{
int val_low1, val_high1; //define the MSB and LSB
val_high1 = mag_read_register1(msb_reg1);
delayMicroseconds(2); //needs at least 1.3us free time between start and stop
val_low1 = mag_read_register1(lsb_reg1);
int out1 = (val_low1|(val_high1 << 8)); //concatenate the MSB and LSB
return out1;
}
int read_x1(void)
{
return mag_read_value1(0x01, 0x02);
}
int read_y1(void)
{
return mag_read_value1(0x03, 0x04);
}
int read_z1(void)
{
return mag_read_value1(0x05, 0x06);
}
You really must avoid interspersing Wire. and Wire1 commands together because you end up with errors like the above.
Do an entire transaction with Wire and then do one with Wire1.