オシロスコープで Seeeduino のタイマー処理を確認してみる

 オシロスコープを借りる機会があったので、使い方の勉強がてら Seeeduino でスレッド処理的な感じでタイマーによる処理を実装してみました。今までオシロスコープは使ったことがなかったので、基本中の基本の確認という感じです。今回お借りしたオシロスコープは、 OWON Japan の PDS5022T という機種です。

www.owonjapan.com

f:id:akanuma-hiroaki:20180524224014j:plain

LED1つでのLチカ

 まずは一番シンプルな形で、LED1つのLチカの回路で確認してみます。回路図は下記のような形になります。LED のアノード側を Seeeduino の6番ピンに接続し、カソード側は抵抗を経由して GND に接続します。また、アノード側にオシロスコープの Positive 側を接続し、カソード側に Negative 側を接続しています。

f:id:akanuma-hiroaki:20180524233526p:plain

 最初は delay を入れず、 Seeeduino が処理できる最速の速度で LED の HIGH/LOW を切り替えてみます。コードは下記のようになります。

void setup() {
  pinMode(6, OUTPUT);
}

void loop() {
  digitalWrite(6, HIGH);
  digitalWrite(6, LOW);
}

 これをオシロスコープで確認すると下記のようなグラフになります。赤色が今回接続しているプローブの計測値になります。縦軸は電圧で一目盛が 1V なので、HIGH の場合に 5V の電圧がかかっていることがわかります。横軸は時間で、一目盛が 5.0μs なので、 5.0μs弱の間隔で HIGH と LOW が入れ代わっているようです。ちなみにこのスピードだと LED を目で見ても、点滅している様子はわからず、点灯状態のように見えます。

f:id:akanuma-hiroaki:20180524234050j:plain

LED2つでの時間差Lチカ

 それでは LED を2つ使った回路を組んでみます。回路図は下記の通りです。単純に LED 1つの時と同じセットを追加しているだけのもので、アノード側は Aruduino の5番ピンに接続しています。また、今回使用しているオシロスコープは2チャンネルあるので、もう1つのチャンネルのプローブを追加した回路のアノード側に接続します。

f:id:akanuma-hiroaki:20180524235424p:plain

 まずはいきなりタイマー処理を実装する前に、新しく追加した方の LED は LOW のままで先ほどと同様のLチカを実行してみます。

void setup() {
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  digitalWrite(5, LOW);
}

void loop() {
  digitalWrite(6, HIGH);
  digitalWrite(6, LOW);
}

 するとオシロスコープでの測定結果は下記のようになります。

f:id:akanuma-hiroaki:20180524235951j:plain

 それぞれのプローブの値を分けて表示していて、今回は黄色いグラフが6番ピンのLEDで、赤いグラフが5番ピンのLEDになります。今回 HIGH/LOW の切り替えを行なっているのは6番ピンのみなので、5番ピンのグラフはフラットのままのはずですが、実際には6番ピンの HIGH/LOW の切り替え時に影響を受けてノイズが入るようです。

 さて、それではタイマー処理を実装してみます。2つのLEDを同じタイミングで点滅させたい時には loop メソッドの中で2つ一緒に扱えば良いのですが、それぞれのLEDを違うタイミングで点滅させたい場合にはそれぞれ独立した処理を行う必要があります。PC などでプログラミングする場合は CPU がマルチスレッド対応しているケースがほとんどだと思いますので、 Thread を用いた実装で良いのですが、 Seeeduino ではマルチスレッドに対応していないので、1つのコアをタイムシェアリングする形で擬似的なマルチスレッドとして実装する必要があります。今回やる範囲であればスレッドまではやらなくてもタイマー処理ができれば良いので、今回は TimerOne というライブラリを使ってみました。

TimerOne & TimerThree Arduino Libraries

 実装は下記のようになります。それぞれの LED のステータスを切り替えるメソッドを用意し、片方(今回は赤い LED の処理)は TimerOne を使ったタイマー処理で実行しています。もう一方(緑のLEDの処理)は今まで通り loop メソッドの中で delay を入れて繰り返し実行しています。

#include <TimerOne.h>

const int ledPinRed = 5;
const int ledPinGreen = 6;
const int brinkIntervalRed = 1000; // MicroSeconds
const int brinkIntervalGreen = 500; // MicroSeconds
int ledStatusRed = LOW;
int ledStatusGreen = LOW;

void brinkLedRed()
{
  if (ledStatusRed == LOW) {
    ledStatusRed = HIGH;
  } else {
    ledStatusRed = LOW;
  }
  digitalWrite(ledPinRed, ledStatusRed);
}

void brinkLedGreen()
{
  if (ledStatusGreen == LOW) {
    ledStatusGreen = HIGH;
  } else {
    ledStatusGreen = LOW;
  }
  digitalWrite(ledPinGreen, ledStatusGreen);
}

void setup()
{
  pinMode(ledPinRed, OUTPUT);
  pinMode(ledPinGreen, OUTPUT);
  
  Timer1.initialize(brinkIntervalRed);
  Timer1.attachInterrupt(brinkLedRed);
}

void loop()
{
  brinkLedGreen();
  delayMicroseconds(brinkIntervalGreen);
}

 これを実行して測定した結果が下記のようになります。それぞれのプローブの電圧の切り替わりのタイミングが異なっていて、独立して処理されているのが確認できます。

f:id:akanuma-hiroaki:20180525092502j:plain

まとめ

 今回は初めてオシロスコープを使ったので基本的な使い方ぐらいしかやっていませんが、実際の電圧のかかり方が可視化できるのはとても便利ですね。テスターでもその瞬間の電圧を見ることはできますが、今回のように短い時間で電圧が変わっていき、しかも複数のチャネルを同時に見たいような時にはやはり時系列で変化の様子を確認できるオシロスコープが便利です。 今回は LED の点滅も目視で確認できる速さではなかったので、機械で正しく測定するのは大切ですね。