Close

ATmega1284P/Schematic Design For The TCD1304 CCD chip

A project log for DAV5 V3.01 Raman Spectrometer

The only thing worth doing, is the thing worth doing right!

david-h-haffner-srDavid H Haffner Sr 02/20/2017 at 14:514 Comments

*UPDATE: Go to the bottom of this page for code update*

This is the new re-worked design for the TCD1304 CCD driver circuit, I am utilizing a development board designed by MCDude over @Tindie http://www.tindie.com/products/MCUdude/dip-40-arduino-compatible-development-board/

This board will utilize the ATmega1284P (40pin) microcontroller, using an AD7667 as my ADC and a MAX232 and AD8021 driving the TCD1304, this will be a superior low noise and high efficiency circuit for the DAV5 V3 Raman spectrometer.

I am also in a somewhat collaborative effort with Dave Allmon since we are both using the same microcontroller (1284P,) just some tweaking in the code and this should be ready for testing in a couple of weeks.

Here is the development board;

I'll also be using the FTDI FT232RL USB to serial IC from SparkFun;

I removed the cleanline() part of the code, it was mean't to clean up any shot noise from the CCD, but it will also cause a blip to appear on your plot, so I took it out. Let your external processing software take care of that part. (this is in reference to my last log before this one where the "voodoo" line was included, Dave Allmon suggested to remove it, in cases where you are doing serious science, so I did.

Here is the new code;

#include <util/delay_basic.h>

#define RD (1<<0)

#define CS (1<<1)

#define CNVST (1<<2)

#define BYTESWAP (1<<3)

#define ICG (1<<4)

#define SH (1<<5)

#define MCLK (1<<6)

// Full frame, including dark pixels

// and dead pixels.

#define PIXEL_COUNT 3800

#define CLOCKS PORTF

#define CLOCKS_DDR DDRF

#define DATA_PINS PINK

#define DATA_PORT PORTK

#define DATA_DDR DDRK

// 10mS exposure time.

#define EXPOSURE_TIME 1

// Initial clock state.

uint8_t clocks0 = (RD + CS + CNVST + ICG);

// 16-bit pixel buffer

uint16_t pixBuf[PIXEL_COUNT];

/*

readLine() Reads all pixels into a buffer.

*/

void readLine()

{

// Get an 8-bit pointer to the 16-bit buffer.

uint8_t * buf = (uint8_t *)pixBuf;

int x;

cli();

CLOCKS |= (RD + CS + CNVST + ICG + BYTESWAP + SH);

OCR2A = 5;

TCNT2 = 0;

PORTB &= ~0x02;

for (x = 0; x < PIXEL_COUNT; ++x)

{

CLOCKS ^= SH;

CLOCKS &= ~CNVST;

CLOCKS |= CNVST;

_delay_loop_1(4);

__asm__("nop\n\t");

__asm__("nop\n\t");

__asm__("nop\n\t");

CLOCKS ^= SH;

CLOCKS &= ~(CS + RD);

*buf++ = DATA_PINS;

CLOCKS &= ~(BYTESWAP);

*buf++ = DATA_PINS;

CLOCKS |= (RD + CS + BYTESWAP);

}

sei();

}

/*

startLine() Toggles the clocks to shift the line

into the CCD shift register.

*/

void startLine()

{

// Set ICG low.

CLOCKS &= ~ICG;

_delay_loop_1(5);

// Set SH high.

CLOCKS |= SH;

_delay_loop_1(5); // 10uS.

// Set SH low.

CLOCKS &= ~SH;

_delay_loop_1(10);

// Set ICG high.

CLOCKS |= ICG;

}

/*

sendLine() Send the line of pixels to the user.

*/

void sendLine()

{

int x;

for (x = 0; x < PIXEL_COUNT; ++x)

{

Serial.println(pixBuf[x]);

}

}

/*

setup()

Set the data port to input.

Set the clock port to output.

Start timer2 generating the Mclk signal

Set the pullup on pin 2 for the start switch.

*/

void setup() {

CLOCKS_DDR = 0xff;

CLOCKS = clocks0;

DATA_DDR = 0x0;

Serial.begin(115200);

// Setup timer2 to generate a 1.333MHz frequency on D10

TCCR2A = (0 << COM2A1) | (1 << COM2A0) | (1 << WGM21) | (0 << WGM20);

TCCR2B = (0 << WGM22) | (1 << CS20);

// "5" causes 6 intervals - 0 through 5

OCR2A = 5;

TCNT2 = 0;

// Output Mclk on D2

DDRB |= 0x10;

// For the trigger switch.

pinMode(2, INPUT_PULLUP);

}

/*

loop()

Read the CCD continuously.

Upload to user on switch press.

*/

void loop() {

startLine();

readLine();

delay(EXPOSURE_TIME);

if (!digitalRead(2))

{

sendLine();

}

}


Discussions

Gintaras Valatka wrote 02/24/2017 at 22:53 point

Hey David, my thoughts are that If one was to increase the projection size and also rotate the mirror, one should be able to attain even higher resolutions? any thoughts? https://hackaday.io/project/19913-spectro-scopy-metry-graphi-cally-ginscope

  Are you sure? yes | no

David H Haffner Sr wrote 02/25/2017 at 10:33 point

Hey Neris.io, in spectroscopy, resolution is a product of the ratio of lines per mm on the diffraction grating X wavelength. The mirror is only point of focus and direction, wavelength dispersion is done at the diffraction grating, in Raman spectroscopy the diffraction grating can be rotated in a way so different wavelengths can be dispersed and collected at the CCD. Spectral bandwidth is the wavelength interval in which a radiated spectral quantity is not less than half its maximum value. It is a measure of the extent of the spectrum for a Light source.

Here is an example of spectral resolution using a laser line as our example; a green laser has a wavelength of 532nm, we have a spectrometer set up with a slit width of 0.1mm and a diffraction grating with 1800 ln/mm. My data plot shows a FWHM of 0.89 for my laser line, so my formula to figure out my spectrometers spectral bandwidth would be; 1 X 0.89 X 1800 = 1602
532nm/1602 = 0.33

R = 0.33

So we have a spectral resolution of 0.33

So, spectral resolution is proportional to slit width and the number of lines per mm of the diffraction grating. Optical resolution is a separate factor that I have an explanation of on my details page for my Raman spectrometer project, because that has to do with focal length of the mirror, lens and pixel horizontal and vertical height of the detector.

Whew...I hope this helped :)



   

  Are you sure? yes | no

Ted Yapo wrote 02/22/2017 at 03:20 point

I like this design better than the 10-bit one with the transistor in the signal path!

I don't have a ton of experience with high-precision ADCs, but I know this much: hic sunt dracones.  If you are doing the board design, seek wise counsel about ground planes and analog vs digital grounds and keeping digital return currents out of agnd, and probably a ton of stuff I've never thought about.

Maybe somebody on here can recommend a good reference or supply better pointers.  I know my first attempt at a 22-bit ADC ended up with about 18 usable :-)

  Are you sure? yes | no

David H Haffner Sr wrote 02/22/2017 at 09:43 point

Hey Ted, thanks for your reply, I'm working with Dave Allmon on this one because I have modified his design to fit my project. I also had to learn c/c++, it took me a couple of days but I got the main gist of it and I modified some of his code, because I just need the raw signal without any cleanline voodoo!

Thankfully I knew assembly, which helped with C programming, I have been taking this whole month to refresh myself with all this tech, when I worked for KC Automation, it was 10 years ago, so there was some catching up to do :)

2 very smart placements of a 10 uf cap and NO ground loops should eliminate even further any possible ringing. I'm using CircuitMaker as my platform, as it provides me a vast array of components online to use. 



  Are you sure? yes | no