2013/12/01

Arduino練習:明度感測器TSL2561

從Adafruit Industries買了一塊明度感測器TSL2561分線板,這篇記錄一下使用步驟。這是顆數位IC,比起便宜的CdS光敏電阻更加準確,可調整量測時間與增幅尺度,便可量測0.1 ~ 40,000+ Lux

感測器裡含有可感測全光譜與紅外線的二極體,將全光譜的值減去紅外線部份的值,就可以得到可見光部份的值,人眼無法感知紅外光,但大部分的光二極體可以。

兩個光二極體的量測光譜。


如下圖所示,TSL2561採用I2C傳輸介面,若是Uno:SDA(A4)與SCL(A5),若是Leonardo:SDA(2)與SCL(3)。工作電壓是2.7~3.6V,所以VCC接3.3V,不可接5V。GND接地。至於INT與ADDR,此範例不使用。


這顆感測器晶片的原始資料頗為複雜,當然啦,使用程式庫的話就簡單多了,需下載安裝這兩套程式庫TSL2561(https://github.com/adafruit/Adafruit_TSL2561/archive/master.zip)與Adafruit_Sensor(https://github.com/adafruit/Adafruit_Sensor/archive/master.zip)。

程式碼:

#include <Wire.h>
#include <TSL2561.h> // 匯入程式庫

// 建立代表感測器晶片的物件
// 因為ADDR腳位沒接東西,傳入TSL2561_ADDR_FLOAT
TSL2561 tsl(TSL2561_ADDR_FLOAT);

void setup(void) {
  Serial.begin(19200);
 
  // 設定增幅係數
  //tsl.setGain(TSL2561_GAIN_0X); // 適用於光亮的環境
  tsl.setGain(TSL2561_GAIN_16X); // 適用於昏暗的環境
 
  // 設定整合時間,應該就是量測光線的時間吧
  // 昏暗環境應使用較長的整合時間
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS);
  tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS);
}

void loop(void) {
  uint32_t x = tsl.getFullLuminosity(); // 讀取
  uint16_t f = x & 0xFFFF; // 這部份是全光譜的值
  uint16_t ir = x >> 16; // 這部份是紅外線的值
  uint16_t v = (x & 0xFFFF) - (x >> 16); // 相減後得到可見光的值
  // 以上取得的值會因setTiming的設定而變

  uint32_t lux = tsl.calculateLux(f, ir); // 根據之前的設定計算明度lux
 
  Serial.print("Fullspectrum: ");
  Serial.print(f);
  Serial.print(", visiable: ");
  Serial.print(v);
  Serial.print(", infrared: ");
  Serial.print(ir);
  Serial.print(", lux: ");
  Serial.println(lux);
 
  delay(100);
}

雖然程式庫裡也有提供更方便的方法getLuminosity,但我發現呼叫三次取得全光譜、可見光、紅外線的值後,其關係不太正確,或許是因為每次去讀取時會有些微誤差吧。

8 comments:

  1. 您好
    關注這篇已經多時並嘗試實作
    照著上面步驟做之後程式庫也已經安裝
    除錯時出現
    'TSL2561'does not name a type
    sketch_aug21a.ino: In function 'void loop()':
    sketch_aug21a:23: error: 'tsl' was not declared in this scope
    想請問可能是哪個環節做錯了嗎?
    謝謝

    ReplyDelete
    Replies
    1. 大概是因為Adafruit提供的程式庫改名了,從TSL2561改為Adafruit_TSL2561_U,
      所以TSL2561類別就不見了,以至於出現錯誤「'TSL2561'does not name a type」。

      Delete
  2. 您好 目前問題已排除
    但除錯時換出現在(uint32_t x = tsl.getFullLuminosity(); // 讀取 )一行
    'class Adafruit_TSL2561_Unified'has no named 'getFullLuminosity
    是否表示為程式庫裡沒getFullLuminosity的項目?

    ReplyDelete
    Replies
    1. 是的,應該是Adafruit更新、改寫程式庫了。

      可查看https://github.com/adafruit/Adafruit_TSL2561,看看新的介面有哪些,
      譬如
      void enableAutoRange(bool enable);
      void setIntegrationTime(tsl2561IntegrationTime_t time);
      void setGain(tsl2561Gain_t gain);
      void getLuminosity (uint16_t *broadband, uint16_t *ir);
      uint32_t calculateLux(uint16_t broadband, uint16_t ir);

      Delete
    2. 您好~假設tsl2561並非是adafruit而是Grove的(I2C)TSL2561,在程式上會有什麼變動或是資料庫會有什麼差異嗎?

      Delete
  3. Fullspectrum: 65535, visiable: 0, infrared: 65535, lux: 24
    目前使用Grove的tsl2561所顯示出來的數值為上面所示,但是資料毫無變化,想請問是否為上述問題所導致這種情形發生

    ReplyDelete
    Replies
    1. 不確定。

      既然是買Grove TSL2561模組,那就使用Seeed-Studio自己開發的程式庫吧 https://github.com/Seeed-Studio/Grove_Digital_Light_Sensor 。

      Delete
    2. 謝謝您的建議!

      Delete