diff --git a/device_firmware/cart_firmware/.gitignore b/device_firmware/cart_firmware/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/device_firmware/cart_firmware/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/device_firmware/cart_firmware/src/main.cpp b/device_firmware/cart_firmware/src/main.cpp index 2694f55..6af2c78 100644 --- a/device_firmware/cart_firmware/src/main.cpp +++ b/device_firmware/cart_firmware/src/main.cpp @@ -4,9 +4,9 @@ #include // ---- калибровка стика (АЦП 12 бит, замерено 2026-08-20) ---- -static const int X_FWD = 508, X_MID = 2014, X_BACK = 3625; // PA0 +static const int X_FWD = 650, X_MID = 2014, X_BACK = 3378; // PA0 (плечи равны: 2014-650 = 3378-2014 = 1364) static const int Y_RIGHT = 479, Y_MID = 1981, Y_LEFT = 3586; // PA1 -static const int DEADZONE = 30; // отсечка дребезга вокруг нейтрали +static const int DEADZONE = 15; // отсечка дребезга вокруг нейтрали // ---- SBUS-значения старого пульта ---- static const uint16_t SBUS_MID = 1024; @@ -14,14 +14,22 @@ static const uint16_t CH2_MIN = 433, CH2_MAX = 1643; // назад..вперё static const uint16_t CH4_MIN = 446, CH4_MAX = 1654; // влево..вправо // ---- expo: 0 = линейно, 1 = максимально мягкая нейтраль ---- -static const float EXPO_K = 0.4f; +static const float EXPO_K = 0.0f; // ---- общий масштаб выхода: 1.0 = диапазон старого пульта ---- -static const float RANGE_SCALE = 0.5f; +static const float RANGE_SCALE = 0.75f; // симметричные плечи: вперёд и назад дают одинаковый максимум static const uint16_t CH2_SPAN = 591; // min(1643-1024, 1024-433) static const uint16_t CH4_SPAN = 578; // min(1654-1024, 1024-446) +// ---- профиль газа/поворота ---- +static const float MOVE_START = 0.15f; // старт движения, доля хода стика +static const float POWER_FWD = 0.60f; // потолок «вперёд» +static const float POWER_BACK = 0.50f; // потолок «назад» +static const float POWER_TURN = 0.70f; // потолок поворота +static const uint16_t CH2_DB = 221; // мёртвая зона приёмника тележки (ЗАМЕРИТЬ по монитору) +static const uint16_t CH4_DB = 221; + static const uint32_t FRAME_PERIOD_MS = 50; static const uint32_t PIN_X = PA0; static const uint32_t PIN_Y = PA1; @@ -76,6 +84,20 @@ static uint16_t toSbus(float x, uint16_t span) { return (uint16_t)(SBUS_MID + lroundf(x * span)); } +// стик [-1..1] -> SBUS-значение канала: ниже MOVE_START — нейтраль, выше — +// линейно от порога срабатывания приёмника (db) до POWER_FRAC*span на полном стике +static uint16_t driveToSbus(float x, uint16_t span, uint16_t db, + float powerPos, float powerNeg) { + float mag = fabsf(x); + if (mag <= MOVE_START) + return SBUS_MID; + float outMax = (x > 0.0f ? powerPos : powerNeg) * span; + float t = (mag - MOVE_START) / (1.0f - MOVE_START); + long delta = lroundf(db + t * (outMax - db)); + return (x > 0.0f) ? (uint16_t)(SBUS_MID + delta) + : (uint16_t)(SBUS_MID - delta); +} + static void sbusPack(uint8_t out[25], const uint16_t ch[16]) { out[0] = 0x0F; memset(out + 1, 0, 22); @@ -122,8 +144,8 @@ void loop() { uint16_t ch[16]; for (int i = 0; i < 16; i++) ch[i] = SBUS_MID; - ch[1] = toSbus(expo(fwd) * RANGE_SCALE, CH2_SPAN); // канал 2 - ch[3] = toSbus(expo(right) * RANGE_SCALE, CH4_SPAN); // канал 4 + ch[1] = driveToSbus(fwd, CH2_SPAN, CH2_DB, POWER_FWD, POWER_BACK); // канал 2 — газ + ch[3] = driveToSbus(right, CH4_SPAN, CH4_DB, POWER_TURN, POWER_TURN); // канал 4 — поворот uint8_t frame[25]; sbusPack(frame, ch);