Pages: [1] 2   Go Down
Author Topic: Color sensor with Arduino  (Read 5455 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Am trying to use SFE Color Light Sensor Evaluation Board from spurk fun http://www.robotshop.ca/sfe-color-light-sensor-board-2.html to detect only the primaly colors (red, blue and green). I have connected  the scl and sda pins to arduino pin 4 and 5 analog side and I have powered my sensor board and it's LED  from arduino(3.3v).
Am stuck I don't have the test sketch and not sure of my connections.
Someone to help me with a test sketch I can use to receive the signal.
Are those the correct connections I should use? :'(
Logged

Bristol, UK
Offline Offline
Edison Member
*
Karma: 1
Posts: 1197
Exhibitor at UK Maker Faire
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you installed pull-up resistors on the SCL and SDA signals?
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 603
Posts: 33408
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Have you installed pull-up resistors on the SCL and SDA signals?

And have you pulled them up to 3V3 and not 5V and disabled the internal 5V pull up on these lines?

Quote
Someone to help me with a test sketch I can use to receive the signal.

Look in the playground for the I2C examples and substitute the address used for the one of your device (it's in the data sheet).
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have done all the necessary connection. I have connected pull-up resistor to both SDA and SCL. Am stuck by coming up with the sketch since am new in programming. I have done some C programming but only the basics.
I have been trying to follow thishttp://www.neufeld.newton.ks.us/electronics/?p=241and try coming up with the sketch. I have come up with a number of codes but none seem to give me data from the color sensor. This is one is one of the sketch I come up with but its always returning zero.
Code:
#include <Wire.h>
//  I2C device address is 0 1 0 0   A2 A1 A0
#define SENSOR_ADDRESS (0x4 << 3 | 0x0)
#define REGISTER_INPUT (0)

int sensor_read(int address) {
  int data = 0;

  //  Send input register address
  Wire.beginTransmission(address);
  Wire.send(REGISTER_INPUT);
  Wire.endTransmission();

  //  Connect to device and request two bytes
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);

  if (Wire.available()) {
    data = Wire.receive();
  }
  if (Wire.available()) {
    data |= Wire.receive() << 8;
  }

  Wire.endTransmission();

  return data;
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
}
 
void loop(){
  Serial.print(sensor_read(SENSOR_ADDRESS) & 0x0f);
  /*int value;
value = sensor_read(SENSOR_ADDRESS) & 0x0f;
Serial.print(value);*/
delay(100);
}

The color sensor datasheet is http://www.robotshop.ca/content/PDF/sfe-av02-0314-datasheet.pdf.
What have I not done in the code? I just want to get different value sent by the sensor once it senses a different color.
Is anyone with a possible code that I can use? Please post it if any.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Am completly stuck with reading data from the sensor as the slave to my arduino :'(.Is there anyone who has worked with this kind of color sensor to assist me with a sketch that can input/read data from the sensor?
Any comment is welcomed.
Thanx for your time.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Someone help! Someone to help me change the following PIC code to work on my arduino environment. I have gotten the PIC code from http://www.robotshop.ca/content/ZIP/sfe-adjd-s371-v11-pic-code.zip.
The code is:
Code:
/*
    3-17-08
    Nathan Seidle
    nathan@sparkfun.com
    Copyright Spark Fun Electronics© 2008
    
    Written for a PIC 16F88 running SparkFun bootloader at internal 8MHz.
    Compiled with CC5x compiler.

    Basic software I2C interactions with the ADJD-S371-Q999 color
    sensor. Sensor works great but requires calibration. This firwmare
    is only meant to demonstrate simple command interface.
    
    The software I2C routines are heavily tested and seem to work well
    with many I2C devices.
*/
#define Clock_8MHz
#define Baud_9600

#include "c:\Global\Code\C\16F88.h"  // device dependent interrupt definitions

#pragma origin 4

#include "c:\Global\Code\Pics\Code\Delay.c"   //Standard delays
#include "c:\Global\Code\Pics\Code\stdio.c"   //Software based Basic Serial IO

#define STATUS_LED PORTB.3

void boot_up(void);

#define WRITE_sda() TRISB = TRISB & 0b.1011.1111 //SDA must be output when writing
#define READ_sda()  TRISB = TRISB | 0b.0100.0000 //SDA must be input when reading - don't forget the resistor on SDA!!

#define SCL PORTB.7
#define SDA PORtB.6

#define I2C_DELAY   1

#define ACK     1
#define NO_ACK  0

#define DEVICE_WRITE    0xE8 //Default ADJD-S371 I2C address - write
#define DEVICE_READ     0xE9 //Default ADJD-S371 I2C address - read

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

#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 INT_CLEAR_LO    0x10
#define INT_CLEAR_HI    0x11

#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
#define DATA_CLEAR_LO   0x46
#define DATA_CLEAR_HI   0x47

void adjd_s371_read(void);
void adjd_init(void);

void i2c_ack_polling(uns8 device_address);
void i2c_start(void);
void i2c_stop(void);
uns8 i2c_read_byte(void);
bit i2c_send_byte(uns8 out_byte);
uns8 read_register(uns8 register_name);
void write_register(uns8 register_name, uns8 register_value);

void main(void)
{
    uns8 choice;
    
    boot_up();
        
    printf("\n\r\n\ADJD Testing\n\r", 0);

    adjd_init();
    
    while(1)
    {
        adjd_s371_read();
        //delay_ms(10);
    }
    
    while(1);

}//End Main

void boot_up(void)
{
    //OSCCON = 0b.0111.0000; //Setup internal oscillator for 8MHz
    //while(OSCCON.2 == 0); //Wait for frequency to stabilize

    //Setup Ports
    ANSEL = 0b.0000.0000; //Turn off A/D

    PORTA = 0b.0000.0000;
    TRISA = 0b.0000.0000;

    PORTB = 0b.0001.0000;
    TRISB = 0b.0000.0100;   //0 = Output, 1 = Input RX on RB2

    //Setup the hardware UART module
    //=============================================================
    SPBRG = 51; //8MHz for 9600 inital communication baud rate
    //SPBRG = 59; //9.216MHz for 9600 inital communication baud rate
    //SPBRG = 4; //9.216MHz for 115200 inital communication baud rate
    //SPBRG = 129; //20MHz for 9600 inital communication baud rate

    TXSTA = 0b.0010.0100; //8-bit asych mode, high speed uart enabled
    RCSTA = 0b.1001.0000; //Serial port enable, 8-bit asych continous receive mode
    //=============================================================

}

void adjd_init(void)
{
    write_register(CAP_RED, 0x05);
    write_register(CAP_GREEN, 0x05);
    write_register(CAP_BLUE, 0x05);
    write_register(CAP_CLEAR, 0x05);
    
    write_register(INT_RED_LO, 0xC4);
    write_register(INT_RED_HI, 0x09);
    write_register(INT_GREEN_LO, 0xC4);
    write_register(INT_GREEN_HI, 0x09);
    write_register(INT_BLUE_LO, 0xC4);
    write_register(INT_BLUE_HI, 0x09);
    write_register(INT_CLEAR_LO, 0xC4);
    write_register(INT_CLEAR_HI, 0x09);
}

//Init the sensor and read out the humidity and temperature data
void adjd_s371_read(void)
{
    uns8 response;
    uns16 red, green, blue, clear;

    //Check ability to read CAP_RED (should be 15)
    //response = read_register(CAP_RED);
    //printf("CAP_RED:%d ", response);

    write_register(0x00, 0b.0000.0001); //Get sensor reading
    
    uns8 i = 0;
    while(1)
    {
        response = read_register(0x00);
        if (response == 0) break;
        i++;
    }
    printf("i=%d ", i);
        
    //Red
    red.low8 = read_register(DATA_RED_LO);
    red.high8 = read_register(DATA_RED_HI);

    //Green
    green.low8 = read_register(DATA_GREEN_LO);
    green.high8 = read_register(DATA_GREEN_HI);

    //Blue
    blue.low8 = read_register(DATA_BLUE_LO);
    blue.high8 = read_register(DATA_BLUE_HI);

    //Clear
    clear.low8 = read_register(DATA_CLEAR_LO);
    clear.high8 = read_register(DATA_CLEAR_HI);
    

    printf("R(%h) ", red);
    printf("G(%h) ", green);
    printf("B(%h) ", blue);
    printf("C(%h)", clear);
    
    printf("\r", 0);
}

//Reads a register from LIS
uns8 read_register(uns8 register_name)
{
    uns8 in_byte;
    
    i2c_ack_polling(DEVICE_WRITE);

    i2c_start();
    i2c_send_byte(DEVICE_WRITE);
    i2c_send_byte(register_name); //Write register address  
    //i2c_stop();

    i2c_start(); //Repeat start (SR)
    i2c_send_byte(DEVICE_READ); //Now ask the IC to report on the last command
    in_byte = i2c_read_byte();
    i2c_stop();
        
    return(in_byte);
}

//Write to a register in LIS
void write_register(uns8 register_name, uns8 register_value)
{
    i2c_ack_polling(DEVICE_WRITE);

    i2c_start();
    i2c_send_byte(DEVICE_WRITE);
    i2c_send_byte(register_name); //Write register address
    i2c_send_byte(register_value); //Write data
    i2c_stop();

    //Return nothing
}

//Software I2C Routines
//====================================
void i2c_ack_polling(uns8 device_address)
{
    while(1)
    {
        i2c_start();
        if (i2c_send_byte(device_address) == ACK) break;
    }
    i2c_stop();
}

void i2c_start(void)
{
    WRITE_sda();
    SDA = 1;
    delay_us(I2C_DELAY);

    SCL = 1;
    delay_us(I2C_DELAY);

    SDA = 0;
    delay_us(I2C_DELAY);
}

//The I2C Clock has a minimum of 2us high time and 2us low time
void i2c_stop(void)
{
    SCL = 0;
    delay_us(I2C_DELAY);

    WRITE_sda();

    SDA = 0;
    delay_us(I2C_DELAY);

    SCL = 1;
    delay_us(I2C_DELAY);

    SDA = 1;
    delay_us(I2C_DELAY);
}

//The I2C Clock has a minimum of 2us high time and 2us low time
//8MHz = 0.5us per instruction
uns8 i2c_read_byte(void)
{
    int j, in_byte;

    SCL = 0;

    READ_sda();

    for(j = 0 ; j < 8 ; j++)
    {
        SCL = 0;
        delay_us(I2C_DELAY);

        SCL = 1;
        delay_us(I2C_DELAY);

        in_byte = rl(in_byte);
        in_byte.0 = SDA;
    }

    //Send 9th bit acknowledge
/*
    For single byte reads, there is NMAK or no master acknowledge
    SCL = 0;
    WRITE_sda();
    SDA = 0;
    delay_us(I2C_DELAY);
    SCL = 1;

    delay_us(I2C_DELAY);
    SCL = 0;

    delay_us(I2C_DELAY);
    SDA = 1;
    while(1);
*/
    return(in_byte);
}

//The I2C Clock has a minimum of 2us high time and 2us low time
//8MHz = 500ns per instruction
bit i2c_send_byte(uns8 out_byte)
{
    uns8 i;

    WRITE_sda();

    for(i = 0 ; i < 8 ; i++)
    {
        SCL = 0;
        delay_us(I2C_DELAY);

        out_byte = rl(out_byte);
        SDA = Carry;
        delay_us(5);

        SCL = 1;
        delay_us(I2C_DELAY);
    }

    //Read ack
    SCL = 0;
    delay_us(I2C_DELAY);

    READ_sda();

    SCL = 1;
    delay_us(I2C_DELAY);

    //Wait for IC to acknowledge
    for(i = 0 ; i < 255 ; i++)
        if(SDA == 0) break;

    SCL = 0;
    delay_us(I2C_DELAY);

    if (i == 255) return(NO_ACK);
    
    return(ACK);
}
//====================================

I will be greatful for any help offered.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25854
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't know the sensor device, but the PIC code has a whole lot of device initialisation in adjd_init that I don't see in your code.
Also, on a quick scan of the datasheet, the PIC code and your software, I don't see where you're setting GSSR, which I'm guessing is required to initiate a reading.
If you look at adjd_s371_read, you'll see that you need to write the GSSR bit in the control register before you can read back anything.
Also, between yours and the PIC code, the device address looks different.
The datasheet address is 0x74 (0xE8/9), but yours is (0x4 << 3 == 0x20)
I think somewhere you may be confusing I2C device addresses and register addresses, but it's late and I'm too tired to read all of it.
Note that some I2C implementations do not allow you to read all registers; some may be write only.

HTH
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey there, I am having the same problem.  I found this code:

Code:
#include <Wire.h>
 
const int serialSpeed=9600;
int ledPin = 13;    // the light
 
//ADJD Settings
#define ADJD 0x74
 
#define CAP_RED 0x06
#define CAP_GREEN 0x07
#define CAP_BLUE 0x08
#define CAP_CLEAR 0x09
 
#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 INT_CLEAR_LO 0x10
#define INT_CLEAR_HI 0x11
 
#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
#define DATA_CLEAR_LO 0x46
#define DATA_CLEAR_HI 0x47
 
#define OFFSET_RED 0x48
#define OFFSET_GREEN 0x49
#define OFFSET_BLUE 0x4A
#define OFFSET_CLEAR 0x4B
 
 
void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT  
  Serial.begin(serialSpeed);           // set up Serial library at 9600 bps
  Wire.begin();
  Serial.println("Sending Calibration data ... ");
  adjd_init();
  Serial.println("Calibration data sent. ");
}
 
