AP3216C 模块

AP3216C 模块的核心就是这个芯片本身。这颗芯片集成了光强传感器(ALS:Ambient Light Sensor),接近传感器(PS: Proximity Sensor),还有一个红外LED(IR LED)。这个芯片设计的用途是给手机之类的使用,比如:返回当前环境光强以便调整屏幕亮度;用户接听电话时,将手机放置在耳边后,自动关闭屏幕避免用户误触碰。

ap32

可能是因为模块接线非常简单,我在网上找不到模块的电路图,只能用芯片的DataSheet对照进行查看。
从上到下分别是 :
VLED IR LED的供电,IR LED 电流最高为 20ma。使用 3.3v给模块和IR LED 同时供电时,在IR LED 上串联了一个200欧姆的电阻,这样保证电流不会超过20ma。
GND 地
VCC 模块供电,特别注意:最高 3.6V,对于 Arduino 来说,只能选择 3.3V供电输出
SCL I2C 的 CLOCK,对应 A5
SDA I2C 的 DATA,对应 A4
INT 中断输出,可以通知 Arduino有数据。对于轮询,无需使用。

ap321

参考【参考1】, 可以使用的代码如下:

// Interfacing the AP3216 light / proximity sensor with Arduino UNO

// By RoboRemo
// www.roboremo.com

// Big thanks to ICStation for providing the AP3216 sensor
// http://www.icstation.com/ap3216-ambient-light-sensorals-proximity-sensorps-p-7958.html

// Command examples:
// "write 0x00 0x01\n" - will write value 0x01 to the register 0x00
// "read 0x0C\n" - will read the value from register 0x0C
// "als start\n" - will start streaming the value from the ALS (ambient light sensor)
// "ps start\n" - will start streaming the value from the PS (proximity sensor)
// "stop\n" - will stop streaming the ALS / PS data.

// Commands can be sent using Serial Monitor / Terminal,
// Or using the RoboRemo app from Google Play.

// RoboRemo app can also display a nice plot of the ALS / PS data,
// and also log to a file on the sdcard of the phone.


// Hardware wiring:
// Arduino     AP3216
//             VLED --,
// GND ------- GND   |R| 240 Ohm
// 3.3V ------ VCC ---'
// A5 -------- SCL
// A4 -------- SDA
            


long baud = 115200;

#include <Wire.h>


char cmd[100];
int cmdIndex;

bool als_on = false;
bool ps_on = false;



boolean cmdStartsWith(const char *st) { // checks if cmd starts with st
  for(int i=0; ; i++) {
    if(st[i]==0) return true;
    if(cmd[i]==0) return false;
    if(cmd[i]!=st[i]) return false;;
  }
  return false;
}



int hexCharToInt(char c) {
  if(c>='a') return (c-'a')+10;
  if(c>='A') return (c-'A')+10;
  return c-'0';
}

String hexByteToString(int val) {
  char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'A', 'B', 'C', 'D', 'E', 'F'};

  char a = digits[(val/16) %16];
  char b = digits[val%16];
  
  return (String) "" + a + b;
}



void alsStart() {
  AP3216_write(0x00, 0x01);
  als_on = true;
}


void alsPsStop() {
  als_on = false;
  ps_on = false;
  AP3216_write(0x00, 0x00);
}


void psStart() {
  AP3216_write(0x00, 0x02);
  ps_on = true;
}




void AP3216_write(int regAddress, int value) {
  Wire.beginTransmission(0x1E); // I2C Address of AP3216 sensor is 0x1E
  Wire.write(regAddress);
  Wire.write(value);
  Wire.endTransmission(); 
}

int AP3216_read(int regAddress) {
  Wire.beginTransmission(0x1E); // I2C Address of AP3216 sensor is 0x1E
  Wire.write(regAddress);
  Wire.endTransmission();
  Wire.requestFrom(0x1E, 1, true);
  return Wire.read() & 0xFF;
}


void exeCmd() {

  if( cmdStartsWith("read 0x") ) {  // example: read 0x1A
    int a = hexCharToInt(cmd[7]); // '1' -> 1
    int b = hexCharToInt(cmd[8]); // 'A' -> 10
    
    int regAddress = (a*16)+b; // 0x1A = 26

    int regValue = AP3216_read(regAddress);
    
    Serial.print( (String)"reg_0x");
    Serial.print( hexByteToString(regAddress) );
    Serial.print(" = ");
    Serial.print( hexByteToString(regValue) );
    Serial.print("\n");
  }


  if( cmdStartsWith("write 0x") ) {  // example: write 0x1A 0x55
    int a = hexCharToInt(cmd[8]); // '1' -> 1
    int b = hexCharToInt(cmd[9]); // 'A' -> 10
    int regAddress = (a*16)+b; // 0x1A = 26

    a = hexCharToInt(cmd[13]);
    b = hexCharToInt(cmd[14]);
    int regValue = (a*16)+b;
    
    AP3216_write(regAddress, regValue); 

    Serial.print( (String)"reg_0x");
    Serial.print( hexByteToString(regAddress) );
    Serial.print(" <- ");
    Serial.print( hexByteToString(regValue) );
    Serial.print("\n");
  }

  if( cmdStartsWith("als start") ) {
    alsStart();
  }

  if( cmdStartsWith("stop") ) {
    alsPsStop();
  }


  if( cmdStartsWith("ps start") ) {
    psStart();
  }

  
}


void setup() {
  Wire.begin();
  Serial.begin(baud);
  cmdIndex = 0;
}

void loop() {

  while( Serial.available() ) {
    char c = Serial.read();

    if(c=='\n' || c=='\r') {
      cmd[cmdIndex] = 0; // end cmd string with 0
      exeCmd();  // execute the command
      cmdIndex = 0; // reset the cmdIndex
    } else {      
      cmd[cmdIndex] = c; // append c to the cmd string
      if(cmdIndex<99) cmdIndex++;
    } 
  }

  if(als_on) {
    int a = AP3216_read(0x0D); // ALS Data HIGH Byte
    int b = AP3216_read(0x0C); // ALS Data LOW Byte

    long alsValue = a;
    alsValue = alsValue << 8;
    alsValue = alsValue + b;
    
    Serial.print("als ");
    Serial.print(alsValue);
    Serial.print("\n");
    delay(100);
  }


  if(ps_on) {
    int a = AP3216_read(0x0F) & 0b00111111; // PS Data HIGH 6 bits
    int b = AP3216_read(0x0E) & 0b00001111; // PS Data LOW 4 bits
    long psValue = (a << 4) + b;
    Serial.print("ps ");
    Serial.print(psValue);
    Serial.print("\n");
    delay(13);
  }
   
}

 

使用方法:
串口输入 als start 获取当前的光强
串口输入 ps start获得当前接近传感器的数值
串口输入 stop 停止输出

ap322

目前这个模块没有成熟的库供使用,上述代码只是实现一个大概的功能,如果应用在产品上,还需要根据需求对照DataSheet进行详细的调试。
参考:
1. http://www.roboremo.com/reading-ap3216-with-arduino.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注