TCD1304DG Sensor

Ich habe vor diesen Linear Image Sensor zu verwenden.
Der arbeitet mit einer Taktfrequenz von 0.8 bis 4 MHz.
Um eine genügend hohe Frequenz verwenden zu können, will
ich einen Teensy 4.1 verwenden. (Darf ich in einem Arduino-Forum Fragen
über Teensy stellen?)

Nun meine Frage: Der analoge Messwert muss nur z.B. alle 3694 Perioden
ausgelesen werden.
Kann ich irgendwie den Systemtakt des Teensy
als Takt für den Sensor verwenden, und lässt sich der Auslesetakt des A/D-Wandlers irgendwie
mit diesem Systemtakt synchronisieren?

Für Teensy ist @agmue ein Spezi. :wink:
Muss es genau mit dem Takt sein, oder reicht Dir auch eine Wiederholung auf Zeitbasis?
(Microsekunde / Millisekunde mit einer gewissen Toleranz)

Der Teensy 3.2 funkioniert einwandfrei mit dem TCD1304 Sensor.

Siehe TCD1304 with teensy 3.2

Die TCD1304 Taktfrequenz ist tatsächlich nicht so wichtig, wie im Datablatt angegeben, und man kann sogar einen Arduino Uno verwenden, natürlich mit weniger Pixeln.

1 Like

Ich werde mir den Link nochmal durchlesen. Mal sehen ob ich das alles
verstehe.
So weit ich gelesen habe, kann man den Teensy auch mit höherer Spannung
und dann auch mit höherer Frequenz betreiben.

?? nur 3.3V.

Wie ist das eigentlich mit den internen Timern?
Sind die unabhängig, oder sind die automatisch gegeneinander (Vorraussetzung natürlich geradzahlige Vielfache) synchron? Falls sie unabhängig wären, könnten sie ja über einen längeren Zeitraum hin auseinander driften.
und hier im Thread

steht auch, dass der Start der Timer durchaus verschoben sein könnte.

Der "Spezi" grüßt mit geringer Bandbreite aus dem Urlaub!

Du hast welche.
Bleib gesund und erhol Dich.

1 Like

Ich habe mal versucht, den Code für Teensy 4.1 zu compilieren.
Leider bekomme ich Fehlermeldungen. Da ich mich noch nicht so gut auskenne, denke ich, dass die Bibliothek noch nicht richtig für die 4.1er Version angepasst ist. Stimmt das?
Was kann ich da tun? (Bitte sagt jetzt nicht anpassen, denn das würde mich noch überfordern)
Die IDE schlägt ja einen anderen Namen vor, das hilft aber leider auch nicht weiter.

C:\Users\Oleum\Documents\Arduino\Teensy\TCD1304\TCD1304.ino: In function 'uint16_t analogReadFastADC0(uint8_t)':
C:\Users\Oleum\Documents\Arduino\Teensy\TCD1304\TCD1304.ino:87:23: error: 'ADC0_RA' was not declared in this scope; did you mean 'ADC1_R6'?
87 | result = (uint16_t)ADC0_RA;
| ^~~~~~~
| ADC1_R6

Using library ADC at version 9.1 in folder: C:\Users\Oleum\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\ADC
exit status 1

Compilation error: 'ADC0_RA' was not declared in this scope; did you mean 'ADC1_R6'?


#include "ADC.h"

unsigned long fM  = 1000;       // Mclk in !!!! kHz !!!!!!!!!!
unsigned int t_int = 20000;     // us
unsigned int n = 1;             // nr SH pulses for whole T_ICG
unsigned int nrSHs = 0;         // nr of executed SH pulses
unsigned long T_ICGmin = 3694 * 4 * 1000/fM ;    // us  >= n * t_int;      

unsigned long T_ICG;

int fMPin   = 3;      // Mclk out 3  FTM1
int SHPin   = 14;     // 
int ADCtrc  = 6;      // ADCtriggerClock out 6 FTM0, only internal use
int ICGPin  = 15;     //
int analogPin = A3;   // Pin 17
ADC *adc = new ADC(); // adc object
uint16_t buffer[4000];
elapsedMicros elMi;
char cmdBuffer[16];
int cmdIndex;

void setup()
{
  pinMode(analogPin, INPUT);
  pinMode(SHPin,     OUTPUT);
  pinMode(ICGPin,    OUTPUT);
  pinMode(fMPin,     OUTPUT);   
  pinMode(ADCtrc,    OUTPUT);
  
  Serial.begin(115200);
  
  digitalWriteFast(SHPin, HIGH);
  digitalWriteFast(ICGPin, LOW);
  
  /*  The pulses for Mclk and ADCtrigger are made with PWM outputs.
   *  On teensy 3.2 there are 3 timers for PWM:
   *  FTM0  can drive pins 5, 6, 9, 10, 20, 21, 22, 23 
   *  FTM1  3, 4
   *  FTM2  25, 32
   *  all pins of one timmer have the same frequency, 
   *  so three different frequencies are possible.
   *  We can set the
   *    resolution with analogWriteResolution(bits),
   *    frequency with analogWriteFrequency(pin, frequency) and 
   *    dutycycle with analogWrite(pin, value)
   *  Depending on the resolution we can choose different ranges of 
   *  frequency, the lower the resolution the higher the possible frequency.
   *  e.g. 5 bits up to 1,5 MHz,  4 bits up to 3 MHz. (f_CPU = 96 MHz)
   *  The dutycycle must be half of 2^resolution (16 for 5 bits, 8 for 4 bits)
   *  to get a square wave.
   *  for details: https://www.pjrc.com/teensy/td_pulse.html
   */
  analogWriteResolution(4);             // f <= 3 MHz
  analogWriteFrequency(fMPin, fM*1000);
  analogWrite(fMPin,8);              // dutycycle 50% von 2^4
  analogWriteFrequency(ADCtrc, fM*1000/4);
  analogWrite(ADCtrc, 8);              // dutycycle 50% von 2^4

  /*
   * Settings for analog Read
   * for details: https://forum.pjrc.com/threads/25532-ADC-library-update-now-with-support-for-Teensy-3-1
   */
  adc->setReference(ADC_REFERENCE::REF_3V3, ADC_0); 
  adc->setAveraging(1);                 // set number of averages
  adc->setResolution(12);               // set bits of resolution
  adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); 
  adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); 
  adc->adc0->singleMode();              // is needed for analogReadFastADC0()

  noInterrupts();
  Serial.println(T_ICGmin);
}

/* the function uint16_t analogReadFastADC0(uint8_t pin)
 * is from ADC.cpp and ADC_Module.cpp, here specialised for ADC0 
 * for more speed; this one takes 2,2 us with f_CPU = 96 MHz
 */
uint16_t analogReadFastADC0(uint8_t pin){
  uint16_t result;
  
  adc->adc0->startReadFast(pin);      // start single read (with adc->adc0->singleMode(); in setup() )
  while(adc->adc0->isConverting()) {} // wait for the ADC to finish
                                      //  __disable_irq();
  result = (uint16_t)ADC0_RA;
                                      //   __enable_irq();
  return result;
}

void readTCD(){
  int i;
  
  n = 1;                                // calculate n and T_ICG from t_int
  while (n * t_int < T_ICGmin){ n++; }  // t_int is given by user input
  T_ICG = n * t_int;
  while (!digitalReadFast(ADCtrc)){}         
  digitalWriteFast(ICGPin, HIGH);
  digitalWriteFast(SHPin, LOW);
  elMi = 0;
  delayMicroseconds(2);
  digitalWriteFast(SHPin, HIGH);
  nrSHs = 1;
  delayMicroseconds(2);
  digitalWriteFast(ICGPin, LOW);       
  for (i=0; i<3694; i++){ 
    while (!digitalReadFast(ADCtrc)){}         
    buffer[i] = analogReadFastADC0(analogPin);  // takes 2,2 us    
    if (elMi >= nrSHs * t_int){                 // new SH-puls
      digitalWriteFast(SHPin, LOW);
      delayMicroseconds(2);
      digitalWriteFast(SHPin, HIGH);
      nrSHs++;
    }
  }
  while (elMi < T_ICG){}
}

void printBuffer(){
  for (int i=0; i<3694; i++){
    Serial.print (i);
    Serial.print (' ');
    Serial.println(buffer[i]);
  }
}

void loop(){
  if (Serial.available())  {
    cmdBuffer[cmdIndex++] = Serial.read();
  }
  if (cmdBuffer[0] == 'r')  {
     printBuffer();
  }
  else if (cmdBuffer[0] == 't')  {
    if (t_int > 100){
      t_int = t_int-100;
    }
    if (t_int < 200){
      t_int = t_int - 10;
    }
    readTCD();
    Serial.print("T_ICG = ");
    Serial.print(T_ICG);
    Serial.print("   n = ");
    Serial.print(n);
    Serial.print("   t_int = ");
    Serial.println(t_int);
    if (t_int < 0) t_int = 0;
  }
  else if (cmdBuffer[0] == 'T')  {
    t_int = t_int + 100;
    readTCD();
    Serial.print("T_ICG = ");
    Serial.print(T_ICG);
    Serial.print("   n = ");
    Serial.print(n);
    Serial.print("   t_int = ");
    Serial.println(t_int);
  }
  cmdBuffer[0] = '\0';
  cmdIndex = 0;
  readTCD();
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.