Please be aware of all shipping deadlines before placing your order - we cannot guarantee orders will arrive before Christmas!

help with code for reading a linear CCD
Moderators: adafruit_support_bill, adafruit

help with code for reading a linear CCD

by IanJohnson on Mon Jun 03, 2013 7:33 pm

I am working on an Arduino based laser micrometer using a linear ccd sensor like the Taos TSL1401. I found some code for reading the pixels and detecting edges, which is what I need to do. I need some help figuring out how it is being done.

The first part is the pixels are read, and displayed in the serial monitor as "1" for a lit pixel and "." for a dark one. The sensor has 128 pixels (PIXEL_CNT). It outputs about 0v for dark pixels, 2v for white and 3v for saturated.

There is an array defined, with a length of 16 -

Code: Select all | TOGGLE FULL SIZE
byte pdata[PIXEL_CNT/8];


The sensor is sent a pulse to its SI pin to start the read, then the readings are shifted in to the array -

Code: Select all | TOGGLE FULL SIZE
  clockSI(si, clk);                    // Clock out another SI pulse.

  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)   
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i


I don't see why the array is shortened to 16. Also the sensor analog output (ao) is mapped to Pin 0 which could be digital or analog. Is shiftin inherently an analogRead? Since pdata is a byte, it is a binary number between 0 and 255, but the Atmega reads the analog pins as 0-1023, correct? Will it remap to 0-255, or does anything over 255 get clipped?

The pixels then get displayed in the serial monitor as "1" for lit pixels and "0" for dark-

Code: Select all | TOGGLE FULL SIZE
// dispPix
// Display 128 pixels: light pixels as "1"; dark, as "_".
void dispPix()
{
  for(int i = 0; i < PIXEL_CNT; i++)
    Serial.print( bitRead(pdata[i >> 3], i % 8) ? "1" : ".");
}


This is confusing, because now Pixel_CNT isn't divided by 8. Also the bitshift changes the array position to 0 for the first 8 counts , and "i % 8" cycles the bit address through 0,2,4,6,0. Then for i=9 it reads the 2nd bit, i=10 reads the 3rd, and so on until i=16 at which point it goes back to the first bit.

I don't see how sampling individual bits throughout the readings will determine whether a pixel was light or dark. It seems like it would make more sense to check the leftmost bit for each pixel, because for readings under 128 it will always be 0 and over 128 it will always be 1. Is the code wrong, or am I missing something fundamental? Here is the full code for context -

Code: Select all | TOGGLE FULL SIZE
 
/*
* =========================================================================
 *
 *   File...... TSL1401_scan.ino
*   Purpose... Image capture and processing demo using the TSL1401-DB
 *   Author.... Phil Pilgrim, Bueno Systems, Inc.
 *   Started... 11 July 2007
 *
*   Author.... Martin Heermance
 *   Updated... 13 September 2012 - ported to C++ on Arduino.
*
 * =========================================================================
 * Program Description
* This program demonstrates image capture and processing using the
 * TSL1401-DB (Parallax p/n 28317). It continuously acquires and displays
 * images from the TSL1401R sensor chip. It then locates both left and right
* bright edges, displaying them graphically using DEBUG. Finally it
 * computes both the area and extent of the object found.
 * Revision History
*/

// I/O Definitions

const int ao = 0;            // TSL1401's analog output (threhsolded by MCU).
const int si = 1;            // TSL1401's SI pin.
const int clk = 2;           // TSL1401's CLK pin.

// Constants
const int DRK = 0;           // Value assignd to "which" for dark pixels.
const int BRT = 1;           // Value assigned to "which" for bright pixels.
const int FWD = 0;           // Value assigned to "dir" for left-to-right search.
const int BKWD = 1;          // Value assigned to "dir" for right-to-left search.
const int PIXEL_CNT = 128;

// ASCII terminal control codes to match PBASIC commands.
const char * CLREOL = "\033[K";       //Clear next line
const char * CRSRXY = "\033[%d;%dH";   //Set cursor positon
const char * HOME = "\033[H";       

// Variables
byte pdata[PIXEL_CNT/8];     // Pixel data, as acquired LSB first from sensor. The array is 16 bits long for 128 pixel sensor

