M5StickCにはLCDが付いているので、画面上で図形を動かすようなスケッチを作ることができます。
今回は、M5StickCの画面上で、ボールを自由落下させ、地面に着いた時に跳ね返るようなスケッチを作ってみます。
ひとつひとつのステップごとに、動作確認をしながら、進めていきます。
ボールを自由落下させる
まず最初に、ボールを自由落下させてみます。
F = mg の式で重力を求め、そこからボールの加速度「a」、ボールの速度「v」、ボールの移動距離「x」を求めていきます(画面のサイズが小さいので、それにあわせて数値を補正しています)。
その結果に基づいて、ボール(円)を描画します。
これを一定間隔で繰り返します。
スケッチは以下のとおりです。
#include <M5StickC.h>
float t = 0.0f; // 画面の上端座標
float g = 9.8f; // 重力加速度
float m = 1.0f; // ボールの質量
float r = 10.0f; // ボールの半径
float x = t+r; // ボールの位置(中心座標)
float v = 0.0f; // ボールの速度
void setup() {
M5.begin();
M5.Lcd.setRotation(1);
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
x = r;
v = 0.0;
}
float f = m * g;
float a = f / m / 10;
v += a;
x += v;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW);
delay(20);
}
結果は以下のとおりです。ボタンAを押すと、ボールが落ちます。
ボールをバウンドさせる
上記のスケッチでは、ボールは落ちていくだけなので、ここでは、ボールが地面に到達したときに、バウンドさせてみます。
ボールが地面に沈み込んだ時に、F = kx の式で、弾性力を考慮します。
スケッチは以下のとおりです。
#include <M5StickC.h>
float t = 0.0f; // 画面の上端座標
float b = 160.0f; // 画面の下端座標
float g = 9.8f; // 重力加速度
float m = 1.0f; // ボールの質量
float r = 10.0f; // ボールの半径
float k = 20.0f; // バネ定数
float x = t+r; // ボールの位置(中心座標)
float v = 0.0f; // ボールの速度
void setup() {
M5.begin();
M5.Lcd.setRotation(1);
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
x = r;
v = 0.0;
}
float f = m * g;
if(x+r > b) {
float f2 = k * ((x+r)-b);
f = f - f2;
}
float a = f / m / 10;
v += a;
x += v;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW);
delay(20);
}
結果は以下のとおりで、ボールが地面に到達すると、跳ね返るようになりました。
ただし、ボールの勢いは減衰せず、永遠にバウンドを繰り返します。
ボールのバウンドを減衰させる
上記では、ボールが永遠にバウンドし続けるので、これを減衰させ、最終的には止まるようにしてみます。
弾性力を考慮する時に、同時に F = cv の式で、粘性抵抗も考慮します。
スケッチは以下のとおりです。
#include <M5StickC.h>
float t = 0.0f; // 画面の上端座標
float b = 160.0f; // 画面の下端座標
float g = 9.8f; // 重力加速度
float m = 1.0f; // ボールの質量
float r = 10.0f; // ボールの半径
float k = 20.0f; // バネ定数
float c = 2.0f; // 粘性係数
float x = t+r; // ボールの位置(中心座標)
float v = 0.0f; // ボールの速度
void setup() {
M5.begin();
M5.Lcd.setRotation(1);
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
x = r;
v = 0.0;
}
float f = m * g;
if(x+r > b) {
float f2 = k * ((x+r)-b);
float f3 = c * v;
f = f - f2 - f3;
}
float a = f / m / 10;
v += a;
x += v;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW);
delay(20);
}
結果は以下のとおりです。ボールが地面に到達すると跳ね返りますが、跳ね返るごとに高さが低くなり、最終的には止まるようになりました。
それほど難しい処理はしていませんが、視覚的にも結構おもしろいスケッチを作ることができました。
このような処理を組み合わせることで、より複雑な描画もできそうです。
なお、私がM5Stack、M5StickCの使い方を習得するのにあたっては、以下の書籍を参考にさせていただきました。
ごく基本的なところから、かなり複雑なスケッチや、ネットワーク接続など、比較的高度なものまで、つまづかずに読み進めていけるような構成になっており、大変わかりやすい本です。