Arduino Due はクロック周波数が 84 MHz と Arduino Uno (16 MHz) と比べて高速ですが、色々と高速化する必要があったので、使った方法をいくつかまとめました。気が向いたら追記・修正予定です。
作業環境は macOS Big Sur/Monterey、Arduino IDE を使用しています。
digitalRead()
の高速化
Arduino Uno とは少し記法が違います。
REG_PIOD_SODR = 0b1111 // これで 25~28 番 pin が HIGH
REG_PIOD_CODR = 0b1111 // これで 25~28 番 pin が LOW
この方法でやると 20 ns 程度 (2 clock?) で HIGH/LOW の切り替えが可能です。
A~D に割り振られているので、使用する pin に合わせて変更します。
コンパイルオプションの変更
Arduino IDE でコンパイルオプションを変更するには、まず環境設定の
より詳細な情報を表示する
のコンパイルにチェックを入れます。この状態でコンパイルを実行すると3行目ぐらいに
/Users/USERNAME/Library/Arduino15/packages/arduino/hardware/sam/1.6.12
という感じのパスが表示されます。このフォルダ内の "platform.txt" にコンパイル時の設定が保存されています。
今回は最適化オプションを -Os から -O3 に変更してやります。こうすることで、for
や while
でループする際の処理が少し速くなって 45 ns (4 clock?) ぐらいのデッドタイムで繰り返し処理が可能です。ただ、確認はしていませんが繰り返し回数が決まったループであれば、その回数だけ書いてしまう方が速い(はず)です。
今回は繰り返し処理の間に適当な間隔が欲しかったので、あえて for
を使っています。
割り込み関数 attachInterrupt()
外部入力を受けてからすぐに処理を開始したい場合、最初は
void loop() {
int trigger = 0;
while (trigger != 1) {
trigger = REG_PIOD_PDSR & 0b1; // digitalRead(25) の高速版
}
// 25 番 pin が HIGH になった以降の処理
}
と書いていたのですが、この方法だと処理後に先頭に戻る際にも時間がかかってしまうので、25 番 pin の状態を 45 ns ごとに確認することになります。そのデッドタイムを減らすためには、割り込み関数が使えます。割り込み関数を使用する場合は
void setup() {
attachInterrupt(25, USERFUNCTION, RISING);
// 使用する割り込み関数の準備:25 番 pin が LOW -> HIGH で USERFUNCTION を実行
}
void loop() { // loop の中は空で良い
}
void USERFUNCTION() { // 割り込み関数の中身
}
void serialEvent() { // シリアルを受け取った時の割り込み処理も書ける。
}
と書くことで、25 番 pin が LOW から HIGH に変わった瞬間に USERFUNCTION()
内の処理が開始されます。RISING
以外にも LOW, CHANGE, FALLING, HIGH (Arduino Due、Zero、MKR1000 のみ)
が指定できます。
詳細は Arduino リファレンスを参照してください。
逆に割り込まれたくない場合は noInterrupts()
と interrupts()
で挟んでやることで、命令の実行中に割り込まれることがなくなります。意図していない割り込みを防ぐためにタイミングがシビアな部分にはこれが必要です。
気が向いたら Arduino Uno との比較等もまとめたいと思います。