LSM303D - Click Registers

I’m trying to enable click - double click detection, but there seems to be some information missing from the spec sheet.

These registers related to the configuration of click detection don’t list any units.

CLICK_THS  	           _, Ths6, Ths5,Ths4, Ths3, Ths2, Ths1, Ths0		Click-click threshold. Default value: 000 0000
TIME_LIMIT	           _, TLI6, TLI5, TLI4, TLI3, TLI2, TLI1, TLI0		Click-click time limit. Default value: 000 0000
TIME_LATENCY	           TLA7, TLA6, TLA5, TLA4, TLA3, TLA2, TLA1, TLA0		Click-click time latency. Default value: 000 0000
TIME_WINDOW	           TW7, TW6, TW5, TW4, TW3, TW2, TW1, TW0		Click-click time window
Act_THS	                   _, ACTH6, ACTH5, ACTH4, ACTH3, ACTH2, ACTH1, ACTH0		Sleep to Wake, Return to Sleep activation threshold 1LSb = 16mg
Act_DUR                      ActD7, ActD6, ActD5, ActD4, ActD3, ActD2, ActD1, ActD0		Sleep to Wake, Return to Sleep duration DUR = (Act_DUR + 1)*8/ODR

Assuming it’s milliseconds, the CLICK_THS double click threshold could have a max value of 127 with only 7 bits available. Is this correct? That just seems really small considering for instance the default windows double click threshold value is 500ms.

Is this correct or am I just mis-reading something? Are they all in ms or are some different units?

This is what I had pieced together so far. The config values are all maxed out, but they need some realistic values in there.

Haven’t had a chance to test yet, but hopefully I’m on the right track.

void ConfigureClickDetection()
{
	/*
	These are the click related registers from the spec sheet for reference.

	CTRL0   HP_Click(position 3)   High-pass filter enabled for click function. Default value: 0 (0: filter bypassed; 1: filter enabled)
	CTRL3	_Click(position 7)	Click generator interrupt on INT1. Default value: 0 (0: disable; 1: enable)
	CTRL4	_Click(position 8)	Click generator interrupt on INT2. Default value: 0 (0: disable; 1: enable)

	CLICK_CFG
		ZD(position 6)	Enable interrupt double click-click on Z-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
		ZS(position 5)	Enable interrupt single click-click on Z-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
		YD(position 4)	Enable interrupt double click-click on Y-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
		YS(position 3)	Enable interrupt single click-click on Y-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
		XD(position 2)	Enable interrupt double click-click on X-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
		XS(position 1)	Enable interrupt single click-click on X-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)

	CLICK_SRC
		IA(position 7)	Interrupt active. Default value: 0 (0: no interrupt has been generated; 1: one or more interrupts have been generated)
		DClick(position 6)	Double click-click enable. Default value: 0 (0: double click-click detection disable; 1: double click-click detection enable)
		SClick(position 5)	Single click-click enable. Default value: 0 (0: single click-click detection disable; 1: single click-click detection enable)
		Sign(position 4)	Click-click sign. 0: positive detection; 1: negative detection
		Z(position 3)	Click-click sign. 0: positive detection; 1: negative detection
		Y(position 2)	Y click-click detection. Default value: 0 (0: no interrupt; 1: Y high event has occurred)
		X(position 1)	X click-click detection. Default value: 0 (0: no interrupt; 1: X high event has occurred)

	CLICK_THS	_, Ths6, Ths5,Ths4, Ths3, Ths2, Ths1, Ths0		Click-click threshold. Default value: 000 0000
	TIME_LIMIT	_, TLI6, TLI5, TLI4, TLI3, TLI2, TLI1, TLI0		Click-click time limit. Default value: 000 0000
	TIME_LATENCY	TLA7, TLA6, TLA5, TLA4, TLA3, TLA2, TLA1, TLA0		Click-click time latency. Default value: 000 0000
	TIME_WINDOW	TW7, TW6, TW5, TW4, TW3, TW2, TW1, TW0		Click-click time window
	Act_THS	_, ACTH6, ACTH5, ACTH4, ACTH3, ACTH2, ACTH1, ACTH0		Sleep to Wake, Return to Sleep activation threshold 1LSb = 16mg
	Act_DUR	ActD7, ActD6, ActD5, ActD4, ActD3, ActD2, ActD1, ActD0		Sleep to Wake, Return to Sleep duration DUR = (Act_DUR + 1)*8/ODR
	*/

	// Initialize - enable interrupt and click detection
	writeReg(CTRL3, 0x40);		// Turn on click generator interrupt on INT1
	writeReg(CLICK_CFG, 0x33)	// Turn on single and double clicks for Z and X axis

	// Set click/double click configuration values
	writeReg(CLICK_THS, 0x7F);
	writeReg(TIME_LIMIT, 0x7F);
	writeReg(TIME_LATENCY, 0xFF);
	writeReg(TIME_WINDOW, 0xFF);
	writeReg(Act_THS, 0x7F);
	writeReg(Act_DUR, 0xFF);

	int PinNumInt1 = 7;  // ???  need to confirm which pin of Arduino is on INT1 on LSM303D

	pinMode(PinNumInt1, INPUT);
	attachInterrupt(1, InterruptClick, RISING); 
}


