diff --git a/README.md b/README.md index 8d277c7..f1bc75e 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,12 @@ Outdoor flights demo video of the current prototype: +### Position control + +The position control feature is in development. RoboCamp 2026 demo (using an overhead camera, [sources](https://github.com/xTimop/flix-poscontrol/compare/robolager2026...xTimop:flix-poscontrol:poscontrol)): + + + ## Simulation The simulator is implemented using Gazebo and runs the original Arduino code: diff --git a/docs/usage.md b/docs/usage.md index 02e3a63..9c45103 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -25,7 +25,7 @@ You can build and upload the firmware using either **Arduino IDE** (easier for b * `FlixPeriph`, the latest version. * `MAVLink`, version 2.0.25. 5. Open the `flix/flix.ino` sketch from downloaded firmware sources in Arduino IDE. -6. Connect your ESP32 board to the computer and choose correct board type in Arduino IDE (*WEMOS D1 MINI ESP32* for ESP32 Mini) and the port. +6. Connect your ESP32 board to the computer and choose correct board type in Arduino IDE (*WEMOS D1 MINI ESP32* for ESP32 Mini, *ESP32S3 Dev Module* for ESP32-S3 Super Mini) and the port. 7. Set *Tools* ⇒ *Core Debug Level* to *Error* to see the errors in the serial console. Set *Tools* ⇒ *USB CDC on Boot* to *Enabled* for ESP32-S3/ESP32-C3 boards. 8. [Build and upload](https://docs.arduino.cc/software/ide-v2/tutorials/getting-started/ide-v2-uploading-a-sketch) the firmware using Arduino IDE. @@ -96,7 +96,7 @@ To access the console using serial port: To access the console using QGroundControl: 1. Connect to the drone using QGroundControl app. -2. Go to the QGroundControl menu ⇒ *Vehicle Setup* ⇒ *Analyze Tools* ⇒ *MAVLink Console*. +2. Go to the QGroundControl menu ⇒ *Analyze Tools* ⇒ *MAVLink Console*. @@ -337,7 +337,7 @@ To setup ESP-NOW communication: 1. Flash the second ESP32 board with ESP-NOW proxy sketch: [`tools/espnow-proxy/espnow-proxy.ino`](../tools/espnow-proxy/espnow-proxy.ino). Use Arduino IDE or command line: `make upload_proxy`. -2. Open Serial Monitor or use `make monitor` command. The ESP32 will print its MAC address and generated encryption key, for example: +2. Open Serial Monitor in Arduino IDE or use `make monitor` command. The ESP32 will print its MAC address and generated encryption key, for example: ``` espnow 7a:c8:e3:eb:bf:e9 &PiuSysxP9+$L&5E @@ -356,7 +356,10 @@ To setup ESP-NOW communication: * Type: Serial. * Serial Port: choose the port of the proxy ESP32 board, e. g. `/dev/cu.usbserial-0001`. * Baud Rate: 115200. -5. Click *Save*. QGroundControl should connect to the drone using ESP-NOW and begin showing the telemetry. +5. Click *Save*, click *Connect*. QGroundControl should connect to the drone using ESP-NOW and begin showing the telemetry. + +> [!TIP] +> Make sure Arduino IDE is not running when using ESP-NOW proxy board, as it may block the serial port. ## Flight log diff --git a/flix/parameters.ino b/flix/parameters.ino index 0c7da90..6cf9070 100644 --- a/flix/parameters.ino +++ b/flix/parameters.ino @@ -10,7 +10,7 @@ extern int channelZero[16], channelMax[16]; extern int rollChannel, pitchChannel, throttleChannel, yawChannel, armedChannel, modeChannel; extern int rcRxPin, voltagePin; extern int wifiMode, wifiLongRange, udpLocalPort, udpRemotePort, espnowChannel; -extern float rcLossTimeout, descendTime; +extern float rcLossTimeout, descendTime, disarmTilt; extern float voltageScale; extern LowPassFilter voltageFilter; @@ -153,6 +153,7 @@ Parameter parameters[] = { // safety {"SF_RC_LOSS_TIME", &rcLossTimeout}, {"SF_DESCEND_TIME", &descendTime}, + {"SF_DISARM_TILT", &disarmTilt}, }; void setupParameters() { diff --git a/flix/safety.ino b/flix/safety.ino index 05fd758..4e7e9dc 100644 --- a/flix/safety.ino +++ b/flix/safety.ino @@ -8,10 +8,12 @@ extern float controlRoll, controlPitch, controlThrottle, controlYaw; float rcLossTimeout = 1; float descendTime = 10; +float disarmTilt = radians(120); void failsafe() { rcLossFailsafe(); autoFailsafe(); + tiltFailsafe(); } // RC loss failsafe @@ -36,7 +38,7 @@ void descend() { // Allow pilot to interrupt automatic flight void autoFailsafe() { static float roll, pitch, yaw, throttle; - if (roll != controlRoll || pitch != controlPitch || yaw != controlYaw || abs(throttle - controlThrottle) > 0.05) { + if (abs(roll - controlRoll) > 0.05 || abs(pitch - controlPitch) > 0.05 || abs(yaw - controlYaw) > 0.05 || abs(throttle - controlThrottle) > 0.05) { // controls changed and mode switch is not configured if (mode == AUTO && invalid(controlMode)) mode = STAB; // regain control by the pilot } @@ -45,3 +47,15 @@ void autoFailsafe() { yaw = controlYaw; throttle = controlThrottle; } + +// Disarm if tilted too much +void tiltFailsafe() { + if (!armed) return; + if (mode != STAB) return; + + Vector up = Quaternion::rotateVector(Vector(0, 0, 1), attitude); + float tilt = acos(up.z); + if (disarmTilt && tilt > disarmTilt) { + armed = false; + } +} diff --git a/flix/wifi.ino b/flix/wifi.ino index eea9d8a..f316f83 100644 --- a/flix/wifi.ino +++ b/flix/wifi.ino @@ -58,7 +58,7 @@ void sendWiFi(const uint8_t *buf, int len) { espnow.write(buf, len); static Rate discovery(2); - if (discovery) espnowBroadcast.write((const uint8_t *)"flix", 4); // broadcast message to help finding this device + if (espnow.isEncrypted() && discovery) espnowBroadcast.write((const uint8_t *)"flix", 4); // broadcast message to help finding this device return; } diff --git a/gazebo/flix.h b/gazebo/flix.h index a85e068..20afe52 100644 --- a/gazebo/flix.h +++ b/gazebo/flix.h @@ -76,6 +76,7 @@ void failsafe(); void rcLossFailsafe(); void descend(); void autoFailsafe(); +void tiltFailsafe(); int parametersCount(); const char *getParameterName(int index); float getParameter(int index);