p5js:13.grove_beginner_kit

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
p5js:13.grove_beginner_kit [2022/06/28 08:25] – [Lightセンサー] babap5js:13.grove_beginner_kit [2022/07/05 14:18] (現在) – [加速度センサ] baba
行 25: 行 25:
  
 ===== Rotary Potentiometer ===== ===== Rotary Potentiometer =====
 +{{:p5js:jun-28-2022_08-33-02.gif?nolink|}}
 +
 シリアル通信を理解したところで、次はRotary Potentiometerを回し、その値をjs側でうけ、html要素にその結果を反映させてみます。 シリアル通信を理解したところで、次はRotary Potentiometerを回し、その値をjs側でうけ、html要素にその結果を反映させてみます。
 html要素には slider を利用してみます。Rotary Potentiometerを回すと、html上のスライダーが動くようにしてみます。先程の html要素には slider を利用してみます。Rotary Potentiometerを回すと、html上のスライダーが動くようにしてみます。先程の
行 92: 行 94:
  
 以上の処理で、右に回しきると0, 左に回しきると255となる動作になりました。2つめの方法に関してはプログラムがややこしくなってくるので、このページでは紹介しません。データを正しく取得するには、時間によってデータに切れ目が生じることや、データ長の最初と終わりを把握する必要があることなど、少し丁寧なプログラムが必要となります。このページではとにかくデータを1byte送信することの正しい理解をしておいてください。 以上の処理で、右に回しきると0, 左に回しきると255となる動作になりました。2つめの方法に関してはプログラムがややこしくなってくるので、このページでは紹介しません。データを正しく取得するには、時間によってデータに切れ目が生じることや、データ長の最初と終わりを把握する必要があることなど、少し丁寧なプログラムが必要となります。このページではとにかくデータを1byte送信することの正しい理解をしておいてください。
 +
 +ではここまで理解できたところで、最後にhtml上のスライダーを操作してみます。予めindex.htmlにスライダーを準備しておき、そのスライダーにjs側からアクセスします。
 +
 +<WRAP group>
 +<WRAP half column>
 +<file .html index.html>
 +<!DOCTYPE html>
 +<html lang="en">
 +  <head>
 +    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
 +    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
 +    <link rel="stylesheet" type="text/css" href="style.css" />
 +    <meta charset="utf-8" />
 +  </head>
 +  <body>
 +    <main>
 +      <button onclick="serial.begin();">connect</button>
 +      <input id="slider" type="range" max=255 min=0 value=0 />
 +    </main>
 +    <script src="serial.js"></script>
 +    <script src="sketch.js"></script>
 +  </body>
 +</html>
 +
 +</file>
 +</WRAP>
 +
 +<WRAP half column>
 +<file .js sketch.js>
 +var serial_values = [0];
 +var serial = new Serial();
 +    
 +function setup() {
 +  createCanvas(400, 400);
 +}
 +
 +function draw() {
 +  background(220);
 +  textSize(48);
 +  textAlign(CENTER, CENTER);
 +  text(serial_values[0],width/2, height/2);
 +}
 +
 +function gotSerialValues(values) {
 +  serial_values = values;
 +  document.querySelector('#slider').value = serial_values[0];
 +}
 +</file>
 +</WRAP>
 +</WRAP>
  
 ===== Lightセンサー ===== ===== Lightセンサー =====
行 135: 行 187:
 </WRAP> </WRAP>
 </WRAP> </WRAP>
 +
 +
 +===== マイクセンサー =====
 +{{ :p5js:jun-28-2022_08-57-54.gif?nolink |}}
 +
 +音の入力を扱うことができますが、PCにもマイクがついているのであんまりp5.jsと連携させても面白くないかもしれませんが、コーディングの練習として実施します。今回は音声波形をp5.jsのキャンバスに表示してみたいと思います。これまで送信された最新のデータをhtml上に反映させてきましたが、それだけでは波形を見ることができないので、もう少し工夫してみます。まずは最新のデータを確認するプログラムにしてみます。
 +
 +<WRAP group>
 +<WRAP half column>
 +<file .html index.html>
 +<!DOCTYPE html>
 +<html lang="en">
 +  <head>
 +    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
 +    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
 +    <link rel="stylesheet" type="text/css" href="style.css" />
 +    <meta charset="utf-8" />
 +  </head>
 +  <body>
 +    <main>
 +      <button onclick="serial.begin();">connect</button>
 +    </main>
 +    <script src="serial.js"></script>
 +    <script src="sketch.js"></script>
 +  </body>
 +</html>
 +
 +</file>
 +</WRAP>
 +
 +<WRAP half column>
 +<file .js sketch.js>
 +var serial_values = [0];
 +var serial = new Serial();
 +    
 +function setup() {
 +  createCanvas(400, 400);
 +}
 +
 +function draw() {
 +  background(220);
 +  textSize(48);
 +  textAlign(CENTER, CENTER);
 +  text(serial_values[0],width/2, height/2);
 +}
 +
 +function gotSerialValues(values) {
 +  serial_values = values;
 +}
 +</file>
 +</WRAP>
 +</WRAP>
 +
 +上記のコードに一旦戻し、Arduinoから読み取るアナログ値をA2に変更します。
 +  int a = analogRead(2);
 +  
 +実行すると以下のようになります。
 +
 +{{ :p5js:jun-28-2022_08-47-12.gif?nolink |}}
 +
 +というわけで、もう少し時系列を意識した表示になるよう 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, 400);
 +}
 +
 +function draw() {
 +  background(220);
 +  noFill();
 +  beginShape();
 +  for( let i = 0; i < serial_values.length; i++){
 +    vertex(i,height - serial_values[i] );
 +  }
 +  endShape();
 +}
 +
 +function gotSerialValues(values) {
 +  for( let i = 0; i < values.length; i++){
 +    serial_values.push(values[i]);
 +  }
 +  while(serial_values.length > 400){
 +    serial_values.shift();
 +  }
 +}
 +</file>
 +</WRAP>
 +
 +<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);
 +}
 +</file>
 +</WRAP>
 +</WRAP>
 +
 +以上を実行すると本セクションの冒頭で紹介しているgifのような結果が閲覧できると思います。
 +
 +===== 加速度センサ =====
 +{{ :p5js:jul-05-2022_00-51-08.gif?nolink |}}
 +
 +このセクションでは加速度センサからのデータを基にp5js上での画面描画に反映してみます。具体的にはbeginner kitの傾きに応じてボールが転がるプログラムを一緒に記述していきましょう。seeed studio社が提供する[[https://wiki.seeedstudio.com/Grove-Beginner-Kit-For-Arduino/|Grove Beginner Kit for Arduino]]にある加速度センサ用のサンプルコードを参考にコードを記述していきます。
 +
 +まずは以下のサンプルコードをArduinoに書き込みます。
 +
 +<file .pde arduino.pde>
 +//Gravity Acceleration
 +#include "LIS3DHTR.h"
 +#include <Wire.h>
 +
 +LIS3DHTR<TwoWire> LIS;           //Hardware I2C
 +#define WIRE Wire
 +void setup() {
 +  Serial.begin(9600);
 +  while (!Serial) {};
 +  LIS.begin(WIRE, 0x19); //IIC init
 +  delay(100);
 +  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
 +}
 +void loop() {
 +  if (!LIS) {
 +    Serial.println("LIS3DHTR didn't connect.");
 +    while (1);
 +    return;
 +  }
 +  //3 axis
 +  Serial.print(LIS.getAccelerationX()); Serial.print(",");
 +  Serial.print(LIS.getAccelerationY()); Serial.print(",");
 +  Serial.println(LIS.getAccelerationZ());
 +  delay(500);
 +}
 +</file>
 +
 +上記のコードは3軸加速度センサの値を読み取って、500[ms]お気にカンマ区切りの文字列としてデータをPCに送信しています。さて、ここまでの学習ではセンサデータをmap関数を利用して扱いやすい数値(1byteに収まるように)にして値のやり取りを行っていました。今回は加速度値が小数点を含む値で送信されてきています。さらには値の種類はx,y,zと三種類あるのでこれまでとは少しデータ受信方法を考えないといけません。このような場合、ArrayBufferを利用する方法が正攻法になりますが、少し技術的な話が増えるので、ここでは文字列操作によって連続するデータを正しく取得する方法を検討します。
 +
 +現在のArduinoコードでは、例えばx=0.05, y=0.00, z=1.00 の場合は
 +  0.05,0.00,1.00
 +という文字列がPCに送信されています。さらに最後のzに関してはprintln関数を利用しているため、改行コードと呼ばれる改行を示すコード(13,10)が最後に付与されて送信されています。実際にPCがこのデータを受信すると次のような配列形式になっています。
 +  [48, 46, 48, 53, 44, 48, 46, 48, 48, 44, 49, 46, 48, 48, 13, 10]
 +  
 +ここで、数字を表す文字コードでは、以下の対応となっていますので、再度下記対応表をみて、上記文字コードを文字に置き換えてみてください。
 +  * 44=','
 +  * 46='.'
 +  * 48='0'
 +  * 49='1'
 +  * 53='5'
 +
 +いかがでしょうか?ただしく 0.05,0.00,1.00 が読めるようになったと思います。以上のことを理解したら、
 +  - データが届くたびに順次配列に蓄える(push)
 +  - 改行コードの2つめである 10 が届いたらデータが一行分届いたことになる
 +  - ここまで蓄えたデータは文字コードが送られているので、文字に変換する
 +  - データはカンマ区切りになっているので、splitという関数を利用してカンマで区切られた文字列を配列に分ける
 +  - それぞれの文字列は順にx,y,zになっているので、parseFloat関数を利用して数値に変更して変数に保存する
 +という手順で、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, 400);
 +}
 +
 +function draw() {
 +  background(220);
 +  textSize(18);
 +  textAlign(CENTER, CENTER);
 +  text(`${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`, width/2, height/2);
 +}
 +
 +function gotSerialValues(values) {
 +  for( let i = 0; i < values.length; i++ ){
 +     serial_values.push(values[i]);
 +    if( values[i] == 10){
 +      let result = "";
 +      for( s of serial_values){
 +        result += String.fromCharCode(s);
 +      }
 +      //console.log("result:", result, "serial_values", serial_values);
 +      const splits = result.split(',');
 +      x = parseFloat(splits[0]);
 +      y = parseFloat(splits[1]);
 +      z = parseFloat(splits[2]);
 +      //console.log(x,y,z);
 +      serial_values = [];
 +    }
 +  } 
 +}
 +</file>
 +</WRAP>
 +
 +<WRAP half column>
 +<file .pde arduino.pde>
 +//Gravity Acceleration
 +#include "LIS3DHTR.h"
 +
 +#include <Wire.h>
 +LIS3DHTR<TwoWire> LIS;           //Hardware I2C
 +#define WIRE Wire
 +
 +
 +void setup() {
 +  Serial.begin(9600);
 +  while (!Serial) {};
 +  LIS.begin(WIRE, 0x19); //IIC init
 +  delay(100);
 +  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
 +}
 +void loop() {
 +  if (!LIS) {
 +    Serial.println("LIS3DHTR didn't connect.");
 +    while (1);
 +    return;
 +  }
 +  //3 axis
 +  Serial.print(LIS.getAccelerationX()); Serial.print(",");
 +  Serial.print(LIS.getAccelerationY()); Serial.print(",");
 +  Serial.println(LIS.getAccelerationZ());
 +
 +  delay(30);
 +}
 +
 +</file>
 +</WRAP>
 +</WRAP>
 +
 +Arduino側のコードはdelayを30[ms]に変更しただけです。少しむずかしいと思いますが、じっくり読んでアルゴリズムを理解しましょう。
 +
 +さあ、それではセンサデータがしっかりと取得できたのでこの値で画面上のボールを転がしてみます。400x400のキャンバス上の真ん中からスタートし、x,y軸の傾きに応じてボールの位置を移動させてみます。注意しておきたいのは、変数x,yに誤って浮動小数点にならないものが入力された場合はキャンセル処理をすること。もう一つは画面からはみ出さないように最大値、最小値の制約をつけておくことです。以下が動作するプログラムとなります。
 +
 +<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, 400);
 +}
 +
 +function draw() {
 +  background(220);
 +  textSize(12);
 +  textAlign(LEFT, TOP);
 +  text(`${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`, 10,10);
 +  circle(ball.x, ball.y,20);
 +}
 +
 +function gotSerialValues(values) {
 +  for( let i = 0; i < values.length; i++ ){
 +     serial_values.push(values[i]);
 +    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 = [];
 +    }
 +  } 
 +}
 +</file>
 +
 +===== おまけ(マイク入力で丸の大きさも変化させる) =====
 +<WRAP group>
 +<WRAP half column>
 +<file .pde arduino.pde>
 +//Gravity Acceleration
 +#include "LIS3DHTR.h"
 +#include <Wire.h>
 +
 +LIS3DHTR<TwoWire> LIS;           //Hardware I2C
 +#define WIRE Wire
 +void setup() {
 +  Serial.begin(9600);
 +  while (!Serial) {};
 +  LIS.begin(WIRE, 0x19); //IIC init
 +  delay(100);
 +  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
 +}
 +void loop() {
 +  if (!LIS) {
 +    Serial.println("LIS3DHTR didn't connect.");
 +    while (1);
 +    return;
 +  }
 +  //3 axis
 +  Serial.print(LIS.getAccelerationX()); Serial.print(",");
 +  Serial.print(LIS.getAccelerationY()); Serial.print(",");
 +  Serial.print(LIS.getAccelerationZ()); Serial.print(",");
 +  Serial.println(analogRead(2));
 +  delay(30);
 +}
 +</file>
 +</WRAP>
 +
 +<WRAP half column>
 +<file .js sketch.js>
 +var serial_values = [];
 +var serial = new Serial();
 +var x=0;
 +var y=0;
 +var z=0;
 +var mic = 0;
 +
 +function setup() {
 +  createCanvas(400, 400);
 +}
 +
 +var ball = {
 +  x:0,
 +  y:0,
 +  r:0
 +}
 +
 +function draw() {
 +  background(220);
 +  textSize(18);
 +  textAlign(CENTER, CENTER);
 +  text(`${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`, width/2, height/2);
 +  
 +  circle(ball.x, ball.y, ball.r/10);
 +
 +}
 + 
 +function gotSerialValues(values) {
 +  for( let i = 0; i < values.length; i++ ){
 +     serial_values.push(values[i]);
 +    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]);
 +      mic = parseFloat(splits[3]);
 +      serial_values = [];
 +      
 +      ball.x -= y*10;
 +      ball.y -= x*10;
 +      ball.r = mic;
 +      
 +    }
 +  } 
 +}
 +</file>
 +</WRAP>
 +</WRAP>
 +
  
  • /home/users/2/lolipop.jp-4404d470cd64c603/web/ws/data/attic/p5js/13.grove_beginner_kit.1656372325.txt.gz
  • 最終更新: 2022/06/28 08:25
  • by baba