// Handle interrupt: examine generated values, do something.
void InterruptClick()
{
	// Read click bit info from source register.
	byte clickInfo = readReg(CLICK_SRC);	// Get the source register byte, click data from accelerometer.
	int IA = clickInfo & 0x40;				// bit is 1 if interrupt occurred (i.e. it registered a click)
	int DClick = clickInfo & 0x20;			// bit is 1 if it is a double click
	int SClick = clickInfo & 0x10;			// bit is 1 if it is a single click
	int Sign = clickInfo & 0x8;				// bit is 0 if positive direction, 1 negative direction
	int Z = clickInfo & 0x4;				// bit is 1 if click is on the Z axis
	int Y = clickInfo & 0x2;				// bit is 1 if click is on the Y axis
	int X = clickInfo & 0x1;				// bit is 1 if click is on the X axis

	if (IA == 1)
	{
		// Do something here based on click input.
	}
}

Hello.

Unfortunately, we have not used that feature, so we do not know what units those registers are in. All of the information we have available for that sensor can be found inside its datasheet. It sounds like you are on the right track by experimenting with the registers to determine the units.

-Jon

I have a header put together for this, and it is working. Somewhat.

There are still some issues. I’m examining the CLICK_SRC register within the loop, but I never see single clicks, only double clicks. It also seems to be more sensitive on certain axis than others.

The text in the data sheet for the previous version (LSM303DLHC) was actually a bit more descriptive, although they are still structured differently.

ConfigureClickDetection() is called from setup(), GetClickInfo() is called from within the loop() and the if the return indicates a click occurred then PrintClickInfo() is called to display the individual bit values from the result register.

#ifndef ClickStuff_h
#define ClickStuff_h

#include <Arduino.h>
#include <LSM303.h>
#include <Adafruit_CharacterOLED.h>



typedef struct
{
  bool isInterrupt;
  bool isDouble; 
  bool isSingle;
  bool isPositive;
  bool isZ;
  bool isY;
  bool isX;
} ClickInfo;



// Retrieves the info on the click status and returns a struct populated with that data.
ClickInfo GetClickInfo(LSM303 compass)
{
   ClickInfo inf;
  
   // Read click bit info from source register.
   byte clickInf = compass.readReg(LSM303::CLICK_SRC);      // Get the source register byte, click data from accelerometer.
   inf.isInterrupt = clickInf & 0x40;                       // bit is 1 if interrupt occurred (i.e. it registered a click)
   inf.isDouble = clickInf & 0x20;                          // bit is 1 if it is a double click
   inf.isSingle = clickInf & 0x10;                          // bit is 1 if it is a single click
   inf.isPositive = clickInf & 0x8;                         // bit is 0 if positive direction, 1 negative direction
   inf.isZ = clickInf & 0x4;                                // bit is 1 if click is on the Z axis
   inf.isY = clickInf  & 0x2;                               // bit is 1 if click is on the Y axis
   inf.isX = clickInf & 0x1;                                // bit is 1 if click is on the X axis
 
   return inf;
}


void PrintClickInfo(ClickInfo inf, Adafruit_CharacterOLED lcd)
{
   lcd.clear();
   lcd.setCursor(0, 2);
       
   lcd.print(String(inf.isInterrupt) + "," + String(inf.isDouble) + "," + String(inf.isSingle) + "," + String(inf.isPositive) + "," + String(inf.isZ) + "," + String(inf.isY) + "," + String(inf.isX));
}


// Handle click: examine generated values, do something.
void Click(ClickInfo inf, Adafruit_CharacterOLED lcd)
{
       // Do something here based on click input.
      PrintClickInfo(inf, lcd);
       // Give us time to read results on display.
       delay(4000); 
}


