上位に戻る 模型ホーバクラフト スマホでラジコン 自作 初版2025/9/28

Bluetoothを使ってスマホをリモコンにしてホバークラフトのラジコン模型を作ってみました
ラジコン模型(グライダーとか船を作っていた)は、小中学生以来 久々だあ 
孫もおらんしなあ即刻ゴミになる
まあ新規で買ったのは、発泡スチロールと、モータだけだけど






  1. どんな構成
    制御部には、Bluetooth機能が付いているESP32C3 切手サイズの小型マイコンを使うことにします
    しかし、技適マークがついていない 袋にCEマークが付いていて、メーカ名も記載あるので、
    総務省に、技適未取得機器を用いた実験等の届け出しようとしたのですが、シリアルナンバーがわからん!
    取り合えず、ちょこっと実験で使ってみることにします 正式には、Seeed studio ESP32C6を別途購入することにします
    スマホ側のアプリ android studioで作ろうかと調べていたら、ESP32で使えるスマホアプリを発見しました
    今更作る必要ないですね・・・。
    Dabble App - STEMpedia Education STEMpedia IT教育用の教材を作っている会社みたいです
    これのGamepad Moduleを利用させてもらうことにします スマホは、Android 又はiOS(iPhone)どちらでも使用可能
    です
    後は、揚力用モータを1個 推進用モータを1個 ちびこいモータドライバと、電源は、リチウム電池にします
    電動ドライバで使っていたものを流用します(1Ahのもの) それと、リチウム電池の保護回路と、充電ユニット
    3.3V作るのに3端子レギュレータ ESP32C3内蔵のものでもいいかもしれないが保護回路のダイオードで電圧低下
    するかもしれないので外部で作ることにします
  2. 使った材料

    マイコン本体
    アンテナ内蔵
    モータドライバ
    羽付モータ
    充電保護
    ユニット

    後は、チャク付ポリ袋 紙コップ 発泡スチロール ジュースの空きコップ 両面テープ 接着剤 薄いダンボール


  3. 作り方
    ■筐体
    ダイソーで買った、厚さ10mmの発泡スチロール
    を使いました
    ホバークラフトのスカート部をチャック付の
    ポリ袋を使いました
    サイズは、B6
    発泡スチロールをポリ袋より、5mmくらい
    小さめに切り出します

    0.3mmのステンレス線に電気流して
    熱線できりましたが、結構真っすぐ切るのが
    ムズイです
    新品歯のカッターナイフで切ったほうが
    加工しやすいみたいです
    一番下部は、周囲20mmを残して切り抜き
    ました
    上部2枚は、揚力ファンの穴を開けました
    出来上がった底面

    後部のスカートの膨らみが悪いです
    チャックの部分が硬いので、スカート
    前部よりも長めに出したほうがいいかも
    です

    ■部品関係
    0.3mmのアルミパネルを使って
    モータを固定しています

    円筒形のプラスチックは、
    飲み物の空きコップを使って
    います
    推進モータを取り付けた
    ところ、プラスチックネジで
    挟みこみ

    ファンのカバーは紙コップ
    です
    ラダーは、薄いダンボール
    を切り出して
    サーボのガイドにから2mm
    のネジをダンボールの隙間に
    ねじ込んでいます

    0.5mmのアルミ板に
    サーボモータを取付ました
    ラダー 愛猫に、噛まれて
    猫の歯型がついてます
    取れなくて良かったス
    ポリ袋を底面に合わせて
    切り抜きます

    20mmの両面テープで
    貼り付けました


    ■制御部
     回路図


    実装写真
    空き箱の紙に各ユニットを
    両面テープで貼り付けて
    います

    右上が、ESP32C3Mini
    左上がモータドライバ
    右下SWと、レギュレータ
    左下 リチウム電池の
    保護充電ユニット
    ユニットの下は、電池です

    これが一番重いので、
    これの実装位置で
    重心が中央になるように
    配置します

  4. プログラムについて
    ■スマホ側
     小生Androidなので、Google Playストアからインストールします
    Google Playストアで、

    dabble app で検索して
    左記アプリを
    インストールします
    起動すると、左記のような
    メニューが表示されます

    今回は、Gamepadを使
    います
    Gamepadを選択すると
    Digital Padが開きますので
    右上の□ボタンを押します
    モードの選択画面になります
    ので、Joystickモードを
    選択します
    Bluetoothで、ESP32と接続
    するには、
    接続アイコンを選択します
    ESP32が起動していれば、
    一覧に出ますので選択
    することで接続します


    ■ESP32側(Arduino IDE)
    ライブラリマネージャで、DabbleESP32と検索します

    2025年10月現在バージョンは、1.5.1です

    exampleのGamepadコンパイルしたら、エラーだらけ エラーの内容みたら、Arduino-esp32のバージョンが、v2から
    v3に上がった時に構文の書き方が変更になったところです もうこの時小生もニキシー管の時計を作っているときで、
    バージョン上げたらいきなりコンパイルエラー もうなんじゃコレでした
    V2に下げるのもいまいちなので、エラー部 ライブラリのソースを修正しました
    だいたい、構文変わってもいいけど、古い構文も互換で使えるようにしてほしいものです・・・。

    上記6ファイルの中身を修正しました
    修正分は、下記においておきます 6ファイルを入れ替えます V1.5.1用です
    DabbleESP32.zip


    参考プログラム例 サンプルにちょこっと追記しています

    Startボタンを押すと、揚力ファンを起動します
    Selectボタンを押すと、揚力ファンを停止します
    ▲ボタンを押すと、推力ファンを前進にセットします
    ×ボタンを押すと、推力ファンを後退にセットします
    Joystickは、前方向のみに反応します 倒す量によって推力ファンの回転数が変化します
    方向で、ラダーが変化します

    /*
       Gamepad module provides three different mode namely Digital, JoyStick and Accerleometer.

       You can reduce the size of library compiled by enabling only those modules that you want to
       use. For this first define CUSTOM_SETTINGS followed by defining INCLUDE_modulename.

       Explore more on: https://thestempedia.com/docs/dabble/game-pad-module/
    */
    #define CUSTOM_SETTINGS
    #define INCLUDE_GAMEPAD_MODULE
    #include <DabbleESP32.h>
    #include <ESP32Servo.h>
    #define SERVO_PIN 5
    #define AIN1 6
    #define AIN2 7
    #define BIN1 8
    #define BIN2 9

    Servo myServo;
    int Fstart=0;
    int Fford=1;

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);      // make sure your Serial Monitor is also set at this baud rate.
      Dabble.begin("MyEsp32");       //set bluetooth name of your device
      Serial.println("Start");
      myServo.attach(SERVO_PIN);
      pinMode(AIN1, OUTPUT);
      pinMode(AIN2, OUTPUT);
      pinMode(BIN1, OUTPUT);
      pinMode(BIN2, OUTPUT);
    }

    int pwmB=0;
    void loop() {
      Dabble.processInput();             //this function is used to refresh data obtained from smartphone.Hence calling this function is mandatory in order to get data properly from your mobile.
      //Serial.print("KeyPressed: ");
      if (GamePad.isUpPressed())
      {
        //Serial.print("Up");
      }

      if (GamePad.isDownPressed())
      {
        //Serial.print("Down");
      }

      if (GamePad.isLeftPressed())
      {
        //Serial.print("Left");
      }

      if (GamePad.isRightPressed())
      {
        //Serial.print("Right");
      }

      if (GamePad.isSquarePressed())
      {
        //Serial.print("Square");
      }

      if (GamePad.isCirclePressed())
      {
        //Serial.print("Circle");
      }

      if (GamePad.isCrossPressed())
      {
        //Serial.print("Cross");
        Fford=0;
      }

      if (GamePad.isTrianglePressed())
      {
        //Serial.print("Triangle");
        Fford=1;

      }

      if (GamePad.isStartPressed())
      {
        //Serial.print("Start");
        if(Fstart==0){
          Fstart=1;
          analogWrite(AIN1, 255); // IN1にPWM信号
          analogWrite(AIN2, LOW);  // IN2をLOWにして正回転
        }

      }

      if (GamePad.isSelectPressed())
      {
        //Serial.print("Select");
        if(Fstart==1){
          Fstart=0;
          analogWrite(AIN1, LOW); // IN1にPWM信号
          analogWrite(AIN2, LOW);  // IN2をLOWにして正回転
        }
      }
      //Serial.print('\t');

      int a = GamePad.getAngle();
      if (a != 0){
      //Serial.print("Angle: ");
      //Serial.print(a);
      //Serial.print('\t');
        if(pwmB!=0){
          if(a <181){
            int out=map(a,0,180,30,150);
            myServo.write(out);
          }
        }
       
      }


      int b = GamePad.getRadius();
      //Serial.print("Radius: ");
      //Serial.print(b);
      //Serial.print('\t');
      int XB=map(b,0,7,0,255);
      if (XB!=pwmB){
        pwmB=XB;
        if(Fford==1){
          analogWrite(BIN1, pwmB); // IN1にPWM信号
          analogWrite(BIN2, LOW);  // IN2をLOWにして正回転
        }
        else{
          analogWrite(BIN1, LOW); // IN1にPWM信号
          analogWrite(BIN2, pwmB);  // IN2をLOWにして正回転      
        }
          if(pwmB==0){myServo.write(90);}
      }


      float c = GamePad.getXaxisData();
      //Serial.print("x_axis: ");
      //Serial.print(c);
      //Serial.print('\t');
      float d = GamePad.getYaxisData();
      //Serial.print("y_axis: ");
      //Serial.println(d);
      //Serial.println();
    }





    以上間違い等ありましたら、以下ご意見箱にお願いします

   

    ご意見箱