Project Started


รับทราบ—กำหนด โซลเดอร์มาสก์สีดำ และแนะนำซิลค์สกรีนสีขาวเพื่อให้อ่านป้ายขาและลูกศรทิศทางได้ชัด ผมจะบันทึกเป็นข้อกำหนดการผลิตของบอร์ด
สร้างสเปกและวงจรต้นแบบแล้ว รวม 42 อุปกรณ์ / 24 เน็ต พร้อมภาค Buck 2S→5V, ซ็อกเก็ตถอดเสียบ ESP32‑S3 SuperMini, GY‑87 แบบบัดกรีถาวร และคอนเนกเตอร์ ESC แบบ JST‑GH 8 พิน 1.25 มม. กำหนด GPIO ตามที่ระบุ: SDA=8, SCL=9, M1–M4=4–7
รายการที่ยังต้องทำ
  • ตรวจ ERC และยืนยันผังขาคอนเนกเตอร์ ESC ด้วยมัลติมิเตอร์ก่อนเสียบจริง
  • ตรวจตำแหน่งพินของ SuperMini รุ่นที่ซื้อ เนื่องจากแต่ละผู้ผลิตอาจจัดขาไม่เหมือนกัน
  • ตรวจเอกสารเฟิร์มแวร์/แผน Bring-up รอบสุดท้าย
  • จัดวาง PCB, รูยึด 30.5×30.5 มม., antenna keepout และเดินลาย
  • เลือกโซลเดอร์มาสก์สีดำ/ซิลค์สกรีนสีขาวตอนสั่งผลิต
ขณะนี้ ACUs หมด จึงยังตรวจสอบและทำขั้นตอน PCB ต่อไม่ได้ แต่ไฟล์ Project Specification และวงจรที่สร้างไว้ยังอยู่ในโครงการครบถ้วน
Received notification from "Quadcopter Flight Controller" that it finished — picking the work back up.
ตัว executor ทำวงจรต้นแบบเสร็จแล้ว แต่ยังเหลือ ตรวจ ERC/ผังขา ESC และ SuperMini, จัดวาง PCB 30.5×30.5 มม., antenna keepout, เดินลาย และตรวจ DRC ขั้นสุดท้าย ขณะนี้ไม่สามารถดำเนินการต่อได้เพราะ ACUs ไม่เพียงพอ; งานที่สร้างไว้ยังคงอยู่ในโปรเจกต์ครบถ้วน
ตรวจ ERC และขา
ตั้งค่าบอร์ดและวาง
วางแล้วตรวจ DRC

Firmware Getting Started
Hardware Pin Map

Table


FunctionESP32-S3 pinSchematic connection
VBAT ADCGPIO1 / ADC1J2 pin 4, ADC_VBAT_GPIO1
ESC Current ADCGPIO2 / ADC1J2 pin 5, ADC_CURRENT_GPIO2
Motor 1GPIO4J2 pin 7 → R8 → J1 pin 3
Motor 2GPIO5J2 pin 8 → R9 → J1 pin 4
Motor 3GPIO6J2 pin 9 → R10 → J1 pin 5
Motor 4GPIO7J2 pin 10 → R11 → J1 pin 6
I2C SDAGPIO8J3 pin 1 → J4 pin 5
I2C SCLGPIO9J3 pin 2 → J4 pin 4
Before assembling or powering the board, compare the exact purchased ESP32-S3 SuperMini silkscreen labels with socket rows J2/J3. The carrier uses a selected common 1×10 + 1×8 representation; clone variants can differ.
PlatformIO Setup
Create platformio.ini:

Ini


[env:esp32-s3-supermini]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
board_build.flash_mode = qio
board_build.arduino.memory_type = qio_qspi
build_flags =
  -D ARDUINO_USB_CDC_ON_BOOT=1
  -D BOARD_HAS_PSRAM
If the purchased board has no PSRAM, remove BOARD_HAS_PSRAM and board_build.arduino.memory_type. Build and upload:

Bash


pio run
pio run -t upload
pio device monitor
No third-party libraries are required for this starter. Wire.h and WiFi.h are provided by Arduino-ESP32.
Safe Starter Firmware
The skeleton below keeps all motor outputs LOW. It intentionally does not implement arming or throttle commands.

Cpp


#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>

static constexpr uint8_t PIN_VBAT_ADC = 1;
static constexpr uint8_t PIN_CURRENT_ADC = 2;
static constexpr uint8_t PIN_MOTOR[4] = {4, 5, 6, 7};
static constexpr uint8_t PIN_I2C_SDA = 8;
static constexpr uint8_t PIN_I2C_SCL = 9;

static constexpr uint32_t COMMAND_TIMEOUT_MS = 500;
static constexpr float VBAT_R_TOP = 180000.0f;
static constexpr float VBAT_R_BOTTOM = 68000.0f;

