XIAO ESP32C3を使ってみる その6(DUALSHOCK 4との通信、Node-RED)

はじめに

 今回はDUALSHOCK 4でXIAO ESP32C3を用いた小型ロボットを操作してみました。

 以前調べていたときに、DUALSHOCK 4とXIAO ESP32C3はBluetoothの規格が違うので、直接通信できないという結論になっていました。

▼こちらの記事で調べていました。Bluetooth ClassicとBLEの違いです。

ちょっと調べもの:ESP32C3とBluetoothの規格

はじめに  このホームページでは、度々ESP32とPS4のコントローラ(DUALSHOCK4)をBluetoothで接続する方法についてまとめています。今回の記事は、ESP32C3でもPS4のコン…

 最近開発した、Node-REDでDUALSHOCK 4と通信できるdualshock4ノードを使うと、Node-REDで中継して通信できるのではないかということで試してみました。

▼dualshock4ノードについてはこちら

Node-REDのノードを開発してみる その4(dualshock4ノード)

はじめに  今回はNode-REDと、PS4のコントローラであるDUALSHOCK 4で通信できる、dualshock4ノードを開発してみました。  2年ほど前からESP32とDUALSHOCK 4で通信して、…

▼以前の記事はこちら

XIAO ESP32C3を使ってみる その2(analogWrite関数、サーボモーター)

はじめに  今回はXIAO ESP32C3で、analogWrite関数とサーボモーターの制御を試してみました。  サーボモーターについては、既存のライブラリが使えませんでした。そこで…

XIAO ESP32C3を使ってみる その4(WiFi AccessPoint、二輪ロボット)

はじめに  今回はXIAO ESP32C3をWiFiのアクセスポイントにして、ブラウザから操作できるようにしてみました。  そもそもなぜこの機能を試したのかというと、展示会やイ…

Node-RED側の設定

 以前開発したdualshock4ノードでDUALSHOCK 4の入力を受け取り、MQTT通信で送信します。

 RスティックとLスティックのY軸の値に応じて車輪が回転するようにするのですが、出力値は-1~1です。マイコンには0~180の値の範囲で送信するので、rangeノードを使って変換します。

▼ピンが多いので複雑に見えますが、送信しているのは下のmqtt outノードです。

