linear CCD TCD1201d readout and timing issue

I can't any reason why a flip flop would perform better than direct port access on the Arduino.

Salut,

looks like there is no way to read this CCD with an arduino. I have tried all permutations including a flip-flop and a comparator for the signal. I played with all timing and had the same timing on the logic analyzer as it is in the data sheet. Interesting fact is that the DOS signal varies as well with the light intensity.
However, when searching the web I find that all successful linear CCD readouts use CCDs that have the phase1/phase2 signal generation inside the chip (i.e. ILX551 or TCD1304).
So I will give up the attempt to use the TCD1201 (too bad for the four chips I have) and trash them in favor of the Sony ILX511.

I´ll keep you updated once the chips have arrived.
Ciao, Mathias

I'm sure it's possible to read fro that chip using an Arduino. However, unless you have an oscilloscope, you won't know whether you have the signal timings right.

Hi guys. I've been searching for the answer to this problem for months now. I have 3 TCD1201d chips that I need working. I am curious if there is any progress on this topic? If the Arduino doesn't work what will? A comment earlier says that it won't be able to be fixed without a oscilloscope. If I have a oscilloscope, what would I have to do to fix it?

I apologize if my questions seem dumb. I've never had to drive a sensor like this before. The code is a tad bit over my head. Any help would be awesome. Thanks!

Here are my suggestions:

  1. Keep the ground and clock wires between the Arduino and the CCD as short as possible. Run these 3 wires right next to each other to minimise the inductance. Even a small amount of inductance will cause ringing, because of the high capacitance of the CCD clock inputs. If you can't keep the length of the wires to a few cm, then use a 74HC04 chip to buffer the signals, as shown on the datasheet (and keep the wiring between the 74HC04 and the CCD as short as possible).

  2. Make sure you have a 0.1uF decoupling capacitor connected across the CCD power and ground pins, as close to the CCD as possible.

  3. Switch the clock lines simultaneously using direct port access. To help make sure that they cross above 2.5V, try either:

(a) a 150 ohm pullup resistor on each clock line, connected as close to the CCD as possible; or

(b) the Schottky diode/parallel resistor arrangement I suggested earlier.

  1. Double check that you are sequencing all the CCD inputs correctly.

What do you have the output of the CCD connected to?

I'm using a Due to create the signals for a UPD3799CY (5300 pixels/line)
it can create two phase clocks and syncronous RB signals using 2 channels of the PWM,
which can also trigger the ADC
AND also use PDC to fill the buffer(s) ...

downside is the need for level converters of the Due output (clocks,RB & TG1-3 )
& voltage followers on the Due input (ADC) to adjust the level and of course the 12 vdc for the sensor ...

NOTE: this is not 100% tested / waiting for the scope to be delivered before doing the final hookup
BUT raw tests look like i can get 37 lines a sec (4096 pixel lines) and near 88 lines (2048 pixels)

the reason i chose the UPD3799CY is that is ripped out of desktop scanner & came with its own circuit board / decoupling , input & output buffers . ..

Salut ralphnev,

it would be nice to have a view of the code you are using.
I am awaiting the hardware to follow the suggestions dc42 has made to narrow down the issues. I also have to get an oscilloscope with sufficient bandwidth (might even use it as a reason to buy one).
I hope to have all in place starting February 2nd

Ciao, Mathias

Yo Mathias;
code is highly messy , filled full of testing :wink: & very uncommented ...
but PM me your email .. & i'll fwd it ..

Salut,

I have spent all weekend on reading the lCCD without success. I finally decided to order a oscilloscope as I wanted to buy one anyhow and I use this as excuse to finally get one. I need to see the signals and their timing as well as the real output of the CCD ...
It will take 2-3 weeks until I receive it, so there will be no news until then

Ciao, Mathias

Hi Matthias,

you'll need that scope. The problem with these devices is that they're insanely sensitive. If you use them in normal light (in front of a monitor, near lights on the ceiling, ...) they'll go into saturation.

Use your existing software and cover the setup with a box with a narrow rectangular slit on the top (1/4 by 4 inch). Measure on the output pin with the scope so you get a view of an entire cycle (trigger with SH on a second channel). You can use a piece of paper to cover the slit and get an idea of what the useful light level is. Spoiler: not much.

I'll attach some pics of the scope later this evening if I have time.

FYI: I programmed my TCD1201D in C with avrstudio and get around 350 full CCD measurements per second with naive programming. With some tuning this can be increased to 500. Fully optimised I believe 1000/s is possible on an ATMega by positioning the ADC capture and hold (after 1.5 ADC clock) correctly. In my setup I only need 2 or 3 bits from the ADC, so I have the freedom to scale the ADC clock up.

regards,
Fred

