Sony ILX554B for spectrometer

Hello,
I want to use the Sony ILX554B ccd to build a spectrometer. Till now I have the ardunio software, a program called LogView Studio for drawing the information the ccd collects and an Arduino Mega 2560 for controlling the ccd. As alternative I could also use Labview for drawing.
This is my first project, so I have no experience in this matter. Unfortunatelly my C skills are very rusty, but I think I should find my way into it. By what I have read so far, I learned, that every pixel has to be read out one by one, am I right?
Another problem is the function of this ccd. I couldn’t find a manual whether and when to set the ROG or CLK high or low to scan the light/read out the information.

I hope someone has some experience in this topic and can help me.
Thanks in advance.

schmaffz: By what I have read so far, I learned, that every pixel has to be read out one by one, am I right? Yes. Another problem is the function of this ccd. I couldn't find a manual whether and when to set the ROG or CLK high or low to scan the light/read out the information. First link from a google search for ILX554B is here. ROG is normally high and you pulse it low (when CLK is high) for a minimum of 1000ns to start the CCD sample readout.

I hope someone has some experience in this topic and can help me. I have not used the ILX554B but it looks similar to the ILX511 I have played with.

Thank you. I have another question: Do ich need the S/H-mode (sample and hold)? Im not sure whats it's for and whether I need it or not.

schmaffz: I have another question: Do ich need the S/H-mode (sample and hold)? Im not sure whats it's for and whether I need it or not.

From you first post I assumed you already collect data from this CCD using a similar setup. The test code I wrote was for the CCD configured as sample and hold. I never tested it using non S/H mode. If the image on the CCD is likely to change in the time it takes you to read out all the pixels then I would think S/H is the safer option.

I put S/H on GND. This is what I have so far. There is a readout, but it only delivers values around 250, no matter, if I change the light or make it dark at all.
I don’t see the problem…

int vout = 94;
int clk = 96;
int rog = 97;
int pixel = 0;

void setup() {
pinMode(vout,INPUT);
pinMode(clk,OUTPUT);
pinMode(rog,OUTPUT);
Serial.begin(9600);
}

void loop() {
//read
Serial.println(“n\start readout\n”);
digitalWrite(clk,HIGH);
digitalWrite(rog,HIGH);
delayMicroseconds(3);
digitalWrite(rog,LOW);
delayMicroseconds(3);
digitalWrite(rog,HIGH);
delayMicroseconds(5);
for(int i = 0; i < 2087; i++ )
{
digitalWrite(clk,LOW);
delayMicroseconds(1);
digitalWrite(clk,HIGH);
pixel = analogRead(vout);
Serial.println(pixel);
delayMicroseconds(3);
}
}

schmaffz: I put S/H on GND. This is what I have so far. There is a readout, but it only delivers values around 250, no matter, if I change the light or make it dark at all.

S/H to GND = Sample and hold mode.

int vout = 94;
int clk = 96;
int rog = 97;

What Arduino are you using that has >= 97 pins? I only wrote code for UNO & MEGA2560.

S/H to GND = Sample and hold mode.

You mean, it reads 1 value and saves it all the time, so thats why it’s always the same?

What Arduino are you using that has >= 97 pins? I only wrote code for UNO & MEGA2560.

It is the MEGA2560… Pinmap

schmaffz: You mean, it reads 1 value and saves it all the time, so thats why it's always the same? No. With S/H mode on when the CCD receives the ROG signal it samples/stops sampling the pixels until they have all been read out. It is the MEGA2560... Pinmap Looks like your using the physical pin numbers instead of the Arduino IDE pin numbers. You need the pink numbers on the below image.

|500x353

No. With S/H mode on when the CCD receives the ROG signal it samples/stops sampling the pixels until they have all been read out.

So with S/H mode off, it would send the value for 1 pixel one by one? With S/H mode on, I should save the values in an array before giving it to a program, right?

