差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン 次のリビジョン両方とも次のリビジョン | ||
p5js:13.grove_beginner_kit [2022/06/28 06:52] – baba | p5js:13.grove_beginner_kit [2022/07/05 00:56] – [加速度センサ] baba | ||
---|---|---|---|
行 1: | 行 1: | ||
====== p5.jsとGrove Beginner Kitで遊ぼう ====== | ====== p5.jsとGrove Beginner Kitで遊ぼう ====== | ||
- | このページではp5.jsからGrove Beginner Kitへのセンサ入力値やOLED出力等を実習するためのサンプルや解説をまとめます。 | + | このページではp5.jsからGrove Beginner Kitへのセンサ入力値やOLED出力等を実習するためのサンプルや解説をまとめます。なおこのページは最初のシリアル通信で利用するサンプルを雛形とし、各セクションで肉付けしつつ進めていきます。 |
行 25: | 行 25: | ||
===== Rotary Potentiometer ===== | ===== Rotary Potentiometer ===== | ||
+ | {{: | ||
+ | |||
シリアル通信を理解したところで、次はRotary Potentiometerを回し、その値をjs側でうけ、html要素にその結果を反映させてみます。 | シリアル通信を理解したところで、次はRotary Potentiometerを回し、その値をjs側でうけ、html要素にその結果を反映させてみます。 | ||
html要素には slider を利用してみます。Rotary Potentiometerを回すと、html上のスライダーが動くようにしてみます。先程の | html要素には slider を利用してみます。Rotary Potentiometerを回すと、html上のスライダーが動くようにしてみます。先程の | ||
行 93: | 行 95: | ||
以上の処理で、右に回しきると0, | 以上の処理で、右に回しきると0, | ||
+ | ではここまで理解できたところで、最後にhtml上のスライダーを操作してみます。予めindex.htmlにスライダーを準備しておき、そのスライダーにjs側からアクセスします。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | <file .html index.html> | ||
+ | < | ||
+ | <html lang=" | ||
+ | < | ||
+ | <script src=" | ||
+ | <script src=" | ||
+ | <link rel=" | ||
+ | <meta charset=" | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <button onclick=" | ||
+ | <input id=" | ||
+ | </ | ||
+ | <script src=" | ||
+ | <script src=" | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | textSize(48); | ||
+ | textAlign(CENTER, | ||
+ | text(serial_values[0], | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | serial_values = values; | ||
+ | document.querySelector('# | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== Lightセンサー ===== | ||
+ | {{: | ||
+ | |||
+ | では次はLightセンサーの値に基づいてp5jsキャンバスを暗くしたり明るくしたりしてみましょう。やり方は先程と同様になります。Lightセンサー値も0-1023なので、範囲を変換してPCに送信してみましょう。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(serial_values[0]); | ||
+ | textSize(48); | ||
+ | textAlign(CENTER, | ||
+ | text(serial_values[0], | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | serial_values = values; | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | <file .pde arduino.pde> | ||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | int a = analogRead(6); | ||
+ | a = map(a, 0,1023, 0,255); | ||
+ | Serial.write(a); | ||
+ | delay(30); | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== マイクセンサー ===== | ||
+ | {{ : | ||
+ | |||
+ | 音の入力を扱うことができますが、PCにもマイクがついているのであんまりp5.jsと連携させても面白くないかもしれませんが、コーディングの練習として実施します。今回は音声波形をp5.jsのキャンバスに表示してみたいと思います。これまで送信された最新のデータをhtml上に反映させてきましたが、それだけでは波形を見ることができないので、もう少し工夫してみます。まずは最新のデータを確認するプログラムにしてみます。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | <file .html index.html> | ||
+ | < | ||
+ | <html lang=" | ||
+ | < | ||
+ | <script src=" | ||
+ | <script src=" | ||
+ | <link rel=" | ||
+ | <meta charset=" | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <button onclick=" | ||
+ | </ | ||
+ | <script src=" | ||
+ | <script src=" | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | textSize(48); | ||
+ | textAlign(CENTER, | ||
+ | text(serial_values[0], | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | serial_values = values; | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 上記のコードに一旦戻し、Arduinoから読み取るアナログ値をA2に変更します。 | ||
+ | int a = analogRead(2); | ||
+ | | ||
+ | 実行すると以下のようになります。 | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | というわけで、もう少し時系列を意識した表示になるよう sketch.js 側を工夫します。シリアル通信で取得したデータを400個分配列に追加していきます。配列のサイズが400個を超えたところでそれ以上配列が大きくならないように注意する必要があります。これを放っておくと起動すればするほどメモリ領域を消費して、最終的にはOS全体の挙動がカタカタしてしまうので注意が必要です。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | noFill(); | ||
+ | beginShape(); | ||
+ | for( let i = 0; i < serial_values.length; | ||
+ | vertex(i, | ||
+ | } | ||
+ | endShape(); | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | for( let i = 0; i < values.length; | ||
+ | serial_values.push(values[i]); | ||
+ | } | ||
+ | while(serial_values.length > 400){ | ||
+ | serial_values.shift(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | <file .pde arduino.pde> | ||
+ | void setup() { | ||
+ | // put your setup code here, to run once: | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | // put your main code here, to run repeatedly: | ||
+ | int a = analogRead(2); | ||
+ | a = map(a, 0, 1023, 0, 255); | ||
+ | Serial.write(a); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 以上を実行すると本セクションの冒頭で紹介しているgifのような結果が閲覧できると思います。 | ||
+ | |||
+ | ===== 加速度センサ ===== | ||
+ | {{ : | ||
+ | |||
+ | このセクションでは加速度センサからのデータを基にp5js上での画面描画に反映してみます。具体的にはbeginner kitの傾きに応じてボールが転がるプログラムを一緒に記述していきましょう。seeed studio社が提供する[[https:// | ||
+ | |||
+ | まずは以下のサンプルコードをArduinoに書き込みます。 | ||
+ | |||
+ | <file .pde arduino.pde> | ||
+ | //Gravity Acceleration | ||
+ | #include " | ||
+ | |||
+ | #include < | ||
+ | LIS3DHTR< | ||
+ | #define WIRE Wire | ||
+ | |||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | while (!Serial) {}; | ||
+ | LIS.begin(WIRE, | ||
+ | delay(100); | ||
+ | LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ); | ||
+ | } | ||
+ | void loop() { | ||
+ | if (!LIS) { | ||
+ | Serial.println(" | ||
+ | while (1); | ||
+ | return; | ||
+ | } | ||
+ | //3 axis | ||
+ | Serial.print(LIS.getAccelerationX()); | ||
+ | Serial.print(LIS.getAccelerationY()); | ||
+ | Serial.println(LIS.getAccelerationZ()); | ||
+ | |||
+ | delay(500); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 上記のコードは3軸加速度センサの値を読み取って、500[ms]お気にカンマ区切りの文字列としてデータをPCに送信しています。さて、ここまでの学習ではセンサデータをmap関数を利用して扱いやすい数値(1byteに収まるように)にして値のやり取りを行っていました。今回は加速度値が小数点を含む値で送信されてきています。さらには値の種類はx, | ||
+ | |||
+ | 現在のArduinoコードでは、例えばx=0.05, | ||
+ | 0.05, | ||
+ | という文字列がPCに送信されています。さらに最後のzに関してはprintln関数を利用しているため、改行コードと呼ばれる改行を示すコード(13, | ||
+ | [48, 46, 48, 53, 44, 48, 46, 48, 48, 44, 49, 46, 48, 48, 13, 10] | ||
+ | | ||
+ | ここで、数字を表す文字コードでは、以下の対応となっていますので、再度下記対応表をみて、上記文字コードを文字に置き換えてみてください。 | ||
+ | * 44=',' | ||
+ | * 46=' | ||
+ | * 48=' | ||
+ | * 49=' | ||
+ | * 53=' | ||
+ | |||
+ | いかがでしょうか?ただしく 0.05, | ||
+ | - データが届くたびに順次配列に蓄える(push) | ||
+ | - 改行コードの2つめである 10 が届いたらデータが一行分届いたことになる | ||
+ | - ここまで蓄えたデータは文字コードが送られているので、文字に変換する | ||
+ | - データはカンマ区切りになっているので、splitという関数を利用してカンマで区切られた文字列を配列に分ける | ||
+ | - それぞれの文字列は順にx, | ||
+ | という手順で、p5.js上で扱えるようにします。 | ||
+ | |||
+ | 上記を踏まえて記述したコードは以下の通りです。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | var x=0; | ||
+ | var y=0 | ||
+ | var z=0; | ||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | textSize(18); | ||
+ | textAlign(CENTER, | ||
+ | text(`${x.toFixed(2)}, | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | for( let i = 0; i < values.length; | ||
+ | | ||
+ | if( values[i] == 10){ | ||
+ | let result = ""; | ||
+ | for( s of serial_values){ | ||
+ | result += String.fromCharCode(s); | ||
+ | } | ||
+ | // | ||
+ | const splits = result.split(',' | ||
+ | x = parseFloat(splits[0]); | ||
+ | y = parseFloat(splits[1]); | ||
+ | z = parseFloat(splits[2]); | ||
+ | // | ||
+ | serial_values = []; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | <file .pde arduino.pde> | ||
+ | //Gravity Acceleration | ||
+ | #include " | ||
+ | |||
+ | #include < | ||
+ | LIS3DHTR< | ||
+ | #define WIRE Wire | ||
+ | |||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | while (!Serial) {}; | ||
+ | LIS.begin(WIRE, | ||
+ | delay(100); | ||
+ | LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ); | ||
+ | } | ||
+ | void loop() { | ||
+ | if (!LIS) { | ||
+ | Serial.println(" | ||
+ | while (1); | ||
+ | return; | ||
+ | } | ||
+ | //3 axis | ||
+ | Serial.print(LIS.getAccelerationX()); | ||
+ | Serial.print(LIS.getAccelerationY()); | ||
+ | Serial.println(LIS.getAccelerationZ()); | ||
+ | |||
+ | delay(30); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Arduino側のコードはdelayを30[ms]に変更しただけです。少しむずかしいと思いますが、じっくり読んでアルゴリズムを理解しましょう。 | ||
+ | |||
+ | さあ、それではセンサデータがしっかりと取得できたのでこの値で画面上のボールを転がしてみます。400x400のキャンバス上の真ん中からスタートし、x, | ||
+ | |||
+ | <file .js sketch.js> | ||
+ | var serial_values = [0]; | ||
+ | var serial = new Serial(); | ||
+ | var x=0; | ||
+ | var y=0 | ||
+ | var z=0; | ||
+ | |||
+ | var ball = { | ||
+ | x:200, | ||
+ | y:200 | ||
+ | } | ||
+ | |||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | textSize(12); | ||
+ | textAlign(LEFT, | ||
+ | text(`${x.toFixed(2)}, | ||
+ | circle(ball.x, | ||
+ | } | ||
+ | |||
+ | function gotSerialValues(values) { | ||
+ | for( let i = 0; i < values.length; | ||
+ | | ||
+ | if( values[i] == 10){ | ||
+ | let result = ""; | ||
+ | for( s of serial_values){ | ||
+ | result += String.fromCharCode(s); | ||
+ | } | ||
+ | const splits = result.split(',' | ||
+ | x = parseFloat(splits[0]); | ||
+ | if( !x )x = 0; | ||
+ | y = parseFloat(splits[1]); | ||
+ | if( !y )y = 0; | ||
+ | z = parseFloat(splits[2]); | ||
+ | ball.x -= y*5; | ||
+ | ball.y -= x*5; | ||
+ | if( ball.x <= 0)ball.x = 0; | ||
+ | if( ball.x >= width)ball.x = width; | ||
+ | if( ball.y <= 0)ball.y = 0; | ||
+ | if( ball.y >= height)ball.y = height; | ||
+ | serial_values = []; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ |