Can I use Teensy 3.1 to interface / drive a linear CCD (TCD1304AP)

Status
Not open for further replies.

pzyxian

New member
I heard the teensy 3.1 might be capable of driving the TCD1304AP (a linear CCD from Toshiba). I checked that it has a fast enough ADC. However, I still got to start 3 clock like signals at the same time to properly drive the camera.

1st signal is 1MHz (up to 4MHz)
2nd signal is 0.25MHz (1/4 of the main clock);
- Data is coming out from the camera at this clock rate
3rd signal has a maximum period of 20us.

Do you think the teensy 3.1 can power up all these clock signals at the same time? Currently I have the stm32f401re. Though I can power up these clocks, but I can't get them to go at the same time. The stm doesn't have a fast enough ADC as well. Please advise.

Attaching spec sheet of TCD1304AP:View attachment TCD1304DG.pdf
 
Looking at the datasheet, I would say Teensy 3.1 might be able to do this. Maybe. But it'd require some pretty significant fiddling with the DMA controller to keep the ADC reading at that speed and generate the two clock waveforms. Or maybe you'd use the timers to generate the waveforms and trigger the DMA engine to read the ADC in sync? Or maybe create a 3rd waveform in sync, for the purpose of triggering the ADC at a different point in the middle of the SH clock cycle. Either way, it'll be tricky DMA-based design to sustain 250 ksamples/sec while generating those waveforms.
 
I was able to get the chip working with a Teensy 3.1. I didn't have much knowledge on the Arduino or Teensy chip so it's probably not an efficient method but it works. Let me know if you're still interested.
 
I was able to get the chip working with a Teensy 3.1. I didn't have much knowledge on the Arduino or Teensy chip so it's probably not an efficient method but it works. Let me know if you're still interested.

Please share your code. I plan to build an spectrometer with this CCD.
 
Please share your code. I plan to build an spectrometer with this CCD.

Hi, this is only a semi functional version but is all I could find.

I used to PWM at 1 MHZ for the main timing. I tried using multiple PWM but it never worked. Eventually I had to use empty loops and a oscilloscope to get timings better in some area. Realistically I think the Teensy may not be meant for this sort of thing but I'm sure someone more familiar with the chip could get it running well.

Another issue is output of the data. I sent it over serial which is very slow and ended up interfering with the reading on the chip. I think the chip expects to be continuously read so stopping to send the data had some weird results.



Code:
#define MCpin 20
#define ICGpin 10
#define SHpin 12
#include <ADC.h>

volatile int runCode = 0;
volatile bool inter = false;
int aa;
unsigned long t1;
unsigned long t2;
unsigned long dt;
int bb;
int loops = 0;
#define BUFSIZE 3694
uint8_t data_buffer[BUFSIZE];
ADC *adc = new ADC(); // adc object
volatile unsigned long ticks = 0;

void setup()   {
  
  ARM_DEMCR |= ARM_DEMCR_TRCENA;
  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
  memset(data_buffer,0,sizeof(data_buffer));
  pinMode(ICGpin, OUTPUT);
  digitalWriteFast(ICGpin, HIGH);
  pinMode(SHpin, OUTPUT);
  pinMode(MCpin, OUTPUT);
  pinMode(11, OUTPUT);
  digitalWriteFast(11, HIGH);
  pinMode(19, INPUT);
  attachInterrupt(19, isrService, RISING); // interrrupt 1 is data ready  
  Serial.begin(115200);
  //Serial.println("Starting");
  analogWriteResolution(5);
  analogWriteFrequency(MCpin, 1000000);
  analogWrite(MCpin, 16);
  adc->setAveraging(1);  
  adc->setResolution(8);
  adc->setConversionSpeed(ADC_VERY_HIGH_SPEED);
  adc->setSamplingSpeed(ADC_VERY_HIGH_SPEED);
  adc->startContinuous(A0, ADC_0);   
  adc->analogReadContinuous(ADC_0);
  digitalWriteFast(SHpin, LOW);

}

