आर्किटेक्चर: कर्नेल और डेटा प्रवाह
CRSF स्ट्रीम पंख-फड़फड़ाहट और पूँछ कैसे बनती है: मॉड्यूल सीमाएँ, दो मिक्सर कर्नेल, और वह स्टेट मशीन जो लिंक टूटने पर टेरोसॉर को जीवित रखती है।
सिग्नल पाइपलाइन
PteronautOS ExpressLRS 4.x का एक फोर्क है जिसने रिसीवर की "PWM पासथ्रू" पूँछ को एक समर्पित फ़्लाइट-कंट्रोल परत से बदल दिया। डेटा-पथ जान-बूझकर छोटा है:
CRSF radio link
│ 2.4 GHz SX1280
▼
rx_main / CRSF decoder → ChannelData[] (raw 172…1811 µs-window values)
▼
Ornithopter::update() → _readChannels() → voice* fields
▼ kernel select: activeProfile ≥ GEARBOX_2VTAIL_1RUD ?
_computeServoMixer() OR _computeGearboxMixer()
▼
_f[] (indexed by ServoFunc tag, µs)
▼
PWM output stage → funcMap channels → wing / rudder / motor servos
चार संरचनात्मक विचार जानवर को स्थिर और कोड को छोटा रखते हैं:
- चैनल जल्दी सामान्यीकृत होते हैं. 172–1811 CRSF विंडो का हर कच्चा मान एक बार −1…+1(
_crsfToNorm) या प्रतिशत में मैप होता है, और केवल वही इकाई मिक्सर से बहती है — कोई बार-बार जादुई स्थिरांक नहीं। -
आउटपुट टैग होते हैं, पिन से बँधे नहीं. मिक्सर
_f[ServoFunc]में लिखते हैं। कोई टैग किस भौतिक PWM आउटपुट को चलाता है, यह बाद में प्रोफ़ाइल केfuncMapसे तय होता है — देखें मिक्सर संदर्भ .मॉडल को फिर से पिन करने से मिक्सर गणित कभी नहीं छूता। - कर्नेल एक कम्पाइल-टाइम परिवार है, रनटाइम चयन. वेवफ़ॉर्म फ़्लैपर और गियरबॉक्स कंट्रोलर दोनों बाइनरी में रहते हैं; सक्रिय प्रोफ़ाइल हर अपडेट टिक पर कर्नेल चुनती है।
- फेलसेफ़ एक घटना नहीं, एक अवस्था है. लिंक-डाउन, बेंच मोड और स्टिक-ओवरराइड
update()में स्पष्ट द्वार हैं, ताकि रेडियो के शांत रहते सर्वो कभी भाग न सकें।
दो कर्नेल: वेवफ़ॉर्म और गियरबॉक्स
कर्नेल वह ब्लॉक है जो सामान्यीकृत चैनलों को सर्वो-फ़ंक्शन µs में बदलता है। PteronautOS में दो परिवार हैं, जिन्हें मिक्सर-प्रोफ़ाइल संख्या से पहचाना जाता है:
| परिवार | प्रोफ़ाइल | एक्चुएटर | मॉडल आदिरूप |
|---|---|---|---|
| वेवफ़ॉर्म (सर्वो) कर्नेल | 0 SERVO_2WING · 1 SERVO_2WING_1RUD · 2 SERVO_4WING | फ़्लैपिंग विंग सर्वो (2–4), क्रेस्ट रडर | डायरेक्ट-ड्राइव सर्वो ऑर्निथॉप्टर — क्लासिक PteronautOS |
| गियरबॉक्स कर्नेल | 3 GEARBOX_2VTAIL_1RUD · 4 GEARBOX_1MOT_2VTAIL · 5 GEARBOX_1MOT_2VTAIL_1RUD · 6 GEARBOX_1ELE_1RUD · 7 GEARBOX_1MOT_1ELE_1RUD | मोटर ESC, V-टेल या एलेवेटर + रडर | पारंपरिक टेल सतहों वाला गियर/मोटर फ़्लैपर |
चयन update() में एक ही परीक्षण PROFILE_IS_GEARBOX(activeProfile ≥ 3) से होता है। प्रोफ़ाइल स्वयं एक रनटाइम मान है: यह बिल्ड फ़्लैग MIXER_PROFILE से शुरू होती है(पुराना ORNITHOPTER_GEARBOX=1 अब भी प्रोफ़ाइल 5 पर मैप होता है) पर इसे WebUI से setOrnithopterProfile() द्वारा लाइव बदला जा सकता है — फ़र्मवेयर बिना रीफ़्लैश नए एयरफ़्रेम पर फिर निशाना साधता है। कुल आठ प्रोफ़ाइल हैं; उनके सटीक funcMap लेआउट मिक्सर संदर्भ में सारणीबद्ध हैं।
वेवफ़ॉर्म कर्नेल (सर्वो फ़्लैपिंग)
वेवफ़ॉर्म कर्नेल वही है जिसे ज़्यादातर लोग "PteronautOS" कहते हैं: दो विंग सर्वो एक फ़ेज़-निरंतर दोलन चलाते हैं जिसका आकार हर चक्र गढ़ा जाता है। इसकी शारीरिक रचना:
- हिस्टैरिसीस के साथ फ़्लैप द्वार. फ़्लैपिंग में प्रवेश के लिए थ्रॉटल को फ़्लैप सीमा(डिफ़ॉल्ट रॉ ≈303, ≈1.08 ms PWM-समतुल्य) पार करनी होती है; यह केवल सीमा − 50 हिस्टैरिसीस से नीचे निकलता है, ताकि सीमांत थ्रॉटल कभी पंखों को कँपा न सके।
- आवृत्ति. एक FlappingOscillator वास्तविक बीते समय(µs घड़ी, dt अधिकतम 100 ms) से आगे बढ़ता है। कैडेंस लक्ष्य प्रोफ़ाइल के
throttleFrequencyMixसे CH6 फ़्लैप-आवृत्ति चैनल और थ्रॉटल को 0.5 Hz…flapBaseFreq/10 के भीतर मिलाता है। - आयाम. सर्वो-गति सीमा का थ्रॉटल प्रतिशत
ampMax = degPerSec / (2·f)(जहाँdegPerSec = 60°/servoSpeed_ms), गुणक से पहले 55° पर हार्ड-कैप। इसलिए उच्च आवृत्ति पर आयाम स्वाभाविक रूप से ढह जाता है — पंख कभी सर्वो की क्षमता से अधिक नहीं माँगता। - उग्रता. डाउन-स्ट्रोक(पावर) और अप-स्ट्रोक(रिकवरी) की उग्रता हर स्ट्रोक पर गढ़ी जाती है, एलेवेटर से असममित रूप से मॉड्युलेट होती है(खींचने से डाउनस्ट्रोक, धकेलने से अपस्ट्रोक कठोर होता है) और थ्रॉटल युग्मन से, फिर आकार फ़ंक्शन से पहले 0…8 पर सीमित होती है।
- यॉ अंतर. रडर बाएँ/दाएँ-विपरीत उग्रता(
rudderFerocityRange) और बाएँ/दाएँ-विपरीत आयाम(rudderAmplitudeDifferential) जोड़ता है जबकि स्ट्रोक-रिवर्सल फ़ेज़ पंखों के बीच साझा रहता है — मोड़ की क्षमता असममित ड्वेल से आती है, न कि अतुल्यकालिक पंखों से। - ज्यामिति और आउटपुट. गढ़ी गई −1…+1 तरंग को डिग्री में स्केल किया जाता है, एलेरॉन/एलेवेटर स्टीयरिंग(±60° अधिकार × स्केल) के विरुद्ध मिलाया जाता है, ग्लाइड/फ़्लैप-केंद्र ट्रिम से ऑफ़सेट किया जाता है, 0…180° पर क्लैम्प किया जाता है, फिर कॉन्फ़िगर करने योग्य
servoMinUs…servoMaxUsलिफ़ाफ़े(डिफ़ॉल्ट 988…2012) से फ़ंक्शन-वार ट्रिम के साथ µs में बदला जाता है। - ग्लाइड शाखा. फ़्लैप सीमा से नीचे ऑसिलेटर क्षय होता है और पंख एक स्थिर ग्लाइड कोण रखते हैं — बेंच और प्रक्षेपण के लिए आदर्श स्थिति।
गियरबॉक्स कर्नेल (मोटर + पूँछ)
गियरबॉक्स कर्नेल शुद्ध विंगबीट को मोटरयुक्त ड्राइवट्रेन + पारंपरिक टेल सतहों से बदल देता है। क्योंकि मोटर लगातार घूमती है, यह कर्नेल प्रति टिक स्टेटलेस है — कोई ऑसिलेटर नहीं — और इसके बजाय:
- थ्रॉटल(आर्म्ड) को 1000…2000 µs ESC कमांड(
SF_MOTOR) में मैप करता है, डिसआर्म पर आइडल; - टेल मिलाता है: V-टेल प्रोफ़ाइल एलेवॉन ब्लेंड(एलेरॉन+एलेवेटर / एलेरॉन−एलेवेटर) का उपयोग करती हैं, क्लासिक प्रोफ़ाइल अलग एलेवेटर सतह का;
- Zephyrus(सक्षम होने पर) को टेल सर्वो में रोल और पिच PID सुधार इंजेक्ट करने देता है, ±250 µs(
ZEPHYR_GEARBOX_CLAMP_US) पर सीमित ताकि सेंसर गड़बड़ी कभी सर्वो रोक न सके; - वेवफ़ॉर्म कर्नेल के समान रडर मिक्सर और µs/ट्रिम/क्लैम्प लिफ़ाफ़ा बनाए रखता है।
एक ऑर्निथॉप्टर रिग दोनों व्यक्तित्व भी धारण कर सकता है: वेवफ़ॉर्म कर्नेल से फ़्लैपिंग लॉन्च, गियरबॉक्स पर क्रूज़ — रनटाइम प्रोफ़ाइल स्विच update() की वही एक पंक्ति है।
अवस्थाएँ: लिंक, बेंच और फ़ेलसेफ़
update() को WiFi/सर्वो लूप से स्थिर ~10 ms कैडेंस पर बुलाया जाता है और किसी मिक्सर के चलने से पहले तीन फ़्लैग पर द्वार लगाता है:
| अवस्था | स्थिति | व्यवहार |
|---|---|---|
| सामान्य उड़ान | linkUp + आर्म्ड चैनल सक्रिय | पूर्ण कर्नेल आउटपुट स्टिक का अनुसरण करता है |
| बेंच / पैनल मोड | benchMode(WebUI पैनल, कोई RC लिंक नहीं) |
न्यूट्रल स्टिक इंजेक्ट होते हैं, थ्रॉटल फ़्लैप सीमा से नीचे रुकता है — ग्लाइड + ट्रिम संपादन लाइव दिखते हैं |
| स्टिक ओवरराइड | stickOverride(वर्चुअल चैनल) |
फ़र्मवेयर-इंजेक्टेड चैनल मान CRSF को पूरी तरह बदल देते हैं(सर्वो स्वीप, परीक्षण) |
| फेलसेफ़ | लिंक खो गया(onLinkDown / enterFailsafe) |
सभी फ़ंक्शन 1500 µs पर केंद्रित होते हैं, ऑसिलेटर रीसेट, मोटर → न्यूनतम; CRSF पैकेट हानि भी RX स्तर पर केंद्रित होती है |
हानि पर केंद्रित होने का व्यवहार जान-बूझकर दो परतों में दोहराया गया है: CRSF स्टैक चैनल डेटा को फेलसेफ़ करता है, और Ornithopter परत ज्यामिति(दोलन अवस्था सहित) को फेलसेफ़ करती है। इसलिए मृत रेडियो एक ग्लाइडिंग, नियंत्रणीय एयरफ़्रेम छोड़ता है — कभी छटपटाता हुआ नहीं।
स्रोत मानचित्र
| मॉड्यूल | पथ | उत्तरदायित्व |
|---|---|---|
| Ornithopter परत |
src/lib/Ornithopter/
|
कर्नेल चयन, मिक्सर गणित, वेवफ़ॉर्म ऑसिलेटर, प्रोफ़ाइल, ट्रिम |
| फ़्लाइट प्रोफ़ाइल और स्थिरांक |
src/lib/Ornithopter/OrnithopterConfig.h
|
MixerProfile enum, ServoFunc टैग, funcMap, सभी संख्यात्मक डिफ़ॉल्ट |
| ऑसिलेटर / आकार |
src/lib/Ornithopter/OrnithopterWaveform.h
|
फ़ेज़ समाकलन, उग्रता आकार, रिवर्सल लॉजिक |
| Zephyrus(वैकल्पिक) |
src/lib/Zephyrus/
|
MPU6050 + Mahony AHRS, दोहरा PID, क्रेस्ट/टेल सुधार |
| PWM आउटपुट स्टेज |
src/lib/ServoOutput/devServoOutput.cpp
|
CRSF टिक से समकालिक µs लिखता है |
| WebUI कॉन्फ़िग |
src/lib/WIFI/devWIFI.cpp
|
रनटाइम प्रोफ़ाइल + ट्यूनिंग स्थायित्व(/pteronautos) |
अगली निचली परत — संख्याएँ ठीक कौन-सा वेवफ़ॉर्म आकार बनाती हैं, और हर प्रोफ़ाइल फ़ंक्शनों को PWM आउटपुट से कैसे जोड़ती है — रहती है मिक्सर संदर्भ में, और सर्वो-टाइमिंग लिफ़ाफ़ा सर्वो कर्नेल में प्रलेखित है।