SPRESENSEのマルチコアでLEDを制御してみた [SPRESENSE]
前回はスレッドでLEDを制御しましたが、今回は同じ内容をマルチコアでやってみたいと思います。まさに、プチ”並列コンピューティング”ですね。マルチコアにする場合は、複数のArduino IDEを立ち上げて作業します。
それぞれのスケッチを紹介します。まず、MainCore用のスケッチから。SpresenseでMPを使うには、MPライブラリというものを使います。書き込むときにメインかサブか間違わないように、SUBCORE定義を使って書き込みエラーを回避しています。
次に、サブコア側のスケッチです。こちらもメインと同様に書き込みを間違えないようにする工夫を入れています。このスケッチを、そのままサブコア1~サブコア4に書き込みます。(LEDは4つあるので)
サブコア側は、メッセージ出力にSerialライブラリを使わずに、MPLog を使います。ハードウェアの競合を避けるための仕組みだと思います。
メインのスケッチの書き込み時は、Arduino IDE の”Core”の指定を”MainCore”に指定します。
サブのスケッチの書き込み時は、"Core"の指定を”SubCore”に指定してください。
ところで、同じ Arduino IDE プロセス内で、メインとサブのスケッチを開いてしまうと(”File”の”New”とか”Open”を使って開いた場合)、”Core”の指定が連動してしまうのでやっかいです。例えば”メイン書き込み時にMainCore”に指定すると、サブのスケッチも”MainCore”になってしまいます。
これを回避するには、作ったスケッチを一旦保存してファイルをクリックして開いてください。Arduino IDEがそれぞれ別プロセスで起動するので、コア指定の連動がなくなります。ちょっと便利な技です。
動いている姿は地味なので動画にしてません。静止画でどうぞー。(って、使いまわしですが)^^;
しかし、こんなに簡単に並列コンピューティングが試せるなんてすごい世の中になったものです。私が学生の頃は、大学の研究室にあるような代物でしたけど。並列コンピューティングを学習したい人はぜひ試してみてください!
それぞれのスケッチを紹介します。まず、MainCore用のスケッチから。SpresenseでMPを使うには、MPライブラリというものを使います。書き込むときにメインかサブか間違わないように、SUBCORE定義を使って書き込みエラーを回避しています。
#include <MP.h> #ifdef SUBCORE #error "You must select MainCore" #endif #define START 100 #define STOP 99 #define MAXLOOP 60 static int gMainLoop = 0; void setup() { Serial.begin(115200); int8_t sndid = START; for (int subcore = 1; subcore <= 4; ++subcore) { MP.begin(subcore); } static uint16_t param[4][3]; /* need specify "static" to fix the address */ param[0][0] = 0; /* LED number */ param[0][1] = 100; /* LED HIGH duration in msec */ param[0][2] = 200; /* LED LOW duration in msec */ MP.Send(sndid, &param[0], 1); /* SubCore 1 */ delay(100); param[1][0] = 1; /* LED number */ param[1][1] = 200; /* LED HIGH duration in msec */ param[1][2] = 200; /* LED LOW duration in msec */ MP.Send(sndid, &param[1], 2); /* SubCore 2 */ delay(100); param[2][0] = 2; /* LED number */ param[2][1] = 500; /* LED HIGH duration in msec */ param[2][2] = 100; /* LED LOW duration in msec */ MP.Send(sndid, &param[2], 3); /* SubCore 3 */ delay(100); param[3][0] = 3; /* LED number */ param[3][1] = 100; /* LED HIGH duration in msec */ param[3][2] = 500; /* LED LOW duration in msec */ MP.Send(sndid, &param[3], 4); /* SubCore 4 */ delay(100); } void loop() { ++gMainLoop; Serial.println("MainLoop: " + String(gMainLoop)); sleep(1); if (gMainLoop >= MAXLOOP) { int8_t sndid = STOP; uint32_t dummy = 0; for (int subcore = 1; subcore <= 4; ++subcore) { MP.Send(sndid, dummy, subcore); delay(100); } Serial.println("Stop all process on subcores"); while(1); } }
次に、サブコア側のスケッチです。こちらもメインと同様に書き込みを間違えないようにする工夫を入れています。このスケッチを、そのままサブコア1~サブコア4に書き込みます。(LEDは4つあるので)
サブコア側は、メッセージ出力にSerialライブラリを使わずに、MPLog を使います。ハードウェアの競合を避けるための仕組みだと思います。
#include <MP.h> #ifndef SUBCORE #error "You must select SubCore" #endif #define START 100 #define STOP 99 int pin_num = 0; int durationH; int durationL; void setup() { int8_t rcvid; uint16_t *param; int led; MP.begin(); MP.RecvTimeout(MP_RECV_BLOCKING); int ret = MP.Recv(&rcvid, ¶m); if (rcvid != START) { MPLog("Unknown msdid: process halt\n"); while(1); } led = param[0]; durationH = param[1]; durationL = param[2]; MPLog("========================================\n"); MPLog("SubCore %d\n", SUBCORE); MPLog("LED%d blink interval\n", led); MPLog("High duration: %03d msec\n", durationH); MPLog("Low duration: %03d msec\n", durationL); MPLog("========================================\n\n"); if (led > 3 || led < 0) { MPLog("Error: number of LED is %d", led); while(1); } switch(led) { case 0: pin_num = LED0; break; case 1: pin_num = LED1; break; case 2: pin_num = LED2; break; case 3: pin_num = LED3; } pinMode(pin_num, OUTPUT); MP.RecvTimeout(MP_RECV_POLLING); } void loop() { int8_t rcvid; uint32_t dummy; MP.Recv(&rcvid, &dummy); if (rcvid == STOP) { MPLog("SubCore %d is stopped\n", SUBCORE); while(1); } digitalWrite(pin_num, HIGH); delay(durationH); digitalWrite(pin_num, LOW); delay(durationL); // msec to usec /* You can use "delay(msec)" because * * the process is running on a different cpu */ }
メインのスケッチの書き込み時は、Arduino IDE の”Core”の指定を”MainCore”に指定します。
サブのスケッチの書き込み時は、"Core"の指定を”SubCore”に指定してください。
ところで、同じ Arduino IDE プロセス内で、メインとサブのスケッチを開いてしまうと(”File”の”New”とか”Open”を使って開いた場合)、”Core”の指定が連動してしまうのでやっかいです。例えば”メイン書き込み時にMainCore”に指定すると、サブのスケッチも”MainCore”になってしまいます。
これを回避するには、作ったスケッチを一旦保存してファイルをクリックして開いてください。Arduino IDEがそれぞれ別プロセスで起動するので、コア指定の連動がなくなります。ちょっと便利な技です。
動いている姿は地味なので動画にしてません。静止画でどうぞー。(って、使いまわしですが)^^;
しかし、こんなに簡単に並列コンピューティングが試せるなんてすごい世の中になったものです。私が学生の頃は、大学の研究室にあるような代物でしたけど。並列コンピューティングを学習したい人はぜひ試してみてください!
コメント 0