Shop OBEX P1 Docs P2 Docs Learn Events
Reading TSL 1401R-LF Voltage — Parallax Forums

Reading TSL 1401R-LF Voltage

mclparkermclparker Posts: 15
edited 2015-02-03 11:17 in Accessories
Hi again group,

I have a BS2pe and tsl1401DB connected in position B. I have tried to sort out the commands and pin assignments myself but the different reference materials are difficult for me to sort out.

My objective is to scan the tsl1401R-LF and screen display individual pixel. Here are code fragments I have cobbled from posts here. It generates debug values that don't make sense. Also, I commented out the owin 10 material because it gets stuch in that loop for reasons i don't understand. Can someone help me with the pin assignments and code please. I'm not certain I assigned owio correctly. No error messages come from the flags scan.

Thank all for any help.

mike


ao PIN 0
si PIN 1
clk PIN 2
owio PIN 10
exp VAR Word
vdata VAR Word(8)
pulsw VAR Byte
i VAR Byte
Busy VAR Bit
flags VAR Byte

exp=8333
pulsw = 1

DEBUG HOME


SHIFTOUT si, clk, 0, [1\1] 'Clock out the SI pulse.
PWM clk, 128, 1 'Rapidly send 150 or so CLKs.
PULSOUT si, exp >> 1 MIN 1016 - 1016 'Wait for remaining integration time.
SHIFTOUT si, clk, 0, [1\1] 'Clock out another SI pulse.

FOR i = 0 TO 128 'scan pixels


PULSOUT clk, pulsw '129 pixel clk pulses


OWOUT Owio, 0, [%00001011]
'DO
'OWIN 10, 4, [Busy]
'LOOP WHILE Busy
OWIN Owio, 0, [vdata.HIGHBYTE, vdata.LOWBYTE]
GOSUB GetError
DEBUG DEC vdata,CR
DEBUG flags


NEXT