Looks like your using the physical pin numbers instead of the Arduino IDE pin numbers. You need the pink numbers on the below image.

Oh, okay. Thanks

schmaffz: So with S/H mode off, it would send the value for 1 pixel one by one? With S/H mode on, I should save the values in an array before giving it to a program, right?

With S/H on when the ROG signal is sent the CCD pixels freeze their readings until they have all been read out (or to be more precise x number of clock cycles have elapsed since the ROG signal). With iS/H off the CCD pixels continue to register light changes as your reading them out.

Look here to see my sample code for the Mega and also processing code to view the results.

I suppose, I don’t need the S/H mode.
I changed the cables. This ist what I have now. Maybe I made a mistake with the cables?

Klick

int vout = 12;
int clk = 5;
int rog = 11;
int pixel = 0;

void setup() {
  pinMode(vout,INPUT);
  pinMode(clk,OUTPUT);
  pinMode(rog,OUTPUT); 
  Serial.begin(9600);
}

void loop() {
 //read
    Serial.println("n\start readout\n");
    digitalWrite(clk,HIGH);  
    digitalWrite(rog,HIGH);
    delayMicroseconds(3);
    digitalWrite(rog,LOW);
    delayMicroseconds(3);
    digitalWrite(rog,HIGH);
    delayMicroseconds(5);
        for(int i = 0; i < 2087; i++ )
      {
        digitalWrite(clk,LOW);
        delayMicroseconds(1);
        digitalWrite(clk,HIGH);
        pixel = analogRead(vout);
        Serial.println(pixel);
        delayMicroseconds(3);
}
}

I don’t see any decoupling, resistors or transistor as suggested in the datasheets reference design in your picture.
I would also be surprised if you can read anything sensible out with your code as digitalWrite is to slow.
I had to resort to direct port manipulation, increase the ADC read speed and buffer the readings before sending them over serial.

Attached is a picture of the module I made up. It has tape over most of the CCD window but still the CCD is still VERY sensitive to light.

I changed the timings and added the needed parts.
Nothing changed… I have the same output as before. So I pulled out the cable for Vout. And suprise… it doesn’t matter. I don’t know where it takes the data from, but surely not from the sensor. I looked in this topic http://forum.arduino.cc/index.php?topic=136921.0. You used A0 as Vout, not an IDE pin, is that right? If yes, which number do I have to give A0, because there is no pink number for it on the pin map.

Klick

int vout = 12;
int clk = 5;
int rog = 11;
int pixel = 0;

void setup() {
  pinMode(vout,INPUT);
  pinMode(clk,OUTPUT);
  pinMode(rog,OUTPUT); 
  Serial.begin(9600);
}

void loop() {
 //read
    Serial.println("\nstart readout\n");
    digitalWrite(clk,HIGH);  
    digitalWrite(rog,HIGH);
    delayMicroseconds(1);
    digitalWrite(rog,LOW);
    delayMicroseconds(1.01);
    digitalWrite(rog,HIGH);
    delayMicroseconds(5);
        for(int i = 0; i < 2087; i++ )
      {
        digitalWrite(clk,LOW);
        delayMicroseconds(1);
        digitalWrite(clk,HIGH);
        pixel = analogRead(vout);
        Serial.println(pixel);
        delayMicroseconds(1);
}
}

schmaffz: You used A0 as Vout, not an IDE pin, is that right? If yes, which number do I have to give A0, because there is no pink number for it on the pin map.

The pins I use are...

//******************
//* MEGA ONLY CODE *
//******************

// CLK pin = D5
// ROG pin = D11
// Vout pin = A0
// Debug pin = D7

A0 is the first analogue pin (green). As the output of the ILX is an analogue signal you need to read it using analogue.

You code says your using A12 as vout but the picture does not show anything plugged into analogue 12 on the mega board. Also, I have not looked in detail but your breadboard layout looks suspect. If the breadboard is a standard layout then your shorting pins 4 & 11 together.

