文書の過去の版を表示しています。
p5.jsとGrove Beginner Kitで遊ぼう
このページではp5.jsからGrove Beginner Kitへのセンサ入力値やOLED出力等を実習するためのサンプルや解説をまとめます。なおこのページは最初のシリアル通信で利用するサンプルを雛形とし、各セクションで肉付けしつつ進めていきます。
Serial通信
ブラウザからSerial通信を行う場合は、Web Serial APIを利用します。p5.jsとは関係がなく、単純にjsで提供されている機能です。まずはこのWeb Serial APIを利用して、シリアル通信を確認します。ブラウザからデバイスにアクセスするには必ずユーザ操作がトリガーである必要が、セキュリテイの面から決められているので、ボタンを押してシリアル通信を行うプログラムにしておく必要があります。p5.js editorにひな形をおいておきますのでこちらを利用しましょう。
練習問題
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
シリアル通信を理解したところで、次は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送信することの正しい理解をしておいてください。
Lightセンサー
では次は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); }