void loop()                     
{

  //turn interrupts on, these will be used for syncronization of the signals  
  interrupts();

  // increment loops to allow us to make decisions based on how many reads have been performed
  loops += 1;
  //if (loops>20){digitalWriteFast(11, HIGH);}
  
  // ticks tracks the main PWM, should be at 1 MHZ
  ticks = 0;
  
  // wait for first PWM tick, the main interrupt based on the PWM increments the ticks value
  while (ticks < 1){};
  // cycle ICG low
  digitalWriteFast(ICGpin, LOW);
  
  // loop used for timing, checked wait time with oscilliscope, has weird jumps in wait time based on number of loops, must be optimized by the compiler?
  // not sure why I didn't use the tick counter for this timing, pretty sure tick counter was only reliable for longer waits
  // see sensor sheet for timing reasons, using the default here i think
  for (bb=0;bb<20 ;bb++){};
  digitalWriteFast(SHpin, HIGH);
  while (ticks < 6){};
  digitalWriteFast(SHpin, LOW); //for norm
  while (ticks < 10){};
  digitalWriteFast(ICGpin, HIGH);
  
  // turn off interrupts for the main loop where we read the analog signal
  // in order for loop to run uninterrupted, cycles through all data
  noInterrupts();
  for (aa=0;aa<923;aa++){
    digitalWriteFast(SHpin, HIGH);
    for (bb=0;bb<60;bb++){};
    data_buffer[2*aa] = adc->analogReadContinuous(ADC_0);
    for (bb=0;bb<60;bb++){};
    digitalWriteFast(SHpin, LOW);
    for (bb=0;bb<60;bb++){}; 
    data_buffer[2*aa+1] = adc->analogReadContinuous(ADC_0);
    for (bb=0;bb<60;bb++){};   
  }

  digitalWriteFast(SHpin, HIGH);
  for (aa=0;aa<923;aa++){
    digitalWriteFast(SHpin, HIGH);
    for (bb=0;bb<60;bb++){};
    data_buffer[923+2*aa] = adc->analogReadContinuous(ADC_0);
    for (bb=0;bb<60;bb++){};
    digitalWriteFast(SHpin, LOW);
    for (bb=0;bb<60;bb++){}; 
    data_buffer[923+2*aa+1] = adc->analogReadContinuous(ADC_0);
    for (bb=0;bb<60;bb++){};
  }
  
  //t2 = ARM_DWT_CYCCNT;
  interrupts();
  ticks = 0;
  while (ticks < 1){};
//  digitalWriteFast(ICGpin, LOW);
  adc->analogReadContinuous(ADC_0);
  digitalWriteFast(SHpin, HIGH);
  while (ticks < 6){};
  digitalWriteFast(SHpin, LOW);
  
  // turn off interrupts so can send serial data uninterrupted
  // print out every reading, can change if we want to print every X  
  noInterrupts();
  if (loops > 0){
    for (aa=0;aa<3694;aa++){
      Serial.print(data_buffer[aa]);
      Serial.print(" ");
      data_buffer[aa] = 0;
    }
    Serial.println(" end");
    loops = 0;
    //delay(100);
  }
  interrupts();
  delay(3000);
}



void isrService()
{
  ticks = ticks + 1;

}
 
Do you think the teensy 3.1 can power up all these clock signals at the same time? Currently I have the stm32f401re. Though I can power up these clocks, but I can't get them to go at the same time. The stm doesn't have a fast enough ADC as well. Please advise.


ibps clerk result 2017
 
I don't mean to be blunt, but if you can't get the stm32f401re to drive and read the TCD1304, you're doing it wrong.

It's possible that the MCU isn't fast enough if you want the main loop to do everything, but that's exactly what I mean by doing it the wrong way. You should use the peripherals.

I have a stable firmware including command-line interfaces for linux and mac, and a german guy wrote a windows GUI as well. I have documented it as well as I could here:
https://tcd1304.wordpress.com

I don't know the teensies, but if the 3.1 has enough peripherals and is as fast or faster than the stm32f103 "blue-pill" which can also drive and read the TCD1304 (another german ported my firmware to this chip, but hasn't yet published it, and I've confirmed it works), then it should just be a matter of utilizing the chip properly.
 
Status
Not open for further replies.
Back
Top