END

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-12-21 19:16
    If you are using the BS2pe MoBo, you do not need to clock the TSL1401 chip from the Stamp. (In fact, you cannot read the levels from the Stamp anyway, since they connect only to the onboard AVR coprocessor.) What you need to do is load the TSL1401 driver firmware into the AVR chip and let it do the work for you. The TSL1401 documentation provides all the info you need for getting pixel values out of the sensor, via the 1401 AVR firmware.

    -Phil
  • mclparkermclparker Posts: 15
    edited 2010-12-22 15:38
    Thank you Phil,

    I followed your steps with one exception...the hex file I loaded was TSL1401.hex - not TSL1401DB01.hex [which I could not find].

    My DB is loaded in socket B and I have the Mobo jumper set at 3.3v.

    I ran the code below. When the debug screen comes up...nothing is shown. I commented out the "loop while busy", and got screen data [all 65535s] that don't make sense. It seems, among other things, that the loop is getting stuck. What am I doing wrong?

    ' {$STAMP BS2pe}
    ' {$PBASIC 2.5}

    owio PIN 6 ' PIN 10 for socket "A"; PIN 6 for socket "B".

    Voltage VAR Word
    Busy VAR Bit

    DO
    OWOUT Owio, 0, [%00001011]
    DO : OWIN Owio, 4, [Busy] : LOOP WHILE Busy
    OWIN Owio, 0, [Voltage.HIGHBYTE, Voltage.LOWBYTE]
    DEBUG DEC Voltage, CR
    LOOP
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-12-22 19:52
    Try this (copy and paste):
    ' =========================================================================
    '
    '   File...... tsl1401_dump_gray.bpe
    '   Purpose... Dump pixel values from the TSL1401-DB using the MoBoStamp-pe.
    '   Author.... Phil Pilgrim
    '   E-mail.... propeller@phipi.com
    '   Started... 22 Dec 2010
    '   Updated...
    '
    '   {$STAMP BS2pe}
    '   {$PBASIC 2.5}
    '
    ' =========================================================================
    
    
    ' -----[ Program Description ]---------------------------------------------
    
    ' This program dumps analog pixel values from the TSL1401-DB via the
    ' TSL1401.hex firmware for the MoBo's AVR coprocessor.
    
    ' -----[ I/O Definitions ]-------------------------------------------------
    
    owio            PIN     6     'Pin for OWIN and OWOUT to AVR coprocessor.
    
    ' -----[ Constants ]-------------------------------------------------------
    
    ' Commands
    
    SETLED          CON     $EB   'Set LED strobe and brightness/time from next byte.
    
      'Flag to OR to brightness/time (0 - 127) value.
    
      TIME          CON     $80   'Set strobe: value (0 - 127) is 0 - 3.4mS at 100% on.
      INTEN         CON     $00   'Set intensity: value (0 - 127) is 0 - 49.6% on.
    
    SETBIN          CON     $EC   'Set threshold, hysteresis, and filter (3 bytes).
    
      'Filter flags.
    
      FLOAT         CON     $80   'Threshold is floating per filter value (0 - 7).
      FIXED         CON     $00   'Threshold is fixed.
      WINDOW        CON     $40   'Threshold is a window (outside of hysteresis band).
      LEVEL         CON     $00   'Threshold is a level with hysteresis.
    
    SETEXP          CON     $EE   'Set exposure to byte (1 - 255) following: 0.27 - 68mS.
    
    ACQGRAY         CON     $A0   'Acquire and dump a grayscale image.
    ACQBIN          CON     $A4   'Acquire a binary image.
    ACQAND          CON     $A1   'Acquire binary image ANDed w/ previous.
    ACQOR           CON     $A2   'Acquire binary image ORed w/ previous.
    ACQXOR          CON     $A3   'Acquire binary image XORed w/ previous.
    ACQANDNOT       CON     $A5   'Acquire binary image ANDed w/ NOT prev.
    ACQORNOT        CON     $A6   'Acquire binary image ORed w/ NOT prev.
    ACQXORNOT       CON     $A7   'Acquire binary image XORed w/ NOT prev.
    
    ACQDIFF         CON     $A3   'Idiom for ACQXOR.
    ACQSAME         CON     $A7   'Idiom for ACQXORNOT.
    
      XTRIG         CON     $08   'External trigger flag, ORed to ACQ commands.
    
    CNTNEW          CON     $C8   'Count pixels/edges between new bounds.
    CNTNXT          CON     $C0   'Count pixels/edges between current bounds.
    FNDNEW          CON     $F8   'Find first pixel/edge between new bounds.
    FNDNXT          CON     $F0   'Find first pixel/edge between current bounds.
    
      'Modifiers, ORed to CNTNEW, CNTNXT, FNDNEW, and FNDNXT.
    
      NXT           CON     $00   'Continue from where last CNT or FND left off.
      BKWD          CON     $04   'Search backward.
      FWD           CON     $00   'Search forward.
      DRKPIX        CON     $00   'Target is a dark pixel.
      BRTPIX        CON     $02   'Target is a bright pixel.
      DRKEDG        CON     $03   'Target is a bright-to-dark edge.
      BRTEDG        CON     $01   'Target is a dark-to-bright edge.
    
    DUMPADR         CON     $DA   'Dump data, beginning at addr, and until reset.
    
      'Address constants for single byte arg following DUMPADR.
    
      PIXELS        CON     $00   'Beginning of binary pixel buffer (32 bytes).
      RESULTS       CON     $20   'Beginning of results buffer.
      MINPIX        CON     $20   'Value of darkest pixel (0 - 255).
      MINLOC        CON     $21   'Location of darkest pixel (0 - 127).
      MAXPIX        CON     $22   'Value of brightest pixel (0 - 255).
      MAXLOC        CON     $23   'Location of brightest pixel (0 - 127).
      AVGPIX        CON     $24   'Average pixel value (0 - 255).
    
    DUMPID          CON     $DD   'Dump the firmware ID (returns 3 bytes).
    
    DUMPFLAGS       CON     $DF   'Dump error flags (returns 1 byte).
    
      'Bit positions in returned byte.
    
      BADCMD        CON     $80   'Unrecognized command.
      CANTBUF       CON     $40   'Attempt to buffer unbufferable command.
      CMDOVF        CON     $20   'Command buffer overflow.
      DATOVF        CON     $10   'Result data buffer overflow.
    
    ' -----[ Variables ]-------------------------------------------------------
    
    flags           VAR     Byte
    busy            VAR     Bit
    
    ' -----[ Initialization ]--------------------------------------------------
    
    PAUSE 10                      'Wait for AVR to finish reset.
    
    ' -----[ Program Code ]----------------------------------------------------
    
    EXPTIME        CON       60
    i              VAR       Byte
    j              VAR       Byte
    char           VAR       Byte(16)
    
    DO
      OWOUT owio, 1, [SETEXP, EXPTIME, ACQGRAY]
      GOSUB Ready
      FOR i = 0 TO 7
        OWIN owio, 8, [STR char\16]
        FOR j = 0 TO 15
          PUT i << 4 + j, char(j)
        NEXT
      NEXT
      FOR i = 0 TO 127
        GET i, char
        IF (i = 127) THEN
          DEBUG DEC char(15), 13, 13
        ELSE
          DEBUG DEC char, ","
        ENDIF
      NEXT
    LOOP
    END
    
    ' -----[ Subroutines ]-----------------------------------------------------
    
    ' -----[ Ready ]-----------------------------------------------------------
    ' Wait for the driver to become not busy.
    
    Ready:
      DO
        OWIN owio, 4, [busy]     'Read busy bit.
      LOOP WHILE busy            'Keep checking until it goes low.
      RETURN
    
    ' -----[ GetError ]--------------------------------------------------------
    ' Read the error flags from the driver.
    
    GetError:
      OWOUT owio, 0, [DUMPFLAGS]   'Read the error flags.
      OWIN owio, 0, [flags]
      IF (flags = $FF) THEN        'If $FF, driver is waiting for a reset.
        OWOUT owio, 1, [DUMPFLAGS] 'So reset and try again.
        OWIN owio, 0, [flags]
      ENDIF
      RETURN
    
    I would encourage you to use this template when writing code for the TSL1401-DB. It makes it much more readable and provides the necessary delay at the beginning for the AVR to come out of reset. Also, when you post code, please enclose it in [noparse]
    ...
    
    [/noparse] tags. Finally, yes, there's a disconnect between the doc and the download files regarding the name of the .hex file. You used the right one. :)

    -Phil
  • mclparkermclparker Posts: 15
    edited 2010-12-31 10:37
    Hi Phil,

    My sincere thanks for your time and effort, and the code you handed me. I would like to give something back to the group, so when I have finished my spectroscopy system, I intend to post the results [and the code if I can figure out what "enclose it in [code]...[/code] tags" means] here.

    I read in one of your past posts somewhere a genuine desire to reach out to non-programmers thereby making your work more widely accessible. My business is physics. I am not a programmer by any legitimate measure.

    So, in the genuine spirit of being helpful to you, I offer a non-programmers perspective:

    1. Try to understand the skills and applications of your intended audience. I know this is daunting and it is much easier said than done. When I want to communicate my work broadly, I give it to a non-physicist to critique. It works.

    I fully realize that your 1401DB and command sets are intended for machine vision applications, and for machine vision audiences I am confident your work is superior. I also realize that my intended application is not what the 1401db was designed for. However, the 1401db is an elegant solution for my application.

    2. My application was mundane by comparison but nonetheless one for which I think there is an important [and profitable] role. Here are some example applications:
    a. Spectrometers for astronomers
    b. Spectrometers for medical applications [bio-molecule identification, dyslexia and other light-based environmental impact vision studies]
    c. Spectrometers for field environmental sampling
    d. Simple and inexpensive process sensor [temp, pressure, flow, volts, current, etc] monitoring
    e. Simple and inexpensive thermal monitoring
    f. etc

    3. Above I mentioned spectrometers several times. You may not realize this, but the mechanical aspects of spectrometers are relatively simple, the difficult part, and one for which the spectrometer industry keeps close to their breasts, is processing collimated light. It is here that you and Parallax shine. For spectrometers, the important parameters are:
    a. Pixel number [spectrometers aim [or try to aim] specific wavelengths at specific pixel groups.
    b. Voltage [preferably] or some other voltage related parameter specific to each pixel. Specific wavelengths transfer specific energies for which algorithms can "reasonably" relate voltage to wavelength energy.


    4. Here are some examples of where I had [and still have to some extent] trouble [you may laugh at will]:

    a. The syntax for certain key commands uses the word "PIN". To me, PIN refers to the physical chip pin number - not its "pin name".
    b. I had trouble sorting out which chip pin name was initiating the command, which pin name were receiving the command, and what the chip was doing with the command, e.g., commands issued by the stamp, commands issued by the attiny, commands received by the photodiode array. I partially solved this by creating a new schematic that overlaid the 1401db schematic on the bs2pe mobo schematic and ignoring the literal meaning of the word "PIN".
    c. I had trouble sorting out which documentation to go to get answers...the 1401db document, the AVR document, the pbasic code documents, etc.
    d. I had [and still have] trouble penetrating the details of what certain specialized commands do. For instance, the AVR ACQGRAY command.

    The code you so generously wrote for me [using ACQGRAY] provides 128 distinct numbers, but I can't relate those numbers to a physical quantity, e.g., volts. I expected numbers ranging in value according to the photodiode array ADC volt output ranges, but this is not the case. As a result, I do not have absolute confidence that I understand the numbers.

    As a prudent measure [I would have done this anyway], I will put a data capturing oscope on terminal AO of the photodiode array and try to develop correlations with the ACQGRAY code outputs that way.


    Finally, I still don't understand why the code in my last post does not work.

    Thank you Phil for all your work.

    Mike
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-12-31 19:59
    Mike,

    The numbers that my program outputs range from 0 to 255. That corresponds to a voltage range that goes from 0 to Vdd (either 3.3V or 5.0V). So, if Vdd = 3.3V (recommended for USB-powered MoBos), then a reading of 255 would be 3.3V, and 128 would be roughly half that (128 / 255 * 3.3V = 1.656V). To relate that to luminance, you can refer to the TSL1401R datasheet.

    In the latest program you posted, you are attempting to use the GPIO3 firmware to read pixel values, which requires that GPIO3.hex be loaded into the AVR, not TSL1401.hex. However, your PIN designators have to refer to BASIC Stamp pins, not AVR pins. So, in socket "B", CLK would be "PIN 7". However, SI is not connected to the Stamp, so it must be toggled via commands to the AVR. But even then, you would not be able to read all the data from one scan fast enough to avoid "pixel droop." Nonetheless, since your "image" is likely to be static, you could read out the data in several scans, using successively longer strings of pulses (via SHIFTOUT) on CLK to get past the data you've already looked at.

    My recommendation, if 8-bit ADC resolution is good enough, is to stick with the TSL1401 firmware and use ACQGRAY to retrieve the pixel values. However, for spectroscopy, your biggest challenge may be one of sensitivity. In my experience, spectra are rather faint, compared to a focused image. Linear array sensors designed for spectroscopy (e.g. see Hamamatsu's offerings) have very tall pixels in order to capture as much light from each spectral line as possible. The pixels in the TSL1401R, by contrast, are square and designed more for image sensing with either a focusing lens or a bright, unfocused source. Nonetheless, you may still find the TSL1401 to be suitable for your app if your specral lines are bright enough. For analytical work, you will also have to divide the result for each pixel by the TSL1401's response at the corresponding wavelength (obtainable from the TSL1401R datasheet), in order to normalize your spectrum.

    Good luck!

    -Phil
  • mclparkermclparker Posts: 15
    edited 2011-01-19 09:19
    Thank you Phil,

    You are a genius and a good person.
  • edited 2015-02-03 10:52
    Hello,

    Thank you for posting this on a forum, it is awesome to find this 4 years later and be able to use it. I have been able to get your (Phil) code to work, however I am having trouble understanding what exactly is happening. My main issue revolves around this bit:

    FOR j = 0 TO 15
    PUT i << 4 + j, char(j)
    NEXT

    I realize that this is counting from 0 to 127 and storing the value in a byte of RAM, however I guess I dont really understand why you need to do this. Here is the code that I have used to do the same thing:

    EXPTIME CON 60
    i VAR BYTE
    j VAR BYTE
    char VAR BYTE(16)

    DO
    OWOUT owio, 1, [SETEXP, EXPTIME, ACQGRAY]
    GOSUB Ready
    FOR i = 0 TO 7
    OWIN owio, 8, [STR char\16]
    FOR j = 0 TO 15
    DEBUG DEC char(j), CR
    NEXT
    NEXT
    DEBUG CR, CR
    LOOP
    END

    I am able to get the same results I believe but I am just reading out the values as they come. My confusion I think stems from the fact that you are in a loop with regards to 'i' but there is no 'i' called anywhere. Does this just mean that it is reading out 16 values eight times with the 'OWIN' command? If that is the case then I guess it makes sense that the values of the entire 8x16 char array isn't stored, but a 1x16 that needs to be stored somewhere else (or read out). I apologize for any ignorance but I haven't really ever coded anything that controls something, mostly just manipulation of data.

    Thanks for your help.

    Cheers,
    Oliver
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-02-03 11:17
    Oliver,

    The reason for storing the byte data from the camera in aux RAM first is to be able to get it out of the coprocessor as quickly as possible. The TSL1401 sensor is being read as the data are being sent from the AVR, and you do not want to slow this process down by doing intervening serial I/O from the Stamp. The entire nested loop, including an outer loop around the one you cited is:
      FOR i = 0 TO 7
        OWIN owio, 8, [STR char\16]
        FOR j = 0 TO 15
          PUT i << 4 + j, char(j)
        NEXT
      NEXT
    

    It reads eight groups of 16 bytes, each group into the char array, then stores that array, one byte at a time, into aux RAM. From aux RAM the data are available to be analyzed or sent via serial I/O at the program's leisure.

    -Phil
Sign In or Register to comment.