Arduino Linear image sensor not reading pixels

Hi guys, first time posting here.

I am actively trying to figure out why my code is not working properly. I am using an Arduino Uno and the Sony ILX526A linear image sensor.

Datasheet here: http://www.eureca.de/datasheets/01.xx.xxxx/01.01.xxxx/01.01.0021/ILX526A.pdf

I just used the circuit as described on page 8.

My code is attached below. For some reason, the sensor is only reading the first pixel. No matter what the clockpulse is, the value stored in the first sensor will be in the entire array.

I had some theories on why it wasn’t working. I first thought the clk rising/falling times were a bit too slow, hence I used port manipulation, but the issue is the same.

Could the problem then be that the clk duty cycle is way too small? the analogRead function in the Arduino takes a while to run.

Also if someone could thoroughly explain how the image sensor works would be nice as there isn’t a lot of information online about the workings of the device.

I believe that most of my code is correct. But I won’t be surprise if you find mistakes.

Thanks!

//Digital Pins
int clockPin = 11;
int rogPin = 10;
int shutPin = 9;

int timedelay = 500;    //time delay in microseconds
int clockperiod = 2 * timedelay;    //clockperiod is twice the timedelay

int clockpulse = 0;   //Keeps track of the clockpulse value

int sectionPixel = 10;

double pixels [3000 / 10];

void setup()
{
  Serial.begin(9600);

  pinMode(clockPin, OUTPUT);
  pinMode(rogPin, OUTPUT);
  pinMode(shutPin, OUTPUT);
}

void loop()
{
  clockpulse = 0;
  
  //Turns on ROG, initializes the image sensor
  startROG();

  delayed(timedelay);

  for (int x = 0 ; x < 2 ; x++)
  {
    PORTB = B001000;  //clk high
    delayed(timedelay);

    clockpulse ++;

    PORTB = B000000;   //clk low
    delayed(timedelay);
  }

  for (int x = 0 ; x < 55 ; x++)
  {
    PORTB = B001000;  //clk high
    delayed(timedelay);

    clockpulse ++;

    PORTB = B000000;   //clk low
    delayed(timedelay);
  }

  //Read from pixel 1 to pixel 3000 and stores them in the array: "pixels"
  readPixelData();

  //Starts the shutter
  startSHUT();

  //Prints out the contents of the array "pixels"
  printPixelData();
  
  delayed(10 * clockperiod);

}

void readPixelData()
{

  int index = 0;

  for (int x = 0 ; x < 3000/sectionPixel ; x++)
  {

    double sumOfSection = 0;

    for (int y = 0 ; y < sectionPixel ; y++)
    {
      PORTB = B001000;  //clk high
      clockpulse ++;

      //Capture pixel data
      sumOfSection += analogRead(A0);

      //delayed(timedelay);

      PORTB = B000000;   //clk low
      delayed(timedelay);
    }

    pixels[index] = sumOfSection / double(sectionPixel);

    index ++;
  }
}

void startROG()
{
  PORTB = B001000;  //clk high
  delayed(timedelay / 2);

  clockpulse ++;

  PORTB = B001100;  //clk high, rog high
  delayed(timedelay / 2);

  PORTB = B000100;   //clk low, rog high
  delayed(timedelay);

  //Do this for 10 clock periods
  for (int x = 0 ; x < 10; x++)
  {
    PORTB = B001100;  //clk high, rog high
    delayed(timedelay);

    clockpulse ++;

    PORTB = B000100;   //clk low, rog high
    delayed(timedelay);
  }

  PORTB = B001100;  //clk high, rog high
  delayed(timedelay / 2);

  clockpulse ++;

  PORTB = B001000;  //clk high, rog low
  delayed(timedelay / 2);

  PORTB = B000000;  //clk low, rog low
}

void startSHUT()
{
  PORTB = B001000;  //clk high
  delayed(timedelay);

  clockpulse ++;

  PORTB = B000000;   //clk low
  delayed(timedelay);

  PORTB = B001000;  //clk high
  delayed(timedelay);

  clockpulse ++;

  PORTB = B000000;   //clk low
  delayed(2);

  PORTB = B000010;  //clk low, shut high

  delayed(timedelay - 2);

  for(int x = 0 ; x < 5 ; x++)
  {
    PORTB = B001010;  //clk high, shut high
    delayed(timedelay);

    clockpulse ++;

    PORTB = B000010;   //clk low, shut high
    delayed(timedelay);
  }

  PORTB = B001010;  //clk high, shut high
  delayed(timedelay);

  clockpulse ++;

  PORTB = B000010;   //clk low, shut high
  delayed(2);
  
  PORTB = B000000;   //clk low, shut low

}