If the breadboard is a standard layout then your shorting pins 4 & 11 together.

Yes right, thank you. I used it the wrong way.

You code says your using A12 as vout but the picture does not show anything plugged into analogue 12 on the mega board.

Didn't you mean that the numbers in the pink field of the pin map are the pins I have to write in the code? So I thought Vout = 12 is "pin 12"(digital) on the right side. I get, that I have to use an analog pin, but thats why I ask, what number I have to give it, when the 12 ist reserved for the pin on the right side of the board.

schmaffz: Didn't you mean that the numbers in the pink field of the pin map are the pins I have to write in the code? So I thought Vout = 12 is "pin 12"(digital) on the right side. I get, that I have to use an analog pin, but thats why I ask, what number I have to give it, when the 12 ist reserved for the pin on the right side of the board.

If your using analogRead(12) then the 12 would always be referring to A12 (analogue pin 12) as only these pins can convert a variable voltage (0-5V) into a variable number (0-1023) but if your using digitalRead(12) it will refer to digital pin 12 that can only read HIGH or LOW. I always use the A in front of analogue read pins so I don't get confused with digital pins of the same number.

Now I use pin A12 and I use an Array for saving the samples. It seems that that only the half field of the sensor works. When I tested it by holding my finger over different positions of the sensor. Do you have an idea why it is like that?

Further there is the same output all the time. There is one value for the output. If I change the light this one value changes too. There is just this one value, not one value per pixel or sth like that.

int vout = 1;
int clk = 5;
int rog = 11;
int pixel;
int s = 0;

void setup() {
  pinMode(vout,INPUT);
  pinMode(clk,OUTPUT);
  pinMode(rog,OUTPUT); 
  Serial.begin(9600);
}

void loop() {
 //read
    Serial.println("\nstart readout\n");
    digitalWrite(clk,HIGH);  
    digitalWrite(rog,HIGH);
    delayMicroseconds(1);
    digitalWrite(rog,LOW);
    delayMicroseconds(1.01);
    digitalWrite(rog,HIGH);
    delayMicroseconds(5);
        for(int i = 0; i < 2087; i++ )
      {
        digitalWrite(clk,LOW);
        delayMicroseconds(1);
        digitalWrite(clk,HIGH);
        int sampleArray[2088] = {analogRead(vout)};
        s = s++;
        int samplecount = s;
        pixel = sampleArray[samplecount];
        Serial.println(pixel);
        delayMicroseconds(1); 
       }


}

There are a lot of problems with your code. You say your using A12 to analogue read but it's defined as 1 (A1) in the code.

int vout = 1;

Your defining the array to store the data within the (for) reading loop and only storing the result to the first cell of the 2089 cell array so you will only ever have one value (in the first cell), the rest will be empty.

int sampleArray[2088] = {analogRead(vout)};

Your also trying to print out the contents of the array while reading the CCD and this will really foul up timings. The datasheet does not show a maximum timing for CLK but it does show an expected duty cycle of 50% +- 10%.

I found the only way to get proper data out of the chip was to use a timer to generate the CLK. I also had to speed up the analogue read as by default it is to slow and lastly I read the entire CCD pixels before sending results to PC over serial.

The CCD looks like it's pin compatible to the ILX511 so why don't you try the code I wrote (here) to see if it works.

There are a lot of problems with your code.
You say your using A12 to analogue read but it’s defined as 1 (A1) in the code.

Ah sorry, I meant A1. So theres not problem.

Your defining the array to store the data within the (for) reading loop and only storing the result to the first cell of the 2089 cell array so you will only ever have one value (in the first cell), the rest will be empty.

int vout = 1;
int clk = 5;
int rog = 11;
int pixel;
int s = 0;
int u = 0;
int sampleArray[2087];

