阈值比较法实现psensor功能

1 P_Sensor功能简述

    接近传感器(proximity sensor)可以不断向外发射红外光,当有遮挡物遮挡住其所发射的红外光时,会有部分甚至全部的红外光反射至接近传感器。由此,可以根据遮挡物反射的红外光的能量信号检测用户的移动信息。接近传感器可以将光强度转换为数字信号,且可以通过I2C进行数据的读取。psensor的红外线会周期性的计算反光量,并将光强度转化为数字值,存储于psensor的DATA寄存器中。当遮挡效果最好时,反光量最大,DATA寄存器中的测量数值最大为2047,当无遮挡时,则无反光量,此时,DATA寄存器中的测量值最小为0。MCU周期性读取proximity sensor中寄存器中的测量数据,并与设定的阈值相比较,从而检测头戴的佩戴状态。

2 设计方案

 

1).通过IIC配置P_Sensor的参数(以LTR-559ALS-01为例)

 

Setting

Value

Register

PS Mode

Enabled

0x81

Pulse frequency

60Hz

0x82

Duty cycle

100%

0x82

Pulse current

100mA

0x82

Pulse count

1

0x83

PS measurement rate

100ms

0x84

 

2). 循环读取P_Sensor测量数据

3). 将测量数据与设置的阈值相比较,以检测佩戴情况

3 P_Sensor 主要寄存器介绍

1)PS_COUNER Rigister (0x81) 

用来控制psensor工作模式,在配置psensor时要将PS Mode配置为Active 模式,因为默认为standby 模式

2)PS_LED Register(0x82)

主要用来控制LED的脉冲频率、占空比、峰值电流。这三个参数,会影响发射能量,从而影响测量距离

脉冲频率越低,导通时间越长,则在相同的距离下,测量的Psensor的DATA值越大,也就是要想得到同样的DATA值

的话,需要的测量距离要越远

占空比越大,在相同距离下,测量的Psensor的DATA值越大

电流越大,在相同距离下,测量的Psensor的DATA值越大

3)PS_N_Pulse Register (0x83)用来控制发射脉冲个数,影响发射能量

发射的脉冲个数越多,在相同距离下,测量的Psensor的DATA值越大

4)PS_MEAS_RATE Register(0x84)

控制psensor 在active mode下的周期性测量时间(psensor会周期性的将测量值写入DATA寄存器中)

这个时间设置的越长的话,psensor测量数据(DATA值)就会更新的越慢,实时性较差

脉冲频率、占空比、峰值电流、脉冲个数、周期性测量时间关系如图:

1 脉冲频率:为采样周期的倒数,即为1/T2

2 占空比:T1/T2

3 峰值电流:I1

4 测量时间:T3(psensor来将测量值写入寄存器中的周期性时间)

5 脉冲个数:在T3时间内发送的脉冲数,脉冲如图① ② ③所示,均为脉冲

一般来讲采样周期会远小于psensor的周期测量时间,而在psensor去存一次测量数据的时间(T3)内,脉冲

发送个数是可调的,发送个数越多,则能量越大

5)PS_DATA Registers(0x8D/0x8E)  (Read Only)

psensor测量值存储在这两个寄存器中,有效数据11位(bit)

4 代码实现

1)先对寄存器进行配置

UHAL_ASSERT(ltr559als01_ps_configure(&m_regmap, &m_config),
                "Failed to configure proximity sensor");sensor");
 
/**
 * @brief Sensor configuration
 */
static ltr559als01_ps_configuration_t m_config = {
    .current = LTR559ALS01_PS_LED_CURRENT_100mA,
    .duty_cycle = LTR559ALS01_PS_LED_DUTY_CYCLE_100PCT,
    .pulse_modulation_frequency = LTR559ALS01_PS_LED_PULSE_MODULATION_FREQUENCY_60kHz,
    .pulse_count = 1,
    .repeat_rate = LTR559ALS01_PS_MEASUREMENT_RATE_100ms
};
// Global register map handle
static fwregmap_handle_t m_regmap = {
    .context = NULL,
    .reg_reader_fn = reg_reader,
    .reg_writer_fn = reg_writer
};
bool ltr559als01_ps_configure(
        fwregmap_handle_t* device,
        const ltr559als01_ps_configuration_t* config)
{
    UHAL_ASSERT((config->pulse_count > 0) &&
                (config->pulse_count < 16),
                "Pulse count should be 1-15 inclusive");

    int status = 0;

    ltr559als01_PS_LED_t led = {
        .current = config->current,
        .duty_cycle = config->duty_cycle,
        .pulse_modulation_frequency = config->pulse_modulation_frequency
    };

    ltr559als01_PS_N_PULSES_t n_pulses = {};
    n_pulses.pulse_count = config->pulse_count;

    ltr559als01_PS_MEAS_RATE_t meas_rate = {};
    meas_rate.repeat_rate = config->repeat_rate;

    if ((status = ltr559als01_write_PS_LED(device, led)) != 0) {
        LOG_ERROR("Failed to write PS_LED: %i", status);
        return false;
    }

    if ((status = ltr559als01_write_PS_N_PULSES(device, n_pulses)) != 0) {
        LOG_ERROR("Failed to write PS_N_PULSES: %i", status);
        return false;
    }

    if ((status = ltr559als01_write_PS_MEAS_RATE(device, meas_rate)) != 0) {
        LOG_ERROR("Failed to write PS_MEAS_RATE: %i", status);
        return false;
    }

    return true;
}