void printPixelData()
{
  for(int x = 0 ; x < sizeof(pixels) ; x++)
  {
    Serial.println(pixels[x]);
  }
  /*Serial.print("[");
  byte i;
  for(i = 0 ; i < sizeof(pixels) ; i++)
  {
    Serial.print(pixels[i]);
    Serial.print(", ");
  }
  Serial.print(pixels[i]);
  Serial.println("]");*/
}

//delays the time w/o using the delay function
//t is in microseconds
void delayed(double t)
{
  double t1 = micros();

  while (micros() - t1 < t) {
  }
}

Some additional information: I used the image sensor in a laboratory environment that is constantly bright. A lot of people work here, so turning off the lights wouldn't be an option. I sometime use like these really dark strips that is supposed to block > 90% of the light. However, the same issues are still present.

And I used processing to graph out the result.

There's too much code there to be worth reviewing in detail, but I'm surprised to see that you're hitting the I/O registers directly, and using floating point values for time, and have invented your own version of delayMicroseconds(). I suggest you try to write a test sketch that does the absolute minimum needed to get data out of the chip and don't worry about buffering images etc until you know you can talk to it OK.

It would help if you described / illustrated the overall circuit including the Arduino and the sensor, and gave a summary of what your code was intended to do for example how you're configuring the chip and how you're communicating with it in terms of clock and data signals.

The data sheet says this:

Clock frequency: 100kHz (Min), 1MHz (Max)

What frequency are you trying to use, and how are you controlling the clock frequency?

@PeterH

Well, I basically wrote my code based on the chart in the data sheet I used (link on the OP). I believe that the the by turning on the ROG (set high) will initialize the sensor? and similarly the SHUT will end the sensor. (correct me if this is wrong). After going through a certain number of clk pulses, I am then able to read the 3000 pixels. While reading these pixels, I average 10 at a time and store this value in one spot on the array. (since arduino uno has a limited memory).

Again, I followed the exact circuit as the one shown in the datasheet. I have a research mentor, who works at the university, and he checked the circuit for me. He also used the same circuit without the arduino using a function generator or something (I forgot), but he said that it was kinda working. However, he’s isn’t that experienced with the arduino like I am so he doesn’t know exactly what to do either.

I have some images from the oscilloscope so please take a look at them. The first is the rog with the clk pulse (clk is the regular square wave), the second shows the regular clk pulses after rog and before shut.

The second one looks a little off too me. I think this is a result of the arduino analogRead() function that is causing the delay?

To address the clock frequency issue, in my program I set the time delay between clk pulses to be 500 micro sec. Obviously, this is way too slow, so I’ll prob change this to like 2 micro sec or something. My mentor says that the arduino cannot handle delays slower than 10 micros effectively, so what do I do?

Also if I change the timedelay between clk pulses, this would in turn change the clk freq am I correct?

Another thing, my mentor suggested that I use something called nop (no operation), I’m not entirely sure how this would work. Can anybody care to explain? He said something about delaying the clk pulses?

Thanks.

Sorry, b/c of maximum file attachment, I couldn't post the second image.

Here is the second image showing the regular clock pulse, however it's not regular. Will this be a problem.

Could this be the result of the arduino analogRead() function?

Also messes up duty cycle too. I got like 34% I think last time I checked.

Evernote Camera Roll 20140720 230242[1].jpg|3264x2448

Does anyone have any suggestions or ideas?

Does anyone have any suggestions or ideas?

They might if you were to behave in a better manor.
Have you read the how to use this forum sticky post?
If so why have you ignored the bit about picture size?

First of all, I want to apologize if I wasn’t behaving nicely on the forum… I’m a new user and was kinda in a rush so I didn’t read the forum rules. Sorry about that guys. :slight_smile: I’ll make sure to pay attention to that next time. Thanks

So I did what PeterH said about cutting the program down to its bare bones and it seems to work on the oscilloscope! (Image attached below) I took off the analogRead() function as this was causing the problem in my code

yellow = clk pulse
purple = output voltage
blue = rog pulse

So I’m wondering is there a way to make analogRead faster? I read this article: http://frenki.net/2013/10/fast-analogread-with-arduino-due/, but I’m not sure whether this would work for the uno. And would changing analogRead() speed be a more efficient way than playing around with the clkpulse delay?