void setup() {
  pinMode(vout,INPUT);
  pinMode(clk,OUTPUT);
  pinMode(rog,OUTPUT); 
  Serial.begin(9600);
}

void loop() {
 //read
    Serial.println("\nstart readout\n");
    digitalWrite(clk,HIGH);  
    digitalWrite(rog,HIGH);
    delayMicroseconds(1);
    digitalWrite(rog,LOW);
    delayMicroseconds(1.01);
    digitalWrite(rog,HIGH);
    delayMicroseconds(5);
        for(int i = 0; i < 2087; i++ )
        {
        digitalWrite(clk,LOW);
        delayMicroseconds(1);
        digitalWrite(clk,HIGH);
        sampleArray[s] = {analogRead(vout)};
        s = s++;                              //counter
        delayMicroseconds(1);
        }
       for(int i = 0; i < 2087; i++ )
       {
       Serial.println(sampleArray[u]);
       u = u++;
       delayMicroseconds(1);
       }

}

I tried it this way, but it doesn’t work either. How do store the data in different places of the array and how do I get it out of the “for” loop to print the results?

I found the only way to get proper data out of the chip was to use a timer to generate the CLK. I also had to speed up the analogue read as by default it is to slow and lastly I read the entire CCD pixels before sending results to PC over serial.

I care about this problem, after the others ones are solved. I come to this later, but thanks.

The CCD looks like it’s pin compatible to the ILX511 so why don’t you try the code I wrote (here) to see if it works.

Even if it works, I can’t explain all the steps and things you wrote in your code, but I have to explain it in my project, so I think the better way is to write an own code, I can explain step by step.

schmaffz:
I care about this problem, after the others ones are solved. I come to this later, but thanks.
Even if it works, I can’t explain all the steps and things you wrote in your code, but I have to explain it in my project, so I think the better way is to write an own code, I can explain step by step.

I have added a couple of comments to your latest code and changed it slightly as you was using variables you did not need to.

const int vout = A1;    // Changed to Constant so RAM memory not wasted on values that don't change when program is running
const int clk = 5;
const int rog = 11;

const int arraySize = 2087;

int sampleArray[arraySize];

void setup() {
  pinMode(vout,INPUT);  // Not really needed as pins default to input and using analogRead will switch pin to input
  pinMode(clk,OUTPUT);
  pinMode(rog,OUTPUT);
  Serial.begin(9600);   // Use a faster baud rate to get results out quicker. I use 115200
}

void loop() {
  //read
  Serial.println("\nstart readout\n");
  digitalWrite(clk,HIGH); 
  digitalWrite(rog,HIGH);
  delayMicroseconds(1);
  digitalWrite(rog,LOW);
  delayMicroseconds(1.01);  // No fractional times
  digitalWrite(rog,HIGH);
  delayMicroseconds(5);
  for(int i = 0; i < arraySize; i++ )
  {
    digitalWrite(clk,LOW);
    delayMicroseconds(1);
    digitalWrite(clk,HIGH);
    sampleArray[i] = analogRead(vout);
    delayMicroseconds(1);
  }
  for(int i = 0; i < arraySize; i++ )
  {
    Serial.println(sampleArray[i]);
  }
  
}

To have any chance of reading the sensor on the Mega the first thing you will need to learn is how to speed up the ADC. There is code here used to perform benchmarks that may help but the definitive guide would be to read the ATMEGA-2560 datasheet and maybe Google others explanations.
The second thing is ‘Direct Port Manipulation’ to speed up digitalWrite commands as they are to slow by default.

I took the liberty of reading the ROG/CLK pins with a logic analyzer and the images are posted below.
1.png is a snapshot of a small section of the signal as the full 2087 reads would make the transitions so small you could no see them. The point of note is the very asymmetric nature of your CLK signal but the CCD is expecting a 50% duty cycle CLK.
2.png and 3.png are just closer zooms of the start but with time measurements added. You will see the CLK high time is about 123uS and the clock low time is about 8uS