RAK12021 proximity sensor not working?

Hello! One of my homemade smart home devices is working.
as an infrared temperature sensor (RAK12003, open fire or body temperature) and an indicator of color temperature and illumination. Color temperature and illumination data are used to determine open combustion, time of day morning-afternoon-evening, light level, and other things.

The two sensors work together and perform multiple tasks.
IR Temperature Sensor (RAK12003) measures the temperature when an object (such as a person’s wrist) is brought near the device or when an RGB sensor interrupt is triggered. Also, the AMS TCS37725FN (RAK12021) sensor detects
color temperature and illumination in the room and transmits data via LoRaWAN. This is part of the smart home kit. It allows you to identify, for example, electric lighting that was left on out of forgetfulness.

Everything works very well, but I recently realized that I can use the built-in proximity sensor of the AMS TCS37725FN to measure the temperature of an object the moment an object is brought to the IR sensor.

There appears to be some inaccuracy in the official code RAK12021-TCS37725.
Thus, proximity sensor data is not read in the getMeasurement() function

This is the function.


TCS3772_DataScaled TCS3772::getMeasurement(void)
{  
  uint8_t i2cData[1];
  TCS3772_DataScaled scaledData;

// Probably due to the operating mode of the sensor, data is not read here

  readRegister(REG_PROX_DATAL | CMD_INCREMENT, i2cData, 1);
  scaledData.prox  = i2cData[0];

  readRegister(REG_PROX_DATAH | CMD_INCREMENT, i2cData, 1);
  scaledData.prox  += (i2cData[0]<<8);

//  readRegister(REG_PROX_DATAL | CMD_INCREMENT, i2cData, 2);
//  scaledData.prox   = (i2cData[1]<<8) + i2cData[0];
  
  return scaledData;
}

I know that the proximity sensor interrupt (unfortunately!) does not work in
Wisblock due to the electronic circuitry, but proximity sensor data must be output. Or are there any reasons why the AMS TCS37725FN proximity sensor data cannot be obtained?

A working proximity sensor would be very valuable for my programs, it could also work as an “electronic button”.

By the way, if the proximity sensor cannot be turned on, perhaps it makes sense to change the part of the library code that turns on the infrared LED? (to reduce power consumption)

// Should I change the datasheet here to 0x00?
i2cData = 0x5A;
  setRegister(REG_PULSE_COUNT | CMD_INCREMENT , i2cData , i2cData);// Set Proximity Time Register (0x02) to 0xFF.

Below is the code I use to work with beegee-tokyo/WisBlock-Sensor-For-LoRaWAN. I also added the necessary changes to initialization etc.
The code works stably and allows me to determine the type of lighting (color temperature) and the level of illumination in the room with sufficient accuracy.
Sometimes I use the AMS TCS37725FN sensor for photographic purposes as a “relatively accurate” colorimeter =)



// It use WB_IO2 to power up and is conflicting with INT1, so better use 
// in SlotA/SlotC/SlotD.

// Slot A      WB_IO1
// Slot B      WB_IO2 ( not recommended, pin conflict with IO2)
// Slot C      WB_IO3
// Slot D      WB_IO5
// Slot E      WB_IO4
// Slot F      WB_IO6


#include "app.h"
#if RAK_RGB_ID > 0

#define INT_RGB WB_IO5
//#define INT_RGB WB_IO1

/* Sensor polling time for display */
#define INTERVAL_RGB 500
#include <Arduino.h>

#include "TCS3772.h"		// Click here to get the library: http://librarymanager/All#TCS37725
#include <math.h>

TCS3772 tcs3772;

volatile boolean g_threshold_exceeded = false;

void RGB_CallBack ()
{
  g_threshold_exceeded = true;
}

/* Clear channel Interrupt event */
void printEventSrc (void)
{
  uint8_t eventSrc = tcs3772.getInterruptSrc ();
  if( eventSrc & TCS3772_AINT)
  {
    /* Clear channel Interrupt event */
	MYLOG("RGB", "<<<<< event %d >>>>>>", eventSrc);
  }
  g_threshold_exceeded = false;
  tcs3772.clearAllInterrupt ();
}

/*!
* @brief Implements missing powf function
* @param x
* 	Base number
* @param y
* 	Exponent
* @return x raised to the power of y
*/
float powf (const float x, const float y)
{
  return (float) (pow ((double) x, (double) y));
}

