Arduino Uno + APDS9930 实现手势控制LED灯亮灭调光等

Posted Love丶伊卡洛斯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino Uno + APDS9930 实现手势控制LED灯亮灭调光等相关的知识,希望对你有一定的参考价值。

前言

开发板:Arduino Uno Rev3 创客主板
开发环境:Arduino IDE
开发语言:Arduino 语言(类C语言)
模块:APDS9930

源码参考:https://github.com/Depau/APDS9930

功能介绍:

1、靠近亮灯、距离保持约10cm常亮,远离延时熄灭

当有物体靠近传感器约10cm的位置时,触发中断,点亮LED LIGHT_TIME毫秒,持续触发则常亮,无则灭灯。 通过修改 宏定义 LIGHT_TIME调节延时,LED负极接在数字10口(正极 3.3V供电)

2、靠近点亮/熄灭LED,延时期间操作不响应

当有物体靠近传感器约10cm的位置时,触发中断,点亮/熄灭LED,延时RESPONSE_TIME毫秒,延时期间操作不响应。 通过修改 宏定义 RESPONSE_TIME调节延时响应。

3、挥手点亮/熄灭LED,悬停进行非无极pwm调光

当有物体靠近传感器约10cm的位置时,可以触发中断。

  • 如果4RESPONSE_TIME毫秒内 没有触发4次中断,即4RESPONSE_TIME毫秒内,划过传感区域,则为开关模式,会进行LED的亮灭操作(亮到设定的pwm_val)
  • 如果4RESPONSE_TIME毫秒内 触发了4次中断,即4RESPONSE_TIME毫秒以上,物体一直停留在传感区域内,则为pwm调光模式,会进行LED的pwm非无极调光(每次在当前基础上增加PWM_CHANGE_VAL)
  • 如果在pwm调光模式下,物体移出了传感区域,则会结束pwm值的调节。若下次继续快划,则进行开关,若继续悬停,则继续调光。
  • 单位延时RESPONSE_TIME毫秒,延时期间操作不响应。
  • 通过修改 宏定义 RESPONSE_TIME调节延时响应,若想增加调光速率,可减小此值。
  • 通过修改 宏定义 PWM_CHANGE_VAL,调节单次pwm调光的大小,范围1-255。若想要更细致的调光,可减小此值。

接线

 Arduino Pin  APDS-9930 Board  Function
 
 3.3V         VL               据说用作参考电压,得接上
 3.3V         VCC              Power
 GND          GND              Ground
 A4           SDA              I2C Data
 A5           SCL              I2C Clock
 2            INT              Interrupt
 10           -                LED

效果图

Arduino+APDS9930 实现手势控制灯亮灭、调光等

源码

通用部分

APDS9930.cpp

/**
   @file    APDS-9930.cpp
   @brief   Library for the SparkFun APDS-9930 breakout board
   @author  Shawn Hymel (SparkFun Electronics)

   @copyright	This code is public domain but you buy me a beer if you use
   this and we meet someday (Beerware license).

   This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
   relies on the Arduino Wire (I2C) library. to use the library, instantiate an
   APDS9930 object, call init(), and call the appropriate functions.

   APDS-9930 current draw tests (default parameters):
     Off:                   1mA
     Waiting for gesture:   14mA
     Gesture in progress:   35mA
*/

#include <Arduino.h>
#include <Wire.h>

#include "APDS9930.h"

/**
   @brief Constructor - Instantiates APDS9930 object
*/
APDS9930::APDS9930()
{

}

/**
   @brief Destructor
*/
APDS9930::~APDS9930()
{

}

/**
   @brief Configures I2C communications and initializes registers to defaults

   @return True if initialized successfully. False otherwise.
*/
bool APDS9930::init()
{
  uint8_t id;

  /* Initialize I2C */
  Wire.begin();

  /* Read ID register and check against known values for APDS-9930 */
  if ( !wireReadDataByte(APDS9930_ID, id) ) {
    Serial.println(F("ID read"));
    return false;
  }
  if ( !(id == APDS9930_ID_1 || id == APDS9930_ID_2) ) {
    Serial.println(F("ID check"));
    Serial.println(String("ID is ") + String(id, HEX));
    //return false;
  }

  /* Set ENABLE register to 0 (disable all features) */
  if ( !setMode(ALL, OFF) ) {
    Serial.println(F("Regs off"));
    return false;
  }

  /* Set default values for ambient light and proximity registers */
  if ( !wireWriteDataByte(APDS9930_ATIME, DEFAULT_ATIME) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_WTIME, DEFAULT_WTIME) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_PPULSE, DEFAULT_PPULSE) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_POFFSET, DEFAULT_POFFSET) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_CONFIG, DEFAULT_CONFIG) ) {
    return false;
  }
  if ( !setLEDDrive(DEFAULT_PDRIVE) ) {
    return false;
  }
  if ( !setProximityGain(DEFAULT_PGAIN) ) {
    return false;
  }
  if ( !setAmbientLightGain(DEFAULT_AGAIN) ) {
    return false;
  }
  if ( !setProximityDiode(DEFAULT_PDIODE) ) {
    return false;
  }
  if ( !setProximityIntLowThreshold(DEFAULT_PILT) ) {
    return false;
  }
  if ( !setProximityIntHighThreshold(DEFAULT_PIHT) ) {
    return false;
  }
  if ( !setLightIntLowThreshold(DEFAULT_AILT) ) {
    return false;
  }
  if ( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_PERS, DEFAULT_PERS) ) {
    return false;
  }

  return true;
}

/*******************************************************************************
   Public methods for controlling the APDS-9930
 ******************************************************************************/

/**
   @brief Reads and returns the contents of the ENABLE register

   @return Contents of the ENABLE register. 0xFF if error.
*/
uint8_t APDS9930::getMode()
{
  uint8_t enable_value;

  /* Read current ENABLE register */
  if ( !wireReadDataByte(APDS9930_ENABLE, enable_value) ) {
    return ERROR;
  }

  return enable_value;
}

/**
   @brief Enables or disables a feature in the APDS-9930

   @param[in] mode which feature to enable
   @param[in] enable ON (1) or OFF (0)
   @return True if operation success. False otherwise.
*/
bool APDS9930::setMode(uint8_t mode, uint8_t enable)
{
  uint8_t reg_val;

  /* Read current ENABLE register */
  reg_val = getMode();
  if ( reg_val == ERROR ) {
    return false;
  }

  /* Change bit(s) in ENABLE register */
  enable = enable & 0x01;
  if ( mode >= 0 && mode <= 6 ) {
    if (enable) {
      reg_val |= (1 << mode);
    } else {
      reg_val &= ~(1 << mode);
    }
  } else if ( mode == ALL ) {
    if (enable) {
      reg_val = 0x7F;
    } else {
      reg_val = 0x00;
    }
  }

  /* Write value back to ENABLE register */
  if ( !wireWriteDataByte(APDS9930_ENABLE, reg_val) ) {
    return false;
  }

  return true;
}

/**
   @brief Starts the light (Ambient/IR) sensor on the APDS-9930

   @param[in] interrupts true to enable hardware interrupt on high or low light
   @return True if sensor enabled correctly. False on error.
*/
bool APDS9930::enableLightSensor(bool interrupts)
{

  /* Set default gain, interrupts, enable power, and enable sensor */
  if ( !setAmbientLightGain(DEFAULT_AGAIN) ) {
    return false;
  }
  if ( interrupts ) {
    if ( !setAmbientLightIntEnable(1) ) {
      return false;
    }
  } else {
    if ( !setAmbientLightIntEnable(0) ) {
      return false;
    }
  }
  if ( !enablePower() ) {
    return false;
  }
  if ( !setMode(AMBIENT_LIGHT, 1) ) {
    return false;
  }

  return true;

}

/**
   @brief Ends the light sensor on the APDS-9930

   @return True if sensor disabled correctly. False on error.
*/
bool APDS9930::disableLightSensor()
{
  if ( !setAmbientLightIntEnable(0) ) {
    return false;
  }
  if ( !setMode(AMBIENT_LIGHT, 0) ) {
    return false;
  }

  return true;
}

/**
   @brief Starts the proximity sensor on the APDS-9930

   @param[in] interrupts true to enable hardware external interrupt on proximity
   @return True if sensor enabled correctly. False on error.
*/
bool APDS9930::enableProximitySensor(bool interrupts)
{
  /* Set default gain, LED, interrupts, enable power, and enable sensor */
  if ( !setProximityGain(DEFAULT_PGAIN) ) {
    return false;
  }
  if ( !setLEDDrive(DEFAULT_PDRIVE) ) {
    return false;
  }
  if ( interrupts ) {
    if ( !setProximityIntEnable(1) ) {
      return false;
    }
  } else {
    if ( !setProximityIntEnable(0) ) {
      return false;
    }
  }
  if ( !enablePower() ) {
    return false;
  }
  if ( !setMode(PROXIMITY, 1) ) {
    return false;
  }

  return true;
}

/**
   @brief Ends the proximity sensor on the APDS-9930

   @return True if sensor disabled correctly. False on error.
*/
bool APDS9930::disableProximitySensor()
{
  if ( !setProximityIntEnable(0) ) {
    return false;
  }
  if ( !setMode(PROXIMITY, 0) ) {
    return false;
  }

  return true;
}

/**
   Turn the APDS-9930 on

   @return True if operation successful. False otherwise.
*/
bool APDS9930::enablePower()
{
  if ( !setMode(POWER, 1) ) {
    return false;
  }

  return true;
}

/**
   Turn the APDS-9930 off

   @return True if operation successful. False otherwise.
*/
bool APDS9930::disablePower()
{
  if ( !setMode(POWER, 0) ) {
    return false;
  }

  return true;
}

/*******************************************************************************
   Ambient light sensor controls
 ******************************************************************************/

/**
   @brief Reads the ambient (clear) light level as a 16-bit value

   @param[out] val value of the light sensor.
   @return True if operation successful. False otherwise.
*/
bool APDS9930::readAmbientLightLux(float &val)
{
  uint16_t Ch0;
  uint16_t Ch1;

  /* Read value from channel 0 */
  if ( !readCh0Light(Ch0) ) {
    return false;
  }

  /* Read value from channel 1 */
  if ( !readCh1Light(Ch1) ) {
    return false;
  }

  val = floatAmbientToLux(Ch0, Ch1);
  return true;
}

bool APDS9930::readAmbientLightLux(unsigned long &val)
{
  uint16_t Ch0;
  uint16_t Ch1;

  /* Read value from channel 0 */
  if ( !readCh0Light(Ch0) ) {
    return false;
  }

  /* Read value from channel 1 */
  if ( !readCh1Light(Ch1) ) {
    return false;
  }

  val = ulongAmbientToLux(Ch0, Ch1);
  return true;
}

float APDS9930::floatAmbientToLux(uint16_t Ch0, uint16_t Ch1)
{
  uint8_t x[4] = {1, 8, 16, 120};
  float ALSIT = 2.73 * (256 - DEFAULT_ATIME);
  float iac  = max(Ch0 - ALS_B * Ch1, ALS_C * Ch0 - ALS_D * Ch1);
  if (iac < 0) iac = 0;
  float lpc  = GA * DF / (ALSIT * x[getAmbientLightGain()]);
  return iac * lpc;
}

unsigned long APDS9930::ulongAmbientToLux(uint16_t Ch0, uint16_t Ch1)
{
  uint8_t x[4] = {1, 8, 16, 120};
  unsigned long ALSIT = 2.73 * (256 - DEFAULT_ATIME);
  unsigned long iac  = max(Ch0 - ALS_B * Ch1, ALS_C * Ch0 - ALS_D * Ch1);
  if (iac < 0) iac = 0;
  unsigned long lpc  = GA * DF / (ALSIT * x[getAmbientLightGain()]);
  return iac * lpc;
}

bool APDS9930::readCh0Light(uint16_t &val)
{
  uint8_t val_byte;
  val = 0;

  /* Read value from channel 0 */
  if ( !wireReadDataByte(APDS9930_Ch0DATAL, val_byte) ) {
    return false;
  }
  val = val_byte;
  if ( !wireReadDataByte(APDS9930_Ch0DATAH, val_byte) ) {
    return false;
  }
  val += ((uint16_t)val_byte << 8);
  return true;
}

bool APDS9930::readCh1Light(uint16_t &val)
{
  uint8_t val_byte;
  val = 0;

  /* Read value from channel 0 */
  if ( !wireReadDataByte(APDS9930_Ch1DATAL, val_byte) ) {
    return false;
  }
  val = val_byte;
  if ( !wireReadDataByte(APDS9930_Ch1DATAH, val_byte) ) {
    return false;
  }
  val += ((uint16_t)val_byte << 8);
  return true;
}

/*******************************************************************************
   Proximity sensor controls
 ******************************************************************************/

/**
   @brief Reads the proximity level as an 8-bit value

   @param[out] val value of the proximity sensor.
   @return True if operation successful. False otherwise.
*/
bool APDS9930::readProximity(uint16_t &val)
{
  val = 0;
  uint8_t val_byte;

  /* Read value from proximity data register */
  if ( !wireReadDataByte(APDS9930_PDATAL, val_byte) ) {
    return false;
  }
  val = val_byte;
  if ( !wireReadDataByte(APDS9930_PDATAH, val_byte) ) {
    return false;
  }
  val += ((uint16_t)val_byte << 8);

  return true;
}

/*******************************************************************************
   Getters and setters for register values
 ******************************************************************************/

/**
   @brief Returns the lower threshold for proximity detection

   @return lower threshold
*/
uint16_t APDS9930::getProximityIntLowThreshold()
{
  uint16_t val;
  uint8_t val_byte;

  /* Read value from PILT register */
  if ( !wireReadDataByte(APDS9930_PILTL, val_byte) ) {
    val = 0;
  }
  val = val_byte;
  if ( !wireReadDataByte(APDS9930_PILTH, val_byte) ) {
    val = 0;
  }
  val |= ((uint16_t)val_byte << 8);

  return val;
}

/**
   @brief Sets the lower threshold for proximity detection

   @param[in] threshold the lower proximity threshold
   @return True if operation successful. False otherwise.
*/
bool APDS9930::setProximityIntLowThreshold(uint16_t threshold)
{
  uint8_t lo;
  uint8_t hi;
  hi = threshold >> 8;
  lo = threshold & 0x00FF;

  if ( !wireWriteDataByte(APDS9930_PILTL, lo) ) {
    return false;
  }
  if ( !wireWriteDataByte(APDS9930_PILTH, hi) ) {
    return false;
  }

  return true;
}

/**
   @brief Returns the high threshold for proximity detection

   @return high threshold
*/
uint16_t APDS9930::getProximityIntHighThreshold()
{
  uint16_t val;
  uint8_t val_byte;

  怎麼用智峰软件给arduino uno r3烧bootloader

arduino leonardo r3 和 arduino uno r3 有啥区别

Arduino UNO通过电容的直接检测实现简易触摸开关

Arduino Uno 实现的 Lora sx1278

Proteus仿真Arduino UNO利用Stepper库实现uln2003驱动步进电机转动

Arduino Uno + PAJ7620U2 实现手势识别控制LED灯工作