WiFiServer configServer(80);
uint32_t lastValidCommandMs = 0;
bool armed = false;

void forceDisarmed() {
  armed = false;
  for (uint8_t pin : PIN_MOTOR) {
    digitalWrite(pin, LOW);
  }
}

void initMotorOutputsSafe() {
  // Configure outputs and force LOW before starting I2C, radio, or ADC work.
  for (uint8_t pin : PIN_MOTOR) {
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
  }
  forceDisarmed();
}

void scanI2C() {
  Serial.println("I2C scan:");
  for (uint8_t address = 1; address < 127; ++address) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.printf("  found 0x%02X\n", address);
    }
  }
}

float readVbatVolts() {
  // analogReadMilliVolts uses the Arduino-ESP32 calibration path when supported.
  const float adcV = analogReadMilliVolts(PIN_VBAT_ADC) / 1000.0f;
  return adcV * (VBAT_R_TOP + VBAT_R_BOTTOM) / VBAT_R_BOTTOM;
}

uint32_t readCurrentSenseMilliVolts() {
  // Do not convert this to amperes until the exact ESC scale is calibrated.
  return analogReadMilliVolts(PIN_CURRENT_ADC);
}

void startSafeConfigInterface() {
  // Prototype-only AP. Replace credentials and add authentication before flight use.
  WiFi.mode(WIFI_AP);
  WiFi.softAP("FC-BRINGUP", "change-this-password");
  configServer.begin();
  Serial.print("Config AP IP: ");
  Serial.println(WiFi.softAPIP());

  // BLE placeholder: initialize a BLE service here only after the disarm/failsafe
  // behavior has been validated. Never let radio initialization arm motors.
}

void serviceConfigInterface() {
  WiFiClient client = configServer.available();
  if (!client) return;

  client.setTimeout(50);
  String line = client.readStringUntil('\n');
  line.trim();

  // Only a harmless heartbeat/status command is recognized in this starter.
  if (line == "PING") {
    lastValidCommandMs = millis();
    client.printf("DISARMED=%d VBAT=%.3fV CURRENT_RAW=%lumV\n",
                  armed ? 0 : 1,
                  readVbatVolts(),
                  static_cast<unsigned long>(readCurrentSenseMilliVolts()));
  } else {
    client.println("ERR SAFE STARTER: ARM/THROTTLE NOT IMPLEMENTED");
  }
  client.stop();
}

void enforceFailsafe() {
  if ((millis() - lastValidCommandMs) > COMMAND_TIMEOUT_MS) {
    forceDisarmed();
  }
}

void setup() {
  initMotorOutputsSafe();

  Serial.begin(115200);
  delay(200);
  Serial.println("Flight controller safe bring-up firmware");

  analogReadResolution(12);
  analogSetPinAttenuation(PIN_VBAT_ADC, ADC_11db);
  analogSetPinAttenuation(PIN_CURRENT_ADC, ADC_11db);

  Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL, 400000);
  scanI2C();

  lastValidCommandMs = millis();
  startSafeConfigInterface();
  forceDisarmed();
}

void loop() {
  serviceConfigInterface();
  enforceFailsafe();

  static uint32_t nextReport = 0;
  if (millis() >= nextReport) {
    nextReport = millis() + 1000;
    Serial.printf("DISARMED VBAT=%.3fV CURRENT_RAW=%lumV\n",
                  readVbatVolts(),
                  static_cast<unsigned long>(readCurrentSenseMilliVolts()));
  }

  delay(1);
}
Startup Sequence
  1. Configure GPIO4-GPIO7 as outputs and drive LOW.
  2. Start USB serial.
  3. Configure GPIO1/GPIO2 ADC attenuation.
  4. Start I2C on GPIO8/GPIO9 and scan the bus.
  5. Start the safe Wi-Fi configuration interface.
  6. Reassert the disarmed state.
  7. Continuously enforce the command-loss timeout.
Sensor Notes
  • J4 is a permanent soldered GY-87 interface, not a removable socket. Verify its pin order and orientation before soldering.
  • Expected GY-87 addresses often depend on the exact module revision and populated sensor clones. Use the scan result rather than assuming identities.
  • Some modules require enabling MPU6050 bypass mode before the magnetometer is visible.
  • Confirm the physical sensor axes and create a firmware axis transform matching the board forward arrow.
Motor Output Development
  • Begin with static LOW/HIGH oscilloscope checks through R8-R11, with the ESC disconnected.
  • Add PWM or DShot only after validating the pin map and failsafe.
  • Keep propellers removed for every bench motor test.
  • An actual flight-control loop, arming state machine, authenticated command transport, sensor fusion, and DShot generation are outside this safe starter.
  • Hardware Pin Map

  • PlatformIO Setup

  • Safe Starter Firmware

  • Startup Sequence

  • Sensor Notes

  • Motor Output Development