بيان المشكلة
عند تطوير جهاز آخر على متحكم دقيق ، واجهت موقفًا يلزم فيه تسجيل مستمر لكمية كبيرة من البيانات. كان على الجهاز حفظ مجموعة بيانات تتكون من طابع زمني وستة قياسات ADC من 100 مرة في الثانية إلى بطاقة SD (دعنا نسمي هذه البيانات لتعيين حزمة) ، ثم تحليل هذه البيانات على جهاز كمبيوتر في شكل رسوم بيانية. كان من الضروري أيضًا بالتوازي مع كتابة البيانات على بطاقة SD ، ونقلها عبر UART. يجب أن تأخذ هذه البيانات أقل مساحة ممكنة ، نظرًا لوجود الكثير من البيانات. في الوقت نفسه ، كان من الضروري فصل هذه الحزم بطريقة أو بأخرى ، لأن البيانات دخلت مجرى مستمر. بعد البحث عن شيء جيد عبر الإنترنت ، لم أجده ، لذا فقد تقرر إنشاء بروتوكول ومكتبات خاصة بي.
ثم ظهر - بروتوكول تدفق الحزمة (PSP1N)
نتيجة لبعض الاعتبارات ، تقرر ما يلي: في البروتوكول ، سيتم إرسال البيانات في حزم تتكون من N بايت ، حيث يتم تخصيص البتة الأولى من كل بايت لإشارة بت البدء لمزامنة الرزم (اسم البروتوكول) ، ويتم تخصيص البتات السبعة المتبقية للبيانات. يُعرف تسلسل وحجم البيانات مقدمًا.
مثال:
نحن نخصص 32 بت للطابع الزمني ، 60 بت لقياسات ADC (6 قنوات لكل 10 بتات) ، بإجمالي 92 بت. نظرًا لأنه يمكنك نقل 7 بتات من البيانات المفيدة في بايت ، ستتألف الحزمة من 14 بايت (92 بت / 7 بت = 13.14 ... تقريبًا تصل إلى 14). هناك 112 بت من المعلومات في 14 بايت ، منها 14 بت يتم شغلها بواسطة سمة بداية بت التي تبلغ 92 بت من البيانات المفيدة ، وهناك 6 بتات غير مستخدمة (والتي يمكننا من خلالها كتابة بعض المعلومات الأخرى ، ولكن من أجل البساطة لن نستخدمها).

عندما تكون البتة السابعة هي علامة بت البدء (تشير إلى بداية الحزمة) ، فإن 6،5،4،3،2،1،0 عبارة عن وحدات بت للبيانات.
يعلم الجانب المتلقي أيضًا أنه يتلقى حزمة من 14 بايت يكون فيها البتة الأولى من البايتة الأولى هي بتة البدء (1) (في البايتات المتبقية ، تكون بتات البدء هي 0) ، ثم في بتات البيانات بالترتيب تكون 32 بتة من الطابع الزمني ، ثم 10 بتات من قياس ADC. 1 ، ثم 10 بتات من ADC # 2 وهكذا ...
وبالمثل ، تتم الكتابة على بطاقة SD والقراءة منها وفقًا للبروتوكول. في المجموع ، نحصل على 115.4 ميغابايت من المعلومات (لمدة 14 بايت × 100 قياسات في الثانية × 3600 ثانية × 24 ساعة) ليوم واحد من التسجيل على بطاقة SD.
لا تزال بنية البيانات هذه ملائمة لأننا في المستقبل يمكننا تحديد كتل البيانات من أي مكان في الملف وعرضها في شكل رسوم بيانية ، وبالتالي لا يتم تحميل الملف بأكمله على ذاكرة الوصول العشوائي (والتي يمكن أن تصل إلى عشرات الجيجابايت). وكذلك يمكننا تنفيذ التمرير المريح لهذه الرسوم البيانية عن طريق تحميل الحزم اللازمة.

لقد حان الوقت لبدء تنفيذ برنامج متحكم دقيق
نكتب مكتبة متحكم في C ++.
للراحة ، قم بإنشاء فصل:
class PSP { public: void init(byte startBit, byte* arrayByte, byte sizeArrayByte); void pushData(byte sizeBit, uint32_t value); byte* popData(); protected: byte startBit;
مع طريقة التهيئة ، أعتقد أن كل شيء واضح:
void PSP::init(byte startBit, byte* arrayByte, byte sizeArrayByte) { this->startBit = startBit; this->arrayByte = arrayByte; this->sizeArrayByte = sizeArrayByte; }
طريقة إضافة البيانات أكثر تعقيدًا ، وهنا ، عن طريق معالجة التلاعب في اتجاه bitwise ، نضع البيانات في صفيف البايت الخاص بنا.
void PSP::pushData(byte sizeBit, uint32_t value) { byte free; byte y; int remBit = 0;
طريقة للحصول على صفيف بايت من حزمة:
byte* PSP::popData() { position = 0;
وأخيراً ، بضع وظائف مساعدة:
لتلخيص
كنتيجة للعمل المنجز ، وُلد البروتوكول المدمج لتدفق البيانات PSP1N والمكتبات الجاهزة التي يمكن تنزيلها من GitHub هنا . في هذا المستودع ، ستجد:
- مثال على استخدام مكتبة مثال ExampleColsolePSP1N / C #
- PSP1N_CPP / يحتوي على مكتبة PSP للعمل مع البروتوكول ومثال على استخدامه على Arduino
- PSP1N_CSHARP / بروتوكول مكتبة لـ .NET
للتدليل على تشغيل البروتوكول ، يمكنك وميض الرسم إلى Arduino وفي مثال ExampleSerialPortRead على الكمبيوتر ، قم باستقبال البيانات من متحكم دقيق عبر منفذ COM. هناك ، يتم فك تشفير هذه البيانات وعرضها في تطبيق وحدة التحكم. سأتحدث عن المكتبة المكتوبة بلغة C # للجانب المستقبل في وقت آخر.
TestingConsole:

تحديث (03/31/19): تم تغيير خوارزمية التشفير وفك التشفير