//This is the firmware developed by David Allmon @ http://davidallmon.com/pages/adc0820-spectrograph

I built this circuit on a proto breadboard (David H Haffner Sr,) and tested it and it works beautifully @ my website on Hackaday are the full project details and PCB gerber files + schematics so please take a look :) //

  1. include <util/delay_basic.h>

// Debug point pin 16

  1. define DBG 0x04

// ADC RD signal pin 17

  1. define RD 0x08

// ADC write signal pin 18

  1. define WR 0x10

// CCD Shift Gate pin 19

  1. define SH 0x20

// CCD Integration Clear Gate pin 20

  1. define ICG 0x40

// CCD Master clock pin 21

  1. define MCLK 0x80

// CCD and ADC clocks

  1. define CLOCK PORTD

// ADC data

  1. define ADATA PINC

uint8_t buffer[3694]; char cmdBuffer[16]; int cmdIndex; int exposureTime = 10;

void setup() {

  // Initialize the clocks.
  DDRD |= (WR | SH | ICG | MCLK | RD | DBG);  // Set the clock lines to outputs
  CLOCK |= ICG;              // Set the integration clear gate high.
  CLOCK |= (RD | WR);        // Set the ADC wr line high.

  // Setup the ADC data port.
  DDRC = 0;
  // Enable the serial port.
  Serial.begin(115200);

  // Setup timer2 to generate a 470kHz frequency on pin 21
  TCCR2A =  + (0 << COM2A1) | (1 << COM2A0) | (1 << WGM21) | (0 << WGM20);
  TCCR2B = (0 << WGM22) | (1 << CS20);
  OCR2A = 16;
  TCNT2 = 1;

}

void readCCD(void) {

  int x;
  uint8_t dummy;

  // Clear the CCD shift register and
  // dump the electrons into it.
  CLOCK |= DBG;
  CLOCK &= ~ICG;
  _delay_loop_1(12);
  CLOCK |= SH;
  delayMicroseconds(5);
  CLOCK &= ~SH;
  delayMicroseconds(10);
  CLOCK |= ICG;
  delayMicroseconds(1);

  for (x = 0; x < 3694; x++)
  {
    // Shift out one pixel and
    // digitize it.
    CLOCK |= SH;

    // ADC write.
    CLOCK &= ~WR;
    delayMicroseconds(1);
    CLOCK |= WR;

    // ADC convert.
    delayMicroseconds(2);

    // ADC read.
    CLOCK &= ~RD;
    delayMicroseconds(1);
    buffer[x] = ADATA;
    CLOCK |= RD;

    // Eat up a few cycles for timing.
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");

    CLOCK &= ~SH;
    delayMicroseconds(4);
  }
  CLOCK &= ~DBG;

}

void sendData(void) {

  int x;

  for (x = 30; x < 3678; ++x)
  {
    Serial.print(x - 30);
    Serial.print(",");
    Serial.print(buffer[x]);
    Serial.print("\n");
  }

}

int cmdRecvd = 0;

void loop() {

  int x;
  char ch;

  if (cmdRecvd) {
    if (cmdBuffer[0] == 'r')
    {
      sendData();
    }
    else if (cmdBuffer[0] == 'e')
    {
      sscanf(cmdBuffer+1,"%d", &exposureTime);
      if (exposureTime > 1000) exposureTime = 1000;
    }
    memset(cmdBuffer, 0, sizeof(cmdBuffer));
    cmdIndex = 0;
    cmdRecvd = 0;
  }
  delay(exposureTime);
  readCCD();
  if (Serial.available())
  {
    ch = Serial.read();
    if (ch == 0x0a) {
      cmdBuffer[cmdIndex++] = '\0';
      cmdRecvd = 1;
    } else {
      cmdBuffer[cmdIndex++] = ch;
      cmdRecvd = 0;
    }
  }

}

Share