TLS 1401 CCS linear image sensor

edmunds

Senior Member
SOLVED. TLS 1401 CCS linear image sensor

Dear all,

Here is my current code and a problem I have spent a few hours now on locating and figuring out the cause for, which has not worked :). In the procedure below, called cal_exposure, I'm doing an ADC scan of the output of the sensor. This works as expected. However, the consequent scan of real data in procedure read_data works well as long as I do not do the ADC scan. I.e. if I comment out the line with ADC, I get expected results from the sensor zeroes and ones depending on how much light falls on the sensor and what it 'sees'. However it is missing the auto-calibration to light conditions. If I add the line back in, I only read zeroes from the sensor no matter what the light.

I'm guessing there is a timing problem, but then again it is difficult to imagine as I'm doing a dummy_cycle both, before calibration read and the data read and in both cases separately it works as expected.

Code:
#rem
2016-12-01
Test code to run TSL 1401 CCS sensor in 'single shot mode' with picaxe40x2.
3.30V power supply, all pins connected strictly according to data sheet reference diagram.
Single external component related to sensor - 0.1uF cap over supply pins.
#endrem

#picaxe40x2                            'Code for picaxe40x2
#no_data                                  'EEPROM not in use
#no_table                                 'Table not in use

setfreq em64                           '8 or 16MHz is too slow, 32 might work, but need to be tested

'Outputs
Symbol CLK = C.1                    'Clock - 5kHz ... 8 MHz
Symbol SI = B.2                        'Signal In pin of the sensor
Symbol HOLD = B.3                  'Hold pin of the sensor, tied to SI

'Inputs
Symbol AO = B.1                      'Analog out of the sensor
Symbol pinAO = pinB.1            'Analog out of the sensor

'Byte variables
Symbol dat0 = b4                    'Data byte 0
Symbol dat1 = b5                    'Data byte 1

Symbol counter = b20             'Just a counter

Symbol exp = w27                  'Exposure time

init:
  low SI                                     'Initialize SI pin low

main:
  gosub cal_exposure                'Try to adjust exposure to the lighting conditions
  gosub read_data                     'Read 128 data bits - 1 for white and 0 for dark
  gosub show_data                    'Show the string of ones and zeroes in the terminal
goto main

cal_exposure:
  exp = 80                                 'Set exposure to minimum value that works
  gosub dummy_cycle               'Run dummy cycle to clock out the remainder of the previous scan
  exp = 32640                           'Set exposure to half fully saturated value (128x255)
  for counter = 0 to 127            'Read 128 pixels ...
  	readadc 10, dat1                   '... with 8 bit ADC ...
  	pulsout CLK, 10                    '... pulse the clock as fast as possible to read the next pixel ...
  	exp = exp - dat1                   '...subtract to get longer exposure with lower number (darker) ...
  next counter                            '... continue until done with all pixels
  exp = exp / 100                      '... some equation to get the nexessary exposure to set high/low treshold in the right place
return

read_data:
  gosub dummy_cycle               'Run dummy cycle to clock out the remainder of the previous scan
  for counter = 0 to 127            'Read 128 pixels ...
    if pinAO = 1 then                  '... in case pin high (voltage over ~2.10V) ...
  	  dat0 = 1                              '... set dat0 to 1 ...
  	elseif pinAO = 0 then           '... in case pin low (voltage below ~2.00 V) ...
  	  dat0 = 0                              '... set dat0 to 0
  	endif
  	pulsout CLK, 10                    'Pulse the clock to go to next pixel
    put counter, dat0                  'Store the value in scratch pad as one byte per pixel (to be changed to bits later)
  next counter                           '... continue until done with all pixels
return

show_data:
  setfreq m8                                       'Go down to 8MHz to work around MacAXEPad terminal problem
  sertxd ("EXP= ",#exp,";", LF, CR)       'Display what the calculated exposure is
  for counter = 0 to 127                      'For every pixel value stored in scratchpad ...
  	get counter, dat0                            '... get 0 or 1 ...
  	sertxd (#dat0,";")                            '... display in teminal window ...
  next counter                                     '... continue until done with all pixels
  setfreq em64                                   '... go back to 64MHz as 8MHz is two slow for the sensor
return

dummy_cycle:
  gosub SI_pulse                                  'Pulse SI to start the scan
  pwmout CLK, 15, 32                          'Clock out some fast pulses
'  pauseus exp                                      'Allow for sufficient integration time
  pauseus 300                                      'A constant to check the problem is not the exp value
  pwmout CLK, OFF                              'Stop the clock
  gosub SI_pulse                                   'Pulse SI to end the scan/start the next scan
return

SI_pulse:                                              'Have to use this as could not get a positive pulse from pulsout, should be investigated further
  high SI
  pulsout CLK, 10
  low SI
return
All and any help appreciated. Thank you,

Edmunds
 
Last edited:

edmunds

Senior Member
It turns out the pin needs to be set back to digital, once it has been used as analog :). Adding the line below in procedure read_data fixed the problem. If anyone can give further details on why this is, if it is always like this and other guidance - I would be most interested.

Code:
  adcsetup = %0000000000000000

Thank you for your time,

Edmunds
 

hippy

Technical Support
Staff member
It turns out the pin needs to be set back to digital, once it has been used as analog ... If anyone can give further details on why this is, if it is always like this and other guidance - I would be most interested.
On more recent PICmicro parts, when an input is configured as analogue the digital part is disconnected from the pin and always digitally reads as zero until it is no longer configured for analogue.

READADC on an M2 will automatically configure the pin for analogue so needs reverting back to read as digital, but I understood that for the X2's this was not the case.

In your 'read_data' routine you could change all those IF-ELSEIF to ... "dat0=pinA0". And perhaps that may be part of the problem; the first read of pinA0 not being the same for the second ?

I'm not sure without more analysis. You could perhaps PEEKSFR the analogue enable bits after the READADC to see if they are set and whether adcsetup=0 is resolving that or whether that just happens to make things work even though it's not having the affect it looks like it is having.
 

edmunds

Senior Member
In your 'read_data' routine you could change all those IF-ELSEIF to ... "dat0=pinA0". And perhaps that may be part of the problem; the first read of pinA0 not being the same for the second ?
Well spotted, thanks. I don't know what I was thinking. However, this did not change anything in the analog/digital part. I will toy with peeksfr some time later.

Edmunds
 

edmunds

Senior Member
While this is still very crude and there is a lot more work, but this is a valid linear camera line follower after all!

The video shows me moving the sample dark surface with 2mm white line a few mm to the right or left. While this particular camera is not a "hobby friendly" package like DIP, it is perfectly solderable with 0.2mm wires for one-off or prototype project. Also, the width of the sensor is only 9mm, but sensors allow for cascading, so you can add multiple sensors in line, connect them with SO-SI pins and have them read as much width as you like with the same number of picaxe pins. Processing the data will become a challenge at some point, but it all depends on what compromises you are ready to make.

[video]https://youtu.be/UkQsV2txGWA[/video]


Have a cool weekend,

Edmunds
 
Last edited:

AllyCat

Senior Member
Hi,

As I understand it, it is the PICaxe interpreter READADC firmware which disables the digital input, it is not inherent in the opeation of the PIC silicon (hardware). So it is possible to read the ADC value using SFR commands without disabling the digital input However, apparently this is not recommended by Microchip and the SFR commands are probably slower and use more codespace than simply reconnecting the digital input with ADCSETUP = OFF.

But if you want to try it, there's a little more detail in this thread, including sample SFR code to read the ADC, but for M2 not X2 SFR register addresses.

Cheers, Alan.
 
Top