1
\$\begingroup\$

So I'm programming a TSL1401R-LF line scan camera module that reads in a a 1 X 128 array of pixels. I've run into a problem with the accuracy of the output. Basically the camera becomes less accurate as the delay times decrease. For debugging I hooked it up to an oscilloscope and monitored the SI and CLK pulses sent to the clock as well as the analog signals coming from it.

That's why I noticed the the duration of the CLK signal appeared to be over 300 microseconds long. This is strange because my code sets the duration to 170 microseconds. Since this is my first electrical project I'm not sure what to make of this so I'm hoping someone can take a look at my code and a screenshot of the oscilloscope and let me know if what I'm seeing is natural or not.

Here is the code:

int delayTime = 170;

void timming()
{

  //The timing for the impluses was found through direct experimentation.
  //(Meaing that I played around with different delayTimes until the code worked)

  digitalWriteFast(SI, HIGH);
  delayMicroseconds(delayTime/2);
  digitalWriteFast(CLK, HIGH);
  delayMicroseconds(delayTime/2);
  digitalWriteFast(SI, LOW);
  delayMicroseconds(delayTime/2);
  digitalWriteFast(CLK, LOW);
  delayMicroseconds(delayTime);

  for(int i = 0; i < 129; i++)
  {
    digitalWriteFast(CLK, HIGH);
    delayMicroseconds(delayTime);
    digitalWriteFast(CLK, LOW);
    delayMicroseconds(delayTime);
  }

}

Here is the screenshot

enter image description here

The yellow Line is the SI pulse, the light blue is the CLK pulse and the purple is the analog output.

\$\endgroup\$
8
  • \$\begingroup\$ This may be helpful, especially if you have interrupts running somewhere: arduino : delaymicroseconds(). I'm not an arduino user, but you would probably be better off using a hardware timer triggering an interrupt. \$\endgroup\$
    – Tut
    Jun 28, 2016 at 19:23
  • \$\begingroup\$ The period of the clock pulse seems to be different between pulses 1-2 and 2-3. If delaymicroseconds() is a software timer, then its accuracy is suspect depending if anything interrupts it. As @Tut mentions, a hardware timer will provide a very repeatable clock. The AVR has several timer options for different waveforms, although you'll have to match your desired timer with your wiring. \$\endgroup\$
    – Smith
    Jun 28, 2016 at 19:34
  • \$\begingroup\$ @Smith Perhaps the center of the display marks the start of execution. Then it's consistent. SI goes high, then CLK high, then SI low, then CLK low, after which CLK is toggled. \$\endgroup\$
    – Kaz
    Jun 28, 2016 at 19:42
  • \$\begingroup\$ Sounds like the calibration in delayMicroseconds is off. Is this dynamically calibrated? If so, are you supposed to call something to get it calibrated? \$\endgroup\$
    – Kaz
    Jun 28, 2016 at 19:45
  • 1
    \$\begingroup\$ as written your code will always be slower, you are doing something that takes time, then waiting some amount of time then doing something that takes time. the things in between timing are not completely free. Likewise the timing routing quite likely has overhead so it is a little longer either due to the code, the function call or the fractions of a time period on either end of the measurement. this is not how to do accurate timing. you want to use a timer and eliminate the cost of the code or average it out. \$\endgroup\$
    – old_timer
    Jun 29, 2016 at 0:00

1 Answer 1

2
\$\begingroup\$

The main problem

It looks like the chip is running at a slower clock speed than it should be. If delayMicroseconds assumes a 16MHz clock and the chip is actually using it's 8MHz internal oscillator, for example, the pulses would double in length. You could check that:

  • The crystal oscillator is running and at the correct frequency
  • The atmega's fuse bits are set to use the external oscillator
  • There is no prescaler set

Also

The Arduino delayMicroseconds function is not a good way of making something happen every 85uS, and digitalWrite is not helping your case either. If you go digging into the definition of the two functions (which are provided by the Arduino project, not by Atmel, who make the actual microprocessor) you'll see that they are actually remarkably complicated. Now, the compiler will simplify them quite a lot, but even then you'll be left with a lot of operations, and those operations will lengthen the pulse.

You could rewrite the code to speed things up, but there is a better way. The AVR chip used in the Arduino has several timers on it. These run in parallel with the cpu which runs your code, and they can toggle pins or run short pieces of code at very precise intervals. The downside is that although the timers are a core feature of the AVR chips, they are rarely used in the Arduino world. So you'll have to go diving into some less user-friendly documentation to figure out how to use them.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ It also depends on the particular model of Arduino: I have a Chinese Nano clone that can output (using DigitalWrite) a square wave of 5us + the us specified in DigitalWrite like a Swiss clock. The added 5 us is roughy the time required to have the delay and write instruction enacted. On the other hand, a 10x more expensive original Micro is not capable of doing that, with timings all over the place. Perhaps it's because it has USB integrated within the microcontroller and it has to serve that too. Perhaps the OP should specify what Arduino is using. \$\endgroup\$ Jun 28, 2016 at 21:40
  • \$\begingroup\$ I agree with this answer. The timing being off by almost exactly a factor of two suggests a clock configuration problem. \$\endgroup\$
    – Adam Haun
    Jun 29, 2016 at 3:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.