[{"id":"6d44dbded6b925e9","type":"inject","z":"d6fad9e77ecc8414","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2330,"y":460,"wires":[["1b99baa42461afc5"]]},{"id":"e448101471980908","type":"inject","z":"d6fad9e77ecc8414","name":"Finish","props":[{"p":"kill","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":2330,"y":500,"wires":[["1b99baa42461afc5"]]},{"id":"39761b80535b3527","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"62a28eb47ad4b20e","order":6,"width":0,"height":0,"gtype":"compass","title":"Left X","label":"","format":"{{value}}","min":"1","max":"-1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2930,"y":400,"wires":[]},{"id":"3ce2279ab30c4ce3","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"62a28eb47ad4b20e","order":6,"width":0,"height":0,"gtype":"compass","title":"Left Y","label":"","format":"{{value}}","min":"-1","max":"1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2930,"y":440,"wires":[]},{"id":"d712775e6b8074bd","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"6e28d9e8ae4ff93d","order":6,"width":0,"height":0,"gtype":"compass","title":"Right X","label":"","format":"{{value}}","min":"1","max":"-1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2940,"y":480,"wires":[]},{"id":"76d35c2ab7bfa619","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"6e28d9e8ae4ff93d","order":6,"width":0,"height":0,"gtype":"compass","title":"Right Y","label":"","format":"{{value}}","min":"-1","max":"1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2940,"y":520,"wires":[]},{"id":"81258300e2a180ca","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"62a28eb47ad4b20e","order":6,"width":0,"height":0,"gtype":"gage","title":"L2","label":"","format":"{{value}}","min":"-1","max":"1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2930,"y":560,"wires":[]},{"id":"8a00aa6ab2b170be","type":"ui_gauge","z":"d6fad9e77ecc8414","name":"","group":"6e28d9e8ae4ff93d","order":6,"width":0,"height":0,"gtype":"gage","title":"R2","label":"","format":"{{value}}","min":"-1","max":"1","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":2930,"y":600,"wires":[]},{"id":"d6ec5892bc127fe9","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Cross","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":260,"wires":[]},{"id":"9cc87a9c3e6f0035","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Circle","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":300,"wires":[]},{"id":"1f57f89452d3afe7","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Square","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2780,"y":340,"wires":[]},{"id":"46f52d05fa3c247a","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Triangle","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2780,"y":380,"wires":[]},{"id":"1a75d59c7a27052a","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":0,"height":0,"name":"","label":"PS","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":460,"wires":[]},{"id":"aa67e9490b49afb8","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":0,"height":0,"name":"","label":"Share","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":420,"wires":[]},{"id":"a54da400d2fea125","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":0,"height":0,"name":"","label":"Options","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2780,"y":500,"wires":[]},{"id":"0c3040e3a045dde5","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"L3","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":540,"wires":[]},{"id":"75885030a7baedc9","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"R3","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":580,"wires":[]},{"id":"2c5e7d6378b5313d","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"L1","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":620,"wires":[]},{"id":"c0e5db9534442249","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"R1","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":660,"wires":[]},{"id":"ac98c870a5f214d2","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Up","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":700,"wires":[]},{"id":"066bb1ab3979c7ae","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Down","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":740,"wires":[]},{"id":"4dd05ee6ec60fadb","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Left","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":780,"wires":[]},{"id":"91fd7eba418305a4","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":"3","height":"1","name":"","label":"Right","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2770,"y":820,"wires":[]},{"id":"c5f5d5bb1ed13491","type":"ui_text","z":"d6fad9e77ecc8414","group":"227d3ca77163ce82","order":0,"width":0,"height":0,"name":"","label":"TouchPad","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":2780,"y":860,"wires":[]},{"id":"f3e18b9fa99890ea","type":"range","z":"d6fad9e77ecc8414","minin":"-1","maxin":"1","minout":"0","maxout":"180","action":"scale","round":false,"property":"payload","name":"","x":2780,"y":940,"wires":[["3592dfa80b138081"]]},{"id":"4cf5f35918f4293c","type":"range","z":"d6fad9e77ecc8414","minin":"-1","maxin":"1","minout":"180","maxout":"0","action":"scale","round":false,"property":"payload","name":"","x":2780,"y":900,"wires":[["790ecd8e383b167b"]]},{"id":"790ecd8e383b167b","type":"mqtt out","z":"d6fad9e77ecc8414","name":"","topic":"/right","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"f414466379b9f58d","x":2930,"y":900,"wires":[]},{"id":"3592dfa80b138081","type":"mqtt out","z":"d6fad9e77ecc8414","name":"","topic":"/left","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"f414466379b9f58d","x":2930,"y":940,"wires":[]},{"id":"1b99baa42461afc5","type":"dualshock4_multi","z":"d6fad9e77ecc8414","name":"","sleep":"100","x":2520,"y":480,"wires":[["d6ec5892bc127fe9"],["9cc87a9c3e6f0035"],["1f57f89452d3afe7"],["46f52d05fa3c247a"],["aa67e9490b49afb8"],["1a75d59c7a27052a"],["a54da400d2fea125"],["0c3040e3a045dde5"],["75885030a7baedc9"],["2c5e7d6378b5313d"],["c0e5db9534442249"],["ac98c870a5f214d2"],["066bb1ab3979c7ae"],["4dd05ee6ec60fadb"],["91fd7eba418305a4"],["c5f5d5bb1ed13491"],["39761b80535b3527"],["3ce2279ab30c4ce3","f3e18b9fa99890ea"],["d712775e6b8074bd"],["76d35c2ab7bfa619","4cf5f35918f4293c"],["81258300e2a180ca"],["8a00aa6ab2b170be"]]},{"id":"62a28eb47ad4b20e","type":"ui_group","name":"Left","tab":"f6642a80f4f5605a","order":3,"disp":true,"width":"6","collapse":false,"className":""},{"id":"6e28d9e8ae4ff93d","type":"ui_group","name":"Right","tab":"f6642a80f4f5605a","order":4,"disp":true,"width":"6","collapse":false,"className":""},{"id":"227d3ca77163ce82","type":"ui_group","name":"Buttons","tab":"f6642a80f4f5605a","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"f414466379b9f58d","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"f6642a80f4f5605a","type":"ui_tab","name":"Controller","icon":"dashboard","disabled":false,"hidden":false}]

▼rangeノードで値の範囲を変更しています。

 なお速度を0~180で指定するのは、180度回転するサーボモータ用のノードを開発していたときの名残です。もちろんマイコン側で値の範囲を変更することもできます。

マイコン側の設定

 以前も利用した小型のロボットを用いて、Node-REDとMQTT通信をして操作できるようにしました。

▼この記事ではコマンドを受け取って動くようにしていましたが、今回はそれぞれの連続回転サーボの回転速度を送るようにしています。

音声でロボットを操作してみる(Node-RED、Gemma2、Faster Whisper、XIAO ESP32C3)

はじめに  今回は音声でロボットの操作を試してみました。今まで試してきたことの、ちょっとしたまとめのような感じです。  音声でロボットを操作するにあたって、音声…

 プログラムはChatGPTに相談しながら作成しました。MQTT通信の/right、/leftのトピックで受信した値で連続回転サーボが回転するようになっています。

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "<your SSID>";
const char* password = "<your password>";
const char* mqtt_server = "<your ip>";  

const int ServoPin1 = D1;
const int ServoPin2 = D2;
const int DutyMax = 2300;
const int DutyMin = 700;
int speed1 = 0;
int speed2 = 0;

WiFiClient espClient;
PubSubClient client(espClient);

void ServoSpeed(int pin, int speed) {
  int Duty = map(speed, -10, 10, DutyMin, DutyMax);
  digitalWrite(pin, HIGH);
  delayMicroseconds(Duty);
  digitalWrite(pin, LOW);
  delayMicroseconds(20000 - Duty);
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("MQTT接続を試みています...");
    if (client.connect("ESP32Client")) {
      Serial.println(" 接続成功");
      client.subscribe("/right");
      client.subscribe("/left");
    } else {
      Serial.print(" 失敗 (rc=");
      Serial.print(client.state());
      Serial.println(") 5秒後に再試行します");
      delay(1000);
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  int value = message.toInt();
  int mappedSpeed = map(value, 0, 180, -10, 10);

  if (strcmp(topic, "/right") == 0) {
    speed1 = mappedSpeed;
    Serial.print("右車輪速度: "); Serial.println(speed1);
  } else if (strcmp(topic, "/left") == 0) {
    speed2 = mappedSpeed;
    Serial.print("左車輪速度: "); Serial.println(speed2);
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(ServoPin1, OUTPUT);
  pinMode(ServoPin2, OUTPUT);
  ServoSpeed(ServoPin1, 0);
  ServoSpeed(ServoPin2, 0);

  Serial.print("WiFiに接続中...");
  WiFi.begin(ssid, password);
  int attempt = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
    attempt++;
    if (attempt > 20) {
      Serial.println("\nWiFi接続に失敗しました。再起動します。");
      ESP.restart();
    }
  }
  Serial.println("\nWiFiに接続しました");

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  reconnect();
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  ServoSpeed(ServoPin1, speed1);
  ServoSpeed(ServoPin2, speed2);
}

 連続回転サーボの制御は、ライブラリを使わずに行っています。

▼こちらの記事で試していました。

XIAO ESP32C3を使ってみる その3(OLEDディスプレイ、連続回転サーボ)

はじめに  今回はXIAO ESP32C3で、OLEDディスプレイと連続回転サーボを制御してみました。小型のマイコンには小型のディスプレイを一緒に使いたくなります。  OLEDディ…

 要はパルス幅を指定してピンの制御を行っています。

動作を確認してみる

 実際に通信して動かしてみました。

▼通信のラグがあり、機体がふらつくので操作しにくいです。

▼ちょっと慣れたころの操作。回転速度を細かく調整できないので、回転が難しいです。

▼ダッシュボードと並べるとこんな感じ。

 右と左の回転速度があっていない気もするので、エンコーダ等で制御するか、もっと精度のいいモーターを使いたいところです。

最後に

 新しく開発したdualshock4ノードを利用することで、XIAO ESP32C3と通信できるようになりました。通信のラグはできるだけ解消したいところです。

▼こちらの記事で通信していたときの方が、すぐに反応していた気がします。

Node-REDを使ってみる その4(MQTT通信、ロボットアーム)

はじめに  今回は以前Amazonで購入したロボットアームを、Node-REDでMQTT通信を利用して制御できるようにしてみました。  これまではボタンで制御していたのですが、ネ…

 ロボットのソフトウェア開発に使えそうな技術は集まってきたので、久しぶりに機体と基板の設計をしたいなと思っています。

▼ちなみにXIAO ESP32C3とDUALSHOCK 4で通信できるのかをChatGPTに聞いてみたのですが、最初は通信できると回答されました。もう一度聞いてみると、DUALSHOCK 4ではBLE通信できないと回答されました。ハードウェアには弱い印象があります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です