void readPixelData()
{
  for (int x = 0 ; x < 3000/sectionPixel ; x++)
  {

    double sumOfSection = 0;
    for (int y = 0 ; y < sectionPixel ; y++)
    {
      PORTB = B001000;  //clk high
      delayed(timedelay);
      
      sumOfSection += analogRead(A0);


      PORTB = B000000;   //clk low
      delayed(timedelay);
      
    }

    pixels[x] = sumOfSection / double(sectionPixel);
  }
}

New delayed function

void delayed(double t)
{
 int cycles = t*4;
 for(int k = 0;k<cycles;k++)
 {
   __asm__("nop\n\t"); 
 }
}

photo 1.JPG

I'll make sure to pay attention to that next time.

Thanks, we all appreciate it.

For the Uno I have used this to speed up the analogue read, include it in the setup function:-

// set up fast ADC mode
   ADCSRA = (ADCSRA & 0xf8) | 0x04; // set 16 times division

Grumpy_Mike:
For the Uno I have used this to speed up the analogue read, include it in the setup function:-

// set up fast ADC mode

ADCSRA = (ADCSRA & 0xf8) | 0x04; // set 16 times division

wow, the function went from taking 128 micro sec to 32 micro secs to run! Concerning the “0x04” bit on your code, are there other options for speed values? Is this the fastest speed? It would be great if I could get it to < 10 micros. or somewhere in that range.

I have trimmed down my code a lot after a few days, and the program seems to be working just fine.

I only have one problem though. I have an array of size 300 to store all of the output voltages from the image sensor. (the pixels). The program runs though each pixel in the sensor and reads the analog voltage of each pixel. After reading a certain number of voltages (sectionPixel), it then averages the voltages in the section and stores this value in the array. The program continues doing this until it finishes reading all of the pixels.

After recording all of the pixels (hence filling up the array), I would like to print out the values into the serial via serial.println(), and maybe later be able to save this into a file or something. However, when I don’t print out the array, the program works as expected(shown in the first picture), whereas if I do print the array out(second picture), it doesn’t appear to be working properly. I’m not exactly sure why this is happening, other than the fact that the array is receiving some values, just not the correct ones.

In both images, I am placing my finger in the middle of the sensor.

purple – analog voltage reading
yellow – rog pulse
blue – clk pulse

void loop()
{
  //Turns on ROG, initializes the image sensor
  startROG();

  delayed(timedelay);

  for (int x = 0 ; x < 2 ; x++)
  {
    digitalWrite(clockPin, HIGH); //clk high
    delayed(timedelay);

    digitalWrite(clockPin, LOW);  //clk low
    delayed(timedelay);
  }

  for (int x = 0 ; x < 55 ; x++)
  {
    digitalWrite(clockPin, HIGH); //clk high
    delayed(timedelay);

    digitalWrite(clockPin, LOW);  //clk low
    delayed(timedelay);
  }

  //Read from pixel 1 to pixel 3000 and stores them in the array: "pixels"
  readPixelData();

  //Starts the shutter
  startSHUT();
  
  //double t1 = micros();
  //Prints out the contents of the array "pixels"
  printPixelDataArray();
  //Serial.println(micros() - t1);

  delayed(50);
  //delayed(10 * clockperiod);

}
void printPixelDataArray()
{
  Serial.print("[");
  byte i;
  for (i = 0 ; i < sizeof(pixels) / 8 ; i++)
  {
    Serial.print(pixels[i]);
    Serial.print(", ");
  }
  Serial.print(pixels[i]);
  Serial.println("]");
}
void readPixelData()
{
  for (int x = 0 ; x < 3000 / sectionPixel ; x++)
  {

    double sumOfSection = 0;
    for (int y = 0 ; y < sectionPixel ; y++)
    {
      //double t1 = micros();
      digitalWrite(clockPin, HIGH); //clk high
      delayed(timedelay);

      //double t2 = micros();

      sumOfSection += analogRead(A0);
      //double t3 = micros();

      digitalWrite(clockPin, LOW); //clk low
      delayed(timedelay);

      //double t3 = micros();
      //Serial.println(t3-t2);
      //Serial.println((t2-t1)/(t3-t1) * 100);
    }

    pixels[x] = sumOfSection / double(sectionPixel);
  }
}

photo 1(1).JPG

photo 2.JPG

Printing values does take quite a time. So maybe that your sensor is saturating with the extra intergration time caused by the printing.

You have not included all the code so I can't see what baud rate you are using, Maybe make this faster.