p5js:13.grove_beginner_kit

文書の過去の版を表示しています。


p5.jsとGrove Beginner Kitで遊ぼう

このページではp5.jsからGrove Beginner Kitへのセンサ入力値やOLED出力等を実習するためのサンプルや解説をまとめます。なおこのページは最初のシリアル通信で利用するサンプルを雛形とし、各セクションで肉付けしつつ進めていきます。

ブラウザからSerial通信を行う場合は、Web Serial APIを利用します。p5.jsとは関係がなく、単純にjsで提供されている機能です。まずはこのWeb Serial APIを利用して、シリアル通信を確認します。ブラウザからデバイスにアクセスするには必ずユーザ操作がトリガーである必要が、セキュリテイの面から決められているので、ボタンを押してシリアル通信を行うプログラムにしておく必要があります。p5.js editorにひな形をおいておきますのでこちらを利用しましょう。

2022/06/27 17:31 · baba

javascriptでは以下のように記述をすると任意の処理を定期的に呼び出すことができます。これを利用して、1秒おきにLEDが自動で点灯を繰り返すプログラムをjavascript側で実装してみましょう。

interval.js
setInterval(function(){
  // ここに実行したい処理を記述
},1000);

例えばsetup()の中にintervalを利用して記述をすると、errorになります。これはまだシリアル通信を開始していないのにシリアルポートにデータを書き込もうとしたためです。そこでユーザ側でintervalを開始するタイミングを任意で実行させることにします。keyPressed()関数を利用すると手軽にユーザ側からトリガーをつくれるので、「iキーを押したらsetIntervalを実行する」プログラムにしてみましょう。具体的には以下のようなコードをkeyPressed()関数に追加します。

 setInterval(function(){
      if( is_led_on )serial.write(1);
      else serial.write(2);
      is_led_on = !is_led_on;
    },1000);

is_led_on変数はglobalで

var is_led_on = false;

等として初期化して宣言しておきます。

シリアル通信を理解したところで、次はRotary Potentiometerを回し、その値をjs側でうけ、html要素にその結果を反映させてみます。 html要素には slider を利用してみます。Rotary Potentiometerを回すと、html上のスライダーが動くようにしてみます。先程の シリアル通信で gotSerialValuesから値が渡されるので、それに応じてslider要素を変更すればよいのですが、A0はanaloRead()関数を 利用しており、その値は 0 - 1023の間で変化します。シリアル通信での内容をひな形にして、sketch.jsとArduinoプログラムを以下のように書き換え、 まずは振る舞いを確認してみます。

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;
}
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:
  Serial.write(analogRead(0));
  delay(30);
}

するとどうでしょうか?キャンバス上の数値は0-255の間で変化を繰り返している様子が観察できると思います。こちらで想定していた動作はそれぞれのツマミを回しきったところで0-1023まで変化するものでしたがどうやら何かおかしなことになっているようです。

この原因は、シリアル通信が8bit単位での通信を行っている為です。8bitは0-255までの表現が可能なわけですが、この値の範囲に対して、10bit(0-1023)を渡しているので、データは下位8bit分しか読み取られていないためです。そこでこの解決方法ですが、大きく分けて2種類あります。

  • 値の範囲を0-255に変更してしまう。
  • 別のやり方で0-1023を渡せるように送信方法を変更する

まずは、簡単な値の範囲を狭めるやり方からです。そもそも0-1023の値を0-255に変更する場合は単純な値の比率を変更すればよいだけです。このような場合には便利なmap()という関数が用意されているので、そちらを利用します。具体的にはArduino側のコードを変更するだけです。

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(0);
  a = map(a, 0, 1023, 0, 255);
  Serial.write(a);
  delay(30);
}

以上の処理で、右に回しきると0, 左に回しきると255となる動作になりました。2つめの方法に関してはプログラムがややこしくなってくるので、このページでは紹介しません。データを正しく取得するには、時間によってデータに切れ目が生じることや、データ長の最初と終わりを把握する必要があることなど、少し丁寧なプログラムが必要となります。このページではとにかくデータを1byte送信することの正しい理解をしておいてください。

ではここまで理解できたところで、最後にhtml上のスライダーを操作してみます。予めindex.htmlにスライダーを準備しておき、そのスライダーにjs側からアクセスします。

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>
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];
}

では次はLightセンサーの値に基づいてp5jsキャンバスを暗くしたり明るくしたりしてみましょう。やり方は先程と同様になります。Lightセンサー値も0-1023なので、範囲を変換してPCに送信してみましょう。

sketch.js
var serial_values = [0];
var serial = new Serial();
 
function setup() {
  createCanvas(400, 400);
}
 
function draw() {
  background(serial_values[0]);
  textSize(48);
  textAlign(CENTER, CENTER);
  text(serial_values[0], width/2, height/2);
}
 
function gotSerialValues(values) {
  serial_values = values;
}
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上に反映させてきましたが、それだけでは波形を見ることができないので、もう少し工夫してみます。まずは最新のデータを確認するプログラムにしてみます。

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>
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;
}

上記のコードに一旦戻し、Arduinoから読み取るアナログ値をA2に変更します。

int a = analogRead(2);

実行すると以下のようになります。

  • /home/users/2/lolipop.jp-4404d470cd64c603/web/ws/data/attic/p5js/13.grove_beginner_kit.1656373675.txt.gz
  • 最終更新: 2022/06/28 08:47
  • by baba