0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

できるだけ正確な周期で処理を繰り返す方法(シェルスクリプト・Python・Arduino IDE)

Posted at

はじめに

最近、Arduinoやラズパイ等でいろいろな時計を作成するのにはまっています。
サーボを動かしたり、7SEGを表示させたりと方法は様々ですが、その処理命令をsleep関数やdelay関数等を使って繰り返し実行していました。
複数の時計を作成して並べてながめていてようやく気がついたのですが、それぞれの秒の桁のカウント(もしくは秒針の運針)の間隔が微妙にずれていました。
よく考えるとあたりまえなのですが、sleepやdelayで次の実行まで待っても、実際の処理にかかる時間が加算されるため、実行間隔は
sleepやdelayで処理を待つ時間 + 実際の処理にかかる時間
ということになります。
当初は実際の処理にかかる時間を計測してsleep,delayで待つ時間を減算していましたが、処理時間も常に一定ではなかったりと限界を感じたため、根本的な対処を考えました。

テンプレートプログラム

シェルスクリプト

#!/bin/sh

interval=0.5 # 秒単位で実行周期を設定  

while :
 do
  next_time=$(echo "scale=3; `date +%s.%3N` + $interval" | bc ) # 次回実行時刻を取得
  # 処理(interval以下で終わるように設定する必要あり)
  sleep $(echo "scale=3; $next_time - `date +%s.%3N`" | bc ) # 次回実行時刻まで待つ
 done

python

from time import time
from time import sleep
interval = 0.5 # 秒単位で実行周期を設定
while True:
  next_time =  round((time() + interval),1) # 次回実行時刻を取得
  # 処理(interval以下で終わるように設定する必要あり)
  sleep( next_time - time() ) # 次回実行時刻まで待つ

Arduino IDE

void setup() {
  last_time = 0;    // 前回実行時刻を初期化
  interval = 500;  // ミリ秒単位で実行周期を設定
}
void loop() {
  unsigned long current_time = millis();         // 現在時刻を取得
  if ((current_time - last_time) >= interval) {  // 前回実行時刻から実行周期以上経過していたら
    // 処理(interval以下で終わるように設定する必要あり)
    last_time = current_time;                    // 前回実行時刻を現在時刻で更新
  }
}

課題

pythonとArduino IDEではそこそこ正確なのですが、シェルスクリプトがどうしても指定した実行周期よりも15/1000秒程度間隔が長くなってしまいます。
bcやdateの処理時間が原因なのかなと思いいろいろなスペックのLinuxで試してみましたが状況は同じでした。
基本pythonと同じ考え方で作っているつもりなのですが・・・。
解決方法が見つかったら更新します。

0
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?