removed blog content, modified joplin export to export only notes/notebooks tagged with -blog-, readme update

This commit is contained in:
Yuriy 2024-07-05 18:45:24 -04:00
parent 435907d0fe
commit cac1ebb031
95 changed files with 28 additions and 5731 deletions

View File

@ -1,3 +1,14 @@
# This project is a fork of the very skilled [Stavros Korokithakis's Project](https://gitlab.com/stavros/notes/)
## Notable Changes
- Notes and Folders are grabbed based on a whitelist instead of a blacklist
- Instead of checking if a notebook/note is tagged with "private", instead checks if the notebook/note is tagged with "blog"
Stavros' notes
==============

View File

@ -1,13 +1,13 @@
[book]
authors = ["Stavros Korokithakis"]
authors = ["Yuriy Zinchuk"]
language = "en"
multilingual = false
src = "content"
title = "Stavros' Notes"
title = "Yuriy's Notes"
[output.html]
curly-quotes = true
no-section-label = true
git-repository-url = "https://gitlab.com/stavros/notes/"
git-repository-url = "https://zinchuk.xyz"
git-repository-icon = "fa-gitlab"
additional-css = ["static/custom.css"]

View File

@ -1,9 +1,9 @@
# The URL the site will be built for
base_url = "https://notes.stavros.io"
base_url = "https://zinchuk.xyz"
compile_sass = false
highlight_code = true
build_search_index = true
theme = "book"
title = "Stavros' Notes"
title = "Yuriy's Notes"
[extra]

View File

