まずはCoreInkの開発環境を整えよう
CoreInk以外の連携の可能性が考えられるので、UIFlow以外の選択肢をとる
ArduinoIDEの場合
久しぶりの起動なので、まずはアップデートが必要そう。
ということで最新版です。
M5StackCoreInk クイックスタートガイドを用意する
https://docs.m5stack.com/en/arduino/arduino_ide
日本語表記も選択できるのでひとあんしん。
ボード管理
リンク押下でページ遷移。
下の図のように、URLをコピーします。
ArduinoIDEで「基本設定」をクリックします。
下の図のように、「追加のボードマネージャのURL」にある右端のアイコンをクリックします。
下の図のようにペーストします。すでにURLがある場合は、改行します。
基本設定から出て、左のサイドバーからボードマネージャをクリックして、下の図のように「m5」などで検索します。M5Stackの項目が出るので、インストールします。
インストール完了。
下の図のように、「ツール」→「ボード」→「M5Stack」を選択します。今回はCoreInkの開発なので、「M5Core」を選択します。
ライブラリ管理
つづいてライブラリ。
下の図のように、サイドバーからライブラリマネージャーをクリックして、「m5core」で検索します。一覧の中から「M5Core-Ink」をインストールします。
依存関係があるものは全てインストールします。
サンプル
サンプルを起動してみます。
下の図のように、「ファイル」→「スケッチ例」→「M5StackCore-Ink」の中からサンプルを選択します。
今回は、「Basics」→「Button」にします。
下の図のように、新しくスケッチが表示されました。
コンパイル
引き続き、サンプルプログラムを使います。
ドライバのインストール
よくわからないので、今回はドキュメントのとおり、下の図のように2種類インストールしました。
書き込み
「ボード」と「ポート」が適切な情報にします。うのっちの環境では、COM6にCoreInkを接続しているので、COM6になっています。
また、UIFlowなど別ツールですでに接続していると、コンパイルエラーが出るので気をつけましょう。(出た)
動かしてみた
「ArduinoからM5StackCoreInkをサンプル起動させてみた」
https://youtube.com/shorts/XJJ-F9IE9-Y
toioのArduino開発環境を整えよう
M5StackToioのサイトを開いておく
https://github.com/futomi/M5StackToio
M5StackToioのダウンロード~インポート
zipファイルでダウンロードする。
下の図のように インストールする。zipファイルは展開しなくてもよい。
ライブラリを追加。
ArduinoIDEの再起動
たぶんこのタイミングで再起動したほうがいいかも。M5StackToioのアップデートがかかりました。
toioコアキューブのアップデート
コンソールおよびコアキューブは2024年にアップデートがありました。
サンプルスケッチで動かす
CoreInkのサンプルスケッチ「HelloWorld」をベースに、M5StackToioのサンプルコードを加えました。
下はスクリプトになります。
*******************************************************************************
* Copyright (c) 2021 by M5Stack
* Equipped with CoreInk sample source code
* 配套 CoreInk 示例源代码
* Visit for more information: https://docs.m5stack.com/en/core/coreink
* 获取更多资料请访问:https://docs.m5stack.com/zh_CN/core/coreink
*
* Describe: Hello World
* Date: 2021/11/14
*******************************************************************************
*/
#include "M5CoreInk.h"
#include <Toio.h>
// Toio オブジェクト生成
Toio toio;
// ToioCore オブジェクトのポインタ
ToioCore* toiocore = nullptr;
// BLE 接続・切断のタイムスタンプ
unsigned long conn_time = millis();
Ink_Sprite InkPageSprite(&M5.M5Ink); //创建 M5Ink实例
/* After CoreInk is started or reset
the program in the setUp () function will be run, and this part will only be
run once. 在 CoreInk
启动或者复位后,即会开始执行setup()函数中的程序,该部分只会执行一次。 */
void setup() {
M5.begin(); // Initialize CoreInk. 初始化 CoreInk
if (!M5.M5Ink.isInit()) { // check if the initialization is successful.
// 检查初始化是否成功
Serial.printf("Ink Init faild");
while (1) delay(100);
}
M5.M5Ink.clear(); // clear the screen. 清屏
delay(1000);
// creat ink Sprite. 创建图像区域
if (InkPageSprite.creatSprite(0, 0, 200, 200, true) != 0) {
Serial.printf("Ink Sprite creat faild");
}
InkPageSprite.drawString(35, 50, "Hello World!"); // draw string.
// 绘制字符串
InkPageSprite.pushSprite(); // push the sprite. 推送图片
// toio コア キューブのスキャン開始
std::vector<ToioCore*> toiocore_list = toio.scan(3);
if (toiocore_list.size() > 0) {
toiocore = toiocore_list.at(0);
}
// BLE 接続状態イベントのコールバックをセット
toiocore->onConnection([](bool state) {
Serial.println(state ? "接続" : "切断");
});
}
void loop() {
// コールバックを使う場合には必ず Toio オブジェクトの loop() を呼び出す
toio.loop();
if (toiocore) {
// 10 秒おきに BLE 接続・切断を繰り返す
unsigned long now = millis();
if (now - conn_time >= 10000) {
if (toiocore->isConnected()) {
toiocore->disconnect();
} else {
toiocore->connect();
}
conn_time = now;
}
}
}
プロトタイプをつくってみよう
7/21時点
setupメソッドでtoioのサンプルスクリプトが起動。loopメソッドでcoreinkのボタン判定。loop内でtoioの機能を使うと切断されるので、たぶん書き方がまずい気がする。(toio.loop();
は入れている)
7/22
CoreInkを頑丈にしました。
コアキューブにも手を加えました。(デコっているだけ)
動きました!!
https://youtube.com/shorts/WnDf-RaaKSg?feature=share
この日のスクリプト
/* ----------------------------------------------------------------
Toio Core Cube が発見された後、M5Stack の A ボタンを押すと Toio Core
Cube と BLE 接続します。接続が完了すると、ジョイスティックで Toio Core
Cute を運転することができます。
BLE 接続中、ジョイスティックの z 軸を押すと、チャルメロが再生されます。
また、M5Stack の B ボタンを押すと、Toio Core Cube の LED が白で点灯し
ます。
-------------------------------------------------------------- */
#include "M5CoreInk.h"
#include <Toio.h>
Ink_Sprite InkPageSprite(&M5.M5Ink);
// ライト ON/OFF 状態
static bool light_on = false;
// MIDI データ (チャルメラ)
static const uint8_t CHARUMERA_LEN = 39;
static uint8_t CHARUMERA_DATA[CHARUMERA_LEN] = {
3, // Type of Sound control (MIDI)
1, // Repeat count
12, // Number of operations
14, 69, 255, // 140ms, A5
14, 71, 255, // 140ms, B5
56, 73, 255, // 560ms, C#6
14, 71, 255, // 140ms, B5
14, 69, 255, // 140ms, A5
114, 128, 255, // no sound
14, 69, 255, // 140ms, A5
14, 71, 255, // 140ms, B5
14, 73, 255, // 560ms, C#6
14, 71, 255, // 140ms, B5
14, 69, 255, // 140ms, A5
56, 71, 255 // 560ms, B5
};
// Toio オブジェクト生成
Toio toio;
// 発見された ToioCore オブジェクトのポインタ変数を定義
ToioCore* toiocore = nullptr;
void ButtonTest(char* str) {
InkPageSprite.clear(); // clear the screen. 清屏
InkPageSprite.drawString(35, 59, str); // draw the string. 绘制字符串
InkPageSprite.pushSprite(); // push the sprite. 推送图片
delay(2000);
}
void setup() {
//coreinkの初期化ここから
M5.begin();
if (!M5.M5Ink.isInit()) {
Serial.printf("Ink Init faild");
while (1) delay(100);
}
M5.M5Ink.clear();
delay(1000);
if (InkPageSprite.creatSprite(0, 0, 200, 200, true) != 0) {
Serial.printf("Ink Sprite create faild");
}
InkPageSprite.drawString(5, 20, "Hello toio");
//coreinkの初期化ここまで
ButtonTest("HelloCoreInk");
// 3 秒間 Toio Core Cube をスキャン
std::vector<ToioCore*> toiocore_list = toio.scan(3);
// 最初に見つかった Toio Core Cube の ToioCore オブジェクト
toiocore = toiocore_list.at(0);
// toiocore->onConnection([](bool state) {
// InkPageSprite.drawString(5, 20, "Hello Core-INK toio");
// });
ButtonTest("toio OK");
Serial.printf("toio OK");
delay(1000);
M5.M5Ink.clear(); // Clear the screen.
}
void loop() {
// イベントを扱う場合は、必ずここで Toio オブジェクトの
// loop() メソッドを呼び出すこと
toio.loop();
// Toio core Cube が見つかっていなければ loop () を抜ける
if (!toiocore) {
M5.M5Ink.clear(); // Clear the screen.
delay(1000);
ButtonTest("toio lost");
Serial.printf("toio lost");
return;
}
if (M5.BtnUP.wasPressed())
{
ButtonTest("Btn UP Pressed");
Serial.printf("Btn UP Pressed");
// Toio Core Cube と BLE 接続中かどうかをチェック
if (toiocore->isConnected()) {
// toiocore->disconnect(); // 接続中なら切断
} else {
toiocore->connect(); // 切断中なら接続
}
// return;
}
// // Toio core Cube が未接続なら loop () を抜ける
// if (!toiocore->isConnected()) {
// return;
// }
// if (M5.BtnUP.wasPressed())
// {
// ButtonTest("Btn UP Pressed"); // Scroll wheel up.
// Serial.printf("Btn UP Pressed");
// }
if (M5.BtnMID.wasPressed())
{
ButtonTest("Btn MID Pressed");
Serial.printf("Btn MID Pressed");
if (light_on) {
toiocore->turnOffLed(); // 点灯中なら消灯
toiocore->controlMotor(true, 40, false, 40, 4500);
} else {
// 2 秒間だけ右に曲がりながら進む (左右のモーターを個別に制御)
toiocore->controlMotor(true, 40, false, 40, 4500);
delay(5000);
toiocore->turnOnLed(255, 0, 0); // 消灯中なら赤で点灯
}
light_on = !light_on;
}
if (M5.BtnDOWN.wasPressed())
{
ButtonTest("Btn DOWN Pressed");
Serial.printf("Btn DOWN Pressed");
toiocore->playSoundRaw(CHARUMERA_DATA, CHARUMERA_LEN);
}
if (M5.BtnPWR.wasPressed()) { // Right button press.
ButtonTest("Btn PWR Pressed");
Serial.printf("Btn PWR Pressed");
M5.shutdown(); // Turn off the power, restart it, you need to wake up
// through the PWR button.
}
// // スロットル
// int8_t throttle = jy;
// if (throttle > 100) {
// throttle = 100;
// }
// if (throttle < -100) {
// throttle = -100;
// }
// // 最大速度が速すぎて操作しづらいので値を 2/3 にする
// throttle = (float)throttle * 2 / 3;
// // ステアリング
// int8_t steering = (abs(jx) < 10) ? 0 : jx; // 10 ほど遊びを入れる
// if (steering > 100) {
// steering = 100;
// }
// if (steering < -100) {
// steering = -100;
// }
// // 左右の動きの反応が敏感すぎるので値を 2/3 にする
// steering = (float)steering * 2 / 3;
// toiocore->drive(throttle, steering);
M5.update();
}
7/31 完成しよう
構成図
スクリプト
/* ----------------------------------------------------------------
Toio Core Cube が発見された後、M5Stack の A ボタンを押すと Toio Core
Cube と BLE 接続します。接続が完了すると、ジョイスティックで Toio Core
Cute を運転することができます。
BLE 接続中、ジョイスティックの z 軸を押すと、チャルメロが再生されます。
また、M5Stack の B ボタンを押すと、Toio Core Cube の LED が白で点灯し
ます。
-------------------------------------------------------------- */
#include "M5CoreInk.h"
#include <Toio.h>
Ink_Sprite InkPageSprite(&M5.M5Ink);
// ライト ON/OFF 状態
static bool light_on = false;
// MIDI データ (チャルメラ)
static const uint8_t CHARUMERA_LEN = 39;
static uint8_t CHARUMERA_DATA[CHARUMERA_LEN] = {
3, // Type of Sound control (MIDI)
1, // Repeat count
12, // Number of operations
14, 69, 255, // 140ms, A5
14, 71, 255, // 140ms, B5
56, 73, 255, // 560ms, C#6
14, 71, 255, // 140ms, B5
14, 69, 255, // 140ms, A5
114, 128, 255, // no sound
14, 69, 255, // 140ms, A5
14, 71, 255, // 140ms, B5
14, 73, 255, // 560ms, C#6
14, 71, 255, // 140ms, B5
14, 69, 255, // 140ms, A5
56, 71, 255 // 560ms, B5
};
// Toio オブジェクト生成
Toio toio;
// 発見された ToioCore オブジェクトのポインタ変数を定義
ToioCore* toiocore = nullptr;
void ButtonTest(char* str) {
InkPageSprite.clear(); // clear the screen. 清屏
InkPageSprite.drawString(35, 59, str); // draw the string. 绘制字符串
InkPageSprite.pushSprite(); // push the sprite. 推送图片
delay(2000);
}
void setup() {
//coreinkの初期化ここから
M5.begin();
if (!M5.M5Ink.isInit()) {
Serial.printf("Ink Init faild");
while (1) delay(100);
}
M5.M5Ink.clear();
delay(1000);
if (InkPageSprite.creatSprite(0, 0, 200, 200, true) != 0) {
Serial.printf("Ink Sprite create faild");
}
InkPageSprite.drawString(5, 20, "Hello toio");
//coreinkの初期化ここまで
ButtonTest("HelloCoreInk");
// 3 秒間 Toio Core Cube をスキャン
std::vector<ToioCore*> toiocore_list = toio.scan(3);
// 最初に見つかった Toio Core Cube の ToioCore オブジェクト
toiocore = toiocore_list.at(0);
// toiocore->onConnection([](bool state) {
// InkPageSprite.drawString(5, 20, "Hello Core-INK toio");
// });
ButtonTest("toio OK");
Serial.printf("toio OK");
delay(1000);
M5.M5Ink.clear(); // Clear the screen.
}
void loop() {
// イベントを扱う場合は、必ずここで Toio オブジェクトの
// loop() メソッドを呼び出すこと
toio.loop();
// Toio core Cube が見つかっていなければ loop () を抜ける
if (!toiocore) {
M5.M5Ink.clear(); // Clear the screen.
delay(1000);
ButtonTest("toio lost");
Serial.printf("toio lost");
return;
}
if (M5.BtnUP.wasPressed())
{
ButtonTest("Btn UP Pressed");
Serial.printf("Btn UP Pressed");
// Toio Core Cube と BLE 接続中かどうかをチェック
if (toiocore->isConnected()) {
// toiocore->disconnect(); // 接続中なら切断
} else {
toiocore->connect(); // 切断中なら接続
toiocore->playSoundRaw(CHARUMERA_DATA, CHARUMERA_LEN);
}
// return;
}
// // Toio core Cube が未接続なら loop () を抜ける
// if (!toiocore->isConnected()) {
// return;
// }
// if (M5.BtnUP.wasPressed())
// {
// ButtonTest("Btn UP Pressed"); // Scroll wheel up.
// Serial.printf("Btn UP Pressed");
// }
if (M5.BtnMID.wasPressed())
{
ButtonTest("Btn MID Pressed");
Serial.printf("Btn MID Pressed");
if (light_on) {
toiocore->turnOffLed(); // 点灯中なら消灯
toiocore->controlMotor(false, 10, false, 10, 1000);
delay(1000);
toiocore->controlMotor(false, 20, false, 20, 1000);
delay(1000);
toiocore->controlMotor(false, 30, false, 30, 1000);
delay(1000);
toiocore->controlMotor(false, 40, false, 40, 1000);
delay(1000);
toiocore->controlMotor(false, 50, false, 50, 1000);
delay(1000);
toiocore->controlMotor(false, 60, false, 60, 1000);
delay(1000);
toiocore->controlMotor(false, 70, false, 70, 1000);
delay(1000);
toiocore->controlMotor(false, 80, false, 80, 1000);
delay(1000);
toiocore->controlMotor(false, 90, false, 90, 1000);
delay(1000);
toiocore->controlMotor(false, 100, false, 100, 1000);
delay(1000);
toiocore->controlMotor(false, 10, false, 100, 1000);
delay(1000);
toiocore->controlMotor(false, 100, false, 100, 1000);
delay(1000);
toiocore->controlMotor(false, 10, false, 100, 1000);
delay(1000);
toiocore->controlMotor(false, 100, false, 100, 1000);
delay(1000);
toiocore->controlMotor(false, 100, true, 100, 4500);
delay(3000);
toiocore->controlMotor(true, 100, false, 100, 4500);
} else {
// 2 秒間だけ右に曲がりながら進む (左右のモーターを個別に制御)
toiocore->turnOnLed(255, 0, 0); // 消灯中なら赤で点灯
toiocore->controlMotor(true, 10, true, 10, 1000);
delay(1000);
toiocore->controlMotor(true, 20, true, 20, 1000);
delay(1000);
toiocore->controlMotor(true, 30, true, 30, 1000);
delay(1000);
toiocore->controlMotor(true, 40, true, 40, 1000);
delay(1000);
toiocore->controlMotor(true, 50, true, 50, 1000);
delay(1000);
toiocore->controlMotor(true, 60, true, 60, 1000);
delay(1000);
toiocore->controlMotor(true, 70, true, 70, 1000);
delay(1000);
toiocore->controlMotor(true, 80, true, 80, 1000);
delay(1000);
toiocore->controlMotor(true, 90, true, 90, 1000);
delay(1000);
toiocore->controlMotor(true, 100, true, 100, 1000);
delay(1000);
toiocore->controlMotor(true, 100, true, 10, 1000);
delay(1000);
toiocore->controlMotor(true, 100, true, 100, 1000);
delay(1000);
toiocore->controlMotor(true, 100, true, 10, 1000);
delay(1000);
toiocore->controlMotor(true, 100, true, 100, 1000);
delay(1000);
}
light_on = !light_on;
}
if (M5.BtnDOWN.wasPressed())
{
ButtonTest("Btn DOWN Pressed");
Serial.printf("Btn DOWN Pressed");
if (light_on) {
toiocore->controlMotor(false, 100, false, 100, 500);
delay(500);
toiocore->controlMotor(true, 100, true, 5, 1000);
} else {
// 2 秒間だけ右に曲がりながら進む (左右のモーターを個別に制御)
toiocore->controlMotor(true, 100, true, 100, 500);
delay(500);
toiocore->controlMotor(false, 5, false, 100, 1000);
}
light_on = !light_on;
}
if (M5.BtnPWR.wasPressed()) { // Right button press.
ButtonTest("Btn PWR Pressed");
Serial.printf("Btn PWR Pressed");
delay(3000);
M5.shutdown(); // Turn off the power, restart it, you need to wake up
// through the PWR button.
}
// // スロットル
// int8_t throttle = jy;
// if (throttle > 100) {
// throttle = 100;
// }
// if (throttle < -100) {
// throttle = -100;
// }
// // 最大速度が速すぎて操作しづらいので値を 2/3 にする
// throttle = (float)throttle * 2 / 3;
// // ステアリング
// int8_t steering = (abs(jx) < 10) ? 0 : jx; // 10 ほど遊びを入れる
// if (steering > 100) {
// steering = 100;
// }
// if (steering < -100) {
// steering = -100;
// }
// // 左右の動きの反応が敏感すぎるので値を 2/3 にする
// steering = (float)steering * 2 / 3;
// toiocore->drive(throttle, steering);
M5.update();
}