Arduino筆記(87):接近和姿態感測模組APDS-9930

先前在網路上購買這個模組時,賣家把 APDS-9930 誤當作 APDS-9960賣給我,因模組上沒有標示 9930 或 9960 的型號,讓我測試手勢感測的程式,一直都不成功。後來查資料才發現這兩個模組幾乎一樣,差別只在手勢感測功能,改用 APDS-9930 的程式後就可以正常運作。我購買 APDS-9960 是要用手勢感測來控制 LED 燈的箭頭方向,因模組的錯誤暫時沒辦法做了。剛好利用這個機會瞭解一下 APDS-9930 接近和姿態感測模組的功能與用法。另一篇再來實作 APDS-9960 RGB非接觸手勢檢測感測的功能。

APDS-9930 是I2C介面的環境光傳感器(ALS)和帶有IR LED 的接近傳感器,採用單個8引腳封裝。環境光傳感器利用雙光電二極管以 0.01 lux 的低照度性能近似人眼的響應。這種高靈敏度使該設備可以在變暗的玻璃後面運行。接近傳感器可檢測到100毫米的物體,從明亮的陽光到黑暗的房間,接近檢測功能都可以正常運行。模塊內增加了微光學透鏡,可高效地發送和接收紅外能量,從而降低了總功耗。

APDS-9930規格:
  • 集成 ALS、紅外 LED 和接近檢測器的光學模組
  • 環境亮度感測 (ALS, Ambient Light Sensing) 近似人眼的視覺反應
  • 帶有上限和下限閾值的可程式中斷功能
  • 高達 16 位解析度
  • 深色玻璃後運作的高靈敏度
  • 0.01lux 低流明性能
  • 接近檢測完全校準到 100 毫米檢測
  • 程式範圍為 2.7 毫秒到大於 8 秒
  • 提供專用中斷引腳

[安裝APDS9930 Library]

APDS9930 函式庫提供用於從 APDS-9930 環境光和接近傳感器讀取數據。本實作需要安裝以下程式庫: 程式庫(Library)安裝方法請參考另一篇文章:  Arduino筆記:安裝 Arduino IDE 程式庫(Library)

[材料]

  • Arduino Uno x 1
  • APDS-9930 顏色、非接觸手勢檢測傳感器模組 x1
  • LED x 1
  • 連接線 x 4

[接線圖]

Arduino UnoAPDS-9930其他
3.3VVCC-
GNDGND-
A5SCL-
A4SDA-
GND-接LED負極
D10-接LED正極



[程式]

以下是 Depau/APDS9930 函式庫中的參考範例,當物體接近APDS-9930感測器時,接在 D10 的 LED燈,會偵測物體接近時,LED燈變暗,遠離感測器時, LED燈變亮的情況。
/****************************************************************
AmbientLightLED.ino
Source:Depau/APDS9930
****************************************************************/

#define PWM_LED_PIN       10
#define DUMP_REGS

#include <Wire.h>
#include <APDS9930.h>

// Global Variables
APDS9930 apds = APDS9930();
float ambient_light = 0; // can also be an unsigned long
uint16_t ch0 = 0;
uint16_t ch1 = 1;
float max_light = 0;

void setup() {
  //analogReference(EXTERNAL);
  pinMode(PWM_LED_PIN, OUTPUT);
  
  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("APDS-9930 - Ambient light sensor"));
  Serial.println(F("--------------------------------"));
  
  // Initialize APDS-9930 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9930 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9930 init!"));
  }
  
  // Start running the APDS-9930 light sensor (no interrupts)
  if ( apds.enableLightSensor(false) ) {
    Serial.println(F("Light sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during light sensor init!"));
  }

#ifdef DUMP_REGS
  /* Register dump */
  uint8_t reg;
  uint8_t val;

  for(reg = 0x00; reg <= 0x19; reg++) {
    if( (reg != 0x10) && \
        (reg != 0x11) )
    {
      apds.wireReadDataByte(reg, val);
      Serial.print(reg, HEX);
      Serial.print(": 0x");
      Serial.println(val, HEX);
    }
  }
  apds.wireReadDataByte(0x1E, val);
  Serial.print(0x1E, HEX);
  Serial.print(": 0x");
  Serial.println(val, HEX);
#endif

  // Wait for initialization and calibration to finish
  delay(500);
}

void loop() {
  
  // Read the light levels (ambient, red, green, blue)
  if (  !apds.readAmbientLightLux(ambient_light) ||
        !apds.readCh0Light(ch0) || 
        !apds.readCh1Light(ch1) ) {
    Serial.println(F("Error reading light values"));
  } else {
    Serial.print(F("Ambient: "));
    Serial.print(ambient_light);
    Serial.print(F("  Ch0: "));
    Serial.print(ch0);
    Serial.print(F("  Ch1: "));
    Serial.println(ch1);

    if ( ambient_light > max_light ) {
      max_light = ambient_light;
    }
    ambient_light = map(ambient_light, 0, max_light, 0, 1023); //將測得的值換算成1023的比例給D10 PWM
    analogWrite(PWM_LED_PIN, ambient_light);
  }
  
  // Wait 1 second before next reading
  delay(100);
}

[執行結果]



[參考資料]

Post a Comment

較新的 較舊