-
しばさん>>はにゃさん
ありがとうございます。
パターンカットして使うかもです。
ふたを開閉するためだけにDCモーターを駆動させる予定なので(^^;)
海外フォーラムでこんなの見つけました。
IDE上で/dev/tty* permission denied.などと出る方は参考にしてください。
https://communities.intel.com/thread/457512014/03/06
-
はにゃさんattachInterrupt(pin, handler, RISING)と
attachInterrupt(pin, handler, FALLING)が動作していないようです。
となると動くのは
attachInterrupt(pin, handler, CHANGE)だけ?2014/03/08
-
つきさん23: はにゃ さん
タイマ割り込みできました。
1か所変更しました。
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
↓
Timer1.attachInterrupt( timerIsr, 500000 ); // attach the service routine here
C言語のライブラリを使うときは
-----
#include <interrupt.h>
void setup() {
setMinimumTimerFreq(100000);
attachTimerInterrupt(timerIsr, 500000);
pinMode(13, OUTPUT);
}
void loop() {
}
void timerIsr()
{
// Toggle LED
digitalWrite( 13, digitalRead( 13 ) ^ 1 );
}2014/03/08
-
はにゃさんつきさん
2にタクトスイッチ
12,13にLED(制限抵抗つき)
という回路で
13はタクトスイッチの押下時のみ点灯
12はタイマーで 50%デューティー 1Hz点灯
させてみました。
さすがにちゃんと動きますね。
次はこれをもう少し工夫して タクトスイッチ押下時間を計測しますかね。
#include <TimerOne.h>
volatile int led1;
volatile int led2;
void setup() {
// put your setup code here, to run once:
pinMode(2, INPUT_FAST);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
led1 = LOW;
led2 = LOW;
attachInterrupt(2, proc1, CHANGE);
Timer1.initialize(100000);
Timer1.attachInterrupt(timerProc, 500000);
}
void proc1() {
int p2;
p2 = digitalRead(2);
if (p2) {
led1 = HIGH;
} else {
led1 = LOW;
}
}
void timerProc() {
led2 = !led2;
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(13, led1);
digitalWrite(12, led2);
}2014/03/08
-
はにゃさんタクトスイッチの押下時間を簡単に計測したバージョンです。
100ms弱までは計測できました。
このあと矩形波を入力してみてどうなるか見てみたい気がします。
GalileoのattachInterruptは疑似割り込みだと思うので、Fast GPIOが動作したとしても、
1KHzは超えられないような気がします。
#include <TimerOne.h>
volatile int led1;
volatile int led2;
volatile int last_mills;
volatile int duration;
volatile int flg_display;
void setup() {
// put your setup code here, to run once:
pinMode(2, INPUT_FAST);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
led1 = LOW;
led2 = LOW;
last_mills = 0;
duration = 0;
flg_display = false;
attachInterrupt(2, proc1, CHANGE);
Timer1.initialize(100000);
Timer1.attachInterrupt(timerProc, 500000);
}
void proc1() {
int p2;
p2 = digitalRead(2);
if (p2) {
led1 = HIGH;
last_mills = millis();
} else {
led1 = LOW;
duration = millis() - last_mills;
flg_display = true;
}
}
void timerProc() {
led2 = !led2;
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(13, led1);
digitalWrite(12, led2);
if (flg_display) {
Serial.print(duration);
Serial.print("\n");
flg_display = false;
}
}2014/03/09
-
ちばとどさんTimerOne.h のタイマ割り込みの実測をしました。
Timer1.initialize(1000); // 最小間隔 1msec=1kHz
(1000より小さいパラメータでは、コンパイルできるが、プログラムが開始されない)
としても、
ハンドラ側でGPIOを使ってLEDを1個点滅させているときは230Hz、(GPIOの仕組み上の限界?)
ハンドラで何もしないで帰るようにしても、480Hzくらいでした。
これより速くできる工夫の余地はありますか?2014/03/20
-
はにゃさんhardware/arduino/x86/libraries/TimerOne/TimerOne.cppを読んで、
TimerOneの実装を確認したところ、
TimerOne::initilize は、setMinimumTimerFreqの、
TimerOne::attachInterrupt は、attachTimerInterruptのラッパーでした。
次にhardware/arduino/x86/cores/arduino/interrupt.c を読んで、
Galileoのタイマ割り込み実装を確認しました。
Galileoのタイマ割り込みは高精度イベントタイマー(HPET)を使用してます。
HPETはx86で以前のIntel 8253(PIT)やリアルタイムクロック割り込みに代わり導入されたもので、Vista以降、現代のLinux/FreeBSD などでは普通に使用されています。
Galileoは Linux のHPETサポート,libGPIO,pthreadを使って、Arduino風味の ピン割り込み、タイマ割り込みを実現していますね。
main() から interrupt_init() を呼び出し、pthread_create で
タイマ割り込みハンドラ interrupt_main のスレッドを作成します。
interrupt_main は、割り込みか、シャットダウンコマンドが来るまでループしますが、
ループ内で、
1)GPIOによる割り込みをチェックするために FD_SET
2)HPETによる割り込みをチェックするために FD_SET
3)非同期I/O(select) で無限に待つ
4)selectの返り値>0なら どの要因だったか確認
ピンベースの割り込みなら
コールバック関数をキック
LinuxGPIOライブラリのreopenする(GPIO Lib.がそういう仕様らしい)
タイマベースなら
カウンタ値を増やす
カウンタ値が周期に応じたカウンタ閾値を超えれば カウンタをリセットして、コールバック関数をキック
という実装になってます。
HPETの周期は、setMinimumTimerFreq関数で
μsで指定したパラメータを、1000000で除して周期(Hz)に変換して与えていますが、
ここで
MAX_VARIANT_HPET_FREQ_HZ より高い周波数なら -EINVAL を返して異常終了となります。
MAX_VARIANT_HPET_FREQ_HZは variant.h で 1000と定義されていますから、
1KHz未満に設定する必要があります。
ちばとどさんが、1000μS未満を与えて実行できなかったのは、このせいですね。
Arduinoが使うタイマ割り込みの周期は attachTimerInterrupt関数で指定しますが、
周期(μs)は周波数に変換したのちに、setMinimumTimerFreqが設定した HPETタイマの値で除して、カウンタ閾値となります。
ところで、
#include <TimerOne.h>
volatile int t;
void setup() {
// put your setup code here, to run once:
Timer1.initialize(1000);
t = 0;
Timer1.attachInterrupt(timer1_proc, 1000000);
Timer1.attachInterrupt(timer2_proc, 1000);
}
void timer1_proc() {
char buf[100];
sprintf(buf, "Times %d \n", t);
Serial.print(buf);
t=0;
}
void timer2_proc() {
t++;
}
void loop() {
// put your main code here, to run repeatedly:
// Serial.print("X");
// Serial.print("\n");
// sleep(1);
//t=0;
}
というサンプルを作って実行してみたところ
1s周期で500 or 501回でした。2014/03/21
-
kilifさん割り込みだと数msはかなり厳しそうですね。そもそもLinux上のC、C++プログラムで1ms刻みの処理をタイマーでやることが可能なんでしょうか。
私は高周波の処理をPCにやらせる時には、
スリープ時間でチューニングするか、時刻を逐次取得するしかないと認識しているので、
ArduinoIDE上ではloop()の中で何とかするしか無いと感じます。
Windowsでの少ない経験しかないので的外れかもしれませんが、いかがでしょう。2014/03/22
-
蒼-aoi-さん私事の些細な報告ですが、私のレビューでアップしていたマトリクスLEDのダイナミック点灯ですが、なめらか化できたので一応。
レビューに書いた通り、シフトレジスタタイプのエキスパンダでLEDのA/Kを挟んだ形にしています。
信号はDAT/CLK/STB(LAT)/CLR(OE)の4本ですが、CLR(OE)は使用していないので、実質3本です。
DAT/CLKはOUTPUT_FASTで高速化しましたが、STBは普通のGPIOだったため、それに引っ張られてチラつきが大分ありました。
結論としてはSTBの出力を高速化した結果、滑らかに。
STB周期を計測すると4.3kHz、24ラインなので約180fps相当ということでしょうか。
あくまでSketchで対応できる範囲で試しています。2014/04/05
-
蒼-aoi-さん日記にソースを載せみました。
ユーザー登録してない人は見られないわけですが、画像だとコピペできないので、自分のバックアップ用に掲載しました。
<pre>ないの改行が上手くいかないのと、<table>が認識しないのは痛いですが、それほど手間でもなく載せられました。
今後もレビュー更新都度、アップしたいと思います。
リンク貼り忘れたので、あとでものリンク張っておきます。
ちなみに上の動画のソースはアップしてません。2014/04/12
Galileo 雑談