CCD Transmission Spectrograph


This unit captures 800 or so pixels from the TCD1304's 3648 pixels. Peer pressure being what it is, I've updated the project to use a fast 8-bit external ADC. Now it captures all 3648 pixels in 8-bit resolution. There is a fast 8-bit spectrograph project. There is a fast 16-bit spectrograph in the works.


A transmission spectrograph is a device which records the spectra of light passing through a subject. In this case, the subject is a photographic or color separation filter, specifically a dichroic filter - red, green, blue, cyan, magenta, yellow, Ha, O-III, and so on.


An ATmega328 in the form of an Arduino Uno R3 acts as the controller for the spectrograph. The sensor is a Toshiba TCD1304AP, a 3648 pixel linear CCD sensor which operates on a single voltage (3.0V to 5.5V). The sensor is driven directly by the microcontroller, and the analog output is buffered by a transistor and an op-amp. The signal is digitized by an analog pin on the Arduino Uno, as a series of 800 10-bit readings.

Microcontroller Software

The Arduino spectrograph software is written in C in the Arduino IDE. Line readout consists of driving the clocks and reading the output with the ADC. The data is read in as fast as the Arduino can go, with the ADC clock sped up a little bit. The Mclk on the CCD is adjusted such that the 3648 pixels are output during the time it takes to digitize 800 readings with the ADC It doesn't matter that the two don't match up - the CCD output is continuous, so there are no aliasing problems.


  • r - Readout
  • L - Lamp on
  • l - Lamp off
  • E - ++Exposure time
  • e - --Exposure time
  • c - Centroid the data

Host Software

Amplitude Calibration

Standard darks and flats are used to calibrate the amplitude readings. What this basically means is that you take one line with the lamp off and call it a dark. Take another with the lamp on and call it a flat. Subtract the dark from the flat. The new flat has no dark signal in it - it is only the signal from the light. The pixels in the flat are each divided by the highest pixel reading in the flat. That gives pixel values that range from zero to one.

When you read the real line, you subtract the pixels in the dark line from the pixels in the real line to remove the background signal. Then you divide each pixel in the resulting real line by the adjusted flat values. That will adjust for gain irregularities in the CCD. You're done.

Wavelength Calibration

This is more tricky. The angle of incidence of light hitting a prism, the distance from the prism to the sensor, and the angle of incidence of the light hitting the sensor all conspire to make this difficult. I didn't want to make it a mathematical issue, so I cheated. I measured the spectra of a sodium vapor light, and calibrated to the lines. I've since tried LEDs and like their ease of use more. The problem is getting LEDs with spec sheets, which I accidentally did.

TCD1304AP conditioned signal


The scope trace shows the output of the TCD1304 after it has been processed by our buffer circuit. Higher is brighter. Maximum signal to the ADC is 2.5V at saturation. The minimum is about 0.8V. This signal is digitized by the analog to digital converter in the Arduino to a value from 0 to 1023. Less than half of the range is used, because the input signal is not 0 to 5V, but 0.8V to 2.5V.

The pattern is made by light shining through a row of holes in a mask, and is only to demonstrate the fact that the CCD shows the amount of light hitting any given part of it.

Assembled board

The parts all fit on an Arduino prototype board with room to spare. I used an IRF540 to control the lamp because I had one. The Arduino has LEDs that need to be blacked out or removed or they will affect the readings. Electrical tape works well. The pins seen on the left are programming pins, needed because I don't use the bootloader. The pins on the right are for the lamp that supplies the light to be measured. An ordinary incandescent lamp must be used to provide a more-or-less uniform spectrum. It needs to burn hot in order to put out some blue light.

Spectrograph layout (prism)
Spectrograph layout (DVD)


So far we've only done the electronics. There are some mechanical/optical tasks to do as well. A spectrograph has to break the light into it's constituent colors in order to measure them. There are three ways to do that, and I tried two of them. A prism and a broken DVD. Both worked. I did not try a transmission diffraction grating. I don't have one to try, and they cost too much for this project. No matter which type you use, you must use a slit. I used two utility knife replacement blades (Home Depot) edge to edge, with a piece of paper between to space them. Screwing them down over a drilled hole, then removing the paper, leaves a tiny little slit that is just what is needed.

To use a prism, the angles of the light entering, the prism angle, and the distance to the CCD must be figured out. It is possible, but insane, to calculate these angles. It is best to set it all up on the kitchen table with the lights out and just measure the result.

To use a DVD or CD, you should do the same thing, but since they reflect the spectrum, you will position the CCD in a different place than when using a prism. Again, darkness is your friend.


The device needs to be calibrated so you can tell what the wavelengths you measure really are. There are several ways to do that, and the way I've settled on is to get a deep red (650nm) and a blue (470nm) LED. Arrange the CCD and prism/DVD so that the center of the spectrum hits the center of the CCD perpendicular, so the error is equally divided between the blue and red ends. Find the index of your two LEDs and set those as your reference points. Assume the spectrum is uniform. The highest error will be in the orange and blue-green areas. The error is geometric - it has to do with the angle of the rays hitting the CCD. The farther from green (the center) you get the higher the error will be, but by calibrating at blue and red, we cut the error in half-ish.

"First light" - an RGB LED

The colored line is cheesey but serves to illustrate the CCD's orientation. The reason the humps are humps instead of lines is the width of the slit and the non-colimated light beam from the LED. The SNR is pretty low because the thing is mostly cardboard and there is a little light leakage. I wound up not using the prism because the dispersion was too low for the small size of the spectragraph. It would need to be a little over two feet from the prism to the CCD to get full coverage in the visible range. With a piece of a DVD, the whole thing is no bigger than 5 x 7 inches.

Total investment in this project was less than $20, and it appears to work great. I will refine the mechanics a little to toughen it up, and provide the collimated light source. Those two things should make it perfect for measuring overlap in dichroic filters.