void loop() {
  digitalWrite(ledPin,HIGH);
  read_register(DATA_RED_LO);
  digitalWrite(ledPin,LOW);
 
  delay(4000);
}
 
static void adjd_init()
{
  write_register(CAP_RED, 0x05);
  write_register(CAP_GREEN, 0x05);
  write_register(CAP_BLUE, 0x05);
  write_register(CAP_CLEAR, 0x05);
 
  write_register(INT_RED_LO, 0xC4);
  write_register(INT_RED_HI, 0x09);
  write_register(INT_GREEN_LO, 0xC4);
  write_register(INT_GREEN_HI, 0x09);
  write_register(INT_BLUE_LO, 0xC4);
  write_register(INT_BLUE_HI, 0x09);
  write_register(INT_CLEAR_LO, 0xC4);
  write_register(INT_CLEAR_HI, 0x09);
}
 
void read_adjd_offset() {
}
 
static void write_register(uint8_t register_name, uint8_t register_value)
{
  Wire.beginTransmission(ADJD);
  Wire.send(register_name);
  Wire.send(register_value);
  Wire.endTransmission();
}
 
static uint8_t read_register(uint8_t register_name)
{
  Wire.beginTransmission(ADJD);
  Wire.send(register_name);
  Wire.endTransmission();
  Wire.requestFrom(ADJD,2);
  Serial.print("read:");
  while (Wire.available()<1) {
    Serial.print(".");
  }
  int result = Wire.receive();
  Serial.println(result);
  return 0;
}

