Journey's End

May 17
2009

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.

``` brush:cpp

include

/ 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