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
byte pdata[PIXEL_CNT/8];
Code: Select all
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
The pixels then get displayed in the serial monitor as "1" for lit pixels and "0" for dark-
Code: Select all
// 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" : ".");
}
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
/*
* =========================================================================
*
* 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;
}