@ -1,58 +0,0 @@
# Summary
[🗈 Stavros' notes](welcome/stavros-notes.md)
- [🛸 Drone stuff](drone-stuff/index.md)
- [🗈 A simple guide to PID control](drone-stuff/a-simple-guide-to-pid-control.md)
- [🗈 E6000 hinges](drone-stuff/e6000-hinges.md)
- [🗈 Fixing the Matek ELRS receivers](drone-stuff/fixing-the-matek-elrs-receivers.md)
- [🗈 FPV frequency chart](drone-stuff/fpv-frequency-chart.md)
- [🗈 Getting uninverted SBUS on a no-name FrSky-compatible receiver](drone-stuff/getting-uninverted-sbus-on-a-no-name-frsky-compatible-receiver.md)
- [🗈 Getting uninverted SBUS/SmartPort on the FrSky XSR receiver](drone-stuff/getting-uninverted-sbus-smartport-on-the-frsky-xsr-receiver.md)
- [🗈 INAV tuning tips](drone-stuff/inav-tuning-tips.md)
- [🗈 Miscellaneous](drone-stuff/miscellaneous.md)
- [🗈 Omnibus F4 pro servo diode](drone-stuff/omnibus-f4-pro-servo-diode.md)
- [🗈 Omnibus F4 V3 pinout](drone-stuff/omnibus-f4-v3-pinout.md)
- [🗈 QGroundControl to Mission Planner conversion script](drone-stuff/qgroundcontrol-to-mission-planner-conversion-script.md)
- [🗈 Transmitter external module pinout](drone-stuff/transmitter-external-module-pinout.md)
- [🗈 Transportable C1 Chaser](drone-stuff/transportable-c1-chaser.md)
- [🛩️ ArduPilot](ardupilot/index.md)
- [🗈 ArduPilot recommended settings](ardupilot/ardupilot-recommended-settings.md)
- [🗈 ArduPilot setup checklist](ardupilot/ardupilot-setup-checklist.md)
- [🗈 Bitmask calculator](ardupilot/bitmask-calculator.md)
- [🗈 Building ArduPilot](ardupilot/building-ardupilot.md)
- [🗈 Configuring a switch as a relay](ardupilot/configuring-a-switch-as-a-relay.md)
- [🗈 Current sensor calibrator](ardupilot/current-sensor-calibrator.md)
- [🗈 DJI FPV configuration](ardupilot/dji-fpv-configuration.md)
- [🗈 ELRS preferred configuration](ardupilot/elrs-preferred-configuration.md)
- [🗈 HD OSD tool](ardupilot/hd-osd-tool.md)
- [🗈 Installing WTFOS on DJI](ardupilot/installing-wtfos-on-dji.md)
- [🗈 Miscellaneous notes](ardupilot/miscellaneous-notes.md)
- [🗈 Reverse thrust](ardupilot/reverse-thrust.md)
- [🗈 Statistics calculator](ardupilot/statistics-calculator.md)
- [🗈 TECS tuning calculator](ardupilot/tecs-tuning-calculator.md)
- [🗈 Transfer config between craft](ardupilot/transfer-config-between-craft.md)
- [🗈 Tuning the TECS](ardupilot/tuning-the-tecs.md)
- [🏗️ Model build notes](model-build-notes/index.md)
- [🗈 Build notes for the FT Mighty Mini Arrow](model-build-notes/build-notes-for-the-ft-mighty-mini-arrow.md)
- [🗈 Mini Drak build condensed instructions](model-build-notes/mini-drak-build-condensed-instructions.md)
- [📁 Maker things](maker-things/index.md)
- [🗈 Battery discharge curves](maker-things/battery-discharge-curves.md)
- [🗈 Details about my Sapphire Pro](maker-things/details-about-my-sapphire-pro.md)
- [🗈 Electronics tips](maker-things/electronics-tips.md)
- [🗈 GRBL_ESP32 tips](maker-things/grbl-esp32-tips.md)
- [🗈 How to properly level your 3D printer](maker-things/how-to-properly-level-your-3d-printer.md)
- [🗈 Info on various hardware components](maker-things/info-on-various-hardware-components.md)
- [🗈 Installing BLTouch-compatible firmware onto the TwoTrees Sapphire Pro](maker-things/installing-bltouch-compatible-firmware-onto-the-twotrees-sapphire-pro.md)
- [🗈 Notes on my TimSav](maker-things/notes-on-my-timsav.md)
- [🖥️ Programming](programming/index.md)
- [🗈 Interesting projects](programming/interesting-projects.md)
- [🐍 Python](python/index.md)
- [🗈 Decorator that runs a function in a thread](python/decorator-that-runs-a-function-in-a-thread.md)
- [💽 Software](software/index.md)
- [🗈 Black pills](software/black-pills.md)
- [🗈 Cloning cards/fobs with a Proxmark3](software/cloning-cards-fobs-with-a-proxmark3.md)
- [🗈 Getting VoWiFi working on Xiaomi.eu](software/getting-vowifi-working-on-xiaomi-eu.md)
- [🗈 Monero GUI syncing stuck with Ledger](software/monero-gui-syncing-stuck-with-ledger.md)
- [🗈 Pairing the Xbox One controller in Linux](software/pairing-the-xbox-one-controller-in-linux.md)
- [🗈 Resetting TP-Link Powerline plugs](software/resetting-tp-link-powerline-plugs.md)
- [🗈 Test and format SD cards](software/test-and-format-sd-cards.md)

View File

@ -1,61 +0,0 @@
# ArduPilot recommended settings
This section contains some recommended settings for ArduPilot. Nothing is set in stone, these are just some defaults I've found to work well.
## GPS
```js
GPS_GNSS_MODE=71 # Enable GPS/SBAS/Galileo/GLONASS.
GPS_RATE_MS=100 # 10 Hz update rate.
```
## Crossfire/ELRS
```js
SERIALn_PROTOCOL=23 # Crossfire/ELRS.
RC_OPTIONS=800 # 5 - Arming check throttle.
# 8 - CRSF telemetry passthrough.
# 9 - Suppress CRSF mode/rate message for ELRS.
```
## Expo
30% expo is a good starting point:
```js
MAN_EXPO_ROLL=30
MAN_EXPO_PITCH=30
MAN_EXPO_RUDDER=30
```
## Miscellaneous
```js
INS_GYRO_FILTER=60 # Faster gyro updates.
SCHED_LOOP_RATE=100 # Faster scheduler updates.
```
## Servo update rate
If you want a higher servo update rate (because of digital servos), it is probably better to set the scheduler loop rate to the frequency you want, and enable ONESHOT on the servos:
```js
SCHED_LOOP_RATE=200 # As above.
ONESHOT_MASK=6 # Change to whatever channels your servos are on.
```
## Switch arming
If you want to use switch arming rather than stick arming, here are the relevant parameters:
```js
RCx_OPTION=153
ARMING_RUDDER=0
```
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 09, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,117 +0,0 @@
# ArduPilot setup checklist
This is a short guide for setting up [ArduPilot](https://ardupilot.org/) on a flying wing. I use an Omnibus F4 that was previously set up for INAV (so motor on 1, elevons on 3/4), so most of this guide will be geared to that. If you use a different controller, your mileage may vary.
You should keep the [full list of ArduPilot parameters](https://ardupilot.org/plane/docs/parameters.html) open, for your reference while tuning.
## Helper utility
I have created a utility that lets you easily get/set/backup/restore parameters from the command line.
It's called Parachute, and you can download it here:
[https://gitlab.com/stavros/parachute](https://gitlab.com/stavros/parachute)
## Building ArduPilot
See [Building ArduPilot](/ardupilot/building-ardupilot.html) for instructions on how to build the latest version.
## Hardware setup
The values in this section are specific to the Omnibus F4, but the settings aren't, so you'll usually need to adjust your outputs to your specific configuration but you probably won't need to skip many of the steps here.
- [ ] Connect GPS to UART 6 (SERIAL4). You don't need to do anything else for GPS, it should work out of the box. If it doesn't, set `SERIALn_PROTOCOL=5`.
- [ ] Change the FC's orientation with `AHRS_ORIENTATION` and monitor the artificial horizon to see if it moves correctly.
- [ ] Make sure the artificial horizon is level when the plane is level on the ground. Use the "calibrate level" button or `AHRS_TRIM_Y` to correct it if it's not.
- [ ] Calibrate the accelerometer. "Forward" here needs to be the forward direction of the plane, not the arrow on the FC.
- [ ] Connect Fport to a UART. I chose UART 3 (SERIAL2). If you want to use UART 1, you should set the RC input jumper to PPM on the F4 to disconnect the SBUS inverter from the pin.
- [ ] To get Fport working with UART 3, you need to set `BRD_ALT_CONFIG=1`, to get UART 3 to act like a UART instead of I2C on the Omnibus F4.
- [ ] Set the following for Fport on UART 3:
```js
SERIAL2_PROTOCOL=23 # RCIN
SERIAL2_BAUD=115
SERIAL2_OPTIONS=4
RSSI_TYPE=3
```
- [ ] Once Fport works, reverse the elevator with `RC2_REVERSED=1`.
- [ ] Set up your servo functions and trims:
```js
SERVO1_FUNCTION=70 # Throttle
SERVO1_MIN=1000
SERVO1_MAX=2000
SERVO1_TRIM=1000
SERVO3_FUNCTION=77 # Left elevon
SERVO3_MIN=1000
SERVO3_MAX=2000
SERVO3_TRIM=1500
SERVO4_FUNCTION=78 # Right elevon
SERVO4_MIN=1000
SERVO4_MAX=2000
SERVO4_TRIM=1500
```
All these values are necessary, because usually the `SERVOn_TRIM` won't be at 1500.
- [ ] Switch to FBWA and validate that the control surfaces move correctly. If they don't, set `SERVOn_REVERSED=1`. It needs to be FBWA and not MANUAL because FBWA has some additional processing like PIDs, etc.
- [ ] Set `SERVO_BLH_OTYPE=4` for DShot150 and `SERVO_BLH_MASK=1` to enable it for the motor.
- [ ] Set `COMPASS_ENABLE=0` if you don't have a compass, otherwise calibrate it (not detailed here).
- [ ] Set `TERRAIN_ENABLE=0` to get rid of the terrain warning.
- [ ] Set the FC's pitch relative to the body with `AHRS_TRIM_Y` and check that FBWA mode flies level.
- [ ] If you don't use logging, set `LOG_BACKEND_TYPE=0`. If you *do* use logging, set `LOG_DISARMED=1 LOG_FILE_DSRMROT=0` to prevent the EKF from diverging and causing problems on takeoff.
- [ ] Check the preflight errors to warn on, though usually leaving it set to "all" is fine.
- [ ] Set up the OSD (Mission Planner has a very nice UI for that). Keep in mind that ArduPilot's airspeed and windspeed estimation are quite good, so you may want to add those even if you don't have an airspeed sensor. You may also want to set up multiple screens, I use a potentiometer to switch between the four different screens of the OSD:
- One with everything on (for debugging), which is also set as the `OSD_ARM_SCR`/`OSD_DSARM_SCR`.
- One with the artificial horizon, system messages and some basic info like RSSI, battery, ground speed and altitude.
- A minimal screen with just system messages and battery/RSSI/speed/altitude.
- A screen with just system messages, for when I want to enjoy the scenery.
## Radio-related
- [ ] Set your radio channels to AETR and run the radio calibration in the calibration section of ArduPilot.
- [ ] Add a killswitch to the radio that overrides the mode to manual and the throttle to 0.
This way it's really easy to kill the motor right away, but you still need to go through the arming procedure to get the motor running (thanks to Michel Pastor for this great idea).
- [ ] Set up modes, possibly having switches override the mode channel to the mode you want.
What I do is set a given channel as the mode channel, and make that channel always output -100% on the radio. Then, I set up channel overrides for each switch, keeping in mind that overrides in OpenTX are executed in order (so the bottom override has the highest priority).
That way, I set MANUAL/ACRO/FBWA to be lowest priority (on the same switch), then CRUISE to override those, then LOITER, RTL in that order. Finally, I add AUTO to a switch on its own channel.
Keep in mind that whatever mode you have on its own channel might be overridden if you flick a different switch.
## Auto modes
- [ ] Set `SERVO_AUTO_TRIM=1` so the aircraft trims itself while flying.
- [ ] Set `FS_SHORT_ACTN`/`FS_SHORT_TIMEOUT`/`FS_LONG_ACTN`/`FS_LONG_TIMEOUT`. I tend to disable the short action and set long to RTL.
- [ ] Set `FLIGHT_OPTIONS+=16` so the aircraft climbs first before starting to return to home.
- [ ] Change `AUTOTUNE_LEVEL` according to how aggressive you want the tune.
- [ ] Set `ACRO_PITCH_RATE`/`ACRO_ROLL_RATE` according to your craft.
- [ ] Set `THR_PASS_STAB=1` so you have total throttle control in ACRO/FBWA/STABILIZE.
- [ ] Set `ARSPD_FBW_MIN`/`ARSPD_FBW_MAX` to the minimum and maximum airspeed you want auto modes to fly (see the TECS tuning guide below for details).
- [ ] Set `MIN_GNDSPD_CM=833` (30 km/h) so the craft makes an effort to return even under high winds.
- [ ] Set `RTL_SINK_MAX=2` to enable a very slow descent on RTL (you generally don't need to descend fast on RTL).
## Auto takeoff
- [ ] Change `TKOFF_THR_MAX` to the desired max takeoff throttle.
- [ ] Change `TKOFF_ALT` to the altitude you want takeoff to reach.
- [ ] Set `THR_SUPP_MAN=1` so you can manually set the autolaunch "idle" throttle (before the throw).
- [ ] Set `TKOFF_THR_MINACC=18` for the takeoff throw to activate takeoff with a minimum of 2g.
- [ ] Set `TKOFF_LVL_PITCH` to your desired angle (20 is a good value).
- [ ] Set `TKOFF_THR_DELAY` to the number of deciseconds that you want the motor to wait before it starts up.
- [ ] Set `FLIGHT_OPTIONS+=64` so the aircraft doesn't oscillate on auto takeoff without an airspeed sensor.
- [ ] Potentially set `TKOFF_THR_SLEW=-1` to make the throttle spin up faster.
## Recommended settings.
See the [recommended settings](/ardupilot/ardupilot-recommended-settings.html) page for other recommended defaults.
## In the field
- [ ] Run an [autotune](/ardupilot/miscellaneous-notes.html).
- [ ] Fly in FBWA and see if you're gaining/losing altitude. Pitch up/down to fly level, check the pitch on the OSD, and use the formula `old_value+pitch*π/180` to get the new value for `AHRS_TRIM_Y` (in radians).
- [ ] After you set `AHRS_TRIM_Y` correctly above, fly in FBWA at full throttle (or whatever throttle you feel is "full" enough, and note that value), and note the pitch you need so that the wing doesn't climb or sink. Then, set `KFF_THR2PTCH` with the formula `pitch_value_in_deg * 100 / throttle_percentage`. `pitch_value_in_deg` should be positive if you needed up pitch and negative if you needed down pitch.
_(Many thanks to Michel Pastor and mfoos for their help with everything in this note.)_
* * *
<p style="font-size:80%; font-style: italic">
Last updated on April 15, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,190 +0,0 @@
# Bitmask calculator
<style>
div.box{
width: 90%;
}
table {
border: 1px solid #222;
}
</style>
<script type="text/javascript">
// 1660727162
var bitmaskDescArr = [];
function dec2bin(dec) {
return reverse((dec >>> 0).toString(2));
}
function reverse(str) {
return str.split("").reverse().join("");
}
async function loadBitmask(){
// using the function:
removeAll(document.getElementById('paramSelect'));
url = document.getElementById("built").value;
console.log("fetching: "+ url);
if (url == ""){
return;
}
const response = await fetch(url,{
method: 'GET',
headers: {
'Content-Type': 'text/plain'
}
})
.then(response => response.text())
.then(data => {
const parser = new DOMParser();
const xml = parser.parseFromString(data, "application/xml");
var params = xml.getElementsByTagName("param");
console.log("retrieved "+ params.length +" params")
for (var i = 0; i < params.length; i++) {
var param = params[i].attributes.name.nodeValue; //works, param name
param = param.replace("ArduPlane:","");
if(params[i].childNodes[1]){
if( typeof params[i].childNodes[1].attributes.name == "object"){
if(params[i].childNodes[1].attributes.name.nodeValue && params[i].childNodes[1].attributes.name.nodeValue == "Bitmask"){
var bitmaskDescTxt = params[i].textContent.trim();
bitmaskDescArr[param] = bitmaskDescTxt.split(',');
}
}
}
}
})
.catch(console.error);
// console.log(bitmaskDescArr.length);
drawSelect();
}
function drawSelect(){
bitmaskDescArr.sort();
Object.keys(bitmaskDescArr)
.sort()
.forEach(function(p, i) {
// console.log(p);
var el = document.createElement("option");
el.textContent = p;
el.value = p;
document.getElementById("paramSelect").appendChild(el);
});
}
function removeAll(selectBox) {
while (selectBox.options.length > 0) {
selectBox.remove(0);
}
}
function bitbox(bit){
dec = parseInt(document.getElementById("decimal").value);
if(!dec ){dec = parseInt(0);}
if(document.getElementById(bit).checked == true){
dec += parseInt(bit);
}else{
dec -= parseInt(bit);
}
document.getElementById("decimal").value = dec;
parseBitmask();
}
function parseBitmask() {
console.log("found "+Object.keys(bitmaskDescArr).length+" bitmask parameters");
document.getElementById("result").innerHTML="";
var tbl = document.createElement('table');
tbl.style="border: 1px solid black; width: 100%";
var tbdy = document.createElement('tbody');
binarybitmask=dec2bin(document.getElementById("decimal").value);
if(!binarybitmask){binarybitmask = parseInt(0);}
console.log("binarybitmask: "+binarybitmask);
var param = document.getElementById("paramSelect").value;
for (var option= 0; option < bitmaskDescArr[param].length; option++) {
var bit = parseInt(bitmaskDescArr[param][option].split(":",1)); //extract the first number before : of description
var enabled = binarybitmask[bit]; // check if it is enabled
if(!enabled){enabled=0};
var singleBitDecvalue = Math.pow(2,bit); // convert the bit to a decimal
var tr = document.createElement('tr');
var td = document.createElement('td');
td.style="border: 1px solid black;";
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.id = singleBitDecvalue;
checkbox.setAttribute("onclick","bitbox("+singleBitDecvalue+")");
if (enabled == "1"){
checkbox.checked = true;
}else{
checkbox.checked = false;
}
td.appendChild(checkbox);
tr.appendChild(td);
var td = document.createElement('td');
td.appendChild(document.createTextNode(bitmaskDescArr[param][option]));
if (enabled == "1"){
td.style = "border: 1px solid black; color: green";
}else{
td.style = "border: 1px solid black; color: red";
}
tr.appendChild(td);
var td = document.createElement('td');
td.style="border: 1px solid black; color: grey";
td.appendChild(document.createTextNode(singleBitDecvalue));
tr.appendChild(td);
tbdy.appendChild(tr);
tbl.appendChild(tbdy);
}
document.getElementById("result").appendChild(tbl);
}
</script>
<div class="box">
<div id="input">
<select id="built" onChange="loadBitmask();">
<option value='https://arducustom.github.io/v/dev/ArduPlane/apm.pdef.xml'>ArduCustom Plane master</option>
<option value='https://arducustom.github.io/v/10.0/ArduPlane/apm.pdef.xml'>ArduCustom Plane v10</option>
<option value='https://arducustom.github.io/v/9.0/ArduPlane/apm.pdef.xml'>ArduCustom Plane v9.0</option>
</select>
<select id="paramSelect" onChange="parseBitmask();">
</select>
<input type="text" id="decimal" value="1" oninput="parseBitmask();">
</div>
<br>
<div id="result">
</div>
</div>
<script type="text/javascript">
loadBitmask();
</script>
_(Many thanks to mfoos for writing this note.)_
* * *
<p style="font-size:80%; font-style: italic">
Last updated on October 07, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,60 +0,0 @@
# Building ArduPilot
Because building ArduPilot is a bit complicated, I've written a short script that uses Docker to build AP in a controlled environment.
Copy it from here, save it to a file called `docker_build.sh` in the root of the ArduPilot repo, and run it with `docker_build.sh <your board>`. Output files will be stored in `build/<yourboard>/bin/`, and you can flash them with the [INAV configurator](https://github.com/iNavFlight/inav-configurator/releases) by putting your board in DFU mode and uploading the `arduplane_with_bl.hex` file.
Here's the script:
```bash
#!/usr/bin/env bash
set -euox pipefail
if [ $# -ne 1 ]
then
echo "No board supplied, run as ./docker_build.sh <board name> or ./docker_build.sh list"
exit 1
fi
BOARD=$1
cd "$(git rev-parse --show-toplevel)"
git submodule update --init --recursive
git checkout Dockerfile
echo "RUN pip install intelhex" >> Dockerfile
echo 'ENV PATH="/home/ardupilot/.local/bin:/usr/lib/ccache:/ardupilot/Tools/autotest:${PATH}"' >> Dockerfile
cat Dockerfile
docker build . -t ardupilot
git checkout Dockerfile
# We need to update the PATH with the location of the ARM EABI inside the Docker
# container, so we write a script that handles this and the actual building.
cat <<EOF > undocker_build_temp.sh
#!/usr/bin/env bash
set -euox pipefail
export ARM_EABI=/opt/\$(ls -1 /opt/ | grep gcc-arm-none-eabi)/bin/
export PATH=\$ARM_EABI:\$PATH
./waf configure --board="\$1"
./waf build
EOF
chmod +x ./undocker_build_temp.sh
docker run --rm -it -v "$(pwd)":/ardupilot ardupilot ./undocker_build_temp.sh "$BOARD"
rm undocker_build_temp.sh
```
* * *
<p style="font-size:80%; font-style: italic">
Last updated on September 07, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,19 +0,0 @@
# Configuring a switch as a relay
If you want to connect a relay of some sort (something that accepts a low/high signal, like a camera control) to a PWM output (the servo outputs), you need to do a few quick things. The actual numbers will vary depending on your FC, but here's what worked for me with a Matek F405-Wing:
1. Set the channel you want the relay to trigger on as a controller for the first relay (here I'll assume you want to control the first relay on channel 11):
`RC11_OPTION=28`
2. Set the pin number for the relay you want to control. This is a bit fuzzy, it depends on your flight controller, but try a few out. This is what worked for me, for S6 on my F405-Wing:
`RELAY_PIN=55`
3. Set a servo to act as a GPIO output. I'm assuming here you want `SERVO6`, though I'm not quite sure how the servo selection maps to the `RELAY_PIN` selection above. For me, `AUXOUT6` and `SERVO6` worked:
`SERVO6_FUNCTION=-1`
If you're amazingly lucky, you should be all set. If not, you need to play with the `50` in the `RELAY_PIN` parameter and the `6` in the `SERVO6_FUNCTION` until something works.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on September 11, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,149 +0,0 @@
# Current sensor calibrator
<style>
div.box{
/* width: 90%; */
}
.number {
width: 60px;
}
</style>
<script type="text/javascript">
// 1674123219
function precisionRoundMod(number, precision) {
var factor = Math.pow(10, precision);
var n = precision < 0 ? number : 0.01 / factor + number;
return Math.round( n * factor) / factor;
}
function apcalc() {
scale = 100;
const measurements = [];
const realvalues = [];
const coeffs = [];
const scale_adjusted_meas = [];
const current_offsets = [];
for (var i = 1; i < 5; i++)
{
meas = parseFloat(document.getElementById('m'+i).value);
real = parseFloat(document.getElementById('r'+i).value);
measurements.push(meas);
realvalues.push(real);
if(i != 1){
var p=i;
p--;
pmeas = parseFloat(document.getElementById('m'+p).value);
preal = parseFloat(document.getElementById('r'+p).value);
coeffs.push( (meas-pmeas)/ (real-preal) );
}
}
for(var i=0, n=coeffs.length; i < n; i++)
{
console.log("coeff: "+parseFloat(coeffs[i]));
}
console.log("coeff sum: "+coeffs.reduce((partialSum, a) => partialSum + a, 0));
const avg_coeffs = coeffs.reduce((partialSum, a) => partialSum + a, 0) / coeffs.length;
console.log("coeff avg: "+avg_coeffs);
for(var i=0, n=measurements.length; i < n; i++)
{
scale_adjusted_meas.push(measurements[i]/avg_coeffs);
console.log("scale_adjusted_meas: "+measurements[i]/avg_coeffs);
}
for(var i=0, n=realvalues.length; i < n; i++)
{
current_offsets.push(scale_adjusted_meas[i] - realvalues[i]);
console.log(scale_adjusted_meas[i] - realvalues[i] );
}
const avg_offset = current_offsets.reduce((partialSum, a) => partialSum + a, 0) / current_offsets.length;
console.log("avg_offset: "+avg_offset);
document.getElementById('r_offset').value = precisionRoundMod( (avg_offset / (scale / avg_coeffs)), 4 );
document.getElementById('r_scale').value = precisionRoundMod( (scale / avg_coeffs) ,4);
}
function init() {
document.querySelectorAll("input").forEach(input => {
input.addEventListener("input", apcalc);
});
}
window.onload = init;
</script>
This calculator will allow you to calibrate your current sensor better than with the mAh charged vs mAh consumed method.
You need a current meter and a way to see what current and throttle percentage the FC reports (the OSD is a good way to do this).
The steps to follow are:
0. Make sure you have capacitors on ESCs so the measurement will not be influenced by errors from ESC noise.
1. Set `BATT_AMP_PERVLT=100` and `BATT_AMP_OFFSET=0`.
3. Power your plane with propellers on and a current meter connected between FC and pack.
4. Arm and run the motor in manual mode. For four different throttle positions, note down: The throttle position (from the OSD), the reported current (from the OSD), and the actual current (from the current meter). The best throttle positions to use would be 25%, 50%, 75% and 100%. Do not check current on idle as this will be inaccurate.
5. Enter the values below, and the calculator will give you the proper BATT_AMP_PERVLT and BATT_AMP_OFFSET values that you now need to write to your plane's parameters.
<div class="box">
<div id="input">
<table style="border: none">
<tr>
<td>OSD current:</td>
<td>
<input class="number" type="text" id="m1" value="1.7" placeholder="OSD value">
<input class="number" type="text" id="m2" value="3.4" placeholder="OSD value">
<input class="number" type="text" id="m3" value="7" placeholder="OSD value">
<input class="number" type="text" id="m4" value="10.3" placeholder="OSD value">
</td>
</tr>
<tr>
<td>
Real current:
</td>
<td>
<input class="number" type="text" id="r1" value="2.0" placeholder="current meter">
<input class="number" type="text" id="r2" value="4.0" placeholder="current meter" >
<input class="number" type="text" id="r3" value="8.0" placeholder="current meter" >
<input class="number" type="text" id="r4" value="12.0" placeholder="current meter">
</td>
</tr>
<tr>
<td>
<br>Results:<br>
</td>
</tr>
<tr>
<td>
<code>BATT_AMP_OFFSET</code>:
</td>
<td>
<input class="number" type="text" id="r_offset" value="" placeholder="offset" ><br>
</td>
</tr>
<tr>
<td>
<code>BATT_AMP_PERVLT</code>:
<td>
<input class="number" type="text" id="r_scale" value="" placeholder="scale" >
</td>
</tr>
</table>
</div>
<br>
<div id="result">
</div>
</div>
_(Many thanks to mfoos for writing this note.)_
* * *
<p style="font-size:80%; font-style: italic">
Last updated on February 05, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,41 +0,0 @@
# DJI FPV configuration
## Configuring ArduPilot for DJI FPV
If you're using the DJI FPV system, here's the relevant configuration you need to set:
1. Set `OSD_TYPE=3`.
2. Set `SERIALn_PROTOCOL=33 SERIALn_BAUD=115 SERIALn_OPTIONS=0` (DJI FPV).
3. Create a text file called `naco.txt` on the SD card of the Air Unit with the text `1` in it [to unlock full power](https://oscarliang.com/dji-fpv-system-fcc-700mw/).
4. Create a text file called `naco_pwr.txt` on the SD card of the goggles with the text `pwr_2` in it [to unlock more full power](https://oscarliang.com/dji-fpv-system-1200mw-output/).
5. Set "Custom OSD" to "on" in the goggles menu.
6. Arrange your OSD elements how you like them.
That's it!
## Configuring AP for the DJI O3
If you're using DJI O3, this is what you need to do:
* Set , `OSD_TYPE=5` for MSP_DISPLAYPORT.
* Set `SERIALn_PROTOCOL=42 SERIALn_BAUD=115 SERIALn_OPTIONS=0` for DisplayPort.
* Set `MSP_OPTIONS=5` for telemetry mode and BTFL fonts.
* Arrange your OSD elements as you want them.
Done!
## Synchronizing the video and audio of the DJI Air Unit
The audio of the DJI air unit is slower than the video, leading to desynchronization, but it is slower by a constant factor, which means it can be easily corrected with the following command:
```bash
$ ffmpeg -i "$1" -c:v copy -filter:a atempo=1.001480,volume=20 \
-c:a aac -b:a 93k "$(basename "$1" .mp4)_fixed_audio.mp4"
```
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 01, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,40 +0,0 @@
# ELRS preferred configuration
If you have an ExpressLRS system, this is my preferred config for ELRS 3.x:
## Packet rate
**100 Hz Full**
As I fly long-range fixed-wing, I go for *100 Hz Full* to get range and telemetry bandwidth.
## Telemetry ratio
**1:2**
I use this to get a high telemetry rate. It could probably go lower, but I don't think it hurts anything.
## Switch mode
**12ch Mixed**
I use this mode because I prefer having full rate on channels 1-4, rather than have three extra channels. For details, see [the documentation](https://www.expresslrs.org/3.0/software/switch-config/).
## TX Power
**Dynamic power at 250 mW max.**
I use this because dynamic power works well enough, and my transmitter only does 250 mW max. If yours does more, feel free to set it to that.
## Model match
**Off**
I don't like model match, as I have one radio model for all my ELRS planes. Having model match enabled would mean that I need one radio model per plane.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 19, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

File diff suppressed because one or more lines are too long

View File

@ -1,20 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [ArduPilot recommended settings](../../ardupilot/ardupilot-recommended-settings.html)
1. [ArduPilot setup checklist](../../ardupilot/ardupilot-setup-checklist.html)
1. [Bitmask calculator](../../ardupilot/bitmask-calculator.html)
1. [Building ArduPilot](../../ardupilot/building-ardupilot.html)
1. [Configuring a switch as a relay](../../ardupilot/configuring-a-switch-as-a-relay.html)
1. [Current sensor calibrator](../../ardupilot/current-sensor-calibrator.html)
1. [DJI FPV configuration](../../ardupilot/dji-fpv-configuration.html)
1. [ELRS preferred configuration](../../ardupilot/elrs-preferred-configuration.html)
1. [HD OSD tool](../../ardupilot/hd-osd-tool.html)
1. [Installing WTFOS on DJI](../../ardupilot/installing-wtfos-on-dji.html)
1. [Miscellaneous notes](../../ardupilot/miscellaneous-notes.html)
1. [Reverse thrust](../../ardupilot/reverse-thrust.html)
1. [Statistics calculator](../../ardupilot/statistics-calculator.html)
1. [TECS tuning calculator](../../ardupilot/tecs-tuning-calculator.html)
1. [Transfer config between craft](../../ardupilot/transfer-config-between-craft.html)
1. [Tuning the TECS](../../ardupilot/tuning-the-tecs.html)

View File

@ -1,37 +0,0 @@
# Installing WTFOS on DJI
The WTFOS OSD is basically a higher-res analog OSD that you can get on DJI goggles. It gives you everything the analog OSD gives you, so configuration menus, OSD elements, post-flight details, etc.
Here's the process to install it:
## On everything
* Make sure you're on version V01.00.0606 on whatever you want to root.
* If you're rooting an AU or Vista, use a fan to cool it down during this process.
* Go to [the WTFOS Configurator's Root section](https://fpv.wtf/root) and click "Root device". Click on your device on the permission popup and continue. Wait until done. DO NOT REBOOT WHEN IT'S DONE.
* Each step (there are five in total) should take around a minute to continue. If it takes longer, it's probably gone wrong, but it should be safe to just reboot the goggles/AU and try again. At least, it's never caused me a problem so far, and I've done it many times.
* Once that's done, go to [the WTFOS Installer section](https://fpv.wtf/wtfos) and click "connect to device", and then "Install WTFOS".
* After installation is done (or if you're upgrading), go to [the Package Manager section](https://fpv.wtf/packages), and install `fcc-unlock` (for full power) and `msp-osd`. You can also install `auto-record` on the goggles, for automatically recording if your video link goes away and comes back. The rest probably isn't necessary.
## On the goggles
* Disable the custom OSD: Settings -> Display -> Custom OSD: Off.
* Download the font files [from the ArduCustom repository](https://github.com/ArduCustom/ardupilot/tree/master_custom/libraries/AP_OSD/fonts/HDFonts). Make sure to get the four fonts ending in `.bin`.
* If they aren't already, rename them to add `_ardu` to the name after `font` (so `font_ardu.bin`, `font_ardu_2.bin`, `font_ardu_hd.bin`, `font_ardu_hd_2.bin`).
* Put the four font files in the root of the goggles' SD card.
* Go to the console and run, to enable MSP OSD recording:
```
package-config set msp-osd rec_enabled true
package-config apply msp-osd
```
## On the plane
* Set `SERIALn_PROTOCOL=42` for DisplayPort, `OSD_TYPE=5` for MSP_DISPLAYPORT and `OSDn_TXT_RES=1` for 50x18 text resolution on the craft. You should also check that `OSD_OPTIONS=0`, just to make sure you don't have problems.
* Arrange your OSD elements as you want them.
That's all!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on March 20, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,39 +0,0 @@
# Miscellaneous notes
These are random AP-related notes that wouldn't fit anywhere else:
## Performing an autotune
The [ArduPilot Autotune documentation](https://ardupilot.org/plane/docs/automatic-tuning-with-autotune.html) and the [demo video](https://www.youtube.com/watch?v=Ud_YPu7fgXE) are very detailed on this, but here's the gist on how to run an autotune.
Some things to know are:
- Autotune does not tune the rotation rates, but does not really depend on them either.
- You should set `AUTOTUNE_LEVEL` depending on the size of your aircraft. For small/agile craft, you can set `AUTOTUNE_LEVEL` to 7 or more. For larger, more sluggish craft, 6 (or less) is a good level. Under the hood, a higher `AUTOTUNE_LEVEL` decreases `*2SRV_TCONST` and increases `*2SRV_RMAX`).
Before you switch into `AUTOTUNE` mode, complete a circle or fly in different directions to allow the airspeed estimator to get an accurate value before running the autotune (or tuning the TECS). Don't start the tune unless your airspeed estimation is (and remains) stable and reasonable, otherwise you'll get bad results (and it probably means something is very wrong and you should land).
After you switch into `AUTOTUNE`, start with left and right roll inputs at maximum stick deflection. You don't need to wait until you hit the max roll angle, what I tend to do is roll max right, leave it for half a second, then roll max left, repeat.
The OSD will start showing you PID numbers, continue until a message saying `ROLL FINISHED` appears. Afterwards, do the same with pitch. Hit full stick deflection up and down, without reaching max pitch limits.
After the `PITCH FINISHED` message appears, continue flying in `AUTOTUNE` for more than ten seconds, to make sure the tune values are saved.
You're done, you can switch to any other mode and continue flying.
_(Thanks to Mike for the above info.)_
## DMA on the Matek F405-Wing
If you want to get DMA on UART3 of the Matek F405-Wing FC (or, more relatedly, the Racerstar F405, because UART1 is Bluetooth there), you can open `libraries/AP_HAL_ChibiOS/hwdef/MatekF405-Wing/hwdef.dat` and comment out line 92ish, where PA15 is defined.
That will enable DMA on UART3, at the expense of disabling the LED pad.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 26, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,21 +0,0 @@
# Reverse thrust
To set up reverse thrust (for higher braking when landing, for example), follow the steps below:
- [ ] Set your BLHeli-compatible ESC to "Reversible soft" and make sure you're using DShot.
- [ ] Set `THR_MIN=-100`.
- [ ] Set `SERVO_BLH_3DMASK=1` (or whatever channel your motor is on).
- [ ] Set `RC9_OPTION=64` for the reversing switch on channel 9 (or whatever channel you want).
- [ ] Set `USE_REV_THRUST=0` to disable reverse thrust on all auto modes.
You're done.
When flipping the switch, throttle will reverse, so your plane will slow down instead of speed up the more you throttle up.
Be careful not to stall or otherwise hurt your craft, I don't recommend going over 20-30% reverse throttle.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on May 01, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,149 +0,0 @@
# Statistics calculator
<script type="text/javascript">
function raw(val){
return val;
}
function ms_to_kph(val){
return parseInt(val*3.6);
}
function m_to_km(val){
return (val/1000).toFixed(2);
}
function sec_to_min(val){
return parseInt(val/60);
}
function parseStats() {
var stats = {
"STAT_ASPD_AVG": { func: "ms_to_kph", "text": "Average air speed", "unit": "km/h"},
"STAT_ASPD_MAX": { func: "ms_to_kph", "text": "Maximum air speed", "unit": "km/h"},
"STAT_GSPD_AVG": { func: "ms_to_kph", "text": "Average ground speed", "unit": "km/h"},
"STAT_GSPD_MAX": { func: "ms_to_kph", "text": "Maximum ground speed", "unit": "km/h"},
"STAT_WSPD_AVG": { func: "ms_to_kph", "text": "Average wind speed", "unit": "km/h"},
"STAT_WSPD_MAX": { func: "ms_to_kph", "text": "Maximum wind speed", "unit": "km/h"},
"STAT_TRAVEL_AIR": { func: "m_to_km", "text": "Air distance traveled", "unit": "km"},
"STAT_TRAVEL_GND": { func: "m_to_km", "text": "Ground distance traveled", "unit": "km"},
"STAT_HOMEALT_MAX": { func: "raw", "text": "Maximum altitude relative to home", "unit": "m"},
"STAT_HOMEDST_MAX": { func: "m_to_km", "text": "Maximum distance from home", "unit": "km"},
"STAT_CURRENT_AVG": { func: "raw", "text": "Average current", "unit": "A"},
"STAT_CURRENT_MAX": { func: "raw", "text": "Maximum current", "unit": "A"},
"STAT_POWER_AVG": { func: "raw", "text": "Average power", "unit": "W"},
"STAT_POWER_MAX": { func: "raw", "text": "Maximum power", "unit": "W"},
"STAT_FLT_ENERGY": { func: "raw", "text": "Consumed energy", "unit": "Wh"},
"STAT_RUN_TIME": { func: "sec_to_min", "text": "Total run time", "unit": "minutes"},
"STAT_FLT_TIME": { func: "sec_to_min", "text": "Total flight time", "unit": "minutes"}
};
document.getElementById("result").innerHTML=""
var txt = document.getElementById("stats").value
var tbl = document.createElement('table');
var tbdy = document.createElement('tbody');
for (const key in stats){
var tr = document.createElement('tr');
// find the parameter in the textblock
var re = new RegExp(`${key}([^\D+])(.+)`,'g')
var matches = txt.match(re) +''
// extract the value
var value = matches.match(/\d+/)
var desc = stats[key]['text']
var unit = stats[key]['unit']
var func = stats[key]['func']
// run the defined function with the value
var out = window[func](value);
var td = document.createElement('td');
td.appendChild(document.createTextNode(desc))
tr.appendChild(td)
var td = document.createElement('td');
td.appendChild(document.createTextNode(out + " "+ unit))
td.style = "text-align:right"
tr.appendChild(td)
//save output for average calculations
stats[key]['out'] = out
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
var tr = document.createElement('tr');
var td = document.createElement('td');
td.appendChild(document.createTextNode("Average air efficiency"))
tr.appendChild(td)
var td = document.createElement('td');
td.appendChild(document.createTextNode((stats["STAT_FLT_ENERGY"]["out"]/stats["STAT_TRAVEL_AIR"]["out"]).toFixed(2) + " Wh/km"))
td.style = "text-align:right"
tr.appendChild(td)
tbdy.appendChild(tr);
var tr = document.createElement('tr');
var td = document.createElement('td');
td.appendChild(document.createTextNode("Average flight time efficiency"))
tr.appendChild(td)
var td = document.createElement('td');
td.appendChild(document.createTextNode(((stats["STAT_FLT_TIME"]["out"]*60)/stats["STAT_FLT_ENERGY"]["out"]).toFixed(2) + " s/Wh"))
td.style = "text-align:right"
tr.appendChild(td)
tbdy.appendChild(tr);
var tr = document.createElement('tr');
var td = document.createElement('td');
td.appendChild(document.createTextNode("Average flight efficiency"))
tr.appendChild(td)
var td = document.createElement('td');
td.appendChild(document.createTextNode((stats["STAT_FLT_ENERGY"]["out"]/(stats["STAT_FLT_TIME"]["out"])).toFixed(2) + " Wh/min"))
td.style = "text-align:right"
tr.appendChild(td)
tbdy.appendChild(tr);
document.getElementById("result").appendChild(tbl)
}
</script>
Paste your `STATS` items (you can get them with `parachute show -f STAT_`) here:
<div><textarea id="stats" name="text" cols="30" rows="8">
STAT_ASPD_AVG 15.243167
STAT_ASPD_MAX 36.461681
STAT_BOOT_CNT 65.000000
STAT_CURRENT_AVG 3.061170
STAT_CURRENT_MAX 11.686898
STAT_FLT_CNT 18.000000
STAT_FLT_ENERGY 118.639687
STAT_FLT_TIME 12486.000000
STAT_GSPD_AVG 14.964579
STAT_GSPD_MAX 37.131924
STAT_HOMEALT_MAX 2456.000000
STAT_HOMEDST_AVG 104.000000
STAT_HOMEDST_MAX 3796.000000
STAT_LOAD 0.000000
STAT_POWER_AVG 36.397156
STAT_POWER_MAX 136.568756
STAT_RESET 1.000000
STAT_RUN_TIME 27828.000000
STAT_TRAVEL_AIR 189796.000000
STAT_TRAVEL_GND 186942.000000
STAT_WSPD_AVG 4.371937
STAT_WSPD_MAX 18.140949
</textarea></div>
<div><input type="button" id="do" value="format" onclick="parseStats();"></div>
<div id="result"></div>
_(Many thanks to mfoos for writing this note.)_
* * *
<p style="font-size:80%; font-style: italic">
Last updated on July 20, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,87 +0,0 @@
# TECS tuning calculator
To use this calculator, first follow the steps in [Tuning the TECS](/ardupilot/tuning-the-tecs.html).
<script>
function kmhToMs(kmh) { return Math.round(kmh / 3.6); }
function kmhToCms(kmh) { return Math.round(kmh / 0.036); }
function calculateParameters(event) {
var maxSpeed = Number(document.getElementById("maxSpeed").value);
var maxThrottle = Number(document.getElementById("maxThrottle").value);
var stallSpeed = Number(document.getElementById("stallSpeed").value);
var trimSpeed = Number(document.getElementById("trimSpeed").value);
var trimThrottle = Number(document.getElementById("trimThrottle").value);
var downPitch = Number(document.getElementById("downPitch").value);
var upPitch = Number(document.getElementById("upPitch").value);
var upSpeed = Number(document.getElementById("upSpeed").value);
var downSpeed = Number(document.getElementById("downSpeed").value);
var downMorePitch = Number(document.getElementById("downMorePitch").value);
var downMoreSpeed = Number(document.getElementById("downMoreSpeed").value);
var output = document.getElementById("parachuteCommand");
output.textContent = ("parachute set"
+ " \\\n TRIM_ARSPD_CM=" + kmhToCms(trimSpeed)
+ " \\\n TRIM_THROTTLE=" + trimThrottle
+ " \\\n THR_MAX=" + maxThrottle
+ " \\\n ARSPD_FBW_MAX=" + kmhToMs(maxSpeed * 0.95)
+ " \\\n ARSPD_FBW_MIN=" + kmhToMs(stallSpeed * 1.05)
+ " \\\n STAB_PITCH_DOWN=" + downPitch
+ " \\\n FBWA_PITCH_DOWN=" + downPitch
+ " \\\n TECS_PITCH_MIN=-" + downMorePitch
+ " \\\n TECS_PITCH_MAX=" + upPitch
+ " \\\n TECS_CLMB_MAX=" + upSpeed
+ " \\\n TECS_SINK_MIN=" + downSpeed
+ " \\\n TECS_SINK_MAX=" + downMoreSpeed
+ " \\\n FBWB_CLIMB_RATE=" + upSpeed
);
}
</script>
<form onsubmit="calculateParameters(event); return false">
<h2>Fly straight</h2>
<p><label>Maximum speed (km/h): <input type="number" min="0" id="maxSpeed" /></label></p>
<p><label>Maximum throttle (%): <input type="number" min="0" max="100" id="maxThrottle" /></label></p>
<p><label>Slowest speed (km/h): <input type="number" min="0" id="stallSpeed" /></label></p>
<p><label>Trim speed (km/h): <input type="number" min="0" id="trimSpeed" /></label></p>
<p><label>Trim throttle percentage (%): <input type="number" min="0" max="100" id="trimThrottle" /></label></p>
<p><label>Down pitch (deg): <input type="number" min="0" max="90" id="downPitch" /></label></p>
<h2>Fly up</h2>
<p><label>Up pitch (deg): <input type="number" min="0" max="90" id="upPitch" /></label></p>
<p><label>Up speed (m/s): <input type="number" min="0" id="upSpeed" /></label></p>
<h2>Fly down</h2>
<p><label>Down speed (m/s): <input type="number" min="0" id="downSpeed" /></label></p>
<h2>Fly down more</h2>
<p><label>Down more pitch (deg): <input type="number" min="0" max="90" id="downMorePitch" /></label></p>
<p><label>Down more speed (m/s): <input type="number" min="0" id="downMoreSpeed" /></label></p>
<p>
<button type="submit">Calculate parameters</button>
</p>
---
<p>
Run this command in a terminal, making sure you have <a href="https://gitlab.com/stavros/parachute">Parachute</a> installed:
<code>
<pre id="parachuteCommand">
(Please fill out the values above first)
</pre>
</code>
</p>
</form>
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 29, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,17 +0,0 @@
# Transfer config between craft
This is the regex I use with Parachute to transfer between planes only the parameters that are transferrable (ie non-plane-specific):
```bash
parachute restore -f '^(ACRO_LOCKING|OSD.*|RC[\d_]+.*|FLTMODE.*|FLIGHT_OPTIONS|FS_.*|RTL_CLIMB_MIN|RTL_RADIUS|THR_PASS_STAB|THR_SLEWRATE|THR_SUPP_MAN|TKOFF_ACCEL_CNT|TKOFF_THR_.*|TKOFF_ALT|TKOFF_DIST|HOME_RESET_ALT|ALT_HOLD_RTL|MIN_GNDSPD_CM|ARMING_RUDDER)$' <backup>
```
This will transfer things like the OSD settings, flight modes, failsafe options, etc etc, but will leave things like PID tuning alone.
Use it to set up a new plane by copying over settings from an older plane.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on September 16, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,107 +0,0 @@
# Tuning the TECS
To tune the TECS, a helpful resource is the official [TECS tuning guide](https://ardupilot.org/plane/docs/tecs-total-energy-control-system-for-speed-height-tuning-guide.html).
Make sure you have run an autotune beforehand, and continue with the tuning below.
In tuning, there are three stages:
- Prepare to measure
- Take measurements in the field.
- Set parameters on the bench, based on your measurements.
### Preparation
- [ ] Set `LIM_PITCH_MAX=4500` (centidegrees), or something similarly high.
This is the maximum pitch you'll be achieving in FBWA, and you don't want to be limited by this while trying to tune.
- [ ] Set `LIM_PITCH_MIN=-4500` (centidegrees) or something similarly low.
This is the minimum pitch you'll be achieving in FBWA, and you don't want to be limited by this either.
- [ ] Set `THR_PASS_STAB=1` to avoid mapping your throttle to a curve in some modes. This is important because you want a raw (non-remapped) throttle value when measuring.
- [ ] Add the airspeed and pitch angle elements to the OSD so you can actually take the measurements.
- [ ] Enable throttle battery voltage compensation with `FWD_BAT_VOLT_MIN`/`FWD_BAT_VOLT_MAX`. Set the max to `4.2 * num_cells` and the min to `3 * num_cells` for Li-Ion and `3.5 * num_cells` for LiPo batteries. This makes your measurements more accurate, as a partially-depleted battery won't make your motor run slower and skew the results.
### In the field
You should perform the measurements in four stages, all in the FBWA mode:
#### Fly straight
Fly straight and note down:
- [ ] The maximum speed you want to be flying at (in km/h).
- [ ] The throttle percentage at that maximum speed. Use the stick position, not the OSD item.
- [ ] Start a turn at the maximum bank angle (full roll deflection to one side) and note the slowest speed you can fly at without stalling.
- [ ] Fly straight at a speed at least 15% higher than the stall speed from the previous step, and note that speed. This is your trim speed.
- [ ] Note the throttle percentage at that speed. Use the stick position, not the OSD item.
- [ ] Turn throttle to 0 and pitch down a bit so you don't stall.
Note the minimum amount of down-pitch required to keep you from stalling (this should only be in the 1-3 degree ballpark).
#### Fly up
Set the throttle stick to the maximum throttle percentage from the previous step and start slowly pitching up until your airspeed equals your trim speed from the previous step.
If you're higher than that speed and need to climb more, change `LIM_PITCH_MAX` to something higher and try again.
Note down:
- [ ] The pitch angle (in degrees).
- [ ] The vertical speed from the variometer (in m/s).
#### Fly down
Set the throttle to 0 and start pitching down until your airspeed equals your trim speed from the previous step.
Note down:
- [ ] The vertical speed from the variometer (in m/s).
#### Fly down more
Keep the throttle at 0 and pitch down until you reach your desired max descent rate in auto modes, keeping in mind not to exceed your desired maximum speed from step 1.
If you're lower than that speed and need to pitch down more, change `LIM_PITCH_MIN` to something lower and try again.
Note down:
- [ ] The pitch angle (in degrees).
- [ ] The vertical speed from the variometer (in m/s).
You're done with this step.
### On the bench
After you have the above measurements, you're ready to tune things. You can use the automatic calculator:
### [TECS tuning calculator](/ardupilot/tecs-tuning-calculator.html)
Otherwise, you can do things manually, following the steps below, but you should really use the calculator instead.
For the level flight measurements:
- [ ] Set `ARSPD_FBW_MAX` (m/s) to something a bit less than the maximum airspeed you achieved in level flight.
- [ ] Set `THR_MAX` (percentage) to the throttle percentage at max speed.
- [ ] Set `ARSPD_FBW_MIN` (m/s) to the slowest speed you could turn at without stalling (maybe go a bit higher for some margin).
- [ ] Set `TRIM_ARSPD_CM` (cm/s) to your trim speed.
- [ ] Set `TRIM_THROTTLE` (percentage) to your trim throttle percentage.
- [ ] Set `STAB_PITCH_DOWN` (degrees) to the pitch angle that keeps you from stalling.
For the ascent measurements:
- [ ] Set `TECS_PITCH_MAX` (degrees) to the pitch angle you measured.
- [ ] Set `TECS_CLMB_MAX` and `FBWB_CLIMB_RATE` (both in m/s) to the climb rate you measured.
For the descent measurements:
- [ ] Set `TECS_SINK_MIN` (m/s) to the descent rate you measured.
For the max descent measurements:
- [ ] Set `TECS_PITCH_MIN` (degrees) to the pitch angle you measured.
- [ ] Set `TECS_SINK_MAX` (m/s) to the descent rate you measured.
That's it!
## Advanced information
This is some more advanced information on tuning the TECS:
- If you have a pitot tube and want more altitude precision and more responsive control, you should lower the `TECS_SPDWEIGHT` parameter value below 1.
- A right `KFF_THR2PTCH` value is crucial for the TECS to work correctly without pitot.
- The `THR_SLEWRATE` value should be set so that the plane doesn't lose airspeed when you yank the pitch stick to `TECS_CLMB_MAX` degrees.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 26, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,29 +0,0 @@
# A simple guide to PID control
I made some changes to my quadcopter the other day for [a new photography project I'm working on](https://www.makerfol.io/project/m8xrLUp-light-painting-with-drones/).
Unfortunately, it turned out that it wasn't good enough, and that I'd have to tune my [PID loop](https://en.wikipedia.org/wiki/PID_controller), which I knew nothing about.
After watching a few videos and reading a few things, I learnt enough to be dangerous, and to hopefully be able to explain the concepts simply, so I want to write them down here before I forget.
Basically, a PID loop can be thought of very simply as an equation that takes your current state as input and gives you what you need to do to reach a desired state as output.
For example, if you had a radiator and wanted to heat a room, the PID loop would take the current temperature as input and tell you how high you needed to set the radiator on a 0-100% scale to achieve a desired temperature.
The PID loop has three components, and to tune it you need to set three weights that you multiply each parameter with.
That means that it's basically `output = P*prop, + I*intgr + D*deriv`, where the terms are explained below:
* **`P` - proportional**: This is the weight of the difference between the current position and the desired position.
What this says about the radiator is "we're still far away, we need more heat!", so the more P you set, the higher the radiator will be set for a given temperature difference.
* **`D` - derivative**: Because `P` is purely based on the difference between the current and target temperatures, it doesn't know anything about inertia.
So, even though your radiator will be getting closer to the target temperature, even when it's very close, P will be saying "more heat, we're not there yet!", and cause you to overshoot your target, having to then go back (possibly turning the AC on, undershooting downwards, and then back upwards, oscillating like that for a long time).
D helps by saying "whoa, we're getting there, slow down with the heat", and reducing the amount of heat you apply proportionally to how fast you're getting to your target temperature.
* **`I` - integral**: `I` helps in the case where you left a window open in the room, and `P` is saying "okay we're pretty close so set the radiator to 10% just for that final push", but the room is leaking so that 10% will never get you to your target temperature.
`I` helps by saying "Okay we've been trying but it's not working, we're still far, so we actually need a bit more heat than 10%", by looking at the constant temperature difference you've been having lately, despite your best efforts.
Basically, `I` deals with accumulated error when you think you're getting closer but all you're doing is fighting losses, so `I` allows you to close that gap.
That's pretty much it!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 07, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,28 +0,0 @@
# E6000 hinges
I love Goop/E6000 glue, it's very versatile and makes for a great bond.
However, do remember to work with it outside, as it is not safe to breathe.
One of the coolest things you can do with it is make hinges, for control surfaces as well as for any hatches you may have.
E6000 hinges are very strong (I tried tearing one by hand but couldn't, in the end I had to cut it), and very flexible (you can easily turn the hinged surface 180 degrees up or down with very little force).
They also have almost zero play, making them ideal for control surfaces.
Here's how:
- [ ] Make sure your surfaces are clean and straight.
Since you're going to make a hinge by placing a very thin layer of glue over the two pieces, the pieces need to actually be straight and contacting on the part where the glue is going to go.
If there's a recess or groove where your elevons meet, this won't work very well because your glue layer will be too thick to bend properly.
- [ ] Apply some masking tape parallel to the hinge line, 1 cm above and 1cm below it, so you don't get glue elsewhere on the wing.
- [ ] Place the elevon/aileron/other control surface in position and apply some masking tape to the two ends, to hold the elevon in place.
Take care to position it straight on both axes, the control surface should be at the same level as the wing surface across its length *and* the control surface shouldn't be deflected up or down.
- [ ] Apply a thin layer of glue (around 1mm thin) on the top of the joint (not on both sides), and spread it evenly with a credit card or piece of paper.
- [ ] Wait for it to dry, and you're done!
Because a description might be hard to follow, you can see the process in more detail [in this video](https://www.youtube.com/watch?v=ar9ttyGs1rM).
* * *
<p style="font-size:80%; font-style: italic">
Last updated on March 22, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,16 +0,0 @@
# Fixing the Matek ELRS receivers
The Matek ELRS receivers (ELRS-R24-D, ELRS-R24-S, etc) are dangerously close to out of spec, [due to the addition of two XTAL capacitors](https://docs.google.com/document/u/1/d/10m25KMzpuve8kn1ToP7wEt3qKzD9NwbL6vCAcM_DwCs/mobilebasic). The Semtech chip Matek is using for the receiver already contains XTAL capacitors in it, so the two added capacitors are redundant and push the frequency close to the edge of the spec. This means that temperature changes might push the frequency off-spec, and cause a failsafe randomly in mid-air.
The Matek receivers with a silver boot button are more prone to the issue, but it's also present in newer batches with gold boot buttons.
Luckily, this issue is easy to fix (and the fix is the same for both batches). You just need to desolder/remove the two capacitors shown below:
![d8d349e62a17404996ff64a377687bf3.png](/resources/8eff90fdedb94cd7b8d9237f948b388c.png)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on December 04, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,29 +0,0 @@
# FPV frequency chart
If you're curious about which frequencies to use for video when there are multiple people flying FPV, as well as which bands are used by various manufacturers, here's a handy chart:
[![FPV frequency chart](/resources/48cfa1097ca847c5a9ff8229005e7f50.png)](/resources/48cfa1097ca847c5a9ff8229005e7f50.png)
It was made by [5zero7 RC](https://youtu.be/wScS5XloviM) with information from [a Propwashed article](https://www.propwashed.com/video-frequency-management/).
## Best channel groups
Here are the best channel groups for each number of pilots, from the chart:
- 2 pilots - E2 (5685), E6 (5905)
- 3 pilots - E2 (5685), F4 (5800), E6(5905)
- 4 pilots - E2 (5685), F2 (5760), F7 (5860) E6 (5905)
- 5 pilots - E2 (5685), F2 (5760), F4 (5800), F7 (5860), E6 (5905)
- IMD5C - R1 (5658), R2 (5695), F2 (5760), F4 (5800), E5 (5885)
- 6 pilots - E2 (5685), F1 (5740), F3 (5780), F5 (5820), F7 (5860), E6 (5905)
- IMD6C - R1 (5658), R2 (5695), F2 (5760), F4 (5800), F8 (5880), R8 (5917)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 09, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,18 +0,0 @@
# Getting uninverted SBUS on a no-name FrSky-compatible receiver
I got an [RC receiver](https://www.banggood.com/2_4G-8CH-D8-Mini-FrSky-Compatibel-Receiver-With-PWM-PPM-SBUS-Output-p-1140478.html?rmmds=myorder&cur_warehouse=CN) from Banggood. There's uninverted SBUS on this pad:
[![rc-sbus.jpg](/resources/ccc7571db5d147328860077fdc0aa745.jpg)](/resources/ccc7571db5d147328860077fdc0aa745.jpg)
To break this out to the SBUS pad, I had to remove/bridge the resistor that is circled in the image, and remove/bridge the FET on the other side:
[![rc-sbus-mosfet.jpg](/resources/1b0f508a533e45b496c6636d49161b0c.jpg)](/resources/1b0f508a533e45b496c6636d49161b0c.jpg)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 24, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,21 +0,0 @@
# Getting uninverted SBUS/SmartPort on the FrSky XSR receiver
To get uninverted SBUS/SmartPort on the FrSky XSR/X4RS receiver, you can repurpose the CPPM pad.
Remove the two small resistors shown in the image, and solder the two lower pads (together) to either the CPPM pad or the MOSFET pin shown in the photo:
[![xsr-sbus.jpeg](/resources/f86da9a7aac1413ebd77825897164f7f.jpg)](/resources/f86da9a7aac1413ebd77825897164f7f.jpg)
They should be soldered like this (remember to solder both resistor pads together):
[![xsr-sbus2.jpeg](/resources/815576429ece43789dbc70dfd33517a1.jpg)](/resources/815576429ece43789dbc70dfd33517a1.jpg)
Now the CPPM pad will be uninverted SBUS/SmartPort instead.
It seems to be a bit of a gamble whether you get SBUS or SmartPort, it might be firmware-dependent.
On firmware 2.1.0 FPort, I actually got the uninverted FPort signal on the CPPM pin, which is what I wanted.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 24, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,35 +0,0 @@
# INAV tuning tips
Here are some general INAV tuning tips and things I've learned throughout my builds. Keep in mind that *these only apply to wings* (and maybe planes), not quads:
* To make turns in automatic modes smoother, use `set nav_fw_control_smoothness = 8`.
* Pawel says that the idea of the software LPF is to replace the hardware LPF. Leave the hardware LPF set to 256 Hz and set the software LPF to 20-30 Hz, with a looptime of 1k.
## Battery monitoring
To monitor how much battery you have left in flight, voltage isn't a good indication because it can sag a lot. mAh is also not a good indication, because it doesn't decrease linearly with voltage (when voltage drops, you need to consume more amps for the same amount of motor RPM, and thus thrust). Remaining energy (in Watt-hours) is a better way, using the "Wh drawn" INAV OSD item. In addition, INAV has heat loss compensation for the energy meter (done by simulating the internal resistance of the battery), which gives you a more accurate reading.
To calculate the Wh a battery can give, the best way is to charge or discharge it and see how many Wh were spent, if your charger shows you. Another way is to get a rough estimate using the formula `no_cells * 3.7 * Ah`. So, for a 1800 4S battery, the maximum Watt-hours are `4 * 3.7 * 1.8 = 26.64 Wh`. You should not discharge more than 80% of that value, or you risk excessive wear to the battery.
For a 4S battery, I go with a rule of thumb: The maximum Wh is `mAh / 85`, so for a 5000 mAh battery I'll land after 58 Wh consumed, which is around 80% of the battery consumed and gives a small margin for error.
More details can be found in the [battery page](https://notes.stavros.io/drone-stuff/inav-tuning-tips/#battery-monitoring) in the INAV wiki.
_(Thanks to Michel Pastor in the INAV Telegram group for this tip.)_
## Horizon drift issues
There's a known problem with horizon drift on fixed wings. To ameliorate it, use `set imu_acc_ignore_rate = 10`. Setting this low is a good idea, but if it's set too low then the accelerometer will effectively be ignored and the horizon will eventually drift. To reduce the accelerometer's influence, you can also reduce `imu_dcm_ki` and/or `imu_dcm_kp`.
You can also try tuning `fw_turn_assist_pitch_gain`, although be careful to not set it too high because then the aircraft will stall trying to climb during a turn.
Adding a piece of black, porous foam (so wind can pass through) over the barometer has been known to help as well.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 01, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,17 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [A simple guide to PID control](../../drone-stuff/a-simple-guide-to-pid-control.html)
1. [E6000 hinges](../../drone-stuff/e6000-hinges.html)
1. [FPV frequency chart](../../drone-stuff/fpv-frequency-chart.html)
1. [Fixing the Matek ELRS receivers](../../drone-stuff/fixing-the-matek-elrs-receivers.html)
1. [Getting uninverted SBUS on a no-name FrSky-compatible receiver](../../drone-stuff/getting-uninverted-sbus-on-a-no-name-frsky-compatible-receiver.html)
1. [Getting uninverted SBUS/SmartPort on the FrSky XSR receiver](../../drone-stuff/getting-uninverted-sbus-smartport-on-the-frsky-xsr-receiver.html)
1. [INAV tuning tips](../../drone-stuff/inav-tuning-tips.html)
1. [Miscellaneous](../../drone-stuff/miscellaneous.html)
1. [Omnibus F4 V3 pinout](../../drone-stuff/omnibus-f4-v3-pinout.html)
1. [Omnibus F4 pro servo diode](../../drone-stuff/omnibus-f4-pro-servo-diode.html)
1. [QGroundControl to Mission Planner conversion script](../../drone-stuff/qgroundcontrol-to-mission-planner-conversion-script.html)
1. [Transmitter external module pinout](../../drone-stuff/transmitter-external-module-pinout.html)
1. [Transportable C1 Chaser](../../drone-stuff/transportable-c1-chaser.html)

View File

@ -1,54 +0,0 @@
# Miscellaneous
This is a bunch of miscellaneous info that wouldn't fit anywhere else:
- The ZOHD Dart 250g with the stock motor draws 4.5A on 2S with the 5x5 propeller. It draws the same amperage at exactly 75% throttle with a 3S battery and the same propeller.
- When wiring your electronics, make sure you don't have any ground loops.
This means that there should only be one ground wire going to each component.
For example, the ESC has one ground wire for power (to the battery) and one for signal (to the FC), you should *only* use one of the two (the one going to the battery).
What you can do for the other ground wire, though, is twist it around the signal wire and only connect it to the FC side, to reduce emissions.
If you have coaxial cable, you can do the same, connect the outer shielding to the FC's ground, and don't connect the other side anywhere, and use the core as signal.
- If you want to embed knurled nuts in foam so you can use screws, use a soldering iron. Set the iron to 150 C, put the nut on the tip of the iron, and push the nut into the foam. It will slowly melt the foam and embed itself quite firmly. Don't use a higher temperature or you'll open a larger hole and the nut won't fit snugly.
- This is the command I used to flash an ESP8285 M3 with [esp-link](https://github.com/jeelabs/esp-link/ ):
```
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash -fs 1MB -fm dout \
0x00000 boot_v1.7.bin 0x1000 user1.bin \
0xFC000 esp_init_data_default.bin 0xFE000 blank.bin
```
- Propellers have a direction: The top usually has letters like, for example, "6040" (which denotes the size and pitch of the propeller), and the top needs to always point towards where the plane will be flying (the front). No matter if you have a pusher or puller, the top of the propeller needs to be pointing forward.
- When it comes to cameras/standards, the difference between PAL and NTSC is that PAL has higher resolution (625 lines, ie 576i for PAL vs 525 lines, ie 480i for NTSC), but lower framerate (25 fps for PAL vs 29.97 fps for NTSC). I use PAL because I prefer having higher resolution.
- If doing manual/hand launches of planes/wings, you'll notice that you need to have your hand on the pitch/roll stick when launching, which means you need to launch with your left hand, which is where the arm and throttle controls usually are. That makes it hard to throttle up to start the launch, or down (or disarm) in an emergency.
To make things a bit easier, I set the back right switch (SG) to override the throttle and set it to the launch throttle (40% for me, for example). That way, I can arm, keep the throttle down, and flip SG with my right hand. That will throttle up enough to easily launch the wing, and if something goes wrong I can still either disarm or flip SG down so the motor stops again.
- ESCs that run on the DShot protocol don't need throttle calibration, you can go ahead and use them right away and they'll do the right thing.
## Motor and prop stuff
Here are the things I know about motors and propellers:
- The larger and steeper the propeller, the harder it is for the motor to turn.
- The more KV the motor is, the faster it turns, and the harder it is for it to turn.
- The harder the motor has to turn, the more current it draws, and the hotter it gets.
- The larger the (physical) size of the motor, the more heat it can dissipate.
- The more amps (current) the motor draws, the hotter it gets (proportional to the square of the current).
- If the motor gets too hot, some part of it may melt. This ruins the motor.
- The smaller a propeller, the more quickly it can turn, and the more it can accelerate.
- The larger a propeller, the more efficient it is.
## Recommended BLHeli ESC configuration for fixed wing
If you have a BLHeli/BLHeli32 ESC, these settings are recommended:
* Temperature protection: 90 C
* Motor timing: Auto
* Throttle cal enabled: Enabled
* Non-damped mode: Enabled
* Sine modulation mode: Enabled
* Brake on stop: 100%
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 17, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,16 +0,0 @@
# Omnibus F4 pro servo diode
To isolate the servo 5V rail from the controller's 5V power supply, remove this diode:
[![a435bcae86912205b6fac41731285b8d.png](/resources/6d668e05d8a54580966b94a752f3b7db.png)](/resources/6d668e05d8a54580966b94a752f3b7db.png)
Now the servos' 5V rail can be powered from another 5V supply to avoid servo current backflow into the FC.
There's also a [schematic for this FC](/resources/805930c3bedc4393ba947f0e0bfa369d.pdf).
* * *
<p style="font-size:80%; font-style: italic">
Last updated on April 09, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,18 +0,0 @@
# Omnibus F4 V3 pinout
This is the pinout of the Omnibus F4 V3:
[![53b3161d509dcc7bbfb43c89b16b0bae.png](/resources/99f5c91454204c1d9740a8d9b876833b.png)](/resources/99f5c91454204c1d9740a8d9b876833b.png)
Also:
![omnibus-f4-v5-pinout2.jpg](/resources/410f3ce004c64fe9af68bfd6856d3e53.jpg)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 06, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,44 +0,0 @@
# QGroundControl to Mission Planner conversion script
If you have a parameter dump from QGroundControl, I wrote a small script that will convert it to a Mission Planner compatible file. You can also use [Parachute](https://gitlab.com/stavros/parachute) to do your backups/restores/conversions.
Just save this script somewhere as `convert_qgc_params` and run it as `./convert_qgc_params <qgc params> <output file>`:
```py
#!/usr/bin/env python3
import sys
from decimal import Decimal
def format_float(f):
return "{0:f}".format(Decimal(f).quantize(Decimal("1.0000000")).normalize())
def main(infile, outfile):
with open(infile) as ins:
inputs = ins.read()
lines = []
for line in inputs.split("\n"):
if not line or line.startswith("#"):
continue
vehicle_id, component_id, name, value, type = line.split("\t")
v = value
if type == "9":
v = format_float(float(value))
lines.append(f"{name},{v}\n")
with open(outfile, "wt") as outs:
outs.writelines(lines)
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2])
```
* * *
<p style="font-size:80%; font-style: italic">
Last updated on March 04, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,22 +0,0 @@
# Transmitter external module pinout
The transmitter (Taranis, Jumper, RadioMaster, etc) pinout is, from top to bottom:
* PPM
* +6V
* +BAT
* GND
* ANT
It's illustrated in this photo:
[![pinout.jpeg](/resources/72d23239af1541d4b170271c1e9e21eb.jpg)](/resources/72d23239af1541d4b170271c1e9e21eb.jpg)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 24, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,89 +0,0 @@
# Transportable C1 Chaser
I have a [C1 Chaser](https://www.banggood.com/C1-Chaser-1200mm-Wingspan-EPO-Flying-Wing-FPV-Racer-Aircraft-RC-Airplane-KIT-p-1102080.html?custlinkid=667416&p=6W16207412782201611V), and it's a fantastic wing.
It flies great, and is very efficient. The only problem I had with it was that it's too long to easily carry around, as it has a 1.2m wingspan.
I thought that a C1 Chaser that can break apart for easy transport would be the ideal long-range wing, so I bought a second one and made some modifications to it.
I'm listing the modifications here so you can do the same if you want to.
## Spar
The biggest issue is making the spar removable.
The best way I've found to do that is to use IKEA drinking straws, they have an internal diameter of around 7.5mm, making them ideal for putting the spar through.
If you find the spar has too much jiggle, I've found that applying some CA glue around it makes it thick enough to fit snugly in the straw.
I've cut three straws to length, sanded the straws and the spar channel a little with coarse sandpaper, and glued the former in the latter, as you can see here (the straw in the photo is not cut to length yet):
[![](/resources/5ac6bff04962497083b8403ed0fded98.jpg)](/resources/5ac6bff04962497083b8403ed0fded98.jpg)
[![](/resources/65ff483180ad483795b32d0b65f72613.jpg)](/resources/65ff483180ad483795b32d0b65f72613.jpg)
Make sure to leave a few mm from the inside edge of the wing (so the straw doesn't touch the edge, again not pictured in the photo), so the spar's edge doesn't rub against the straw, to avoid splitting it.
Also, leave the spar in the straws while gluing, so the straws don't lose their shape (but make sure you don't get glue on the spar and end up gluing it to the straw).
For glue, I use [E6000](https://www.banggood.com/ZHANLIDA-152550ml-E6000-B6000-Adhesive-Transparent-Glue-for-RC-Models-p-1604315.html?cur_warehouse=CN&ID=62834216283418&rmmds=search&custlinkid=667416&p=6W16207412782201611V) (sold as Goop in the US) for pretty much everything, but for this one you can use your favorite glue that you know won't dissolve EPO.
This is what the final result will look like:
[![](/resources/6c9034ecf9d9414d87fbc6b4ec2fa28e.jpg)](/resources/6c9034ecf9d9414d87fbc6b4ec2fa28e.jpg)
## Wings
Connecting the wings has two problems:
First, you need the wing to be stable against rotation around the spar.
Already, the notch the C1 has stops the wing from rotating up, but it does not stop it from rotating down (since you're meant to glue it in place).
Second, you obviously need the wing to be stable against left/right motion, or it will slide off the spar.
To solve these problems, I [designed a simple connector with two halves](https://cad.onshape.com/documents/bd7ed4d575e32e06d46234b6/w/ab2adb2ae56e261604342410/e/ad8c70c01b2f8865eb84f5c6), one of which goes onto the fuselage and one onto the wing:
[![](/resources/dd331e351cd0492794619526ccb89a3f.jpg)](/resources/dd331e351cd0492794619526ccb89a3f.jpg)
The connector has two components, one is a cylindrical channel for a carbon tube (which you can glue to one of the pieces, as in the photo) that stops the wing from rotating around the spar, and the other is a channel for an o-ring, which keeps the two halves from moving left to right.
I used a 6mm outer diameter carbon tube and an o-ring with an inner diameter of 28mm and a cross-section diameter of 3.5mm. A slightly thicker and slightly longer o-ring will also probably work.
To install, place the connector over the underside of the wing and mark the outline, then cut the foam and glue the connector in.
Do the same with the other side, into the fuselage, as shown in the photo below.
To make sure the connectors are glued straight, I recommend cutting the foam to shape, placing the connectors in on both sides, and sliding them into each other (using the tube), making sure to leave some distance and watch for any places where glue has leaked, to prevent the wing and the fuselage from gluing together.
Also, make sure to not use glue the part of the connector that's not going to be next to foam, on the fuselage side, to prevent the wing tab from adhering when you slide them together (watch out for glue seeping from under the connector towards the tab).
This is the end result:
[![](/resources/b765e8d8e3db4eceaad1f33862fb7bcc.jpg)](/resources/b765e8d8e3db4eceaad1f33862fb7bcc.jpg)
To mount the wings, just insert the spar into the fuselage, insert the wings (making sure both tubes go into their respective holes), and place the o-ring into both halves of the connector.
That gives you a secure and quick assembly.
## Vertical stabilizers
The last part is securing the vertical stabilizers. I did this with [two very small 3D-printed pieces](https://cad.onshape.com/documents/2c189f2c6522261154d2323e/w/a7e91c32873cec3a9110e900/e/7b35e4b324d972fd5c8a49f6), I slot the stabilizers horizontally (on the left/right axis) onto the fuselage and then connect the wings, which keeps the stabilizers securely in place.
First, press the stabilizer-side part (the Π-shaped one) onto the stabilizer on the place where you want it (I put it as shown in the photo), and cut slightly *inside* the indentation it creates.
Then, glue it into place:
[![](/resources/9e4279dbc32a4c28886b8dbb5e308f86.jpg)](/resources/9e4279dbc32a4c28886b8dbb5e308f86.jpg)
Then, insert the fuselage-side part (the inverted-T-shaped one) into the stabilizer-side part, align the stabilizer with the fuselage and press it in, to create the indentation onto the fuselage EPO, so you know where to cut.
Insert the part into the cut and glue it in:
[![](/resources/ac25d2c2031441549f266d83ed6ac030.jpg)](/resources/ac25d2c2031441549f266d83ed6ac030.jpg)
When everything has set, you can install the stabilizers by simply slotting the two parts into each other and mounting the wing.
That way, the stabilizer isn't going anywhere, and you can install and remove it very quickly.
## The end
You're done! Enjoy your disassemblable, transportable C1 Chaser!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on February 03, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,68 +0,0 @@
# Battery discharge curves
I wanted to buy some Sony VTC6 batteries, and I was wary of fakes, so I wrote a [battery discharge calculator](https://gitlab.com/stavros/assault-and-battery/) with an associated hardware component (just a simple current and voltage sensor). I then took some measurements of my known-good batteries, and the new ones I bought.
The methodology was the following: I connected the battery to the sensor, and the sensor to a configurable load. I set the load to draw a certain amount of amps until it reached a cutoff voltage, and then to stop. I then plotted mAh drawn versus voltage, as well as amps drawn.
The batteries I connected were in various states of use, and various configurations (for various reasons, I couldn't test single cells). The configuration, state of the battery and provenance are mentioned below.
Here are the graphs:
## Genuine Sony VTC6
This is a genuine (as far as I can tell) Sony VTC6, fairly used in high amp draw situations (I use it in my plane), in a 3S configuration:
![curve_old-3s_2021-09-08_02-53-53.png](/resources/71aaa540c06d48e59559d05627ceffa4.png)
You can see that it output around 2600 mAh before I stopped it at 3V, which is quite good.
Here's a brand new genuine VTC6, again in a 3S configuration:
![curve_new-vtc6-3s_2021-09-09_13-06-52.png](/resources/9a2ed9fc5d474edfab2ec610e994c059.png)
This time I ran it all the way down to 2.8, and you can see it output the full 3000 mAh.
## Fake Sony VTC6
This is a pretty blatantly fake "Sony VTC6", brand new, in a 2S configuration:
![curve_new-vtc6_2021-09-08_18-54-58.png](/resources/2d20e92b9b2247e39de7458e0b341d45.png)
The performance falls off a cliff after around 3.6V, and it only outputs 1600 mAh before it dies completely.
Trying to draw 6-7A is even more spectacular (and it gets very hot to the touch):
![curve_new-vtc6-6a_2021-09-08_23-57-29.png](/resources/b3a7a012f9d5418e9e2e9867fd23df61.png)
Notice the huge voltage sag right as the load starts drawing.
## Reclaimed NKON VTC-6
I bought some [reclaimed Sony VTC-6 from NKON.nl](https://www.nkon.nl/sony-us18650-vtc6-reclaimed.html), and I tested them here, in a 2S configuration at 1.5A.
They seem to be very genuine:
![curve_reclaimed_NKON_VTC-6_2S_1.5A_2022-12-19_14-50-18.png](/resources/55e13b1a5b5142219d655504448e5b02.png)
Not only are they genuine, but if we compare with the graph of the brand new VTC-6 above, we see that the reclaimed NKON batteries have had zero (or very few) cycles, as they gave the same Ah at 3.3V/cell as the new ones.
If you need it, here is the [raw Assault and Battery results CSV](/resources/29e39ead4d104c2c8133b028882b6a98.csv) for this battery.
## White CNHL 4S 4000 mAh
This is a white CNHL 4S 4000 mAh LiPo battery, slightly used:
![curve_cnhl-4ah-used_2021-09-11_20-29-53.png](/resources/ba59455ecc2946fd8b2f001dfa32378a.png)
You can see that it's pretty decent, outputting nearly all of its nominal mAh, decently linearly, with a slightly faster drop after 3.7 V.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on December 19, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,25 +0,0 @@
# Details about my Sapphire Pro
My Sapphire Pro runs the MKS Robin Nano 1.2 board. Details on that board (pinouts, diagrams, etc) are here:
[https://github.com/makerbase-mks/MKS-Robin-Nano-V1.X/wiki/Wiring_Pinout_and_Size](https://github.com/makerbase-mks/MKS-Robin-Nano-V1.X/wiki/Wiring_Pinout_and_Size
)
## TMC2209 drivers
I've installed TMC2209 drivers and wired all their UARTs up to the same pin, PA13, as recommended [in this GitHub issue](https://github.com/Klipper3d/klipper/issues/4779). Their addresses for X, Y, Z, and E are 0, 1, 2, and 3, respectively. It doesn't work with Klipper, I'm only getting the error message `TMC stepper_x failed to init: Unable to read tmc uart 'stepper_x' register IFCNT`. Nothing I've tried has worked, the last resort is setting the baud rate to 19200. If you managed to make this work, please email me.
## SFS 2.0 filament motion runout sensor
I've installed the SFS 2.0 motion runout sensor on MT_DET1 and MT_DET2. This means that the motion sensor pin is PE6, and the switch sensor is PA4. That doesn't work either, Marlin keeps thinking the printer has run out of filament.
Someone here had the same issue as me:
[https://github.com/MarlinFirmware/Marlin/issues/26916](https://github.com/MarlinFirmware/Marlin/issues/26916)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on April 05, 2024. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,47 +0,0 @@
# Electronics tips
This page contains various notes and tips about electronics.
## Decoupling capacitors
StackOverflow has a good answer on [why use decoupling capacitors](https://arduino.stackexchange.com/questions/51712/a4988-and-capacitors) in the context of a stepper driver:
> There are two purposes of such capacitor:
>
> * first it supply power for short peaks in demand, so effectively enabling the 12V power source supply much more current for short time, than it can support over long time and so the driver have more stable power and works generally better. Also it protects the driver from noise of other parts.
> * the other is protect all other parts from voltage drops and noise caused by the driver. It is recomended to have capacitors as near as possible to any IC/driven circuit for this reason.
>
> So basically - if you have good power source, you can often get away even without such capacitors. But if you power also logic from the same source, it is already better to have some capacitors on power lines where posssible. Escpecially if you expect some noise around (like having motors near or lines to motors in paralel with other lines ...). Depends how much you care and how critical you see the project. Hobby project just for fun can go even without capacitors and be all good. Good industry projects have capacitors always everywhere.
>
> I had project, where it worked even without capacitors (laser printer), but now I would place some there in any case near each driver, just to be sure. 100uF is really good capacity, enables for lot power. But if you use any other value (which you have more ready), it should not hurt too. It is not about if it would work or not, it is more about if it ensures, that it would work flawlessly even in bad conditions even under unexpected conditions and would not have "sometimes strange problems, which disapear spontaneously during debugging".
>
> Also note, that for improving power are good high capacity electrolytes. For preventing noise are much better ceramic (which are fast, even if they have a lot smaler capacity) and so many people put both there (like 100uF electrolyte and 100nF ceramic in paralel).
>
> Short answer: Do as you want, it would probably work anyway. I personally would place big+small capacitors near each driver.
## LDO recommendation
Asking for a recommendation for a good 3.3V LDO, someone said:
> There's a number of good parts. In the 500mA range I'd highly recommend the [Holtek HT7833](https://www.holtek.com.tw/documents/10179/82844a36-1633-498c-a6e3-4d99f2d0f6d7). If you need closer to an amp at 3.3, the [Torex XC6220](https://www.torexsemi.com/file/xc6220/XC6220.pdf) is popular, but I haven't used that one myself. Another popular part I haven't used is the [Diodes Inc. AP2112](https://www.diodes.com/assets/Datasheets/AP2112.pdf), 600mA. The Holtek has 4uA quiescent current, the other two are around 50uA. LCSC.com has all three parts.
## Driving a relay
David Albert said:
> When energizing a relay, you are charging a coil (inductor). To turn the relay on, you can use an NPN transistor (e.g. 2N3904) with the collector to the coil and the emitter to ground. The other side of the relay coil will go to +5V. You will need a resistor (try 1K) between your transistor base and your 3.3v control source. You will also need a diode in parallel with the coil: cathode towards +5V, anode at the junction of the transistor collector and coil. The purpose of the diode is to prevent your transistor from being destroyed when you turn off power to the coil. When you remove power from a coil, the energy stored in the coil (as a magnetic field) collapses back into the coil inducing a current flow in the coil. The voltage will climb until the current can flow (e.g. by destroying your transistor). The reverse-biased diode gives the current a path to flow so nothing gets damaged. Also, make sure your transistor is rated to carry the current needed to energize your coil (e.g. a 2N3904 is rated to deliver at most 200mA; if you need more than that, choose a transistor with a larger current rating).
>
> The resistor between the control source (e.g. an ESP32 GPIO pin) and the base of the transistor is to limit current. Whatever goes into the base will flow directly through to the emitter (to ground)...the resistor limits that current. When current is flowing through the base-emitter junction, a much larger current will flow through the collector-emitter junction (energizing the relay coil).
There is more info on StackOverflow: [Selecting a switching transistor for a 5V relay](https://electronics.stackexchange.com/questions/369447/selecting-a-switching-transistor-for-a-5v-relay)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on December 13, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,14 +0,0 @@
# GRBL_ESP32 tips
I made a CNC that uses [a custom board I designed](https://gitlab.com/stavros/esp32-cnc), and which runs [GRBL_ESP32](https://github.com/bdring/Grbl_Esp32/). I couldn't find the following info easily, so I've written it here:
- You can specify the enable pin for the drivers with the `STEPPERS_DISABLE_PIN` option. This should be used like `#define STEPPERS_DISABLE_PIN GPIO_NUM_2`.
- To invert the enable signal, you can use `#define DEFAULT_INVERT_ST_ENABLE 1`. My board needed the enable signal to *not* be inverted (that's what A4988/Trinamic TMC2208 drivers need), so I set it to 0.
- To always keep the steppers enabled (locked) to avoid them moving, you can specify `$Stepper/IdleTime=255`. That's the maximum timeout and will always keep them enabled.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on February 15, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,32 +0,0 @@
# How to properly level your 3D printer
I see many people on our 3D printer Facebook group ask about adhesion issues with their printer. 99% of the time, this is because they have leveled improperly, and not because of the bed material.
I have taken photos of filament when the nozzle was leveled at various heights from the bed. I greatly recommend [an adjustable Z endstop](https://www.thingiverse.com/thing:1370547), which will save you lots of time when leveling/tramming.
In this first photo, I have leveled too high (meaning the nozzle is too high compared to the bed). You can see that the filament is cylindrical, which means that it has just dropped onto the bed (or minimally touched it), leading to very poor adhesion. You can imagine that, if the filament is just dropped onto the bed, it wont adhere well:
![too-high.jpg](/resources/576a1fedf9f144a69fe262866e9f268a.jpg)
The next photo is also a bit too high. Its not as high as the previous photo, so it has partially adhered, but there are gaps between the rows and adhesion still wont be great:
![too-high-2.jpg](/resources/57cca138661644a99f3e9422665cbbb5.jpg)
The next photo has been leveled too low. The filament is mushed against the bed, but its mushed too much, leading to transparent-looking rows of filament. The specific filament Im using tends to look transparent even when leveled properly, but this is too low regardless:
![too-low.jpg](/resources/1aac14963f294f74b1288a02e24eaead.jpg)
For the last photo, Ive leveled it pretty much perfectly. You can see that the rows arent cylindrical at all, instead theyre long strips that are touching each other properly and dont look too transparent. If you insert a piece of paper between the bed and the nozzle, you will be able to move it with some difficulty, but it wont move very freely.
![just-perfect.jpg](/resources/d95ef0cfd696407b82734616ca963205.jpg)
There you have it! If your filament looks cylindrical, follow your printers manual to reduce the distance between bed and nozzle. If it looks transparent and missing in places completely, you need to increase the distance. If it looks mushed and has the proper color, and the rows are touching each other just so, youre perfect and ready to print!
I hope this guide has helped you, feel free to share it with your friends.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 20, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,12 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Battery discharge curves](../../maker-things/battery-discharge-curves.html)
1. [Details about my Sapphire Pro](../../maker-things/details-about-my-sapphire-pro.html)
1. [Electronics tips](../../maker-things/electronics-tips.html)
1. [GRBL_ESP32 tips](../../maker-things/grbl-esp32-tips.html)
1. [How to properly level your 3D printer](../../maker-things/how-to-properly-level-your-3d-printer.html)
1. [Info on various hardware components](../../maker-things/info-on-various-hardware-components.html)
1. [Installing BLTouch-compatible firmware onto the TwoTrees Sapphire Pro](../../maker-things/installing-bltouch-compatible-firmware-onto-the-twotrees-sapphire-pro.html)
1. [Notes on my TimSav](../../maker-things/notes-on-my-timsav.html)

View File

@ -1,31 +0,0 @@
# Info on various hardware components
I bought various components from AliExpress, and sometimes they lack info. I've added info about them here:
## USB-C decoy breakouts: [5V 9V 12V 15V 20V adjustable 3A PD/QC multi-protocol decoy fast charging boost module TYPE-C USB interface](https://www.aliexpress.com/item/1005006064674815.html)
Specification:
* Supports multiple fast charging protocols
* Maximum support 3A
* TYPE-C port power supply
* Support multiple fast charging protocols: PD3.0/2.0, QC3.0/2.0, FCP, AFC
* PD/QC multi-protocol decoy 5V, 9V, 12V, 15V, 20V voltage adjustable
The manufacturer has said that this is the truth table:
| 1 | 2 | 3 | Voltage |
|---|---|---|---------|
| L | L | H | 5 |
| L | L | L | 9 |
| L | H | L | 12 |
| H | H | L | 15 |
| H | L | L | 20 |
This basically seems to be the same truth table as the original [USB PD decoy](https://hackaday.io/project/187112-usb-pd-decoy), except the logic levels are inverted (high becomes low and vice-versa), and SW1 in the original is M3, SW2 is M1, and SW3 is M2. Pretty convoluted, but it works.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 23, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,23 +0,0 @@
# Installing BLTouch-compatible firmware onto the TwoTrees Sapphire Pro
I installed a BLTouch/3D Touch probe onto my TwoTrees Sapphire Pro, and configuring the firmware was a bit involved. The Sapphire Pro has a MKS Robin Nano v1.2 board. Here's the process:
* Clone the [Marlin repo from GitHub](https://github.com/MarlinFirmware/Marlin).
* Download [the configurations](https://github.com/MarlinFirmware/Configurations/archive/bugfix-2.1.x.zip).
* Check out the `2.1` branch (the configurations seem to be tailored to it and I couldn't be bothered changing).
* Replace the `Configuration.h` and `Configuration_adv.h` files with the ones from the configurations zip.
* Uncomment the `SPRO_BLTOUCH` define.
* I also changed my dimensions to `X_BED_SIZE 230` and `Y_BED_SIZE 225`, for a more realistic bed size.
* Enable Universal Bed Leveling (replace the `AUTO_BED_LEVELING_BILINEAR` define with `AUTO_BED_LEVELING_UBL`), as Bilinear was terrible for me.
* You can also enable the Repeatability Test command with `Z_MIN_PROBE_REPEATABILITY_TEST`.
* Build with `pio run -e mks_robin_nano35`.
* Copy `.pio/build/mks_robin_nano35/Robin_nano35.bin` to **a FAT32-formatted** (important) SD card.
* Insert the card into the printer and turn it on.
* Done!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on May 29, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,21 +0,0 @@
# Notes on my TimSav
A few years ago I made a TimSav foam cutter CNC. These are my notes on it, because I keep forgetting things.
* It runs [FluidNC](https://github.com/bdring/FluidNC).
* `M3 S200` enables the spindle at 20%, `M3 S0`/`S0` disables it, `M5` halts it.
To generate the Gcode, I use a program called [LaserWeb](https://laserweb.yurl.ch/). I have a few notes on it:
* After you load an SVG, you need to click the leftmost button below the SVG, with the three cubes. This will select all the paths to generate movements for.
* You need to click "Create single" to create a path to mill.
* I use "Laser Cut" as the tool.
I created a small script, `cnc_unwanted_moves`, to remove unwanted tool off/on at each corner. I won't share it here, as it's too specific to my configuration, and probably useless to anyone else.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on October 02, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,70 +0,0 @@
# Build notes for the FT Mighty Mini Arrow
These notes are a condensed version of the [FT Arrow build video](https://www.youtube.com/watch?v=cD2Ca2oskVs).
![maxresdefault.jpeg](/resources/d4819ca1c3d0490daaa12f62af09aa00.jpg)
## Wings
* Do an "A" fold on the spars and glue, stop 15mm from each edge. Use a triangle to make sure the spar folds are perpendicular.
* Open the servo hole.
* Cut the bevels, double on wing and single on elevon (on the elevon side).
* Add a thin ribbon on glue on the bottom of the elevon hinge for strength, and scrape almost all of it off.
* Remove servo pocket from the wing.
* Fold the wing with the bottom on top, to curve the leading edge without crinkling the airfoil score cuts.
* Cut the side pods if you aren't going to use a center pod.
* Glue the side pod hinges.
* Cut the main pod space on the top of the wing.
* Skewer the wing score cuts.
* Line up the spar's servo hole onto the wing and glue onto the top side.
* Glue the airfoil's score cuts and fold the wing so the score cuts are glued up.
* Cut the excess spar.
* Probably put the servos in now, to avoid having to make a hook later.
* Glue the leading edge, bottoms of the spar, and the end of the trailing edge, and press closed.
### Joining the wings
* Tape the wings together at the bottom, glue them together in the middle, lay them down and wipe the excess glue.
* Cut the excess edge of the nose.
## Center pod
* Pop out the foam tabs on the wings, where the center pod will go.
* Pop out the tabs on the center pod.
* Do an "A" fold on the bottom plate.
* Fold the little edge of the top of the center pod over (and/or add tape).
* Glue the center pod on. The backs of the wing should both be at the same height. Note that still be open/exposed, not glued down. FT leave them like that, but I like to close them up with some tape at the end so junk doesn't get into the wing.
* Install the control horns and servos (I use epoxy for the control horns as they tend to get ripped out with just hot glue).
* Use the reflex checker foam to calibrate the wing's reflex.
* Add a ziptie to the control rod so it doesn't bend.
## Power pod
* Install the motor onto the power pod and install the power pod. You probably don't need to glue this, just make sure it's tight.
* Remove the foam from the sides of the nose.
* Do a "C" fold on the back bit (and probably add some tape).
* Carefully bend the nose.
* Test fit it and glue the front part.
* Use more tape to secure the front and sides.
* Add some tape so you can pull the top open.
* Add some glue to the bottom of the top hatch so it catches and secures on close.
## Winglets
* Only cut the top part of the wing, parallel to the bottom.
* Line up the reference line on the winglets and glue (the front tip of the winglet should be flush with the leading edge).
## Electronics
* The rest is left as an exercise to the reader.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 27, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,6 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Build notes for the FT Mighty Mini Arrow](../../model-build-notes/build-notes-for-the-ft-mighty-mini-arrow.html)
1. [Mini Drak build condensed instructions](../../model-build-notes/mini-drak-build-condensed-instructions.html)

View File

@ -1,58 +0,0 @@
# Mini Drak build condensed instructions
Sources:
1. [Håvard's Mini Drak build video](https://www.youtube.com/watch?v=L4_dJxiQUjs)
2. [Team Legit's build video](https://www.youtube.com/watch?v=LMbbIzs1TOQ)
To start building:
1. Nubs:
1. Cut off all the nubs with **a fresh blade**, and sand the remainder down with a sanding block to make it flush with the rest of the foam.
2. Motor:
1. Cut the top left and right corner of the motor mount off, so it doesn't conflict with the screws in the foam.
2. Use **only a hacksaw** to open a slot in the foam for the motor mount to go through.
3. Insert the mount into the slot, test it out and remove it again.
4. Apply ample glue both inside the slot and on the motor mount, both on the sides and the top.
5. Insert the motor mount into the slot, put a hard surface (like a hardcover book) under the foam, another hard surface at the top, add some weight or clamp and leave to cure.
3. Thick spars:
1. Remove the spars from the sleeves and keep the sleeves. **Do not cut the spars**.
2. Insert the sleeves in the wings and measure them out. Mark the point in which the sleeve sticks out of the wing and cut with a dremel **outdoors**.
3. Trim the sleeves for the main fuselage.
4. Use some sandpaper wrapped around the spar to lightly scuff the body where the spars will go.
5. Put the rear spar into the sleeve, to help you push the sleeve down into the foam. Make sure it's pushed down all the way to the bottom.
6. **Check that the wings are straight.**
7. CA glue the sleeve into the body while making sure it's flat and down all the way inside the body.
8. Fill the cavity with E6000 so it seeps around the edges to hold the entire sleeve. Use **lots** of glue.
9. Put tape over the edges so the tape doesn't spill over either edge.
10. Put the wings on something that keeps them level, so the glue doesn't flow downhill.
11. For the main body, tape the sides of the sleeve and the insides so the glue doesn't seep in.
12. Make sure the main body is level while the glue cures.
13. Add spar caps and glue with E6000.
4. Thin spars:
1. Lightly open the channels with a hacksaw blade, so it sits exactly on the surface.
2. Cut the spars longer, so you can grip the end and spin it while gluing.
3. Tape around the channel so glue doesn't spill out over the channel.
4. Put glue in, turn the spar around and remove excess.
5. Take the tape off ten minutes after you apply the glue, so the tape doesn't stick.
5. Elevons:
1. Mark the top and bottom on the balsa.
2. Cut the balsa in some way.
3. Hold both elevons together and sand them together to make them identical.
4. Possibly sand the balsa where it meets the body, for full articulation.
5. Mount the elevons with two pieces of tape stuck to each other, overlapping, so there are two sticky sides.
6. Servos:
1. Possibly use larger control horns, found on Thingiverse, because reasons.
7. Winglets:
1. Glue the winglets completely flush with the tip of the wing.
Notes:
> Make sure you use the tallest control horns possible and have loads of expo in for the roll axis (pitch is fine). Matt (because the MD is very roll sensitive as I found out to my surprise).
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 27, 2020. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,5 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Interesting projects](../../programming/interesting-projects.html)

View File

@ -1,19 +0,0 @@
# Interesting projects
This is a list of interesting projects that I don't want to forget about, in no particular order:
## AI stuff
* [aider](https://github.com/paul-gauthier/aider): Pair-program with GPT-4 in your terminal.
* [Sweep](https://sweep.dev/): Makes pull requests from GitHub issues.
## Misc
* [VHS](https://github.com/charmbracelet/vhs): Generates gifs of cli programs from pre-written scripts (great for documentation).
* * *
<p style="font-size:80%; font-style: italic">
Last updated on August 07, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,38 +0,0 @@
# Decorator that runs a function in a thread
I wrote a small decorator that will convert any function to run in a thread:
```
import threading
def run_threaded(fn):
"""A decorator that makes a function run in a thread."""
def run(*k, **kw):
t = threading.Thread(target=fn, args=k, kwargs=kw)
t.start()
return t
return run
```
Example:
```
@run_threaded
def add(x, y):
# This runs in a separate thread.
print(x+y)
add(1+2)
```
That's it!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on July 19, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,5 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Decorator that runs a function in a thread](../../python/decorator-that-runs-a-function-in-a-thread.html)

View File

@ -1,32 +0,0 @@
# Black pills
I've been trying to flash these Black Pills I have (STM32F401), the official STM32 flasher worked great, [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html).
Run with:
`./STM32_Programmer.sh -c port=USB1 -d firmware.bin 0x08000000`
`dfu-util` also worked, eventually, after an unspecified amount of messing around with udev rules (if it doesn't work for you out of the box, try the rs-probe udev rules).
## Useful links
* https://therealprof.github.io/blog/usb-c-pill-part1/
* https://blog.tonari.no/rust-simple-hardware-project
* https://github.com/stm32-rs/stm32f4xx-hal
## This finally worked
Clone the repo: https://github.com/stm32-rs/stm32f4xx-hal/ and `cd examples`.
`cargo objcopy --release --example delay-timer-blinky --features="stm32f401,rt" -- -O binary out.bin`
`dfu-util -a 0 --dfuse-address 0x08000000 -D out.bin`
* * *
<p style="font-size:80%; font-style: italic">
Last updated on December 30, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,74 +0,0 @@
# Cloning cards/fobs with a Proxmark3
## Cloning a Paxton fob
Basically, follow this guide:
https://badcfe.org/how-to-paxton-with-proxmark/
I managed to read my fob with:
```
lf hitag read --ht2 -k BDF5E846
```
If you're getting "Password failed!" or nothing back, move the fob around the 125KHz antenna (the top one), it should eventually work.
Afterwards, [convert the fob pages to an EM4100 ID](https://static.badcfe.org/paxton-covert), and flash the ID to a T5577, emulating an EM4100 chip:
```
lf em 410x clone --id <your hex id>
```
Read it back to make sure:
```
lf em 410x reader
```
You should be done, but I haven't tested it as I don't have a Paxton reader handy.
## Cloning MiFare cards
See [Cloning a Mifare Classic 1K](https://www.gavinjl.me/proxmark-3-cloning-a-mifare-classic-1k/).
## Card cloner password
I have an AliExpress cloner which clones LF cards. Unfortunately, whenever it clones a card, it sets the password bit on it. This makes the card not respond to writes/wipes without the password (it just keeps having the same data, no matter what you write).
To remove it with the Proxmark3, run:
```
lf t55 wipe -p 51243648
```
## Cloning T5577 cards
Read the card with:
```
lf em 410x reader
```
Write with:
```
lf EM 410x clone --id <the ID from before>
```
## Related reading
* [Iceman's Proxmark3 firmware (use this one)](https://github.com/RfidResearchGroup/proxmark3)
* [How to copy Paxton fobs using an RFIDler](https://gist.github.com/natmchugh/18e82761dbce52fa284c87c190dc926f#getting-hold-of-hitag2-tags)
* [ How to copy, read and write Paxton fobs and cards with a Proxmark ](https://badcfe.org/how-to-paxton-with-proxmark/)
* * *
<p style="font-size:80%; font-style: italic">
Last updated on March 04, 2024. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,32 +0,0 @@
# Getting VoWiFi working on Xiaomi.eu
I got a new Xiaomi phone (a Poco F4) and flashed it with Xiaomi.eu. Unfortunately, just like my Poco F3, Voice-over-WiFi wouldn't work. I had looked before, but I couldn't find anything, I assumed it was a problem with the phone. This time, I looked again, and found some posts hinting at it being a problem with the provisioning profile, and recommending using Qualcomm's QPST tool to load the MBN profile.
I tried that, but the profiles weren't there, or they wouldn't be enabled, and in general I just couldn't get it to work. Then, I came across [a post on the Xiaomi.eu forums](https://xiaomi.eu/community/threads/activation-of-volte-and-vowifi-in-xiaomi-eu-rom.63469/) that ended up working for me very easily, and I'm writing it up here in case I need it again.
## Enabling the profile
First, you should disable carrier checks for VoLTE and VoWiFi, just in case. You can do that by going to the dialer and entering the following number: `*#*#86583#*#*` (the numbers spell out "volte", which is easier to remember). Make sure the popup says "carrier check disabled", otherwise do it again until it does.
Then, do the same for `*#*#869434#*#*` (spells out "vowifi"), until that check is disabled too. Now you'll have the appropriate menus in the settings.
To actually load the profile, you need to enter the number `*#*#663368378#*#*` ("modemtest"). Then, go to "MBN config loading and activing tool" shown here:
![screen1.png](/resources/b7e313de59d4412382b2c36675085fdc.png)
Then press "Advanced":
![screen2.png](/resources/6489c6e219874e20a55fcb697dcd8ab3.png)
Select `mbn_eea.txt` (if you're in Europe), and then press "validate".
![screen3.png](/resources/f4679b76f438463382a2849083f6d51d.png)
Wait for it to finish, then you should be set. Restart the phone, enable Airplane mode, enable WiFi and make a call. If it works, you're done.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on July 23, 2022. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,11 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Black pills](../../software/black-pills.html)
1. [Cloning cards/fobs with a Proxmark3](../../software/cloning-cards-fobs-with-a-proxmark3.html)
1. [Getting VoWiFi working on Xiaomi.eu](../../software/getting-vowifi-working-on-xiaomi-eu.html)
1. [Monero GUI syncing stuck with Ledger](../../software/monero-gui-syncing-stuck-with-ledger.html)
1. [Pairing the Xbox One controller in Linux](../../software/pairing-the-xbox-one-controller-in-linux.html)
1. [Resetting TP-Link Powerline plugs](../../software/resetting-tp-link-powerline-plugs.html)
1. [Test and format SD cards](../../software/test-and-format-sd-cards.html)

View File

@ -1,24 +0,0 @@
# Monero GUI syncing stuck with Ledger
This is about the Monero desktop GUI, but probably also applies to Monerujo.
If you're trying to sync the blockchain with your Ledger device, you might be getting the conflicting messages of "Waiting for daemon to sync" and "Daemon is synchronized", which then just stays there forever and doesn't move.
You may see something like this in the log:
```
ERROR wallet.wallet2 src/wallet/wallet2.cpp:3449 Error parsing blocks: Unable to send hidapi command. Error 128: Unknown error
ERROR wallet.wallet2 src/wallet/wallet2.cpp:3512 pull_blocks failed, try_count=3
```
These errors are caused by the Ledger not being connected. You need to leave the Ledger connected throughout the syncing, as apparently the node needs some info from it and won't notify you if it's not there. It also doesn't seem to work if you disconnect and then connect the wallet afterwards.
Letting the Ledger go to the screen saver or lock appears safe, at least with the Nano X I tried. Just leave it connected, and it'll sync fine.
I've opened a suggestion on the [Monero issue tracker](https://github.com/monero-project/monero/issues/7276) to improve the UX of the Ledger integration in general.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on January 04, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,16 +0,0 @@
# Pairing the Xbox One controller in Linux
Sometimes, the Xbox One controller won't pair in Linux, instead connecting and disconnecting rapidly. To fix that:
* Install [xpadneo](https://github.com/atar-axis/xpadneo).
* If the controller keeps connecting and disconnecting when you turn it on, make sure you upgrade to the latest firmware, that fixes that issue.
* Pair!
That should be all that's required, your controller should now be paired.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on July 29, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,18 +0,0 @@
# Resetting TP-Link Powerline plugs
A few years ago, I bought a pair of TP-Link Powerline plugs, and I've been paying for that mistake ever since (the Devolo ones have given me zero trouble). They constantly desynchronize and need to be paired again.
This is the process, so I don't forget:
* Press the button for around 7 seconds, until the lights all go dark and light up again. Don't do this while the pairing light is blinking, it doesn't seem to work.
* Press the pairing button once.
* Repeat this process on the second plug.
* They should pair now.
* Get Devolo plugs.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on May 25, 2023. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,27 +0,0 @@
# Test and format SD cards
I wrote a short bash script that tests SD cards with [F3](https://3ds.hacks.guide/f3-(linux).html) to see if they're fake, deletes everything on them, creates a new partition table and one exFAT partition on them.
Here it is:
```bash
#!/usr/bin/env bash
set -euox pipefail
sudo umount --force "$1"1 || true
sudo f3probe --destructive --time-ops "$1"
sudo parted --script "$1" "mklabel msdos" "mkpart primary ext4 0% 100%"
sleep 1
sudo mkfs.exfat -n Stavros "$1"1
eject "$1"
```
Save it as `formatsd.sh` and run it as `./formatsd.sh /dev/sdX`.
* * *
<p style="font-size:80%; font-style: italic">
Last updated on August 18, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -1,5 +0,0 @@
# Contents
Click on a link in the list below to go to that page:
1. [Stavros' notes](../../welcome/stavros-notes.html)

View File

@ -1,20 +0,0 @@
# Stavros' notes
Welcome to my notes.
This site is autogenerated from a bunch of [Joplin](https://joplinapp.org/) notes.
I wrote a small script to read the notes, export them, and generate a static site.
If you want to use the script and generate such a site for yourself, feel free to fork my repository:
[https://gitlab.com/stavros/notes/](https://gitlab.com/stavros/notes/)
Just run `./joplinexport` on your computer, it will read the database and create a site like this one and upload it to GitLab pages. Also, the `build` and `move_html_to_dir` scripts might be of interest.
Otherwise, enjoy my notes!
* * *
<p style="font-size:80%; font-style: italic">
Last updated on November 20, 2021. For any questions/feedback,
email me at <a href="mailto:hi@stavros.io">hi@stavros.io</a>.
</p>

View File

@ -39,9 +39,11 @@ class Folder:
title: str
icon: str
def is_private(self) -> bool:
"""Return whether this folder is private."""
return contains_word("private", self.title)
def is_for_blog(self) -> bool:
"""Return whether this folder is for posting to blog."""
"""Currently looks for the joplin folder named Blog"""
return contains_word("Blog", self.title)
def get_url(self) -> str:
"""Return the folder's relative URL."""
@ -78,15 +80,15 @@ class Note:
updated_time: datetime
tags: List[str] = dataclasses.field(default_factory=list)
def is_private(self) -> bool:
def is_for_blog(self) -> bool:
"""
Check whether a note is private.
Check whether a note is tagged for being published to blog.
This function checks a note's title and tags and returns whether it
should be considered private or whether it should be published.
should be whether it should be published or be considered private
"""
hidden_keywords = ["private", "wip", "draft"]
for keyword in hidden_keywords:
blog_keywords = ["blog"]
for keyword in blog_keywords:
if contains_word(keyword, self.title) or keyword in self.tags:
return True
return False
@ -215,7 +217,7 @@ class JoplinExporter:
}
self.folders = {
id: folder for id, folder in self.folders.items() if not folder.is_private()
id: folder for id, folder in self.folders.items() if folder.is_for_blog()
}
# Get the tags by ID.
@ -252,7 +254,7 @@ class JoplinExporter:
datetime.fromtimestamp(updated_time / 1000),
tags=note_tags[id],
)
if note.is_private():
if note.is_for_blog():
continue
self.notes[note.folder.id].append(note)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 705 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 748 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 655 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB