見出し画像

カタオカ式ゴーグルLED(パレード)

パレードLED

目立ちたがりFPVレーサーの間で感染が拡大しているカタオカ式ゴーグルLEDの応用版でスロットル開度に応じてLEDが光ります
なかなかフルスロットルに入れられないヘナチョコが見栄を張るためにスロットルが7割程度でもパレードが表示できるようにボタンがあります、ディスアーム中にBボタンを押してマイコンのLEDが赤になればヘナチョコモードで、白は通常モードです
注)パレードはドローン部長松原さんのアイデアです

参考資料

中身はこちらの記事の丸パクリです、怒られないかちょっと心配ですが

きよっちさんの動画も参考にしてください

エロス受信機をWiFi設定するような、FCCは通っているけど技適は通っていない機器で電波を出す際にはこちらから前もって申請を行っておいてください

パーツの例

2sリポのバランス端子から電源を取りたいのでDC-DCコンバータ 2sリポからなので8v前後の入力から5vが取り出せて1A以上の容量があるもの
電圧調整機能があるものは配線する前に5vが出力できるように調整する
このコンバータは配線前に必ず電圧調整を行なってください

Seeed Studio XIAO RP2040

エロス受信機

シリアルLED 通常のテープでもいいですがCOBタイプはこちらから
LEDの数は16個を想定しています

長いCOBやテープの場合は16個数えて切り取りラインで切ります

受信機の設定

受信機はファームをエロスv3にします、送信機がV3になっていない場合は送信機もV3にしてください、送信機にはバインドフレーズを設定しておきます
(エロスv2でも成功の報告あり)
アームスイッチは必ずAUX1(ch5)にしてください、エロスはch5を1bitにすることで速度を速めるという小技を使っているので、アームスイッチはch5に固定です
受信機に電源を接続して60秒ほど待ちMac(PC)のWiFiのssidをExpressLRSを選び接続します
バインドフレーズが設定されていない場合は下図のところから入力してSAVEしてください

バインドフレーズが設定できたら送信機と繋がっているか確認します
接続が確認できたら送信機をOFFにしてもう一度WiFiで接続しMODELタブでテレメトリーをOFFにします
テレメトリーがONの場合は送信機を独り占めしますが、OFFの場合は送信機が垂れ流している信号を拾うことができるようになります

配線

ArduinoIDEでスケッチを流し込む

ArduinoIDEのダウンロードはこちらから、「JustDownload」ボタンで寄付しなくても使えますが、寄付しないことを推奨はしません

ArduinoIDEのインストールについてはGPTってください

XIAO RP2040ボードがIDEで扱えるようにセットアップ

ArduinoIDE→Preferencesを開いてAdditional boards manager URL’sにJSONを追加します
追加するJSON
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

ボードマネージャからSeeed XIZO RP2040等で検索しインストールしてください

シリアルLEDが使えるようにライブラリを登録

ライブラリマネージャでneopixel等で検索しライブラリをインストールします

ライブラリにTinyUSBを追加

ライブラリマネージャでadafruit tinyusb等で検索しライブラリをインストールします

ボードとポートの選択

XIAO RP2040をMac(PC)にUSBで接続します
Select other board and port…を選択し

Seeed XIAO RP2040とそれっぽいポートを選びます

USB Stackを選ぶ

スケッチ作成

NewSketchを選択し新しいスケッチを作成
ExpressLRS受信機をUSBドングルにする」ページからコピーしたコードで置き換えて
下記のように3箇所追加・編集します

Code

// #define DEBUG 行の下にブロックを追加

/////////////////////////////////////////////////1箇所目ここから
#include <Adafruit_NeoPixel.h>
#define LED_PIN D1    // LEDのデータ出力ピン
#define LED_COUNT 16  // LEDの数

#define onboardPOWER 11
#define onboardPIN 12
Adafruit_NeoPixel pixels(LED_COUNT, LED_PIN);
Adafruit_NeoPixel onBoard_pixels(1, onboardPIN);
bool updown = true;
bool flg = false;
bool showoff = false; //ヘナチョコモードをデフォルトにする場合は bool showoff = true;
int maxValue = LED_COUNT;
//////////////////////////////////////////////////1箇所目ここまで

SETUPハンドルのwhile (!TinyUSBDevice.mounted()) delay(1);行をコメントアウトして、追加

	///////////////////////////////////2箇所目ここから
  ////////////////////////////////////下の行をコメントアウトする
  // while (!TinyUSBDevice.mounted()) delay(1);  // wait until device mounted
  pixels.begin();
  pixels.clear();
  pixels.show();
  // pinMode(BTN, INPUT_PULLUP);
  pinMode(11, OUTPUT);
  digitalWrite(11, HIGH);
  onBoard_pixels.begin();

  //////////////////////////////////////2箇所目ここまで

LOOPハンドルの if (datardyf) { // データが揃ったらUSB送信 行の下にブロックを追加

アーム時の挙動の部分 //TAERの場合gp.ch[0] 、 AETRの場合gp.[2] に設定

if ((gp.sw & 0x01) == 0) {
      //ディスアーム時の挙動
      if (BOOTSEL) {
    showoff = !showoff;
    delay(500);
  }
  if (!showoff) {
    onBoard_pixels.setPixelColor(0, onBoard_pixels.Color(16, 16, 16));
    maxValue = 1630;
  } else {
    maxValue = 1000;
    onBoard_pixels.setPixelColor(0, onBoard_pixels.Color(32, 0, 0));
  }
  onBoard_pixels.show();

      int time = (millis() / (LED_COUNT * 2)) % LED_COUNT;
      if ((time == 0) && (flg == false)) {
        flg = true;
        updown = !updown;
      }
      if ((time != 0) && (flg == true)) {
        flg = false;
      }

      if (updown) {
        pixels.clear();
        pixels.setPixelColor(time , pixels.Color(0, 50, 0));
        if (time > 1) pixels.setPixelColor(time-1, pixels.Color(0, 20, 0));
        if (time > 2) pixels.setPixelColor(time - 2, pixels.Color(0, 2, 0));
        pixels.show();
      } else {
        pixels.clear();
        pixels.setPixelColor(LED_COUNT - time, pixels.Color(0, 50, 0));
        if (time > 1) pixels.setPixelColor(LED_COUNT - time + 1, pixels.Color(0, 20, 0));
        if (time > 2) pixels.setPixelColor(LED_COUNT - time + 2, pixels.Color(0, 2, 0));
        pixels.show();
      }

    } else {
      //アーム時の挙動

      //スロットルの最小値と最大値によって174または1630を変更する必要がある
      //TAERの場合 gp.ch[0]  AETRの場合gp.ch[2]に設定
      int throttle = (gp.ch[0] - 174) * LED_COUNT / maxValue;
      


      if (throttle >= LED_COUNT) {
        //フルスロットル時の挙動
        for (int i = 0; i < LED_COUNT; i++) {
          switch (random(4)) {
            case 0:
              pixels.setPixelColor(i, pixels.Color(random(255), 0, 0));
              break;
            case 1:
              pixels.setPixelColor(i, pixels.Color(0, random(255), 0));
              break;
            case 2:
              pixels.setPixelColor(i, pixels.Color(0, 0, random(255)));
              break;
            case 3:
              pixels.setPixelColor(i, pixels.Color(random(200), 0, random(200)));
              break;
          }
        }
        pixels.show();
      } else {
        //通常のアーム時、スロットル位置を表示
        for (int i = 0; i < throttle; i++) {
          pixels.setPixelColor(i, pixels.Color(200, 0, 0));
        }
        for (int i = throttle; i < LED_COUNT; i++) {
          pixels.setPixelColor(i, pixels.Color(0, 0, 50));
        }
        pixels.show();
      }
    }
    ///////////////////////////////////////////////3箇所目ここまで

スロットル位置判定のところの値はみなさん違う値だと思うのでDEBUGをONにして値を探る等を行い適当に変更してください
フルスロットルでもパレードにならない場合は1630の値を1600とかに下げてみてください
LEDの表示はお好みで作成してください 明るさや色は pixels.Color(R , G , B) の括弧の中の各RGBの値で調節します。0〜255
ヘナチョコモードをデフォルトにする場合は20行目を bool showoff = true; に変更してください

Code全体

#include "Adafruit_TinyUSB.h"
/* Adafruit_TinyUSB ライブラリは
 *  XIAO の場合 <Version 0.10.5> を使うこと。それ以上だとXIAOではコンパイルエラーが出ます。
 *  XIAO RP2040 は最新バージョンでOKです。
*/

// #define DEBUG

/////////////////////////////////////////////////1箇所目ここから
#include <Adafruit_NeoPixel.h>
#define LED_PIN D1    // LEDのデータ出力ピン
#define LED_COUNT 16  // LEDの数

#define onboardPOWER 11
#define onboardPIN 12
Adafruit_NeoPixel pixels(LED_COUNT, LED_PIN);  //, NEO_GRB + NEO_KHZ800
Adafruit_NeoPixel onBoard_pixels(1, onboardPIN);
bool updown = true;
bool flg = false;
bool showoff = false;//////////////*************へなちょこはここを bool showoff = true
int maxValue = LED_COUNT;
//////////////////////////////////////////////////1箇所目ここまで

// USB HID report descriptor
// ゲームパッドデータの構造を指定します  (プロポ受信機用 (16bitデータ x 8ch) + (1bitデータ x 8ch))
#define TUD_HID_REPORT_DESC_GAMEPAD_9(...) \
  HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
    HID_USAGE(HID_USAGE_DESKTOP_GAMEPAD), \
    HID_COLLECTION(HID_COLLECTION_APPLICATION), /* Report ID if any */ \
    __VA_ARGS__ \
    HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
    HID_USAGE(HID_USAGE_DESKTOP_X), \
    HID_USAGE(HID_USAGE_DESKTOP_Y), \
    HID_USAGE(HID_USAGE_DESKTOP_Z), \
    HID_USAGE(HID_USAGE_DESKTOP_RX), \
    HID_USAGE(HID_USAGE_DESKTOP_RY), \
    HID_USAGE(HID_USAGE_DESKTOP_RZ), \
    HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \
    HID_USAGE(HID_USAGE_DESKTOP_DIAL), \
    HID_LOGICAL_MIN(0), \
    HID_LOGICAL_MAX_N(0x07ff, 2), \
    HID_REPORT_COUNT(8), \
    HID_REPORT_SIZE(16), \
    HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), /* 8 bit Button Map */ \
    HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \
    HID_USAGE_MIN(1), \
    HID_USAGE_MAX(8), \
    HID_LOGICAL_MIN(0), \
    HID_LOGICAL_MAX(1), \
    HID_REPORT_COUNT(8), \
    HID_REPORT_SIZE(1), \
    HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
    HID_COLLECTION_END

// CrossFire用
#define CRSF_BAUDRATE 420000
#define CRSF_MAX_PACKET_LEN 64
#define CRSF_NUM_CHANNELS 16

typedef enum {
  CRSF_ADDRESS_BROADCAST = 0x00,
  CRSF_ADDRESS_USB = 0x10,
  CRSF_ADDRESS_TBS_CORE_PNP_PRO = 0x80,
  CRSF_ADDRESS_RESERVED1 = 0x8A,
  CRSF_ADDRESS_CURRENT_SENSOR = 0xC0,
  CRSF_ADDRESS_GPS = 0xC2,
  CRSF_ADDRESS_TBS_BLACKBOX = 0xC4,
  CRSF_ADDRESS_FLIGHT_CONTROLLER = 0xC8,  // 受信データはこれで来る
  CRSF_ADDRESS_RESERVED2 = 0xCA,
  CRSF_ADDRESS_RACE_TAG = 0xCC,
  CRSF_ADDRESS_RADIO_TRANSMITTER = 0xEA,
  CRSF_ADDRESS_CRSF_RECEIVER = 0xEC,
  CRSF_ADDRESS_CRSF_TRANSMITTER = 0xEE,
} crsf_addr_e;

typedef enum {
  CRSF_FRAMETYPE_GPS = 0x02,
  CRSF_FRAMETYPE_BATTERY_SENSOR = 0x08,
  CRSF_FRAMETYPE_LINK_STATISTICS = 0x14,
  CRSF_FRAMETYPE_OPENTX_SYNC = 0x10,
  CRSF_FRAMETYPE_RADIO_ID = 0x3A,
  CRSF_FRAMETYPE_RC_CHANNELS_PACKED = 0x16,  // チャンネルパックフレーム
  CRSF_FRAMETYPE_ATTITUDE = 0x1E,
  CRSF_FRAMETYPE_FLIGHT_MODE = 0x21,
  // Extended Header Frames, range: 0x28 to 0x96
  CRSF_FRAMETYPE_DEVICE_PING = 0x28,
  CRSF_FRAMETYPE_DEVICE_INFO = 0x29,
  CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY = 0x2B,
  CRSF_FRAMETYPE_PARAMETER_READ = 0x2C,
  CRSF_FRAMETYPE_PARAMETER_WRITE = 0x2D,
  CRSF_FRAMETYPE_COMMAND = 0x32,
  // MSP commands
  CRSF_FRAMETYPE_MSP_REQ = 0x7A,    // response request using msp sequence as command
  CRSF_FRAMETYPE_MSP_RESP = 0x7B,   // reply with 58 byte chunked binary
  CRSF_FRAMETYPE_MSP_WRITE = 0x7C,  // write with 8 byte chunked binary (OpenTX outbound telemetry buffer limit)
} crsf_frame_type_e;

typedef struct crsf_header_s {
  uint8_t device_addr;  // from crsf_addr_e
  uint8_t frame_size;   // counts size after this byte, so it must be the payload size + 2 (type and crc)
  uint8_t type;         // from crsf_frame_type_e
  uint8_t data[0];
} crsf_header_t;

Adafruit_USBD_HID usb_hid;  // USB HID object
uint8_t const desc_hid_report[] = {
  TUD_HID_REPORT_DESC_GAMEPAD_9()  // USB GamePad のデータ構造を指定
};

typedef struct gamepad_data {
  uint16_t ch[8];  // 16bit 8ch
  uint8_t sw;      // 1bit  8ch
} gp_t;

uint8_t rxbuf[CRSF_MAX_PACKET_LEN + 3];  // 受信した生データ
uint8_t rxPos = 0;
static gamepad_data gp;  // CH毎に並び替えたデータ
uint8_t frameSize = 0;
int datardyf = 0;  // USBに送るデータが揃った。
uint32_t gaptime;  // bus 区切り測定用
uint32_t time_m;   // インターバル時間(debug用)

void setup() {
  // USB HID デバイス設定
  usb_hid.setPollInterval(1);  // 1msポーリング(ELRS v3.0の1000Hzに対応)
  usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
  usb_hid.begin();
  ///////////////////////////////////2箇所目ここから
  ////////////////////////////////////下の行をコメントアウトする
  // while (!TinyUSBDevice.mounted()) delay(1);  // wait until device mounted
  pixels.begin();
  pixels.clear();
  pixels.show();
  // pinMode(BTN, INPUT_PULLUP);
  pinMode(11, OUTPUT);
  digitalWrite(11, HIGH);
  onBoard_pixels.begin();

  //////////////////////////////////////2箇所目ここまで
  datardyf = 0;
  gaptime = 0;
  rxPos = 0;
  Serial.begin(CRSF_BAUDRATE);               // PCシリアル通信用 (受信機の速度に合わせる)
  Serial1.begin(CRSF_BAUDRATE, SERIAL_8N1);  // CRSF通信用 (420kbps,8bitdata,nonParity,1stopbit)
  time_m = micros();                         // インターバル測定用
}

void loop() {
  // Remote wakeup
  // if (TinyUSBDevice.suspended()) {
  //   // Wake up host if we are in suspend mode
  //   // and REMOTE_WAKEUP feature is enabled by host
  //   TinyUSBDevice.remoteWakeup();
  // }
  crsf();  // CRSF受信処理
  uart();  // UART通信処理(Firmware書き換え用)
  

  if (datardyf) {  // データが揃ったらUSB送信

    ///////////////////////////////////////////////3箇所目ここから
    if ((gp.sw & 0x01) == 0) {
      //ディスアーム時の挙動
      if (BOOTSEL) {
    showoff = !showoff;
    delay(500);
  }
  if (!showoff) {
    onBoard_pixels.setPixelColor(0, onBoard_pixels.Color(16, 16, 16));
    maxValue = 1630;
  } else {
    maxValue = 1000;
    onBoard_pixels.setPixelColor(0, onBoard_pixels.Color(32, 0, 0));
  }
  onBoard_pixels.show();

      int time = (millis() / (LED_COUNT * 2)) % LED_COUNT;
      if ((time == 0) && (flg == false)) {
        flg = true;
        updown = !updown;
      }
      if ((time != 0) && (flg == true)) {
        flg = false;
      }

      if (updown) {
        pixels.clear();
        pixels.setPixelColor(time , pixels.Color(0, 50, 0));
        if (time > 1) pixels.setPixelColor(time-1, pixels.Color(0, 20, 0));
        if (time > 2) pixels.setPixelColor(time - 2, pixels.Color(0, 2, 0));
        pixels.show();
      } else {
        pixels.clear();
        pixels.setPixelColor(LED_COUNT - time, pixels.Color(0, 50, 0));
        if (time > 1) pixels.setPixelColor(LED_COUNT - time + 1, pixels.Color(0, 20, 0));
        if (time > 2) pixels.setPixelColor(LED_COUNT - time + 2, pixels.Color(0, 2, 0));
        pixels.show();
      }

    } else {
      //アーム時の挙動

      //スロットルの最小値と最大値によって174または1630を変更する必要がある
      //TAERの場合 gp.ch[0]  AETRの場合gp.ch[2]に設定
      int throttle = (gp.ch[0] - 174) * LED_COUNT / maxValue;
      


      if (throttle >= LED_COUNT) {
        //フルスロットル時の挙動
        for (int i = 0; i < LED_COUNT; i++) {
          switch (random(4)) {
            case 0:
              pixels.setPixelColor(i, pixels.Color(random(255), 0, 0));
              break;
            case 1:
              pixels.setPixelColor(i, pixels.Color(0, random(255), 0));
              break;
            case 2:
              pixels.setPixelColor(i, pixels.Color(0, 0, random(255)));
              break;
            case 3:
              pixels.setPixelColor(i, pixels.Color(random(200), 0, random(200)));
              break;
          }
        }
        pixels.show();
      } else {
        //通常のアーム時、スロットル位置を表示
        for (int i = 0; i < throttle; i++) {
          pixels.setPixelColor(i, pixels.Color(200, 0, 0));
        }
        for (int i = throttle; i < LED_COUNT; i++) {
          pixels.setPixelColor(i, pixels.Color(0, 0, 50));
        }
        pixels.show();
      }
    }
    ///////////////////////////////////////////////3箇所目ここまで

    if (usb_hid.ready()) {
      usb_hid.sendReport(0, &gp, 17);  // 17 = sizeof(gp) コンパイルでsizeof()のサイズが変なので直接数値で指定
#ifdef DEBUG
      debug_out();  // デバッグ用 (シリアルモニターで数値を確認)
#endif
    }
    datardyf = 0;  // データ揃ったよフラグをクリア
  }
}

// CRSF受信処理
void crsf(void) {
  uint8_t data;
  // CRSFから1バイト受信
  if (Serial1.available()) {  // Serial1に受信データがあるなら
    data = Serial1.read();    // 8ビットデータ読込
    gaptime = micros();
    if (rxPos == 1) {
      frameSize = data;  // 2byte目はフレームサイズ
    }
    rxbuf[rxPos++] = data;  // 受信データをバッファに格納
    if (rxPos > 1 && rxPos >= frameSize + 2) {
      crsfdecode();  // 1フレーム受信し終わったらデーコードする
      rxPos = 0;
    }
  } else {
    if (rxPos > 0 && micros() - gaptime > 800) {  // 800us以上データが来なかったら区切りと判定
      rxPos = 0;
    }
  }
}

// CRSFから受信した11bitシリアルデータを16bitデータにデコード
void crsfdecode() {
  if (rxbuf[0] == CRSF_ADDRESS_FLIGHT_CONTROLLER) {       // ヘッダチェック
    if (rxbuf[2] == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {  // CHデータならデコード
      gp.sw = 0;
      gp.ch[0] = (rxbuf[3] | rxbuf[4] << 8) & 0x07ff;
      gp.ch[1] = (rxbuf[4] >> 3 | rxbuf[5] << 5) & 0x07ff;
      gp.ch[2] = (rxbuf[5] >> 6 | rxbuf[6] << 2 | rxbuf[7] << 10) & 0x07ff;
      gp.ch[3] = (rxbuf[7] >> 1 | rxbuf[8] << 7) & 0x07ff;
      if (((rxbuf[8] >> 4 | rxbuf[9] << 4) & 0x07ff) > 0x3ff) gp.sw |= 0x01;  // AUX1は2値データ
      gp.ch[4] = (rxbuf[9] >> 7 | rxbuf[10] << 1 | rxbuf[11] << 9) & 0x07ff;
      gp.ch[5] = (rxbuf[11] >> 2 | rxbuf[12] << 6) & 0x07ff;
      gp.ch[6] = (rxbuf[12] >> 5 | rxbuf[13] << 3) & 0x07ff;
      gp.ch[7] = (rxbuf[14] | rxbuf[15] << 8) & 0x7ff;
      if (((rxbuf[15] >> 3 | rxbuf[16] << 5) & 0x07ff) > 0x3ff) gp.sw |= 0x02;
      if (((rxbuf[16] >> 6 | rxbuf[17] << 2 | rxbuf[18] << 10) & 0x07ff) > 0x3ff) gp.sw |= 0x04;
      if (((rxbuf[18] >> 1 | rxbuf[19] << 7) & 0x07ff) > 0x3ff) gp.sw |= 0x08;
      if (((rxbuf[19] >> 4 | rxbuf[20] << 4) & 0x07ff) > 0x3ff) gp.sw |= 0x10;
      if (((rxbuf[20] >> 7 | rxbuf[21] << 1 | rxbuf[22] << 9) & 0x07ff) > 0x3ff) gp.sw |= 0x20;
      if (((rxbuf[22] >> 2 | rxbuf[23] << 6) & 0x07ff) > 0x3ff) gp.sw |= 0x40;
      if (((rxbuf[23] >> 5 | rxbuf[24] << 3) & 0x07ff) > 0x3ff) gp.sw |= 0x80;

      datardyf = 1;  // データ揃ったよフラグ
    }
  }
}

// UART通信処理( Firmware書き換え用 )
// ExpressLRS Configurator の Flashing Method は [UART]ではなく [BetaflightPassthough] にすること。
void uart(void) {
  uint32_t t;

  if (Serial.available()) {  // PCからデータが来たら、強制的に書き換えモードだと判断
    t = millis();
    do {
      while (Serial.available()) {     // PCからデータが来たら
        Serial1.write(Serial.read());  // PCからのデータを受信機に送る
        t = millis();
      }
      while (Serial1.available()) {    // 受信機からデータが来たら
        Serial.write(Serial1.read());  // 受信機のデータをPCに送る
        t = millis();
      }
    } while (millis() - t < 2000);  // データが来なくなったら終了
  }
}

// シリアルモニターに受信データを表示する(デバック用)
void debug_out() {
  int i;
  Serial.print(rxbuf[0], HEX);  // device addr
  Serial.print(" ");
  Serial.print(rxbuf[1]);  // data size +1
  Serial.print(" ");
  Serial.print(rxbuf[2], HEX);  // type
  Serial.print(" ");
  for (i = 0; i < 8; i++) {
    Serial.print(gp.ch[i]);
    Serial.print(" ");
  }
  Serial.print(gp.sw, BIN);
  Serial.print(" ");
  Serial.print(micros() - time_m);  // インターバル時間(us)を表示
  Serial.println("us");
  time_m = micros();
}

書き込み

エラーなく書き込みできれば、自動的に実行されます

使用方法

送信機の電源を先に入れてからパレードLEDに電池をつなぎます
へなちょこモードはXIAOのBボタンを押してXIAO上のLEDを赤にします
それだけ

作ってもらった物を自分用に設定する

  1. 送信機の電源を切る

  2. Mac(PC)を起動し、Chromeを立ち上げておく

  3. パレードLEDに電池をつなぐ

  4. 15秒ほど待つ

  5. Mac(PC)のWiFiのssidをexpressLRSに切り替える

  6. ExpressLRSのウィンドウが出現すればそのウィンドウで、出現しなければ Chromeで10.0.0.1にアクセスする

  7. Runtime OptionsでBinding Phraseを入力し SAVE & REBOOT する

たぶんこれで使えるようになるはず

RP2040のシリアルポートが現れなくなった時

Bボタンを押しながらUSBを接続します
シリアルポートを選ぶダイアログで「Show all ports」を選ぶと多分出てきます

さあ、みんなでパレードしよう


この記事が気に入ったらサポートをしてみませんか?