Go Down

Topic: linear CCD TCD1201d readout and timing issue (Read 11553 times) previous topic - next topic

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  ;) & very uncommented ...
  but PM me your email .. & i'll fwd it ..


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.


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,

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  ;)

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

Feb 14, 2013, 12:56 pm Last Edit: Feb 14, 2013, 01:30 pm by freddy_dreddy Reason: 1
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.


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  ;)

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 :)

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.

Feb 25, 2013, 07:27 pm Last Edit: Feb 26, 2013, 01:47 pm by GastonLagaffe Reason: 1
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
Code: [Select]
while (ADCSRA & (1<<ADSC));
instead of the
Code: [Select]
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

I'm currently away from my desk until tomorrow, I'll dubble-check once I get back.

Go Up