TCD1304DG driver circuit using an ATMega1284P MCU

Details TCD1304DG CCD driver…

This is the main schematic for the 16 bit CCD driver circuit:

7380001493814507988 16bit CCD ciruit schematic june8

This is a project that I have been working on for almost a year on Hackaday.com, it is the CCD detector portion of the 3D printable Raman spectrometer project of mine and I finally got someone far smarter than me to help me out on the AVR part of all this and I guess I must have impressed him by transcribing his schematics on LTspice so he allowed me to use his design (with his invaluble programming help I might add,) and so I put the board together and it should be ready for offical testing sometime next week.

I am including the firmware ( C coding) for the ATMega1284P MCU, which is part of the development board I am using from MCUdude;

ATMega1284P Dev Board

This is the CCD driver circuit board which houses the TCD1304DG chip and the ATMega1284P MCU;

Finished view;

I’m still kind of new to C programming and AVR and I have recently downloaded AtmelStudio 7.0 and I am really glad I did, so I am re-engineering the firmware to remove some “glichyness,” from the timing sequences, and this platform is perfectsmiley

Here is how my Dev board is currently set up with the ATMega1284P chip;

My entire project can be accessed at the link below

*Update* 5/5/2017

I got the idea for the heat sink for the TCD1304dg chip from @esben rossel he recently had a post where he showed how he cut a piece of aluminum block to act as a heat sink for the TCD1304 chip. That got me thinking, and so I formed my own aluminum heat sink out of aluminum industrial tape and will post the procedure also in my build files.

Also I found the perfect heat sinks for the AD7667 (ADC) chip, these little 15 x 15mm aluminum heat sinks are used in a kit for the Xbox 360, for the RAM chips inside, it cools them between 10-12 deg F. Perrrrrrfect 🙂

Here is the magic below;

Firmaware for the Atmel-1284P MCU (TCD1304DG CCD driver circuit)

#include <util/delay_basic.h>

#define RD (1<<2)
#define CNVST (1<<3)
#define BYTESWAP (1<<4)
#define ICG (1<<5)
#define SH (1<<6)
#define MCLK (1<<7)

// Full frame, including dark pixels
// and dead pixels.
#define PIXEL_COUNT 3691

// Ports and pins
#define CLOCKS PORTD
#define CLOCKP PIND
#define CLOCKS_DDR DDRD
#define DATA_PINS PINC
#define DATA_PORT PORTC
#define DATA_DDR DDRC

// 10mS exposure time.
#define EXPOSURE_TIME 10

// Initial clock state.
uint8_t clocks0 = (RD + CNVST + ICG);

// 16-bit pixel buffer
uint16_t pixBuf[PIXEL_COUNT];

char cmdBuffer[16];
int cmdIndex;
int exposureTime = EXPOSURE_TIME;
int cmdRecvd = 0;

/*
* 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 = 0;
uint8_t scratch = 0;

// Disable interrupts or the timer will get us.
cli();

// Synchronize with MCLK and
// set ICG low and SH high.
scratch = CLOCKS;
scratch &= ~ICG;
scratch |= SH;
while(!(CLOCKP & MCLK));
while((CLOCKP & MCLK));
TCNT2 = 0;
_delay_loop_1(1);
__asm__(“nop”);
__asm__(“nop”);
__asm__(“nop”);
__asm__(“nop”);
__asm__(“nop”);
CLOCKS = scratch;

// Wait the remainder of 4uS @ 20MHz.
_delay_loop_1(22);
__asm__(“nop”);
__asm__(“nop”);

// Set SH low.
CLOCKS ^= SH;

// Wait the reaminder of 4uS.
_delay_loop_1(23);

// Start the readout loop at the first pixel.
CLOCKS |= (RD + CNVST + ICG + BYTESWAP + SH);
__asm__(“nop”);

do {
// Wait a minimum of 250nS for acquisition.
_delay_loop_1(2);

// Start the conversion.
CLOCKS &= ~CNVST;
CLOCKS |= CNVST;

// Wait a minimum of 1uS for conversion.
_delay_loop_1(4);

// Read the low byte of the result.
CLOCKS &= ~RD;
_delay_loop_1(4);

*buf++ = DATA_PINS;

// Setup and read the high byte.
CLOCKS &= ~(BYTESWAP);
_delay_loop_1(4);

*buf++ = DATA_PINS;

// Set the clocks back to idle state
CLOCKS |= (RD + BYTESWAP);

// Toggle SH for the next pixel.
CLOCKS ^= SH;

} while (++x < PIXEL_COUNT);

sei();
}

/*
* clearLine() Clears the CCD.
*/

void clearLine() {

int x = 0;

// Set ICG low.
CLOCKS &= ~ICG;
CLOCKS |= SH;
_delay_loop_1(14);

// Set SH low.
CLOCKS ^= SH;
_delay_loop_1(10);

// Reset the timer so the edges line up.
TCNT2 = 0;

CLOCKS |= (RD + CNVST + ICG + BYTESWAP + MCLK);

do {
CLOCKS ^= SH;
_delay_loop_1(10);

} while (++x < PIXEL_COUNT);

}

/*
* sendLine() Send the line of pixels to the user.
*/
void sendLine() {
uint16_t x;

for (x = 0; x < PIXEL_COUNT; ++x) {
Serial.print(x);
Serial.print(“,”);
Serial.print(pixBuf[x]);
Serial.print(“\n”);
}
}

/*
* setup()
* Set the data port to input.
* Set the clock port to output.
* Start timer2 generating the Mclk signal
*/

void setup() {
DDRB |= 0x01;
PORTB &= ~1;
delay(10);
CLOCKS_DDR = 0xff;
CLOCKS = 0; //clocks0;
DATA_DDR = 0x0;
Serial.begin(115200);
PORTB |= 0x01;
// Setup timer2 to generate an 888kHz frequency on D10
TCCR2A = (0 << COM2A1) | (1 << COM2A0) | (1 << WGM21) | (0 << WGM20);
TCCR2B = (0 << WGM22) | (1 << CS20);

OCR2A = 8;
TCNT2 = 0;
delay(10);
}

/*
* loop()
* Read the CCD continuously.
* Upload to user on switch press.
*/

void loop() {

int x;
char ch;

// If we got a command last time, execute it now.
if (cmdRecvd) {
if (cmdBuffer[0] == ‘r’) {

// Send the readout to the host.
sendLine();
} else if (cmdBuffer[0] == ‘e’) {
delay(10);
Serial.write(cmdBuffer);
// Set the exposure time.
sscanf(cmdBuffer + 1, “%d”, &exposureTime);
if (exposureTime > 1000) exposureTime = 1000;
if (exposureTime < 1) exposureTime = 1;
}

// Get ready for the next command.
memset(cmdBuffer, 0, sizeof(cmdBuffer));
cmdIndex = 0;
cmdRecvd = 0;
}
// Clear the CCD.
clearLine();

// Integrate.
delay(exposureTime);

// Read it for real.
readLine();

// See if the host is talking to us.
if (Serial.available()) {
ch = Serial.read();

// If char is linefeed, it is end of command.
if (ch == 0x0a) {
cmdBuffer[cmdIndex++] = ‘\0’;
cmdRecvd = 1;

// Otherwise it is a command character.
} else {
cmdBuffer[cmdIndex++] = ch;
cmdRecvd = 0;
}
}
}

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s