Shop OBEX P1 Docs P2 Docs Learn Events
TSL1401 and Arduino — Parallax Forums

TSL1401 and Arduino

kg1kg1 Posts: 164
edited 2014-09-23 13:24 in Accessories
re Line-Scan Camera TSL1401-DB and DB to 12 pin Expander Board and Arduino Duemilanove Mother Board (http://arduino.cc/en/Main/ArduinoBoardDuemilanove).

I am trying to write Arduino C code to operate the TSL1401-DB in one-shot imaging.

Could an expert in TSL1401-DB programming review my timing in the function "getcamera" below? I would be grateful for your advice.

int syncPin = 12;
int clockPin = 11;
int dataPin = 2; // must be in range 0 to 5
int lightVal[128];
unsigned long utime;
int itime = 0;
int expose = 7390; // 8333uSec ie 1/120th second

void setup()
{
pinMode(clockPin, OUTPUT);
pinMode(syncPin, OUTPUT);
Serial.begin(9600);
}

void loop()
{
int b = Serial.read();
if (b == 's')
{
getCamera();
delay(2000);
}
}


void getCamera()
{
digitalWrite(clockPin, LOW);
pinMode(syncPin, OUTPUT);
digitalWrite(syncPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(syncPin, LOW);
utime = micros();
digitalWrite(clockPin, LOW);
for (int j = 0; j < 128; j++)
{
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
delayMicroseconds(expose);
digitalWrite(syncPin, HIGH);
digitalWrite(clockPin, HIGH);
digitalWrite(syncPin, LOW);
utime = micros() - utime;
digitalWrite(clockPin, LOW);
for (int j = 0; j < 128; j++)
{
delayMicroseconds(20);
lightVal[j] = analogRead(dataPin);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
delayMicroseconds(20);
for (int j = 0; j < 128; j++)
{
itoa(lightVal[j], 'S');
}
itime = (int)utime;
itoa(itime, 'S');
}

Regards,
Kevin

Comments

  • analogbodyanalogbody Posts: 2
    edited 2012-09-24 08:52
    Kev I am doing exactly the same work as you do.
    I have written a code in c, but I have a true doubts how to connect sensor to my arduino.
    I have written datasheet and there is no literal explanation how to connect exactply nodes as:
    tr, sd, st, so

    My question is where to find this? And I have some interesting code for you, but I have to check it so I won't paste it there yet.
    Please help me and if the code works, i will give it to you.

    thanks
    Piter
  • Martin_HMartin_H Posts: 4,051
    edited 2012-09-24 19:01
    It turns out that I was wondering how to do this and translated Phil Pilgrim's PBASIC code into C for the Arduino. I haven't tested it yet, but you're welcome to have it if it does you any good. It should at least give you an idea of what to do.
    /*
    * =========================================================================
     *
     *   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";
    const char * CRSRXY = "\033[%d;%dH";
    const char * HOME = "\033[H";
    
    // Variables
    byte pdata[PIXEL_CNT/8];     // Pixel data, as acquired LSB first from 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.
    }
    
    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.
    
       // Rapidly send CLKs to throw away old image.
      for (int i = 0; i < PIXEL_CNT/8; i++)
        shiftIn(ao, clk, LSBFIRST);
    
      // 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);
    }
    
    // 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++)
      {
        Serial.print (i); // DIG 0
        if (i < 12)
          Serial.print("         ");
        else
          Serial.println("");
      }
    
      // Display ones digits.
      for(int i = 0; i < PIXEL_CNT; i++)
        Serial.print(i % 10);
    }
    
    // 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;
    }
    
  • ianjohnsonianjohnson Posts: 1
    edited 2013-06-07 08:52
    I have been trying to do this with a TSL202 and an Arduino, and I can't get it to work. The sensor should work the same on the microcontroller side as the 1401. Here is the datasheet - http://www.mouser.com/ds/2/588/TSL202R-E-198539.pdf

    Here is the breadboard -

    linearccd-e1370455346522.jpg

    There are 2 64 pixel arrays, so AO1 connects to AO2, and SO1 connects to SI2 to trigger the second array. I've simplified the code to only display the pixel values on a single line in the serial monitor. Once I have that working, I can move on to the more interesting stuff. I also made analog versions of getPix and dispPix so I can see something other than 0 or 1. So far with the digital input all I get are 0 with my Arduino Micro, or 1 with an Uno. With analog inputs, I get 95 from AO2. If I wire the sensor to only use the first 64 pixel array and take only AO1, I get 0.

    I changed clockSI slightly, so SI goes low before the clock goes high. There was a footnote in the datasheet saying that was necessary. Also I left the clock high, because the first bit comes through with the first rising clock after SI. If I take the clock low during clockSI I will miss that first bit.

    It didn't make any difference, I can't get this code to work any more than the original. I have two of these sensor, and neither of them worked. I know it's not the 1401, but I don't see anything different about its operation other than the need for the pulldown resistor.


    /** =========================================================================
     *
     *   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 = 8;            // TSL1401's analog output (threhsolded by MCU).
    const int si = 4;            // TSL1401's SI pin.
    const int clk = 8;           // TSL1401's CLK pin.
    const int analog_ao = 5;
    
    
    // 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
    int analogpdata[PIXEL_CNT];
    // Program Code
    
    
    void setup() {
      // initialize serial communications:
      Serial.begin(115200);
      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(" ");
      //getAnalogPix(8333);
      //analogdispPix();
        Serial.println(" ");
    //  Serial.println(analogRead(analog_ao));
    }
    
    
    // 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(dataPin, LOW);
    
    
       delayMicroseconds(6);       
        
        digitalWrite(clockPin, HIGH);
    
    
    }
    
    
    // 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));}
    }
    
    
    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: light pixels as "1"; dark, as "_".
    void analogdispPix()
    {
      for(int i = 0; i < 24; i++){
        Serial.print(analogpdata[i]);
      Serial.print(",");}
    }
    
    
    
    
    
    484 x 648 - 119K
  • epierreepierre Posts: 1
    edited 2014-09-23 13:24
    Hello,

    I have the same issue with a TSL201R, which is 64 pixel array in one only, both doesn't work, I have 1 everywhere...

    Have you found a solution ?
Sign In or Register to comment.