void ConfigureClickDetection(LSM303 compass)
{
       /*
       These are the click related registers from the spec sheet for reference.

       CTRL0   HP_Click(position 3)   High-pass filter enabled for click function. Default value: 0 (0: filter bypassed; 1: filter enabled)
       CTRL3  _Click(position 7)   Click generator interrupt on INT1. Default value: 0 (0: disable; 1: enable)
       CTRL4  _Click(position 8)   Click generator interrupt on INT2. Default value: 0 (0: disable; 1: enable)

       CLICK_CFG
              ZD(position 6)       Enable interrupt double click-click on Z-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
              ZS(position 5)       Enable interrupt single click-click on Z-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
              YD(position 4)       Enable interrupt double click-click on Y-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
              YS(position 3)       Enable interrupt single click-click on Y-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
              XD(position 2)       Enable interrupt double click-click on X-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
              XS(position 1)       Enable interrupt single click-click on X-axis. Default value: 0 (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)

       CLICK_SRC
              IA(position 7)       Interrupt active. Default value: 0 (0: no interrupt has been generated; 1: one or more interrupts have been generated)
              DClick(position 6)   Double click-click enable. Default value: 0 (0: double click-click detection disable; 1: double click-click detection enable)
              SClick(position 5)   Single click-click enable. Default value: 0 (0: single click-click detection disable; 1: single click-click detection enable)
              Sign(position 4)     Click-click sign. 0: positive detection; 1: negative detection
              Z(position 3) Click-click sign. 0: positive detection; 1: negative detection
              Y(position 2) Y click-click detection. Default value: 0 (0: no interrupt; 1: Y high event has occurred)
              X(position 1) X click-click detection. Default value: 0 (0: no interrupt; 1: X high event has occurred)

       CLICK_THS     _, Ths6, Ths5,Ths4, Ths3, Ths2, Ths1, Ths0             Click-click threshold. Default value: 000 0000
       TIME_LIMIT    _, TLI6, TLI5, TLI4, TLI3, TLI2, TLI1, TLI0            Click-click time limit. Default value: 000 0000
       TIME_LATENCY  TLA7, TLA6, TLA5, TLA4, TLA3, TLA2, TLA1, TLA0         Click-click time latency. Default value: 000 0000
       TIME_WINDOW   TW7, TW6, TW5, TW4, TW3, TW2, TW1, TW0          Click-click time window
       Act_THS       _, ACTH6, ACTH5, ACTH4, ACTH3, ACTH2, ACTH1, ACTH0            Sleep to Wake, Return to Sleep activation threshold 1LSb = 16mg
       Act_DUR       ActD7, ActD6, ActD5, ActD4, ActD3, ActD2, ActD1, ActD0        Sleep to Wake, Return to Sleep duration DUR = (Act_DUR + 1)*8/ODR
       
       IG_CFG1    Inertial interrupt generator 1 configuration register.
           AOI          And/Or combination of interrupt events. Default value: 0.
           6D           6-direction detection function enabled. Default value: 0.
           ZHIE/ZUPE    Enable interrupt generation on Z high event or on direction recognition. Default value: 0 (0: disable interrupt request; 1: enable interrupt request)
           ZLIE/ZDOWNE
           YHIE/YUPE
           YLIE/YDOWNE
           XHIE/XUPE
           XLIE/XDOWNE
           
       IG_THS1      0, THS6, THS5, THS4, THS3, THS2, THS1, THS0      Interrupt generator 1 threshold. Default value: 000 0000
       IG_DUR1      0, D6, D5, D4, D3, D2, D1, D0                    Duration value. Default value: 000 0000.  D6 - D0 bits set the minimum duration of the interrupt 1 event to be recognized. Duration steps and maximum values depend on 

the ODR chosen.
       */
       // Turn on single and double clicks for Z, Y and X axis
       compass.writeReg(LSM303::CLICK_CFG, 0x3F);

       // Set click/double click configuration values
       compass.writeReg(LSM303::CLICK_THS, 0x3C);
       compass.writeReg(LSM303::TIME_LIMIT, 0x46);
       compass.writeReg(LSM303::TIME_LATENCY, 0x40);
       compass.writeReg(LSM303::TIME_WINDOW, 0xFF);
       compass.writeReg(LSM303::Act_THS, 0x0);
       compass.writeReg(LSM303::Act_DUR, 0x30);
       
}

#endif