سباق FPV على جهاز محاكاة (نصنع عصا تحكم USB من جهاز تحكم عن بعد لاسلكي)

الشتاء في خطوط العرض الشمالية هو الوقت الذي يكون فيه طيار FPV لديه الوقت لأخذ استراحة من السباق والانهيارات المستمرة ، والتقاط مكواة لحام ، وصياغة شيء مفيد لهوايته.

نظرًا لأن الجو بارد في الخارج ، فسوف ندرب مهارات التجريب على أجهزة المحاكاة. للقيام بذلك ، تحتاج إلى توصيل جهاز الراديو الخاص بك بالكمبيوتر من خلال محول خاص ، والذي يحول إشارة PPM من جهاز التحكم عن بعد إلى إشارات عصا التحكم USB التي يفهمها الكمبيوتر. هذه المحولات ، بطبيعة الحال ، ليست غير شائعة وتكلف فلسا واحدا في المتاجر الصينية. ومع ذلك ، فإن تسليم الطلب طويل الانتظار ، وهل سيعمل كما توقعنا؟ على سبيل المثال ، لدي هذا:

لسبب ما لم أفهمه بعد ، يرفض بشكل قاطع المعايرة بشكل كاف في محاكي FPV Freerider ، على الرغم من أنه يعمل بشكل رائع في Phoenix RC و Aerofly RC 7. ينقل FPV Freerider بشكل جيد فيزياء الرحلة الجوية على مروحية سباق ، وإلى جانب لديه وضع تجريبي مجاني.

محلولة - نصنع المحول بأنفسنا!

القليل من المعدات:

تحتوي معظم معدات RC الأكثر أو الأقل خطورة على موصل حيث تقوم بإخراج إشارات التحكم بتنسيق PPM (تعديل موضع النبض). إشارة PPM هي سلسلة من النبضات القصيرة ، ويحدد الفاصل الزمني بينها قيمة التحكم لكل من قنوات المعدات الراديوية.
جوهر PPM ينقل الصورة بشكل مثالي:


لفك شفرة PPM ، تحتاج إلى قياس الفترات الزمنية بين النبضات المتتالية بدقة (لا يهم بين الحواف: الأمامية أو الخلفية ، لأن مدة النبضات نفسها دائمًا).

التنفيذ:

إلهام Pocherpnuv من المادة AlexeyStn إنشاء PPM-إلى-USB محول STM32F3Discovery مقرها، ولكن وجود فقط اردوينو برو مايكرو (ليوناردو) مع دعم الأجهزة لUSB، طريقة بسيطة لبدء المحول.

يمكنك العثور على العديد من المشاريع المماثلة على github ، وبعضها لا يتطلب حتى أجهزة USB في وحدة التحكم. ومع ذلك ، يحتاج معظمهم إلى الانتهاء بجدية بملف للحصول على شيء يعمل. كان المشروع المناسب هو rc-leonardo-joy، الذي بدأ في العمل على الفور تقريبًا بعد ملء الرسم ، لكنه أظهر على الفور بعض العيوب: جميع قراءات عصا التحكم لم تكن مستقرة جدًا - رقص المؤشر في لوحة التحكم طوال الوقت حول نقطة التحديد. لا أستطيع أن أقول أن هذا أثر بشكل كبير على المعالجة في المحاكي ، لكننا نريد التدريب على معدات جيدة!

حسنًا ، نتسلق الشفرة ونرى: يتم حساب عرض نبضة PPM عن طريق معالجة مقاطعة خارجية وقياس الفترات الفاصلة بين المكالمات إلى وظيفة المايكرو () :

void rxInt(void) {
  uint16_t now,diff;
  static uint16_t last = 0;
  static uint8_t chan = 0;

  now = micros();
  sei();
  diff = now - last;
  last = now;
  if(diff>3000) chan = 0;
  else {
    if(900<diff && diff<2200 && chan<RC_CHANS ) {
      rcValue[chan] = adjust(diff,chan);
    }
    chan++;
  }
}

اقرأ عن وظيفة المايكرو () في وثائق اردوينو:

