質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

2030閲覧

正確な時間刻みでセンサの値を取得したい

ondela

総合スコア12

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/07/29 09:11

編集2018/07/29 09:23

前提・実現したいこと

raspberry pi3で加速度センサを作ろうとしています。
OSはlinux 使用言語はpython3です。
使用加速度センサはadxl345で、i2c通信にて接続しています。

発生している問題・エラーメッセージ

一定間隔(0.01秒刻み)でセンサから値を取得するプログラムを組んでいますが、
たまに大きく刻み時間を外してしまうことがあります。これを解決したいです。

for文内で取得した時刻(time_act)の差分を取ってみると、ほとんど刻みdt(0.01秒)で打刻できていますが、
まれに1秒とか2秒とかになってしまいます。
計測値の取得に時間がかかっているか、あるいは取得している時刻がおかしくなるタイミングがあるかと思っています。

この問題の解決法でなくとも、例えばRTCのようなものを外付けすれば一定刻みでセンサ値取得が可能なるなど、別の視点からの回答でも構いません。
知見をお持ちの方、何卒宜しくお願い致します。

該当のソースコード

python

1N = 1000000 2dt = 0.01 3VAL = [[0, 0, 0]]*N 4time_all = [[0,0,0,0,0]]*N 5time_act = [0]*N 6act_dt = [0]*N 7 8dta = 0.0001084814598456673 9 10t1 = time.perf_counter() 11for i in range(N): 12 tt1 = time.perf_counter() 13 VAL[i] = adxl345.getAxes() 14 tt2 = time.perf_counter() 15 t2 = dt-(time.perf_counter() - t1) -dta 16 tt3 = time.perf_counter() 17 if t2 > dta: 18 tt4 = time.perf_counter() 19 time.sleep(t2) 20 t1 = time.perf_counter() 21 tt5 = time.perf_counter() 22 time_act[i] = t1 23 tt6 = time.perf_counter() 24 time_all[i] = [tt2-tt1,tt3-tt2,tt4-tt3,tt5-tt4,tt6-tt5] 25 26

※adxl345.getAxes()がセンサから値を取得するコマンドです。
x,y,zの3成分を取得しています。実行時間は概ね0.0001秒くらいなので、for文自体は十分に刻み0.01秒で回せると考えています。

試したこと

各処理にかかっている時刻を計測しました(tt2-tt1,tt3-tt2など)。
これをグラフ化すると、以下のようになりました。
イメージ説明
縦軸は処理にかかった時間です。ループ1周の時間は0.01秒となってほしいのですが、ある種周期的にそれが崩れています。

補足情報(FW/ツールのバージョンなど)

python 3.5.3
Raspbian GNU/Linux 9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

raspberry pi3側で、データ取得/蓄積を考えましょう。
蓄積と言っても 2,3回分で十分と思いますが、、。

一般的なLinixシステムではリアルタイム処理は保証されていません。まあ、設定変更で、結構なリアルタイム処理(0.1秒程度以上も)は可能ですが。さらに、Pythonがインタープリタなので、もっとリアルタイムタイム向きではありません。処理時間を気にするならば、C/C++あたりを検討すべきです。
ただ、raspberry側でリアルタイムデータ取得を行い、それを順次、PC側に送るならば、Pythonでも可能じゃないかと思います。(詳細検討は別途、必要)

投稿2018/07/29 10:44

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ondela

2018/08/01 12:34

ありがとうございます。 pythonはやはり重いのですね。osを搭載しておらず、c言語を扱えるarduinoなどに計測の役割を分割して、確実に計測を行える方針で考えてみます。
guest

0

ベストアンサー

ondelaさん、

どれがうまくいくかわかりませんが、アイデアをあげてみます。

  1. CPUクロックをぱ固定してみる

 echo performance | sudo tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
2. 実行するCPUを固定してみる。(taskset)
3. niceで、優先度を上げてみる
4. 他のタスクをできるだけ実行にしない
o GUIは使わない(Raspbian Liteベースにしてみる。とか、Buildrootで最小限のシステムをつくる)
o バックグラウンドで、タスクをできるだけ動かさない (systemd で使わなそうなサービスを切る?)
o ファイルシステムにアクセスしない(!)
o ネットワークをつかわない(!?)

  1. リアルタイムカーネルを使う

 他の回答者のみなさまが書かれている通り、ふつうのLinuxではリアルタイム応答の保証はありません。
が、応答性を通常のカーネルよりよくしたパッチがあり、最近のRaspberyPiのカーネルソースでは、ブランチがあります。
=> 参考

  1. adxl345のデバイスドライバを使う。

カーネルソースの drivers/input/misc/内に adxl34x*.[ch] にドライバがあるので、参考にして、修正して、使う。
(具体的な使い方とか、わかりません。。)

投稿2018/07/30 23:14

編集2018/07/31 00:10
mt08

総合スコア1825

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ondela

2018/08/01 12:28

ありがとうございます。 このままraspberrypiで計測を行うかは検討しますが、その場合でもある処理はraspberrypiで行わせたいと思っているので、その際の参考にさせて頂きます。
guest

0

すでに回答されている通りで、一般的なLinuxではリアルタイム処理は保証されません。つまり、ユーザー側のプロセスを一定のタイミングでできる保証はありません。いま動いているように見えるのは、たまたまです。
これを解決するにはリアルタイムOSを使うか、加速度センサの値を一定時間ごとに取得して送る処理自体を、OSを乗せない別の組み込みマイコンにやらせるかといった方法があると思います。例えばArduinoなどで加速度センサの値を10msごとに読み込んで、データをラズパイにI2C等で送る方法もあるかと思います

投稿2018/07/29 15:04

yutakau8255

総合スコア99

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ondela

2018/08/01 12:30

ありがとうございます。 確実に一定間隔で計測を行っていきたいので、arduino等の使用を検討したいと思います。
guest

0

通常のプログラムループでは正確な時間間隔は実現できません。
これは、バックグランドで、言語(Python)のガベージコレクションが走ってしまう、とか、
OSで、バックグランドでファイルアクセスが始まる、とか、何らかの通信が行われる、とかで、いろんな要因でコードの実行が遅れたり実行時間が長くなったりします

これをどうにかするには、というのは、OSレベルでどーにかしないといけないってことで、なかなか難しい問題となりますね

投稿2018/07/29 09:27

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ondela

2018/08/01 12:36

ありがとうございます。 ご指摘のように、linux搭載のマイコンで正確な時間計測は難しそうなので、少なくとも計測はOS非搭載のマイコンで行う方針で考えてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問