昨日、ふとiPhoneでメールを確認していると、去年度末にYouTubeにアップしたPixyの動画にコメントがついたよ、とメールが・・・
そのままコメントで返すとわかりづらそうな内容だったので記事にしました。
※ 前相方の「コメント返し」をパクったわけではありません。

コメントをいただいた動画はこの動画です。
コメントの内容は「部活でPixyを使っているが、Pixy公式ライブラリにあるサンプルプログラム「hello_world」のシリアル出力が何を表してるのかわからないから教えて欲しい」とのことでした。
さて、そのプログラムがこちらです。
上記のプログラムでは
1つ目の引数(上記ではbuf)が、文字列を書き込む先の配列、2つ目の引数がひとつ目の引数で指定した変数に書き込む内容になっています。
上記の例では、配列bufに「"Detected %d:\n", blocks」を書き込めという内容になります。
続いて「"Detected %d:\n", blocks」が示す内容ですが、
「Detected」に続いて変数blockの中身を連結し、最後に「:」と改行コードを連結
という内容になります。
引数内にある「%d」は、このあとの,(カンマ)後で指定する変数を整数値で表示を意味します。
したがって、仮に変数block内に数値「1」が入っていたとすれば、「"Detected %d:\n", blocks」で
Detected 1:\n(\nは改行コード)
が生成され、上記の例では配列bufにこの文字列が代入されることとなります。
今回取り上げているプログラムでは、これらのsprintfの直下に

実際の出力画面で言うところの、この垢枠の部分です。
これはPixyライブラリの関数で、ざっくり言えばPixyから受け取ったデータを出力する関数です。

この部分ですね。
blocks[j]は、Pixyは認識したオブジェクト(ブロック)の中で何番のブロックの情報を出すかを指定します。
jで指定している値がオブジェクトの番号で、番号は0から始まって認識した数から1引いた数だけ指定できます。
いくつのオブジェクトを認識したかは、
認識させるオブジェクトの最大個数は、Pixymonから設定できます。

これが示す情報の内容ですが、
Arduinoでこの情報を単体で取得するための関数もあります。
その辺は前の記事を参考にしてください。
私はどこかでプログラミングについてどこかで教えてもらったわけではなく、こういうライブラリからひとりで勉強してほぼひとりプログラムを書いているので、この記事で使っている用語とかの用法が間違っているかもしれません。
用語を使って話を進めないからです。
悪しからず・・・
そのままコメントで返すとわかりづらそうな内容だったので記事にしました。
※ 前相方の「コメント返し」をパクったわけではありません。