إرجاع عدد الميكروثانية منذ أن بدأ مجلس Arduino في تشغيل البرنامج الحالي. سيزيد هذا الرقم (يعود إلى الصفر) ، بعد 70 دقيقة تقريبًا. على لوحات اردوينو 16 ميجاهرتز (مثل Duemilanove و Nano) ، هذه الوظيفة لها دقة أربعة ميكروثانية (أي أن القيمة المعادة هي دائمًا مضاعفة لأربعة). على لوحات 8 MHz Arduino (مثل LilyPad) ، تحتوي هذه الوظيفة على دقة تبلغ ثمانية ميكروثانية.

أي أن الوظيفة ليست دقيقة بشكل خاص فقط وتعرض دائمًا قيمًا مضاعفة لـ 4 μs ، ولكنها أيضًا تفيض بعد 70 دقيقة ، مما يمنحنا نوعًا من القيمة المنحنية للفاصل المقاس. ليس جيد سيكون من الأفضل استخدام مؤقت ومقاطعه لالتقاط الإشارات الخارجية.

ننظر إلى أبعد من ذلك: تقتصر معظم البيانات على موضع عصا التحكم بشكل مصطنع على بايت واحد (0-255):
// Convert a value in the range 1000-2000 to 0-255
byte stickValue(int rcVal) {
  return map( constrain(rcVal - 1000, 0, 1000), 0, 1000, 0, 255);
}

حسنًا ، أود أن أكون أكثر دقة. ولكن لهذا ، سيكون عليك إعادة كتابة واصف HID وتصحيح جميع أنواع البيانات ذات الصلة.

لم يقل من فعله.
نقوم بتخزين المستودع ، ونعيد كتابة الرمز لاستخدام جهاز توقيت لحساب فترات PPM:
void initTimer(void) { 
	// Input Capture setup
	// ICNC1: =0 Disable Input Capture Noise Canceler to prevent delay in reading
	// ICES1: =1 for trigger on rising edge
	// CS11: =1 set prescaler to 1/8 system clock (F_CPU)
	TCCR1A = 0;
	TCCR1B = (0<<ICNC1) | (1<<ICES1) | (1<<CS11);
	TCCR1C = 0;

	// Interrupt setup
	// ICIE1: Input capture 
	TIFR1 = (1<<ICF1); // clear pending
	TIMSK1 = (1<<ICIE1); // and enable
}
...

ISR(TIMER1_CAPT_vect) {
	union twoBytes {
		uint16_t word;
		uint8_t  byte[2];
	} timeValue;

	uint16_t now, diff;
	static uint16_t last = 0;
	static uint8_t chan = 0;
	
	timeValue.byte[0] = ICR1L;    // grab captured timer value (low byte)
	timeValue.byte[1] = ICR1H;    // grab captured timer value (high byte)

	now = timeValue.word;
	diff = now - last;
	last = now;

	//all numbers are microseconds multiplied by TIMER_COUNT_DIVIDER (as prescaler is set to 1/8 of 16 MHz)
	if(diff > (NEWFRAME_PULSE_WIDTH * TIMER_COUNT_DIVIDER)) {
		chan = 0;  // new data frame detected, start again
	}
	else {
		if(diff > (MIN_PULSE_WIDTH * TIMER_COUNT_DIVIDER - THRESHOLD) 
			&& diff < (MAX_PULSE_WIDTH * TIMER_COUNT_DIVIDER + THRESHOLD) 
			&& chan < RC_CHANNELS_COUNT) 
		{
			rcValue[chan] = adjust(diff, chan); //store detected value
		}
		chan++; //no value detected within expected range, move to next channel
	}
}

قم بزيادة فترات انحراف العصا إلى 0-1000 في واصف HID:
	// Joystick
	0x05, 0x01,			// USAGE_PAGE (Generic Desktop)
	0x09, 0x04,			// USAGE (Joystick)
	0xa1, 0x01,			// COLLECTION (Application)
	0x85, JOYSTICK_REPORT_ID,	//   REPORT_ID (3)
	...
	0xA1, 0x00,		    //   COLLECTION (Physical)
	0x09, 0x30,		    //     USAGE (x)
	0x09, 0x31,		    //     USAGE (y)
	0x09, 0x33,		    //     USAGE (rx)
	0x09, 0x34,		    //     USAGE (ry)
	0x15, 0x00,		    //	   LOGICAL_MINIMUM (0)
	0x26, 0xE8, 0x03,	    //     LOGICAL_MAXIMUM (1000)
	0x75, 0x10,	  	    //	   REPORT_SIZE (16)
	0x95, 0x04,		    //     REPORT_COUNT (4)
	0x81, 0x02,		    //     INPUT (Data,Var,Abs)
	0xc0,			    //   END_COLLECTION

	0xc0				// END_COLLECTION

على طول الطريق ، قم بتغيير uint8_t إلى uint16_t أينما يتم إرسال قيم انحراف العصا.
نزيل الكود الإضافي ، ونضيف دستة # تعريف ونحصل على رسم جيد ، شحذ للعمل كمحول PPM-USB.

النتيجة متاحة في github: github.com/voroshkov/Leonardo-USB-RC-Adapter

إعدادات الرسم:

من المنطقي إزالة تعريف فوتابا إذا كان لديك أجهزة أخرى:
#define FUTABA

وإذا لزم الأمر ، قم بتعديل قيم الميكروثانية في المعلمات إذا كانت المعدات الخاصة بك تنتج أوقات أخرى:
#define STICK_HALFWAY 500
#define STICK_CENTER 1500
#define THRESHOLD 100


التجميع:

لتجميع الرسم وتحميله ، تحتاج إلى استبدال مكتبات USB في بيئة Arduino نفسها ، بعد عمل نسخ احتياطية.
للقيام بذلك ، نذهب إلى أحشاء Arduino على طول المسار ... \ Arduino \ hardware \ arduino \ cores \ arduino \ ، النسخ الاحتياطي usbapi.h و hid.cpp ، وبعد ذلك نستبدلها بنفس الملفات من مجلد ArduinoLibs في المستودع. بعد ذلك ، افتح الرسم ، وقم بتوصيل Arduino Leonardo واملأه.

اتصال:

كل شيء بسيط بشكل قبيح: من ناحية ، نقوم بإدخال USB ، من ناحية أخرى ، نقوم بلحام سلكين (على الرقم 4 الرقمي والأرضي) ونلصقه في PPM لجهاز الإرسال والأرض ، على التوالي. اتضح بطريقة أو بأخرى مثل هذا:

في Windows 7 ، يتم التعرف على الجهاز على أنه مركب (لوحة المفاتيح والماوس وعصا التحكم) باسم Arduino Leonardo.

إشارة خاصة تستحق موصل في المعدات. إنه في مكان ما مقبس صوت عادي ، وفي مكان ما (كما هو الحال في Futaba 7C) ، هناك شيء أكثر صعوبة:


لتجميع موصلات "ذكر" مختلفة ، لطالما استخدمت بنجاح الغراء الساخن. للقيام بذلك ، نضع ورقًا أو بولي إيثيلين على "الأم" ، ونخترق هذه الركيزة بالدبابيس بحيث تلتصق بالموصل على الجانب الآخر ، ثم تصب تدريجيًا الغراء بين الدبابيس ، مما يمنحها الشكل بأصابع مبللة في نفس الوقت. بالطبع ، يجب لحام الأسلاك مقدمًا حتى لا تذوب المادة اللاصقة المعالجة عند اللحام. لم يكن دائمًا جماليًا ، ولكنه عملي للغاية:

(هنا ، في الموصل ، هناك حاجة إلى 4 دبابيس لتحديد المواقع بشكل لا لبس فيه ، هناك عاملان فقط.)

هذا كل شيء. نقوم بتنزيل جهاز المحاكاة ، وربط المعدات وتدريب المهارات التجريبية أثناء شرب الشاي الساخن أمام الموقد في أمسيات الشتاء القاتمة.

ملاحظة

ماذا لو لم يكن هناك اردوينو ليوناردو ، ولكن هناك مثل هذا الحد الأدنى من مجلس التنمية على STM32F103C8T6؟

لا تقلق ، على طول الطريق. بالنسبة لك ، وكذلك من أجل تطوري الخاص ، قمت بنقل مشروع Alexey Stankevich المذكور بالفعل .
يمكن العثور على مصادر وثنائيات مجمعة للتحميل إلى وحدة التحكم هنا: github.com/voroshkov/STM32-RC-USB-Adapter .

سأجيب على جميع الأسئلة بسرور في التعليقات.

رحلة سعيدة!

Source: https://habr.com/ru/post/ar388811/


All Articles