/*!
* @brief Converts the raw R/G/B values to color temperature in degrees Kelvin
* @param r
* 	Red value
* @param g
* 	Green value
* @param b
* 	Blue value
* @return Color temperature in degrees Kelvin
*/
u_int16_t calculateColorTemperature (u_int16_t r2, u_int16_t g2, u_int16_t b2)
{
  float X, Y, Z;		// RGB to XYZ correlation 
  float xc, yc;			// Chromaticity co-ordinates 
  float n;			// McCamy's formula 
  float cct;

  if (r2 == 0 && g2 == 0 && b2 == 0)
    {
      return 0;
    }
// https://ams.com/documents/20143/80162/TCS34xx_AN000517_1-00.pdf
/* Map RGB values to their XYZ counterparts. */
/* Based on 6500K fluorescent, 3000K fluorescent */
/* and 60W incandescent values for a wide range. */
/* Note: Y = Illuminance or lux */
  X = (-0.14282F * r2) + (1.54924F * g2) + (-0.95641F * b2);
  Y = (-0.32466F * r2) + (1.57837F * g2) + (-0.73191F * b2); // Illuminance 
  Z = (-0.68202F * r2) + (0.77073F * g2) + (0.56332F * b2);

/* 2. Calculate the chromaticity co-ordinates */
  xc = (X) / (X + Y + Z);
  yc = (Y) / (X + Y + Z);

/* 3. Use McCamy's formula to determine the CCT */
/* CCT = 449n3 + 3525n2  + 6823.3n + 5520.33 */
/* where n = (xc − 0.3320F) / (0.1858F − yc) */
  n = (xc - 0.3320F) / (0.1858F - yc);

/* Calculate the final CCT */
  cct =
    (449.0F * powf (n, 3)) + (3525.0F * powf (n, 2)) + (6823.3F * n) +
    5520.33F;

/* Return the results in degrees Kelvin */
  return (u_int16_t) cct;
}


/*!
* @brief Converts the raw R/G/B values to lux
* @param r
* 	Red value
* @param g
* 	Green value
* @param b
* 	Blue value
* @return Lux value
*/
u_int16_t calculateLux (u_int16_t r2, u_int16_t g2, u_int16_t b2,  u_int16_t c)
{
  float lx;
 /*
     ms    luxmax       der
     50 134333.33   += 12.4
    100  67166.67   += 6.2
    150  44777.78   += 4.13
    200  33583.33   += 3.1
    250  26866.67   += 2.48
    300  22388.89   += 2.07
    350  19190.48   += 1.77
    400  16791.67   += 1.55
    450  14925.93   += 1.38
    500  13433.33   += 1.24
    550  12212.12   += 1.13
    600  11194.44   += 1.03
 */
        /* Device specific values (DN40 Table 1 in Appendix I) */
        const float GA = 1.f;        // Glass Attenuation Factor
        static const float DF = 310.f;             // Device Factor
        static const float R_Coef = 0.136f;        //
        static const float G_Coef = 1.f;           // used in lux computation
        static const float B_Coef = -0.444f;       //

	/* Analog/Digital saturation (DN40 3.5) */
        int atime = 2.4 * 64;
        float saturation = (256 - atime > 63) ? 65535 : 1024 * (256 - atime);
        /* Check for saturation and mark the sample as invalid if true */
        if (c >= saturation)  return 0;

// Lux calculations are also simple but have fractional coefficients.
// One trick is to multiply the coefficients by 1000 making them integer 
// values and using ATIME in microseconds (also an integer) to cancel out 
// this multiplication.
// Gi” = 136 * R’+ 1000 * G’ +(-444) * B’
// Note that CPL is calculated only when the ATIME or AGAIN has changed. 
// This is why it is shown as a separate calculation. 
    /* Lux Calculation (DN40 3.2) */
    // The color Lux equation is a function of the R’, G’ and B’ channels and 
    // associated color coefficients creating a G” as follows:
    // G” = R_Coef * R’ + G_Coef * G’ + B_Coef * B’ 
        float g1 = R_Coef * r2 + G_Coef * g2 + B_Coef * b2;

	/* Set the internal integration time as 2.4*64 ms. */
	// ATIME = 256 − Integration Time / 2.4 ms
	// ATIME = 192 = 256 - 153.6/2.4
	// Inversely, the time can be calculated from the register value as
	// follows: Integration Time = 2.4 ms × (256 − ATIME)

	/* CPL = (ATIME_ms * AGAINx) / (GA * DF) */
        float cpl = (2.4 * 64) / (GA * DF);
	/* Lux = G” / CPL */
        lx = g1 / cpl;
	// lx = (-0.32466F * r2) + (1.57837F * g2) + (-0.73191F * b2);
  return (u_int16_t) lx;
}

// Device  GA*  DF   R_Coef G_Coef  B_Coef  CT_Coef CT_Offset
// TCS3472 1.0  310  0.136  1.000  -0.444   3810    1391
// TCS3772 1.0  310  0.136  1.000  -0.444   3810    1391

u_int16_t calcTemperatureDN40 (u_int16_t r2, u_int16_t b2)
{
  float cct;
  /* Device specific values (DN40 Table 1 in Appendix I) */
  static const float CT_Coef = 3810.f;   // Color Temperature Coefficient
  static const float CT_Offset = 1391.f; // Color Temperatuer Offset
  /* CT Calculations (DN40 3.4) */
  // CT (degrees Kelvin) = CT_Coef*(B’/R’) + CT_Offset
  cct = (CT_Coef * b2) / r2 + CT_Offset;
  return (u_int16_t) cct;
}

bool init_rak12021 ()
{
    Wire.begin ();		//I2C init

  if (tcs3772.begin () == true)
    {
      MYLOG ("TCS34725", "Found sensor TCS34725");
 tcs3772.setClearLowThreshold (25);
 tcs3772.setClearHighThreshold (1000);
 tcs3772.enableClearINT ();
 tcs3772.clearAllInterrupt ();
 pinMode (INT_RGB, INPUT_PULLUP); // Connect with TCS37725 INT1.
 attachInterrupt (digitalPinToInterrupt (INT_RGB), RGB_CallBack, FALLING);
    }
  else
    {
	/* No TCS34725 found */
	return false;
    }
	return true;
}

void read_rak12021 ()
{
  TCS3772_DataScaled tcs3772_data = { 0 };
  tcs3772_data = tcs3772.getMeasurement ();
  uint16_t r, g, b, c, p;
  u_int16_t cct0, cct1, lux;
  float sum, ir, r2, g2, b2;

      r = tcs3772_data.red;
      g = tcs3772_data.green;
      b = tcs3772_data.blue;
      c = tcs3772_data.clear;
      p = tcs3772_data.prox;

    /* AMS RGB sensors have no IR channel, so the IR content must
    be calculated indirectly.  IR Rejection (DN40 3.1) */
      // IR = (R+G+B-C) / 2
      sum = r + g + b;
      // ir = (r + g + b > c) ? (r + g + b - c) / 2.f : 0.f;
      ir = (sum > c) ? ((sum - c) / 2.f) : 0.f;
      r2 = r - ir;
      g2 = g - ir;
      b2 = b - ir;

	 r = (float)r / c * 255.0;
	 g = (float)g / c * 255.0;
	 b = (float)b / c * 255.0;


      lux = calculateLux (r2, g2, b2, c);
      cct0 = calculateColorTemperature (r2, g2, b2);
      cct1 = calcTemperatureDN40 (r2, b2);
/*******************************/
// Here should be a code that allows you to cut off deliberately false color temperature results
/*******************************/

	MYLOG("RGB", "Sensor (~%d'K) %d'K Lux %d' ", cct0, cct1, lux);
	MYLOG("RGB", "r %d' g %d' b  %d' dc' %d p' %d", r, g, b, c, p);

	  if(g_threshold_exceeded == true)
	      {
	        g_threshold_exceeded = false;
	        printEventSrc();
	      }
	g_solution_data.addLuminosity(LPP_CHANNEL_LUMINOSITY, lux);
	g_solution_data.addColour(LPP_CHANNEL_COLOUR, r, g, b);
}

#endif

Hi @renice123 ,

I did some test and I have a constant 1023 readings on the proximity. I am trying to navigate it but still have no success.

However, in your setup, maybe you can check the status register.

I looked at the IR LED in camera and it seems to pulse.

Thanks for the quick response! I will check the possible solution you suggested today. The IR LED works (I checked), but it can be disabled. I turn it off to reduce power consumption. The IR LED is not needed if the proximity sensor is not working.