コメントをいただいた動画はこの動画です。
コメントの内容は「部活でPixyを使っているが、Pixy公式ライブラリにあるサンプルプログラム「hello_world」のシリアル出力が何を表してるのかわからないから教えて欲しい」とのことでした。
さて、そのプログラムがこちらです。
// // begin license header // // This file is part of Pixy CMUcam5 or "Pixy" for short // // All Pixy source code is provided under the terms of the // GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html). // Those wishing to use Pixy source code, software and/or // technologies under different licensing terms should contact us at // cmucam@cs.cmu.edu. Such licensing terms are available for // all portions of the Pixy codebase presented here. // // end license header // // This sketch is a good place to start if you're just getting started with // Pixy and Arduino. This program simply prints the detected object blocks // (including color codes) through the serial console. It uses the Arduino's // ICSP port. For more information go here: // // http://cmucam.org/projects/cmucam5/wiki/Hooking_up_Pixy_to_a_Microcontroller_(like_an_Arduino) // // It prints the detected blocks once per second because printing all of the // blocks for all 50 frames per second would overwhelm the Arduino's serial port. // #include <SPI.h> #include <Pixy.h> // This is the main Pixy object Pixy pixy; void setup() { Serial.begin(9600); Serial.print("Starting...\n"); pixy.init(); } void loop() { static int i = 0; int j; uint16_t blocks; char buf[32]; // grab blocks! blocks = pixy.getBlocks(); // If there are detect blocks, print them! if (blocks) { i++; // do this (print) every 50 frames because printing every // frame would bog down the Arduino if (i%50==0) { sprintf(buf, "Detected %d:\n", blocks); Serial.print(buf); for (j=0; j<blocks; j++) { sprintf(buf, " block %d: ", j); Serial.print(buf); pixy.blocks[j].print(); } } } }問題の部分は59行目〜65行目(「sprintf」〜「pixy.blocks[j].print();」)にかけての部分だと思われますので、この部分を少し解説しようと思います。
sprintf
これはC言語の関数で、指定した配列に指定した書式で文字列を書き込むための関数です。上記のプログラムでは
sprintf(buf, "Detected %d:\n", blocks);などのように使用されています。
1つ目の引数(上記ではbuf)が、文字列を書き込む先の配列、2つ目の引数がひとつ目の引数で指定した変数に書き込む内容になっています。
上記の例では、配列bufに「"Detected %d:\n", blocks」を書き込めという内容になります。
続いて「"Detected %d:\n", blocks」が示す内容ですが、
「Detected」に続いて変数blockの中身を連結し、最後に「:」と改行コードを連結
という内容になります。
引数内にある「%d」は、このあとの,(カンマ)後で指定する変数を整数値で表示を意味します。
したがって、仮に変数block内に数値「1」が入っていたとすれば、「"Detected %d:\n", blocks」で
Detected 1:\n(\nは改行コード)
が生成され、上記の例では配列bufにこの文字列が代入されることとなります。
今回取り上げているプログラムでは、これらのsprintfの直下に
Serial.print(buf);があるので、sprintfで生成した文字列をシリアルモニタに出力していることになります。

実際の出力画面で言うところの、この垢枠の部分です。
pixy.blocks[j].print()
おそらくコメントをくださった方は、これが一番謎なんだと思います。これはPixyライブラリの関数で、ざっくり言えばPixyから受け取ったデータを出力する関数です。

この部分ですね。
pixy.blocks[j].print();最初のpixyは、Pixyライブラリのクラスのインスタンス名で、プログラムの最初の方(30行目)で生成してあります。
Pixy pixy;これですね。
blocks[j]は、Pixyは認識したオブジェクト(ブロック)の中で何番のブロックの情報を出すかを指定します。
jで指定している値がオブジェクトの番号で、番号は0から始まって認識した数から1引いた数だけ指定できます。
いくつのオブジェクトを認識したかは、
pixy.getBlocks()の返り値で得ることができます。
認識させるオブジェクトの最大個数は、Pixymonから設定できます。
シリアルモニタで得られる情報について

これが示す情報の内容ですが、
- Detected n+1: ・・・オブジェクトをn個検出したよ。(n+1はPixyが認識したオブジェクトの数)
- block n: ・・・ここから右の情報はn個目のオブジェクトの情報だよ。(nはPixyが認識したオブジェクトの番号)
- sig: X ・・・このオブジェクトのシグネチャーはXだよ。(Xはシグネチャーの番号)
- x: XXX ・・・このオブジェクトのx(横)方向の座標はXXXだよ。(XXXは座標の値)
- y: XXX ・・・このオブジェクトのy(縦)方向の座標はXXXだよ。(XXXは座標の値)
- width: XXX ・・・このオブジェクトの幅はXXX pxだよ。(XXXはピクセル数)
- height: XXX ・・・このオブジェクトの高さはXXX pxだよ。(XXXはピクセル数)
Arduinoでこの情報を単体で取得するための関数もあります。
その辺は前の記事を参考にしてください。
さいごに
おそらく、このPixy用Arduinoライブラリを書いた人は、プログラマとしてはなかなかな腕の人でしょう。私はどこかでプログラミングについてどこかで教えてもらったわけではなく、こういうライブラリからひとりで勉強してほぼひとりプログラムを書いているので、この記事で使っている用語とかの用法が間違っているかもしれません。
用語を使って話を進めないからです。
悪しからず・・・