// Program Code

void setup() {
  // initialize serial communications:
  Serial.begin(9600);
  Serial.print(HOME);    // Go to home position on DEBUG screen.
  dispHdr();             // Display the pixel location header.  Row of numbers at Row 0
}

void loop() {
  char buf[32];

  //Begin the scan-and-process loop.
  getPix(8333);          // Obtain a pixel scan with exposure time of 8333uSec (1/120th sec).
  sprintf(buf, CRSRXY, 2, 0);
  Serial.print(buf);     // Move to column 0, row 2.
  dispPix();             // Display the pixels here.

  int lptr = 0;          // Left pixel pointer for count and find operations.
  int rptr = 127;        // Right pixel pointer for count and find operations.

  // Indicates pixels found (= 1), or not found (= 0).
  bool found = findEdge(lptr, rptr, FWD, BRT);     // Find first dark-to-light edge going L->R.

  // Switch directions.
  found = found & findEdge(lptr, rptr, BKWD, BRT); // Find first dark-to-light edge going L<-R.
  Serial.print(CLREOL);  // Clear the next line.
  if (found) {           // Both edges found?
    // Yes: Display left edge.
    sprintf(buf, CRSRXY, 3, lptr - 1);
    Serial.print(buf);
    Serial.print("_|");
    // Display right edge.
    sprintf(buf, CRSRXY, 3, rptr);
    Serial.print(buf);
    Serial.print("|_");
    Serial.println("\nArea = ");      // Display area by computing light pixel count.
    Serial.print( countPix(lptr, rptr, BRT) );
    Serial.print("   Extent = ");     //... and extent of object.
    Serial.print(rptr - lptr + 1);
    Serial.print(CLREOL);
  }
  else
  {
    //No:  Display failure message.
    Serial.print("\n\nNo object found.");
    Serial.print(CLREOL);
  }
}

// Subroutines

// getPix
// Acquire 128 thresholded pixels from sensor chip.
// exp is the exposure time in microseconds.
void getPix(int expose)
{
  clockSI(si, clk);                    // Clock out the SI pulse. Tells sensor to start sending data by triggering sync pin

   // Rapidly send CLKs to throw away old image.
  for (int i = 0; i < PIXEL_CNT/8; i++)  //repeat 16 times
    shiftIn(ao, clk, LSBFIRST); //sends a clock pulse and reads a bit each time, starting with the rightmost bit

  // delay to allow the new image to expose.
  delayMicroseconds(expose);

  clockSI(si, clk);                    // Clock out another SI pulse.

  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)   
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i
}

// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
    digitalWrite(dataPin, 1);

    // pulse the clock:
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(clockPin, LOW);
}

// dispHdr
// Display a header to aid in identifying pixel positions.
void dispHdr()
{
  // Display tens digits.
  for(int i = 0; i <= 12; i++) //128 pixels so there are 12 tens digits
  {
    Serial.print (i); // DIG 0
    if (i < 12)
      Serial.print("         ");
    else
      Serial.println("");
  }

  // Display ones digits.
  for(int i = 0; i < PIXEL_CNT; i++)  //There is a ones digit for each of the 128 numbers
    Serial.print(i % 10);   //Diplay the remainder of i/10.  As i rises from 0 to 127, the remainder will loop from 0 to 9.
}

// dispPix
// Display 128 pixels: light pixels as "1"; dark, as "_".
void dispPix()
{
  for(int i = 0; i < PIXEL_CNT; i++)
    Serial.print( bitRead(pdata[i >> 3], i % 8) ? "1" : ".");
}

// findEdge
// Find the first edge within the range lptr through rptr, in the direction
// given by dir and of the type indicated by which (0 = light-to-dark;
// 1 = dark-to-light).
bool findEdge(int & lptr, int & rptr, bool dir, bool which)
{
  which = !which;                    // Look for opposite kind of pixel first.
  bool found = findPix(lptr, rptr, dir, which);
  which = !which;                    // Then look for desired pixel,
                                     //  by falling through to FindPix.
  return found & findPix(lptr, rptr, dir, which);
}

// findPix
// Find the first pixel within the range lptr through rptr, in the direction
// given by dir and of the type indicated by which (0 = dark; 1 = light).
bool findPix(int & lptr, int & rptr, bool dir, bool which)
{
  if (lptr <= rptr && rptr < PIXEL_CNT)
  {                                  // Still looking & within bounds?
    if (dir = FWD)
    {                                //  Yes: Search left-to-right?
      for(; lptr <= rptr; lptr++)    //         Yes: Loop forward.
        if (bitRead(pdata[lptr >> 3], lptr % 8) == which)
          return true;
    }
    else
    {
      for(; rptr >= lptr; rptr--)    //         No:  Loop backward.
        if (bitRead(pdata[rptr >> 3], rptr % 8) == which)
          return true;
    }
  }

  // Didn't look or nothing found.
  return false;
}

// countPix
// Count pixels within the range lptr through rptr, of the type indicated by
// which (0 = dark; 1 = light).
int countPix(int & lptr, int & rptr, int which)
{
  // Initialize count.
  int cnt = 0;

  // Valid range?
  if (lptr <= rptr && rptr < PIXEL_CNT)
  {
    //  Yes: Loop over desired range.
    for (int i = lptr; i < rptr; i++)
    {
      // Add to count when pixel matches.
      if (bitRead(pdata[i >> 3], i % 8) == which)
      {
        cnt++;
      }
    }
  }
  return cnt;
}
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by tldr on Mon Jun 03, 2013 7:53 pm

shiftin is a serial digital read. it shifts eight bits in to a byte.

your code is shifting in 128 bits, 8 bits * 16 bytes. each bit of each byte in your 16 byte array represents one position in the ccd array, either on or off. apparently the sensor is configured for digital output. it is possible that it can output raw analog values, but that is not what your code is having it do.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by IanJohnson on Mon Jun 03, 2013 8:14 pm

If the analog output of the sensor is going into a digital pin, how does the Arduino determine the threshold between 0 and 1?

I see how the readout works now. For all values of i from 8-15, (i >> 3) will equal 1 while the modulo scans from 0 to 7 hitting all the bits for that position in the array. Then for 16-23 (i >>3) = 2, etc. It seems like for i = 0 through 7, the modulo won't work right, and the wrong bits will be read. 1/8 has a remainder of 2, 2/8 has a remainder of 4, 3/8 has a remainder of 6, 4/8 has a remainder of 0, correct?

I'm wondering about readings of individual pixels getting stored as bits. shiftin sends the clock signal that tells the sensor to move to the next pixel. Since pdata is defined as an 8 bit byte, does shiftin automatically send 8 clock pulses to get 8 bits before moving to the next position in the array?
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by tldr on Tue Jun 04, 2013 1:12 am

the code you have just gets a single bit reading for each position on the sensor using a digital read.

i don't quite understand the use of the si pin in your code. it doesn't seem to match the data sheet. si goes high but never goes low. it should go high before the first clock pulse starts and go low, again, before the clock goes low.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by IanJohnson on Tue Jun 04, 2013 2:05 pm

Here is the original clock SI function-

Code: Select all | TOGGLE FULL SIZE
// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
    digitalWrite(dataPin, 1);

    // pulse the clock:
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(clockPin, LOW);
}


So should it instead be

Code: Select all | TOGGLE FULL SIZE
// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
   
    // pulse the SI pin
    digitalWrite(dataPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(dataPin, LOW);

    // pulse the clock:
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(100);
    digitalWrite(clockPin, LOW);
}


or is it-

Code: Select all | TOGGLE FULL SIZE
// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    digitalWrite(dataPin, HIGH);
    digitalWrite(clockPin, HIGH);
 
   delayMicroseconds(100);
    digitalWrite(dataPin, LOW);
    digitalWrite(clockPin, LOW);
}
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by tldr on Wed Jun 05, 2013 12:44 am

this going to be the closest.

Code: Select all | TOGGLE FULL SIZE
// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    digitalWrite(dataPin, HIGH);
    digitalWrite(clockPin, HIGH);

    delayMicroseconds(100);
    digitalWrite(dataPin, LOW);
    digitalWrite(clockPin, LOW);
}


... but you'll be sacrificing one bit of data, because the first bit gets clocked in on that clock pulse. this also means that the last bit you clock in to your data array will be garbage.

that, anyway, is the impression i get from looking at page 5 of the datasheet.

i think the solution is to leave the clock pin high. so try it like this...

Code: Select all | TOGGLE FULL SIZE
// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    digitalWrite(dataPin, HIGH);
    digitalWrite(clockPin, HIGH);

    delayMicroseconds(100);
    digitalWrite(dataPin, LOW);
}
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by tldr on Wed Jun 05, 2013 12:55 am

you'll also need to toggle the clock one last time to reset the sensor. this is how i would write getPix...

Code: Select all | TOGGLE FULL SIZE
void getPix(int expose)
{
  clockSI(si, clk);                    // Clock out the SI pulse. Tells sensor to start sending data by triggering sync pin

   // Rapidly send CLKs to throw away old image.
  for (int i = 0; i++; i < 129) {
    digitalWrite (clk, 1);
    digitalWrite (clk, 0);
  }

  // delay to allow the new image to expose.
  delayMicroseconds(expose);

  clockSI(si, clk);                    // Clock out another SI pulse.

  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)   
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i

  // one last clock to reset the sensor
  digitalWrite (clk, 1);
  digitalWrite (clk, 0);
}


see page two of the data sheet.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by IanJohnson on Wed Jun 05, 2013 2:04 pm

I'm not getting any reading from the CCD. I'm using the TSL202R which is similar - http://www.mouser.com/ds/2/588/TSL202R-E-198539.pdf

It uses 2 64 pixel arrays, with AO1 connected to AO2, and an SO1 to SI2 to trigger the second pixel array. It should still work like a single 128 pixel array. The datasheet recommends a 320ohm pulldown resistor for the AO, but the closest I had was 270ohm. It also says to add a capacitor to VDD for best performance, but I don't know if that is critical.

Image

Here is a simplified version of the code that only tries to ouput the bits in a row to the serial monitor.

Any ideas what might be going wrong? Something with the timing maybe? The datasheet says the pixels can't hold the charge longer than 100ms . The exposure time is much shorter than that (8ms), but could the serial monitor be slowing the program down enough for the pixels to discharge before they are read? I'm getting nothing but 0s.

Code: Select all | TOGGLE FULL SIZE
/*
* =========================================================================
 *
 *   File...... TSL1401_scan.ino
*   Purpose... Image capture and processing demo using the TSL1401-DB
 *   Author.... Phil Pilgrim, Bueno Systems, Inc.
 *   Started... 11 July 2007
 *
*   Author.... Martin Heermance
 *   Updated... 13 September 2012 - ported to C++ on Arduino.
*
 * =========================================================================
 * Program Description
* This program demonstrates image capture and processing using the
 * TSL1401-DB (Parallax p/n 28317). It continuously acquires and displays
 * images from the TSL1401R sensor chip. It then locates both left and right
* bright edges, displaying them graphically using DEBUG. Finally it
 * computes both the area and extent of the object found.
 * Revision History
*/

// I/O Definitions

const int ao = 13;            // TSL1401's analog output (threhsolded by MCU).
const int si = 3;            // TSL1401's SI pin.
const int clk = 2;           // TSL1401's CLK pin.

// Constants
const int PIXEL_CNT = 128;

// Variables
byte pdata[PIXEL_CNT/8];     // Pixel data, as acquired LSB first from sensor. The array is 16 bits long for 128 pixel sensor

// Program Code

void setup() {
  // initialize serial communications:
  Serial.begin(9600);
  pinMode (ao,INPUT);
}


void loop() {

  getPix(8333);          // Obtain a pixel scan with exposure time of 8333uSec (1/120th sec).
  dispPix();             // Display the pixels here.
  Serial.println(" ");
}

// Subroutines

// getPix
// Acquire 128 thresholded pixels from sensor chip.
// exp is the exposure time in microseconds.
void getPix(int expose)
{
  clockSI(si, clk);                    // Clock out the SI pulse. Tells sensor to start sending data by triggering sync pin

   // Rapidly send CLKs to throw away old image.
  for (int i = 0; i++; i < 129) {
    digitalWrite (clk, 1);
    digitalWrite (clk, 0);
  }

  // delay to allow the new image to expose.
  delayMicroseconds(expose);

  clockSI(si, clk);                    // Clock out another SI pulse.

  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)  {
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i

  // one last clock to reset the sensor
  digitalWrite (clk, 1);
  digitalWrite (clk, 0);
}
}

// clockSI is used to signal the TSL1401 that commands are comming.
void clockSI(int dataPin, int clockPin) {
    // set the pinModes for the clock and data pins:
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    digitalWrite(dataPin, HIGH);
    digitalWrite(clockPin, HIGH);

   delayMicroseconds(100);
    digitalWrite(dataPin, LOW);
}

// dispPix
// Display 128 pixels: light pixels as "1"; dark, as "_".
void dispPix()
{
  for(int i = 0; i < PIXEL_CNT; i++)
    Serial.print(bitRead(pdata[i >> 3], i % 8));
}

IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by IanJohnson on Wed Jun 05, 2013 4:00 pm

I wired the sensor using the parallel configuration, making it a 64 pixel sensor with AO going to the Arduino AO. I get 0, and if I plug into the sensor's A2 I get 95 even though that side isn't being driven. I don't know if it is a problem with power, or if it isn't getting or responding to SI or CLK.
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by tldr on Thu Jun 06, 2013 1:53 am

little problem in the code...
Code: Select all | TOGGLE FULL SIZE
  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)  {
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i

  // one last clock to reset the sensor
  digitalWrite (clk, 1);
  digitalWrite (clk, 0);
}

should be...
Code: Select all | TOGGLE FULL SIZE
  // Shift in all the pixels using digital I/O to threshold.
  for (int i = 0; i < PIXEL_CNT/8; i++)  {
    pdata[i] = shiftIn(ao, clk, LSBFIRST);  //shiftIn sends a clock pulse and records data into array position i
  }

  // one last clock to reset the sensor
  digitalWrite (clk, 1);
  digitalWrite (clk, 0);


IanJohnson wrote: if I plug into the sensor's A2 I get 95 even though that side isn't being driven.


not sure what you mean here. your code looks like it should only output ones and zeros. do you get a long string of zeros followed by 1011111?
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by IanJohnson on Thu Jun 06, 2013 2:51 am

I wanted to be sure there was nothing going wrong with plugging the sensor's AO into a digital port. I plugged it into A0, and wrote analog versions of getPix and disPix-

Code: Select all | TOGGLE FULL SIZE
void getAnalogPix(int expose)
{
  clockSI(si, clk);                    // Clock out the SI pulse. Tells sensor to start sending data by triggering sync pin

   // Rapidly send CLKs to throw away old image.
  for (int i = 0; i++; i < 129) {
    digitalWrite (clk, 1);
    digitalWrite (clk, 0);
  }

  // delay to allow the new image to expose.
  delayMicroseconds(expose);

  digitalWrite(si, HIGH);
  for (int i=0;i<=PIXEL_CNT;i++){
    digitalWrite(clk, HIGH);
    analogpdata[i]=analogRead(analog_ao);
    delayMicroseconds(2);
    digitalWrite(clk, LOW);
    delayMicroseconds(2);
    if (i==1) digitalWrite(si, LOW);
  }

  // one last clock to reset the sensor
  digitalWrite (clk, 1);
  digitalWrite (clk, 0);
}

// analogdispPix
// Display 128 pixels
void analogdispPix()
{
  for(int i = 0; i < PIXEL_CNT; i++){
    Serial.print(analogpdata[i]);
  Serial.print(",");}
}


I wanted to get a more direct look at what is going on with the sensor output and not just a 1 or 0, and see if there was any change in value going on that was maybe not reflected by the digital input. The only thing I get out of the analog version of the array is 95. If I hook up to AO1 for the first set of 64 pixels only, I get 0.
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by liuyelian on Thu Jun 06, 2013 4:28 am

you'll also need to toggle the clock one last time to reset the sensor.
liuyelian
 
Posts: 1
Joined: Thu Jun 06, 2013 4:25 am
Location: hefeifeicuilu

Re: help with code for reading a linear CCD

by tldr on Thu Jun 06, 2013 8:32 am

IanJohnson wrote:I wanted to get a more direct look at what is going on with the sensor output and not just a 1 or 0, and see if there was any change in value going on that was maybe not reflected by the digital input. The only thing I get out of the analog version of the array is 95. If I hook up to AO1 for the first set of 64 pixels only, I get 0.


fair enough. could the values on ao1 be caused by the lack of a pull down? if for some reason the output isn't getting turned on it'll just float.

you might try increasing the exposure time. check the data sheet for the maximum.

i do see one bug in your analog code. should be

Code: Select all | TOGGLE FULL SIZE
    if (i==0) digitalWrite(si, LOW);


but you could just go ahead and use the modified version of clockSI before the loop.

i don't wish to shake your confidence in my abilities, (though that may be the kind thing to do), but have you tried running this thing with the example code you started out with? presumably that worked for someone even if they were losing the last value.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: help with code for reading a linear CCD

by IanJohnson on Thu Jun 06, 2013 7:42 pm

I saw that, and I was wondering, does it run through the For loop the first time with i=0, or does the i++ happen first so it is already on i=1 when it gets to the part about setting the SI pin low?

The code I've been working with is a port from a program for a Parallax board. The author said he hadn't actually tried it, though it looks like it should work.

There is this bit of code on Github that I could try. It's incomplete since it only runs the clock, and doesn't read the data. I was wondering about the While at the bottom. Is it supposed to do something as is, or does it look like the start of something that wasn't finished? - From https://github.com/chiva/Arduino-CCD-TSL214/blob/master/ccd.pde

Code: Select all | TOGGLE FULL SIZE
#define CLK 3      // Clock source pin
#define SI 8       // 'Start integration' pin
#define INT_TIME 8 // Integration time (around 1÷8)
#define PIXELS 64  // Number of pixels

void setup(){
  pinMode(CLK, OUTPUT);
  pinMode(SI, OUTPUT);
}

void loop(){
  unsigned long startTime = millis();
  digitalWrite(SI, HIGH);
  for (int i=0;i<=PIXELS;i++){
    digitalWrite(CLK, HIGH);
    delayMicroseconds(2);
    digitalWrite(CLK, LOW);
    delayMicroseconds(2);
    if (i==1) digitalWrite(SI, LOW);
  }
  while (millis() - startTime < INT_TIME);
}
IanJohnson
 
Posts: 16
Joined: Mon Jan 28, 2013 2:16 pm

Re: help with code for reading a linear CCD

by tldr on Fri Jun 07, 2013 1:04 pm

according to the timing diagrams si should come low during the first clock period, so that loop should look like this...

Code: Select all | TOGGLE FULL SIZE
void loop(){
  unsigned long startTime = millis();
  digitalWrite(SI, HIGH);
  for (int i=0;i<=PIXELS;i++){
    digitalWrite(CLK, HIGH);
    delayMicroseconds(2);
    digitalWrite(CLK, LOW);
    delayMicroseconds(2);
    if (i==1) digitalWrite(SI, LOW);
  }
  while (millis() - startTime < INT_TIME);
}


though i'd do it like this...

Code: Select all | TOGGLE FULL SIZE
void loop(){
  unsigned long startTime = millis();
  digitalWrite(SI, HIGH);
  digitalWrite(CLK, HIGH);
  digitalWrite(SI, LOW);
  for (int i=0;i<=PIXELS;i++){
    digitalWrite(CLK, HIGH);
    delayMicroseconds(2);
    digitalWrite(CLK, LOW);
    delayMicroseconds(2);
  }
  while (millis() - startTime < INT_TIME);
}


the while loop at the end is what controls the exposure time. the code is designed to constantly monitor the sensor. taking time to write out the data array might well screw up the timing. you could probably write out the beginning and end or width of a dark band or something as long as the i/o would take less than 8ms, (INT_TIME). you could jack up the baud rate for the serial i/o.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am