but I can not make any sense of it.  I don't totally understand I2C or the commands used in this code.  when i run this program, I get just zeros in the serial monitor.

got the code here  http://interactive-matter.org/2008/08/tinkering-with-adjd-s371-q999/
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have also tried using the code but get zero's too. Am worried wheather the code is setting the optimum digital values for the sensor.
Anyone who has worked with this kind of sensor, Please help us out! Maybe with a simple sketch that has worked for you.
Thanks for your time.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25854
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From the horse's mouth:

http://www.avagotech.com/docs/AV02-0359EN

"Sensor digital values can be acquired by writing 01H to CTRL register (address 00H). Read CTRL register. When the value in CTRL register is 00H, sensor digital values are acquired in sensor sample data registers."

From the PIC example above:
Code:
write_register(0x00, 0b.0000.0001); //Get sensor reading

    uns8 i = 0;
    while(1)
    {
        response = read_register(0x00);
        if (response == 0) break;
        i++;
    }
    printf("i=%d ", i);

    //Red
    red.low8 = read_register(DATA_RED_LO);
    red.high8 = read_register(DATA_RED_HI);
« Last Edit: April 19, 2009, 11:47:40 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi AWOL,
Thanks for your sketch and time. Am working on it to see whether it will work for me. I will keep you posted on my progress.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks, we'll see.. I think the problem here is I don't really get I2C
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 603
Posts: 33408
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Kubia
This bit is wrong in your code:-
//  I2C device address is 0 1 0 0   A2 A1 A0
#define SENSOR_ADDRESS (0x4 << 3 | 0x0)
It should be
//  I2C device address is 0x74
#define SENSOR_ADDRESS 0x74