Salut Fred,
the scope is ordered but due to the Chinese New Year, the shipping is delayed and I expect to have it early March.
I will tackle the issue exactly as you wrote: first I will generate a symmetric clock pulse and check with the scope that the output is as expected. I found in the meantime quite a lot of documentation on these linear CCD and will first try to reproduce the measurements I found there. I then will add the adc readout and change the timing to make sure, the duty cycle of 50% on the clock pulse is still valid. I found code segments that can speed up the adc readout by almost a factor of 10.
In addition, I have a chipkit max32 as well as an arduino due, both running at 80(84) MHz, which may give better results.

As soon as the scope arrives, I'll post an update

Ciao, Mathias

Bonsoir Mathias,

Attached some pics that should get you going before it arrives. Had to use the phone because someone borrowed my serial interface for the scope.

The first one shows the setup: no pull-ups and long wires. Notice that I connect DOS to the Aref of the arduino.

The second one is some data. It's 4 pics combined because I'm only allowed to upload 4 attachments here.

  1. When the sensor is fully exposed to light the levels are not equal, they're one of 2 values. The odd ones are always the same, the even ones are always the same. This is because the chip uses 2 shift registers to push analog data out, these 2 registers are connected to odd or even CCD elements and they're not 100% identical. The minimum voltage is ~1.5V DC, when the sensor is saturated with light
  2. This is with the sensor completely covered with a box, minimum light. Max voltage ~3.0V
  3. I placed 2 cut pieces of ribbon cable on the sensor. The first one overlaps with S1, the second one is somewhere at 2/3
  4. Long exposure over t, I marked the location of S1 (yellow arrow) to show the start. The blue circles show shadow cast by the 3 wires that hang over the sensor. This is with a box with a slit over the setup.

Hope this helps,
Fred

Bonsoir Fred,

merci pour les images!

can you post/send the code and the wiring (well I can guess it either from the code or from the pictures)?

merci d'avance
Ciao, Mathias
PS: My knowledge in writing French is limited :wink:

Currently walking home from work and forgot my usb stick. I'll post the code tomorrow morning.

I modified the code somewhat to check for a level at 2.1V (with DOS at ARef). It stores a bit for each pixel in a 256 byte buffer. That buffer is sent to serial (115200bps, 8N1, no handshake) once every second. 0 = dark, 1 = light 1 = dark, 0 = light

There's loop unfolding to avoid a 16-bit variable in the main loop. Everything compiles to 1230 bytes.

Compile in AVRStudio with compiler optimisation -O1. If you compile with -O0 you'll get wider timings but a chunk of code of ~4Kb.

Enjoy,
Fred

SerialCCD.rar (25.2 KB)

Salut Fred,

thanks for the code. I have installed AVRStudio but not used it yet. I am using the arduino IDE to compile. So I will first try to identify the difference between your code and my approach (as I want to learn and understand)

I'll keep you posted on the progress
Ciao, Mathias

Let me know if you encounter problems. I'll be updating on a different website next week with optimized code, I posted here because there's too little info on these sensors for hobbyists and they're really great devices. And you were so close :wink:

Salut Fred,
I have not yet spotted the difference between your timing and mine ... However, I must admit, that I do not understand how you read the value that is stored in the data array. It looks to me like you are only storing a on/off infomation bit per pixel ... (please excuse my poor C skills but I reactivated my knowledge only a year ago and learned C in 1987)

Can you show the link to the other forum you mentioned? Would be interesting to see more info on these devices

Ciao, Mathias

I read the adc value (redefined as OS at the top of the file) and check the level. I deduce 1 bit per pixel from this (above or below a given threshold) and store that in a 2048 bit array.

What you do with the individual values is up to you, in my case I just need light/dark info with respect to a level - my implementation only needs one bit per pixel.

I haven't looked at your code, sorry I don't know how you process the data.

I haven't yet finished my code, I'll only upload it once it's up to my standards. Tomorrow I have the hole day to work on it so fingers crossed :slight_smile:

BTW, I don't mean to lure you away from the arduino IDE but for timing-critical implementations it's good to have an IDE where you're in full control.

Salut Fred,
due to the Chinese New Year, the delivery of the scope takes a bit longer. So I gave Atmel Studio a try, installed it and loaded your code.
I can see why you prefer the Atmel Studio, as it provides the experienced programmer with more flexibility, but is sometimes quite cumbersome: i.e. I have to declare a external command for each port I have an arduino connected. I will continue to use both where the advantages of one come handy.
I loaded a demo code and it worked fine (there is a wonderful tutorial at http://www.jayconsystems.com/tutorial/atmerpt1/).
Then I loaded the SerialCCD code you provided but the output is nothing but F´s - all pixel seem to be set. I then looked at the code where you read the ADC and I do not understand the while condition. I would have expected to see a

while (ADCSRA & (1<<ADSC));

instead of the while(!(ADCSRA & (1 << ADIF))); ADCSRA |= (1 << ADIF);
If I connect the A0 input with GND, I still get all pixel reported as ones, which indicates that the ADC read is not correct.

As you have tested the code, I am now completely puzzled ...
I attached the wiring

Ciao, Mathias