今回は、エンジニアが教える Arduino 入門 から
#7 EEPROM
#8 加速度センサー
#9 光センサー
を Tinkercad でシミュレーションしてみます。ユーザー登録とチュートリアルは、Tinkercad Circuits で Arduino 入門1 をご参照ください。Arduino 日本語リファレンス ( Arduino の命令の説明 ) も随時ご参照ください。
#7 EEPROM ( 動画 ) $\qquad$ Tinkercad によるシミュレーション
Arduino 内蔵の EEPROM ( 不揮発メモリ ) にデータを書き込み、それを読み出してみます。Tinkercad では Arduino の電源を切る操作はできないのと、シミュレーションを停止すると EEPROM のデータもクリアされてしまいます。そこで、Tinkercad による Arduino シミュレーション 39 から引用して、リセットをかけても EEPROM の内容が保持されていることを確認してみます。
シミュレーションを開始すると、
- Add=0 の値をまず読み込み、1秒待ってから、Add=0 に 0 を書き込みます。
- 2回目のループでは Add=1 の値を読み込み、1秒待ってから、Add=1 に 1 を書き込みます。
- 3回目のループでは Add=2 の値を読み込み、1秒待ってから、Add=2 に 1 を書き込みます。
以後、アドレスをインクリメントしながら同じこと繰り返します。下記の実行例では、Add=4 を読み込んで 1 秒待つときに、リセット ( 基板上の赤いボタンをクリック ) をかけています。Add=0~3 には、リセット前に書き込み済の値が読み出されています。( リセットをかけても EEPROM に書き込んだ値は保持される )
リセット時に Add=0 の前にスペースが入ってますが、手元にあった Arduino Uno Rev3 で、同じプログラムを書き込んで実行してみたところ、スペースが入ることはありませんでした。
また、EEPROM の初期値は 0 ではなく、0xFF ( 1111 1111 ) でした。
- EEPROM のライブラリを読み込みます。
- シリアル通信のビットレートを 9600bps に設定します。
- 最初に EEPROM の 0 番地の値 (value ) を読み込みます。
- "Add=0" の後にタブ(行頭から 8 文字目) して、value をパソコンに送信します。
- a をインクリメントして、256 に達したら、0 に戻します。
- 1 秒待ちます。
- 最初に EEPROM の 0 番地に 0 を書き込みます。
- i をインクリメントして、256 に達したら、0 に戻します。
// C++ code
//
#include <EEPROM.h> //EEPROMライブラリのインクルード...1
int a = 0;
int value = 0;
int i = 0;
void setup()
{
Serial.begin(9600); //シリアル通信のビットレートの設定...2
}
void loop()
{
value = EEPROM.read(a); //EEPROMの0番地から読み込み開始...3
Serial.print("Add="); //読み込んだvalueをシリアル出力...4
Serial.print(a);
Serial.print('\t'); //タブ
Serial.print(value);
Serial.println(); //改行
a++;
if (a == 256) a = 0; //aが256になったら、 0に戻す...5
delay(1000); //1秒待つ...6
EEPROM.write(i, i); //EEPROMの0~255番地に0~255を書き込む...7
i++;
if(i == 256) i = 0; // iが256になったら、0に戻す...8
}
#8 加速度センサー ( 動画 ) $\qquad$ Tinkercad によるシミュレーション
- Tinkercad には、加速度センサーがないので、ポテンショメータを使って 1.5~2.5V の電圧を A/Dコンバータ ( A0, A1 ) に入力してみました。
- A/Dコンバータの出力 ( accel_x : 0~5V の電圧に対応する 0~1023 の数値 ) を実際の角度 ( angle_x ) に換算する式は、オフセット ( 0° の時の電圧 ) が 2.5V ( 512 ) なので、
$$\begin{align}
\text{angle_x}&=(\text{accel_x} - 512)(90°/204.8)\\
&=(\text{accel_x}-307.2-204.8)(90°/204.8)\\
&=(\text{accel_x}-307.2)(180°/409.6)-90°
\end{align}$$
右辺の計算は float型でおこなわれますが、angle_x は int 型なので、小数点以下を切り捨てた整数になります。
$\text{volt}$ | $\text{(volt/5 V)}\times1024$ |
---|---|
1.0 V | 204.8 |
1.5 V | 307.2 |
2.0 V | 409.6 |
2.5 V | 512 |
3.5 V | 716.8 |
- ポテンショメータのノブを左一杯にまわすと 1.5V ( -90° )、中央で 2.5V ( 0° )、右一杯で 3.5V ( 90° ) が Arduino の A0、A1 端子に入力されます。
- シリアルモニタを開いた状態で、正弦波形が描かれたボタンをクリックすると、シリアルモニタが分割されてシリアルプロッタが開きます。
- シリアルプロッタは、取得値に応じて自動的に縦軸のスケールが変わるので、90 と -90 の固定値も角度 ( angle_x, angle_y ) と一緒にパソコンに送信しています。
( シリアルプロッタの縦軸を固定する を参照 ) - プログラムでは、X, Y という凡例も送っていますが、Tinkercad のシリアルプロッタには表示されません。
- 加速度センサーのデータシートと傾斜角度の求め方は下記を参照してください。
KXR94-2050モジュール
加速度センサーから傾斜角度を求める
- シリアル通信のビットレート設定 ( 9600 bps ) します。
- X 軸の電圧 ( A0 ) を読み取ります。( 実際は 307~717 )
- Y 軸の電圧 ( A1 ) を読み取ります。( 実際は 307~717 )
- X 軸の読み取り値を角度に換算します。( -90°~90° )
- Y 軸の読み取り値を角度に換算します。( -90°~90° )
- X, Y の凡例をパソコンに送ります。しかし、Tinkercad では対応していないので、表示されません。
- シリアルプロッタの縦軸固定用の 90 を送ります。
- X 軸の角度を送ります。
- Y 軸の角度を送ります。
- シリアルプロッタの縦軸固定用の -90 を送ります。
// C++ code
//
int accel_x, accel_y; //A/Dコンバータの読み取り値
int angle_x, angle_y; //水平方向に対する角度
void setup()
{
Serial.begin(9600); //シリアル通信のビットレート...1
}
void loop()
{
accel_x = analogRead(A0); //X軸の角度の読み取り(0~1023)...2
accel_y = analogRead(A1); //Y軸の角度の読み取り(0~1023)...3
angle_x = (((accel_x - 307.2) / 409.6) * 180) - 90;//読み取り値を角度へ換算...4
angle_y = (((accel_y - 307.2) / 409.6) * 180) - 90;//読み取り値を角度へ換算...5
Serial.print("X"); //凡例を送る。Tinkercadでは、凡例は表示されない...6
Serial.print(",");
Serial.println("Y");
Serial.print(90); //シリアルプロッタの縦軸固定用...7
Serial.print(",");
Serial.print(angle_x);//X軸の角度を送る...8
Serial.print(",");
Serial.print(angle_y);//Y軸の角度を送る...9
Serial.print(",");
Serial.println(-90); //シリアルプロッタの縦軸固定用...10
}
#9 光センサー ( 動画 ) $\qquad$ Tinkercad によるシミュレーション
光センサーの明るさによる抵抗値の変化は以下のとおりでした。下図の接続で、「シミュレーション開始」をクリックして、センサーをクリックすると、センサーの周囲の明るさをスライダで調整できるようになります。スライダの位置によって抵抗値は以下のように変わりました。
スライダの位置 | 抵抗値 |
---|---|
明 | 506 Ω |
中央 | 912 Ω |
暗 | 180 kΩ |
動画では実例が紹介されていなかったので、以下のような機能をもつ回路とプログラムを作成しました。
- 周囲が明るいときには電球 ( 5V 100 mA ) を消灯させ、周囲が暗いときには電球を点灯させる。
- Arduino のポートは、電球を点灯するだけの電流 ( 100 mA ) を供給できないので、リレーを介して電球を ON/OFF する。
- A/Dコンバータで読み取った値 ( 0~1023 ) を map( ) 関数で 0~255 に変換し、シリアルプロッタに表示する。
- 5 ピンを出力に設定します。
- シリアル通信のビットレートを 9600 bps に設定します。
- A0 の電圧 ( value ) を読み取ります。
- value ( 0~1023 ) を 0~255 に変換します。
- 明暗のしきい値を 50 として、明るくなったら ( val < 50 )、電球を消灯します。
- 暗くなったら ( val > 50 )、電球を点灯します。
- シリアルプロッタの縦軸を固定するために、0 と 250 をパソコンに送信します。
- val ( 0~255 ) をパソコンに送信します。
シミュレーション開始後にセンサーをクリックすると、周囲の明るさを調整するスライダーが表示されます。
// C++ code
//
int value, val;
void setup()
{
pinMode(5, OUTPUT); //5ピンを出力端子に設定...1
Serial.begin(9600); //シリアル通信のビットレート設定...2
}
void loop()
{
value = analogRead(A0); //A0の電圧(value)の読み込み(0~1023)...3
val = map(value, 0, 1023, 0, 255); //valueを0~255に変換...4
if(val < 50)
{
digitalWrite(5, HIGH); //明るくなったら電球消灯...5
}
else
{
digitalWrite(5, LOW); //暗くなったら電球点灯...6
}
Serial.print(0); //シリアルプロッタの縦軸固定用(下側)...7
Serial.print(",");
Serial.print(250); //シリアルプロッタの縦軸固定用(上側)
Serial.print(",");
Serial.println(val); //valをパソコンに送信...8
}