It's in the data sheet page 10.

Then you need to look at page 18 to define what commands you want to send to it. Here you are better off reading the application note. Page 3 of this note tells you what you have to do in order to read the values.
However, all you code does is request two bytes from the I2C device without setting up any registers.

You need to:-
Quote
Sensor digital values can be acquired by writing 01H to CTRL register (address 00H). Read CTRL register. When the value in CTRL register is 00H, sensor digital values are acquired in sensor sample data registers.

Then you need to read the sample registers.

All this assumes that you haven't set up the sensor for offset and span so I don't know how useful the results will be with out this. Again the application notes describe how this should be done.

I am sorry not to be able to give you the code but I do not have one of these sensors (yet).
If it is any help I do plan to use four of these sensors in an up coming project so I will have code available in a month or so.

Just done a web search and come up with this:-
http://jp.makezine.com/blog/AvagoDemo.txt
« Last Edit: April 20, 2009, 10:45:17 am by Grumpy_Mike » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OMG thank you, that code works

thanks thanks thanks
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 20
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Grumpy_Mike,
Thanx for the code and the link. Am working on it and atleast i can get some reading from the sensor.The problem is only that the reading seems to be abit unstable i.e. when the sensor reflects from a red material the reading keep on varying again clear channel seems to have more output even when the object is 0mm to the sensor.
But all the same this is a good progress. With time am sure we shall have a concete sketch.
Thanks for your time and info'.
Logged

Pages: [1] 2   Go Up
Jump to: