月別アーカイブ: 2013年12月

Arduino UNO での Serial.println() にかかる時間

今やっている実験の一環でこんなコードを走らせています:

   if (digitalRead(pinDeviceReadReady) == HIGH) {
    Serial.println("DATA READY");
    spiSend(0x20); // command "read request"
    readBuffer.deviceId = spiReceive();
    Serial.println(readBuffer.deviceId);
    readBuffer.wireId = spiReceive();
    Serial.println(readBuffer.wireId);
    readBuffer.length = spiReceive();
    Serial.println(readBuffer.length);
    for (int i = 0; i <= readBuffer.length; ++i) {
       readBuffer.data[i] = spiReceive();
       Serial.println(readBuffer.data[i]);
    }
  }

where

inline void spiSend(uint8_t data)
{
  // wait for device ready to write
  while (digitalRead(pinDeviceWriteReady) == LOW);
  SPI.transfer(data);
}

inline uint8_t spiReceive()
{
  while (digitalRead(pinDeviceReadReady) == LOW);
  uint8_t data = SPI.transfer(0);
  return data;
}

実際の動作パタンは以下のようになりました。赤線は DATA READY をあらわすインジケータの出力で、青線はそれを受けて起動される SPI 転送クロックです。見てわかるように、かなり大きな遅延が出ています。

data_ready_and_SPI_clock_with_serial

遅延は、デバッグのためにSPI転送の間に挿入されている Serial.println() が原因のようです。Serial.println() の実装は見ていませんが、どうもこの行の実施には 100μS から 150μS  ぐらいの所要時間がかかるようです。

Serial.println() 行を取り除くと、大きな遅延は見られなくなりました。

data_ready_and_SPI_clock_without_serial

でも波形を拡大してみるとまだ遅延があるようです。

data_ready_and_SPI_clock_closeup

これはおそらく DATA READY インジケータを読むための digialRead() による遅延か SPI.transfer() の実施に遅れがあるためと思われます。この実験では今すぐ除去する必要はないのですが、3μS ほどの遅延があることは頭に入れておいたほうがよさそうです。