ESP32＋QuickJS＋Blocklyの例

2022/3/21に、ESP32＋QuickJSで初めて電子書籍を出版してから、細かな機能アップをたくさんしてきました。
その中でも、Blocklyへの対応が一番楽しかったです。

https://qiita.com/poruruba/items/f80ffd52c1b31ac42ea6

電子書籍：M5StackとJavascriptではじめるIoTデバイス制御

https://poruruba.booth.pm/items/3735175

今回は、そのBlocklyでのスケッチ例をいくつか示したいと思います。なかなか、電子書籍への記載の追記のペースよりも、機能アップの方が楽しいので、反映が遅れがちでしたが、この例示が参考になってくれるとうれしいです。

# Lチカ

一番単純なLチカです。M5StackモジュールはM5Stick-Cです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/18bb8830-dceb-c6e3-df1c-cc1d217edf23.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.js
import * as gpio from 'Gpio';
gpio.pinMode(10, gpio.OUTPUT);
setInterval( () => {
  gpio.digitalWrite(10, gpio.LOW);
  delay(500);
  gpio.digitalWrite(10, gpio.HIGH);
  delay(500);
}, 1000);
```

# RGBマトリクスLEDを手動で点灯

M5Stackモジュールは、M5Atom Matrixです。
ボタンを押すたびに、25個のRGBマトリクスLEDに、ランダムな色が増えていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/de42a475-93b2-1d31-f399-977e74a10ce5.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.js
var counter;

function colourRandom() {
  var num = Math.floor(Math.random() * Math.pow(2, 24));
  return '#' + ('00000' + num.toString(16)).substr(-6);
}


import * as pixels from 'Pixels';
import * as input from 'Input';
import * as utils from 'Utils';
pixels.begin(27, 25);
pixels.clear();
counter = 0;

input.onButtonWasPressed(input.BUTTON_A, () => {
  pixels.setPixelColor(counter, (utils.rgb2Number((colourRandom()))));
  counter = (typeof counter === 'number' ? counter : 0) + 1;
  if (counter >= 25) {
    counter = 0;
    pixels.clear();
  }
});
```

# SDカードにあるMP3を再生

ボタンを押すと、MP3の再生を開始します。
M5Stack Core2を使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/b7323a8b-bf73-1586-16d0-a5944bf72114.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.js
import * as audio from 'Audio';
import * as input from 'Input';
import * as utils from 'Utils';
audio.begin(audio.EXTERNAL_I2S);
audio.setPinout(12, 0, 2);

input.onButtonWasPressed(input.BUTTON_A, () => {
  audio.playSd('/g_07.mp3');
});

esp32.setLoop(() => {
  audio.update();
});
```

# サーボを動かす

M5StickCとM5StickC用のServo Hatを使います。
ボタンを押すとサーボが動き出し、再度押すと停止します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/147f8884-56d5-7c57-a733-9c25b96a4801.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.js
var enable, count;


import * as ledc from 'Ledc';
import * as input from 'Input';
ledc.setup(1, 50, 16);
ledc.attachPin(26, 1);
count = 1500;
enable = false;

input.onButtonWasPressed(input.BUTTON_A, () => {
  enable = !enable;
});

esp32.setLoop(() => {
  if (enable) {
    ledc.write(1, count);
    count = (typeof count === 'number' ? count : 0) + 100;
    if (count >= 8500) {
      count = 1500;
    }
    delay(50);
  }
});
```

# LCDに図形や文字を表示

M5Stack Core2を使います。
ボタンを押すと、表示カウンタがインクリメントされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/a7fbf27c-8cd2-7c29-08d5-103dbd626f05.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.ns
var counter;


import * as lcd from 'Lcd';
import * as input from 'Input';
import * as utils from 'Utils';
lcd.fillScreen((utils.rgb2Number('#000000')));
lcd.drawLine(0, 0, 40, 40, (utils.rgb2Number('#ffffff')));
lcd.fillRect(50, 0, 40, 40, (utils.rgb2Number('#009900')));
lcd.fillRoundRect(100, 0, 40, 40, 5, (utils.rgb2Number('#ff6600')));
lcd.fillCircle(170, 20, 20, (utils.rgb2Number('#6600cc')));
lcd.setTextSize(2, 2);
counter = (typeof counter === 'number' ? counter : 0) + 0;
lcd.setCursor(0, 50);
lcd.println(('counter=' + String(counter)));

input.onButtonWasPressed(input.BUTTON_A, () => {
  counter = (typeof counter === 'number' ? counter : 0) + 1;
  lcd.fillRect(0, 50, (lcd.width()), (lcd.fontHeight()), (utils.rgb2Number('#000000')));
  lcd.setCursor(0, 50);
  lcd.println(('counter=' + String(counter)));
});
``` 

M5Core2の画面には以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/b5ef425f-1b75-5852-7d54-e6594cd8e134.png)


# MQTTで送受信

トピックに対するメッセージを受信すると、エコーバックでトピックに返します。
ボタンを押しても、トピックにメッセージを送ります。
事前に、mqtt.setServer(host, port)でMQTTブローカのURLを設定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/721842b7-9cc7-96d6-dc30-630a6f4d58c9.png)

以下のようなJavascriptに展開されてM5Stackモジュールにアップロードされます。

```js:main.js
import * as mqtt from 'Mqtt';
import * as input from 'Input';
mqtt.connect('TestClient');
mqtt.subscribe('TestTopic_M5Stack', () => {
  mqtt.publish('TestTopic_Response', ('echoback: ' + String(mqtt.getPayload().payload)));
});

input.onButtonWasPressed(input.BUTTON_A, () => {
  mqtt.publish('TestTopic_Response', 'Button pressed');
});
```

# 終わりに

まだまだ、いろんなことができそうで、日曜プログラミングのネタ探しにはちょうどよいです。

〇電子書籍とファームウェアのサポートサイト

https://github.com/poruruba/QuickJS_ESP32_IoT_Device


以上