其中:

// PS_LED : (what this does is a mystery)
typedef struct
{
   uint8_t current : 3;
   uint8_t duty_cycle : 2;
   uint8_t pulse_modulation_frequency : 3;
} ltr559als01_PS_LED_t;

// PS_N_PULSES : (what this does is a mystery)
typedef struct
{
   uint8_t pulse_count : 4;
} ltr559als01_PS_N_PULSES_t;


// PS_MEAS_RATE : (what this does is a mystery)
typedef struct
{
   uint8_t repeat_rate : 4;
} ltr559als01_PS_MEAS_RATE_t;

2)psensor线程周期性的读取寄存器中测量数据的值

void proximity_sensor_read(void)
{
    ltr559als01_ps_measurement_t measurement = {};

    if (ltr559als01_ps_read(&m_regmap, &measurement)) {
        __atomic_store(&m_value, &measurement.value, __ATOMIC_RELAXED);
    } else {
        LOG_ERROR("Failed to poll proximity sensor");
    }
}
bool ltr559als01_ps_read(
        fwregmap_handle_t* device,
        ltr559als01_ps_measurement_t* measurement)
{
    int status = 0;

    uint8_t data_0 = 0;
    ltr559als01_PS_DATA_1_t data_1 = {};

    if ((status = ltr559als01_read_PS_DATA_0(device, &data_0)) != 0) {
        LOG_ERROR("Failed to read PS_DATA_0: %i", status);
        return false;
    }

    if ((status = ltr559als01_read_PS_DATA_1(device, &data_1)) != 0) {
        LOG_ERROR("Failed to read PS_DATA_1: %i", status);
        return false;
    }

    measurement->value = (uint16_t)data_0 | ((uint16_t)data_1.high << 8);
    measurement->sensor_saturated = data_1.sensor_saturated;

    return true;
}
// PS_DATA_0 : (what this does is a mystery)
static inline int ltr559als01_read_PS_DATA_0(fwregmap_handle_t* handle, uint8_t* val)
{
   int status = 0;
   FWREGMAP_LOG("Reading PS_DATA_0 (0x8d) ");
   status = handle->reg_reader_fn(handle->context, 0x8d, 1, (uint8_t*)val);
   if (status == 0) {
      FWREGMAP_LOG("--> ");
      FWREGMAP_LOG("0x%02x", (unsigned int)*val);
   } else {
      FWREGMAP_LOG("FAIL (error %i)", status);
   }
   FWREGMAP_LOG("\n");
   return status;
}

 

// PS_DATA_1 : (what this does is a mystery)
typedef struct
{
   uint8_t high : 3;
   uint8_t rsvd0 : 4;
   uint8_t sensor_saturated : 1;
} ltr559als01_PS_DATA_1_t;

static inline int ltr559als01_read_PS_DATA_1(fwregmap_handle_t* handle, ltr559als01_PS_DATA_1_t* val)
{
   int status = 0;
   FWREGMAP_LOG("Reading PS_DATA_1 (0x8e) ");
   status = handle->reg_reader_fn(handle->context, 0x8e, 1, (uint8_t*)val);
   if (status == 0) {
      FWREGMAP_LOG("--> ");
      FWREGMAP_LOG("0x%02x {", *((uint8_t*)&*val)); FWREGMAP_LOG("high = "); FWREGMAP_LOG("%i", (*val).high); FWREGMAP_LOG(", ");FWREGMAP_LOG("sensor_saturated = "); FWREGMAP_LOG("%i", (*val).sensor_saturated); FWREGMAP_LOG(", ");FWREGMAP_LOG("}");
   } else {
      FWREGMAP_LOG("FAIL (error %i)", status);
   }
   FWREGMAP_LOG("\n");
   return status;
}

3)读取的测量数据与设定的阈值进行比较

typedef uint8_t proximity_sensor_digest_t;

static int m_threshold = 512;
proximity_sensor_digest_t proximity_sensor_digest(void)
{
    return (proximity_sensor_digest_t)(proximity_sensor_value() > m_threshold);
}

遮挡为1 不遮挡为0

 

 

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值