Lora one magneto interruts

Hi,

I’m trying to get the loraone to trigger interrupts when the magnetic field has changed with not much luck yet.
Here’s my current test code:

#include <Wire.h>
#include "LSM303.h"

#define CONSOLE_SERIAL SerialUSB
#define MAXMARGIN 50

LSM303 compass;
volatile bool int1_flag = false;

void ISR1()
{
  int1_flag = true;
}

int16_t _baseX, _baseY, _baseZ;


#define ACCEL_ADR 0b0011110

#define ACCELERO_COMPENSATION 0.061

uint8_t writeReg(uint8_t reg, uint8_t val)
{
	Wire.beginTransmission(ACCEL_ADR);
	Wire.write(reg);
	Wire.write(val);
	Wire.endTransmission();
	delayMicroseconds(10000);
}

uint8_t readReg(uint8_t reg)
{
	Wire.beginTransmission(ACCEL_ADR);
	Wire.write(reg);
	Wire.endTransmission();
	Wire.requestFrom(ACCEL_ADR, 0x01);

	uint8_t val = Wire.read();
	Wire.endTransmission();

	return val;
}


void calibrate()
{

	float x, y, z = 0;
	for (int i = 1; i <= 50; i++)
	{
		compass.read();
		SerialUSB.print("x: "); SerialUSB.print(compass.m.x); SerialUSB.print("y: "); SerialUSB.print(compass.m.y);  SerialUSB.print("z: "); SerialUSB.println(compass.m.z);
		x = x - (x / i) + ((float)compass.m.x / i);
		y = y - (y / i) + ((float)compass.m.y / i);
		z = z - (z / i) + ((float)compass.m.z / i);
		SerialUSB.print("avg x: "); SerialUSB.print(x); SerialUSB.print("avg y: "); SerialUSB.print(y);  SerialUSB.print("avg z: "); SerialUSB.println(z);
		delay(100);
	}
	_baseX = (int16_t)x;
	_baseY = (int16_t)y;
	_baseZ = (int16_t)z;
}


void setup() 
{
	while(!CONSOLE_SERIAL){}
	CONSOLE_SERIAL.println("Testing Accelerometer");
  
	pinMode(ACCEL_INT1, INPUT_PULLUP);
	pinMode(ACCEL_INT2, INPUT_PULLUP);
	attachInterrupt(ACCEL_INT1, ISR1, FALLING);
	attachInterrupt(ACCEL_INT1, ISR1, FALLING);
	
	Wire.begin();
	compass.init();
	compass.enableDefault();
	writeReg(0x16, 0);		//make certain that there are no offsets currently stored, so we can calculate the new offsets.
	writeReg(0x17, 0);
	writeReg(0x18, 0);
	writeReg(0x19, 0);
	writeReg(0x1A, 0);
	writeReg(0x1B, 0);

	calibrate();
 
	writeReg(0x20, 0b01010111); //ctrl1
	writeReg(0x12, 0b11100001);  //enable interupt gecongition on all axis for magneto data.
	writeReg(0x13, 0b11111101);

	
	writeReg(0x14, (byte) MAXMARGIN & 0x00FF);
	writeReg(0x15, (byte)(MAXMARGIN & 0xFF00) >> 8);

	writeReg(0x16, _baseX & 0x00FF);
	writeReg(0x17, (_baseX & 0xFF00) >> 8);

	writeReg(0x18, _baseY & 0x00FF);
	writeReg(0x19, (_baseY & 0xFF00) >> 8);

	writeReg(0x1A, _baseZ & 0x00FF);
	writeReg(0x1B, (_baseZ & 0xFF00) >> 8);
	
	writeReg(0x22, 0b00001000);
	writeReg(0x23, 0b00010000);
}

void loop()
{
  if (int1_flag) {
     int1_flag = false;
    CONSOLE_SERIAL.println("INT1 Interrupt");
  }
  compass.read();
  SerialUSB.print("x: "); SerialUSB.print(compass.m.x);
  SerialUSB.print(", y: "); SerialUSB.print(compass.m.y);
  SerialUSB.print(", z: "); SerialUSB.println(compass.m.z);
  
  CONSOLE_SERIAL.print("register: 0x" + String(0x13, HEX));
  CONSOLE_SERIAL.println(", response: 0x" + String(compass.readReg(0x13), BIN));
 

  delay(1000);
}

The basic idea: calculate the offset that has to be applied (calibrate function) , store that in the mangeto meter + set a threshold (50). But this does not produce any interrupts at all.

Does anyone have a working example of interrupts based on the magneto meter or know what I might be doing wrong?

To configure the Magentometer have a look at the following registers:

CTRL5 (0x24h) specifically the M_ODR bits, the default data rate is “Do not use”.
CTRL7 (0x26h) specifically the MD bits, the default mode is Power-down mode.

Datasheet: Link

Here is an example which takes the Magnetometer readings.
It does not have the interrupt system configured. I will look at adding that soon.

Your calibration will also have issues as you are trying to pass 16bit values as the second parameter to writeReg().

I did some further tests with your suggestions but no luck so far. This is what I currently have:

#include <Wire.h>

#define CONSOLE_SERIAL SerialUSB

#define ACCEL_ADR 0b0011110
#define TEST_REG 0x0F

#define TEST_INT1
#define TEST_INT2

#define MAXMARGIN 50

volatile bool int1_flag = false;

void ISR1()
{
  int1_flag = true;
}

int16_t _baseX, _baseY, _baseZ;

void calibrate()
{
	int16_t x_val, y_val, z_val;
	float x, y, z = 0;
	for (int i = 1; i <= 50; i++)
	{
		readMagneto(x_val, y_val, z_val);
		SerialUSB.print("x: "); SerialUSB.print(x_val); SerialUSB.print("y: "); SerialUSB.print(y_val);  SerialUSB.print("z: "); SerialUSB.println(z_val);
		x = x - (x / i) + ((float)x_val / i);
		y = y - (y / i) + ((float)y_val / i);
		z = z - (z / i) + ((float)z_val / i);
		SerialUSB.print("avg x: "); SerialUSB.print(x); SerialUSB.print("avg y: "); SerialUSB.print(y);  SerialUSB.print("avg z: "); SerialUSB.println(z);
		delay(100);
	}
	_baseX = (int16_t)x;
	_baseY = (int16_t)y;
	_baseZ = (int16_t)z;
}

void setup() 
{

	while(!CONSOLE_SERIAL){}
	CONSOLE_SERIAL.println("Testing Magnetometer");

	pinMode(ACCEL_INT1, INPUT_PULLUP);
	pinMode(ACCEL_INT2, INPUT_PULLUP);
	attachInterrupt(ACCEL_INT1, ISR1, FALLING);
	attachInterrupt(ACCEL_INT1, ISR1, FALLING);
	
	Wire.begin();

	writeReg(0x1F, 0b10000000);  //reboot
	writeReg(0x12, 0b11100001);  //enable interupt gecongition on all axis for magneto data.
	writeReg(0x13, 0b11111101);
	writeReg(0x14, (byte) MAXMARGIN & 0x00FF);
	writeReg(0x15, (byte)((MAXMARGIN & 0xFF00) >> 8));
	writeReg(0x20, 0b01010111); //ctrl1
	writeReg(0x16, 0);		//make certain that there are no offsets currently stored, so we can calculate the new offsets.
	writeReg(0x17, 0);
	writeReg(0x18, 0);
	writeReg(0x19, 0);
	writeReg(0x1A, 0);
	writeReg(0x1B, 0);
	
	// Enable Temperature, High Resolution, 50hz, no interrupts
	// CTRL5
	writeReg(0x24, 0b11110000);
	// Magnetic sensor in Continous-conversion mode
	// CTRL7
	writeReg(0x26, 0b00000000);
	
	calibrate();
	

	writeReg(0x16, (byte)_baseX & 0x00FF);
	writeReg(0x17, (byte)((_baseX & 0xFF00) >> 8));

	writeReg(0x18, (byte)_baseY & 0x00FF);
	writeReg(0x19, (byte)((_baseY & 0xFF00) >> 8));

	writeReg(0x1A, (byte)_baseZ & 0x00FF);
	writeReg(0x1B, (byte)((_baseZ & 0xFF00) >> 8));
	
	//writeReg(0x22, 0b00001000);
	writeReg(0x23, 0b00010000);
}

void readMagneto(int16_t &x, int16_t &y, int16_t &z)
{
	x = (readReg(0x09) << 8) | readReg(0x08);
	y = (readReg(0x0B) << 8) | readReg(0x0A);
	z = (readReg(0x0D) << 8) | readReg(0x0C);
}

void loop()
{
	if (int1_flag) {
		int1_flag = false;
		CONSOLE_SERIAL.println("INT1 Interrupt");
	}
	
	int16_t x_val, y_val, z_val;
	readMagneto(x_val, y_val, z_val);
	CONSOLE_SERIAL.println(String("Magnetometer Readings: ") + x_val + ", " + y_val + ", " + z_val);

	int16_t t_val = (readReg(0x06) << 8) | readReg(0x05);
	CONSOLE_SERIAL.println(String("Temperature Reading: ") + t_val);
 
	for (int i=0; i<1000; i++) {
		delayMicroseconds(1000);
	}
}

uint8_t readReg(uint8_t reg)
{
  Wire.beginTransmission(ACCEL_ADR);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(ACCEL_ADR, 0x01);
  
  uint8_t val = Wire.read();
  Wire.endTransmission();

  return val;
}

uint8_t writeReg(uint8_t reg, uint8_t val)
{
  Wire.beginTransmission(ACCEL_ADR);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission();
  delayMicroseconds(10000);
}

Any other suggestions?

Here is a working example:

You can test it with a magnet, and try messing about with the threshold value.

The INT_SRC_M register (0x13h) provides the details as to which axis has generated the interrupt. It appears that it must be read before the interrupt will be generated again. I read it in every iteration of loop().

yes! I got it working. Thanks a lot.

Seems that the ‘offset’ registers aren’t used for the interrupts, the threshold needs to be a bit more then the ‘biggest’ value of the 3 axes.

Hello Gabriel,

I have tried the sketch but I it looks if it’s not working for me. When I run the sketch I got a lot of information about the vector and Magnetude but I never seen that he interupt get fired. Do I have to calibrated it first?

Gerrit