20090518

Sketch to calibrate SEN-08663

Got my hands on a ADJD-S371 on a breakout board from Sparkfun. The code below can be used to calibrate it. The most up-to-date version of the code can be found at my git repository under colour_sensor_calibration.

#include <Wire.h>
/* Calibrates the sensor to get white balance. Pin 2 should be connected
 * to LED on the breakout board's LED pin. Calibration is done by placing the
 * breakout board inside a pin pong ball, and using the built-in LED for
 * illumination.
 *
 * Amount of light is measured by charging N capacitors for time X then
 * reading off the voltage. (Conjecture)
 *
 * N is controlled by CAP_XXX
 * T is controlled by INT_XXX
 *
 * Calibration is done by adjusting the integration time. No real reason.
 */
int _slave_id = 0x74;
int _LED_pin = 2;

uint8_t read_register(uint8_t addr)
{
  i2c_send(_slave_id, &addr, 1);
  return i2c_read(_slave_id);
}

void write_register_int(uint8_t addr, int data)
{
 write_register_multibyte(addr, (uint8_t*)&data, 2);
}

/* write data[i] = register+i */
void write_register_multibyte(uint8_t addr, uint8_t* data, uint8_t bytes)
{
 for (int i = 0; i < bytes; ++i)
 {
  write_register(addr+i, data[i]);
 }
}

void write_register(uint8_t addr, uint8_t data)
{
 uint8_t bytes[] = {addr, data};
 i2c_send(_slave_id, bytes, 2);
}

uint8_t i2c_read(uint8_t id)
{
 Wire.requestFrom(_slave_id, 1);
 for(int i = 0; i<10 && !Wire.available(); ++i, delay(10));
 if (!Wire.available())
 {
  return 11;
 }
 return Wire.receive();
 
}

void i2c_send(uint8_t id, uint8_t * data, uint8_t len)
{
 Wire.beginTransmission(id);
 for(int i = 0; i < len; ++i)
 {
  Wire.send(data[i]);
 }
 Wire.endTransmission();
}

#define CTRL    0x00
#define CONFIG    0x01

#define CAP_RED   0x06
#define CAP_GREEN   0x07
#define CAP_BLUE   0x08

#define INT_RED_LO   0x0A
#define INT_RED_HI   0x0B
#define INT_GREEN_LO  0x0C
#define INT_GREEN_HI  0x0D
#define INT_BLUE_LO  0x0E
#define INT_BLUE_HI  0x0F

#define DATA_RED_LO  0x40
#define DATA_RED_HI  0x41
#define DATA_GREEN_LO  0x42
#define DATA_GREEN_HI  0x43
#define DATA_BLUE_LO  0x44
#define DATA_BLUE_HI  0x45

int read_colour(uint8_t low_addr)
{
 int lo = read_register(low_addr);
 int hi = read_register(low_addr+1);

 return lo|(hi<<8);
}

int red_integration_time = 2048;
int green_integration_time = 2048;
int blue_integration_time = 2048;

void set_integration_times(int red, int green, int blue)
{
 write_register_int(INT_RED_LO, red);
 write_register_int(INT_GREEN_LO, green);
 write_register_int(INT_BLUE_LO, blue);
}

void setup()
{
 pinMode(_LED_pin, OUTPUT);
 digitalWrite(_LED_pin, HIGH);

 Serial.begin(57600); 
 Wire.begin(); // join i2c bus (address optional for master)
 Serial.println("Setting up...");

 // datasheet says, wait 10us for hardware reset, so lets wait 1000
 delay(1);

 // gain setup
 write_register(CAP_RED, 0x08);
 write_register(CAP_GREEN, 0x08);
 write_register(CAP_BLUE, 0x08);

 set_integration_times(
  red_integration_time, 
  green_integration_time, 
  blue_integration_time
 );

 // ask for colour data and offset
 write_register(CTRL, 0x01);
}

void loop()
{
 if (read_register(CTRL))
 {
  return;
 }
 
 int red, green, blue;
 red = read_colour(DATA_RED_LO);
 green = read_colour(DATA_GREEN_LO);
 blue = read_colour(DATA_BLUE_LO);
 
 Serial.println("--------------");
 Serial.print("red: ");Serial.println(red);
 Serial.print("green: ");Serial.println(green);
 Serial.print("blue: ");Serial.println(blue);


 Serial.print("red_int: ");Serial.println(red_integration_time);
 Serial.print("green_int: ");Serial.println(green_integration_time);
 Serial.print("blue_int: ");Serial.println(blue_integration_time);

 // have to calibrate against blue, because LED has a blue bias otherwise
 // it would look like blue has high gain than it does
 float P = 1;
 int reference = blue;
 red_integration_time += (reference - red)*P;
 green_integration_time += (reference - green)*P;
 blue_integration_time += (reference - blue)*P;

 // set the new integration times
 set_integration_times(
  red_integration_time, 
  green_integration_time, 
  blue_integration_time
 );
 
 // ask for colour data again
 write_register(CTRL, 0x01);
}

Cheers,
Steve

Labels: , ,


Comments: Post a Comment



Links to this post:

Create a Link



<< Home

This page is powered by Blogger. Isn't yours?