جهاز تعقب GPS محلي الصنع على اردوينو. أفضل أجهزة تتبع GPS للسيارات (المنارات)

جهاز تعقب GPS محلي الصنع على اردوينو.  أفضل أجهزة تتبع GPS للسيارات (المنارات)
جهاز تعقب GPS محلي الصنع على اردوينو. أفضل أجهزة تتبع GPS للسيارات (المنارات)

أجهزة إرسال GPS الشخصية

اليوم، يسير التقدم بوتيرة كبيرة لدرجة أن الأجهزة التي كانت في السابق ضخمة ومكلفة ومتخصصة للغاية تفقد حجمها ووزنها وسعرها بسرعة، ولكنها تكتسب العديد من الوظائف الجديدة.

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

في الأساس، هذه هي نفس أجهزة تعقب نظام تحديد المواقع العالمي (GPS)، المصممة فقط للاستخدام ليس على السيارة، ولكن من قبل الشخص في الحياة اليومية.

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

يوجد بداخله وحدة GPS التي تحدد الإحداثيات على الأرض، ووحدة GSM/GPRS التي تنقل المعلومات وتستقبل أوامر التحكم، بالإضافة إلى مصدر للطاقة يوفر عملية مستقلةخلال فترة طويلة.

وظائف أجهزة إرسال GPS

ومع زيادة الوظائف، تظهر الإمكانيات التالية للجهاز:


خيارات لأجهزة إرسال GPS

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

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

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

مقالات حول أجهزة تعقب GPS

سأوضح في هذه المقالة كيفية استخدام وحدة gsm مع الاردوينو باستخدام sim800L كمثال. نفس التعليمات مناسبة تمامًا لاستخدام أي وحدات GSM أخرى، على سبيل المثال، sim900، وما إلى ذلك، لأن جميع الوحدات تعمل بنفس الطريقة تقريبًا - وهذا هو تبادل أوامر AT عبر المنفذ.

سأعرض استخدام الوحدة مع اردوينو باستخدام مثال مرحل الرسائل القصيرة، والذي يمكن استخدامه للتحكم في الجهاز عن بعد عبر أوامر الرسائل القصيرة. ويمكن استخدامه مع أجهزة إنذار السيارة، وما إلى ذلك.

يتم توصيل الوحدة بـ Arduino عبر واجهة UART الخاصة بالمنفذ التسلسلي للبرنامج، والتي تعمل على 2 و3 المخرجات الرقميةاردوينو نانو.

العمل مع اردوينو مع وحدات GSM

لتشغيل الوحدة، يلزم وجود جهد كهربائي في النطاق من 3.6 فولت إلى 4.2 فولت، وهذا يعني أنه سيتعين عليك استخدام مثبت جهد إضافي، نظرًا لأن Arduino مثبت عليه مثبت 3.3 فولت، وهو غير مناسب لتشغيل الوحدة. ، السبب الثاني لتثبيت مثبت إضافي هو أن وحدة GSM تعاني من حمولة خطيرة، حيث أنها تحتوي على جهاز إرسال ضعيف يوفر اتصالاً مستقرًا مع المحطة الخلوية. يتم توفير الطاقة لـ Arduino nano إلى دبوس VIN - وهو مثبت مدمج في Arduino يضمن تشغيل الوحدة عبر نطاق جهد واسع (6-10 فولت). يتم توصيل وحدة الترحيل وفقًا لنص البرنامج المحدد بالدبوس 10 من Arduino nano ويمكن تغييرها بسهولة إلى أي وحدة أخرى تعمل كمخرج رقمي.

يعمل على النحو التالي: قم بتثبيت بطاقة SIM في وحدة GSM، وقم بتشغيل الطاقة وأرسل رسالة نصية قصيرة تحتوي على النص "1" إلى الرقم بطاقات SIMمن أجل تشغيل التتابع الخاص بنا، لإيقاف تشغيله، نرسل رسالة نصية قصيرة تحتوي على النص "0".

#يشمل
SoftwareSerial gprsSerial(2, 3); // قم بتعيين المسامير 2 و 3 لمنفذ البرنامج
إنت ليدبين = 10؛ // للتتابع

الإعداد باطل()
{
gprsSerial.begin(4800);
pinMode(LedPin, OUTPUT);

// إعداد استقبال الرسائل

gprsSerial.print("AT+CMGF=1\r");
gprsSerial.print("AT+IFC=1, 1\r");
تأخير (500)؛
gprsSerial.print("AT+CPBS=\"SM\"\r");
تأخير (500)؛ // تأخير معالجة الأمر
gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
تأخير (700)؛
}

String currStr = "";
// إذا كان هذا السطر عبارة عن رسالة، فسيأخذ المتغير القيمة True
boolean isStringMessage = false;

حلقة فارغة()
{
إذا (!gprsSerial.available())
يعود؛

char currSymb = gprsSerial.read();
إذا ('\r' == currSymb) (
إذا (isStringMessage) (
// إذا كان السطر الحالي عبارة عن رسالة، إذن...
إذا (!currStr.compareTo("1")) (
الكتابة الرقمية (LedPin، HIGH)؛
) وإلا إذا (!currStr.compareTo("0")) (
الكتابة الرقمية (LedPin، LOW)؛
}
isStringMessage = false;
) آخر (
إذا (currStr.startsWith("+CMT")) (
// إذا كان السطر الحالي يبدأ بـ "+CMT"، فالرسالة التالية
isStringMessage = true;
}
}
currStr = "";
) وإلا إذا ('\n' != currSymb) (
currStr += String(currSymb);
}
}

نسخة الفيديو من المقال:

العلامات: #اردوينو، #SIM800L

بصمتك:

المنتجات المستخدمة في هذا المقال:

← مسجل GPS على الاردوينو | التحكم في التتابع عبر منفذ COM →

الماسح الضوئي GSM على RTL-SDR

| بيت| الإنجليزية | التنمية | الأسئلة الشائعة |

الخصائص الرئيسية للماسح الضوئي

يقوم الماسح الضوئي GSM بمسح قنوات GSM النهائية ويعرض معلومات حول مستوى الإشارة وما إذا كانت القناة تنتمي إلى أحد مشغلي الهواتف الخلوية الثلاثة الرئيسيين MTS وBeeline وMegafon. بناء على نتائج عمله، يسمح لك الماسح الضوئي بحفظ قائمة المعرفات محطات القاعدة MCC وMNC وLAC وCI لجميع القنوات الممسوحة ضوئيًا.
يمكن استخدام الماسح الضوئي GSM لتقييم مستوى إشارة GSM ومقارنة جودة الإشارة مشغلين مختلفين، تقييمات التغطية الراديوية، عند اتخاذ قرار بشأن تركيب مضخمات الإشارة الخلوية وضبط معلماتها، للأغراض التعليمية، وما إلى ذلك.
يعمل الماسح الضوئي بنظام Windows ويستخدم جهاز استقبال بسيط ورخيص - RTL-SDR. يمكنك أن تقرأ عن RTL-SDR على:
RTL-SDR (RTL2832U) والأخبار والمشاريع الإذاعية المحددة بالبرمجيات،
RTL-SDR – أوسموسدر،
RTL-SDR باللغة الروسية.
تحدد معلمات RTL-SDR الخصائص الرئيسية للماسح الضوئي. بالطبع، الماسح الضوئي GSM ليس بديلاً لمعدات القياس العادية.
يتم توزيع الماسح الضوئي مجانًا، دون أي قيود على الاستخدام.
النسخة الحاليةيدعم نطاق GSM 900 ولا يدعم GSM 1800. ويتحدد ذلك من خلال حقيقة أن تردد تشغيل RTL-SDR مع موالف R820T يقتصر على 1760 ميجاهرتز. هناك أمل في أن يسمح استخدام برنامج تشغيل RTL-SDR التجريبي بالتشغيل في جزء على الأقل من نطاق 1800 ميجاهرتز.

إطلاق الماسح الضوئي

يمكن تنزيل أحدث إصدار من الماسح الضوئي من هذا الرابط. ما عليك سوى فك ضغط الملف إلى موقع مناسب وتشغيل gsmscan.exe.
الإصدارات السابقة من الماسح الضوئي، رابط للمستودع مع المصادر والمعلومات الأخرى المتعلقة بالتطوير موجودة في صفحة التطوير.
يتطلب الماسح الضوئي تثبيت برامج تشغيل RTL-SDR، إذا لم يتم تثبيتها بالفعل، فيمكن القيام بذلك بسهولة باستخدام برنامج Zadig، الذي يصف إجراء التثبيت.

استخدام الماسح الضوئي

فيما يلي عرض لنافذة برنامج الماسح الضوئي:

يعرض المحور الأفقي رقم قناة GSM على شكل ARFCN أو بالميغاهرتز، وفقًا لـ محور رأسيمستوى الإشارة في ديسيبل. ارتفاع الخط يدل على قوة الإشارة.

وحدة GSM NEOWAY M590 التواصل مع اردوينو

إذا تم فك تشفير معرفات BS بنجاح وكانت تتوافق مع معرفات مشغلي الاتصالات الرئيسيين الثلاثة، يتم رسم الخطوط بالألوان المقابلة.
تسمح لك القوائم المنسدلة الموجودة أعلى الشاشة باختيار جهاز استقبال SDR، إذا كان هناك عدة أجهزة متصلة، ونطاق التشغيل GSM 900 أو GSM 1800 ووحدات القياس على طول المحور الأفقي ARFCN أو MHz.
تتيح لك الأزرار حفظ تقرير عن تشغيل الماسح الضوئي في شكل قائمة بالمحطات الأساسية التي تم فك تشفيرها، ومسح نتائج فك تشفير BS والحصول على معلومات حول البرنامج.

مبادئ وخصائص العمل.

أثناء التشغيل، يقوم البرنامج بمسح نطاق تردد التشغيل بخطوة 2.0 ميجاهرتز (10 قنوات GSM) ويقوم برقمنة الإشارة بتردد أخذ عينات يبلغ 2.4 ميجاهرتز. تتكون عملية المسح من تمرير سريع عبر النطاق بأكمله لقياس قوة الإشارة وتمرير بطيء لفك تشفير معرفات BS.

يتم تنفيذ خطوة واحدة لفك التشفير بعد اجتياز النطاق بأكمله لقياس الطاقة. وبالتالي، في نطاق GSM 900، يتم تحديث مستوى الإشارة مرة واحدة تقريبًا كل ثانيتين، ويستغرق تمرير فك التشفير الكامل حوالي دقيقة واحدة.
ونظراً للجودة الرديئة للإشارة المستقبلة من RTL-SDR، فإن احتمال فك تشفير معلومات النظام (SI) لقناة التحكم في البث (BCCH) بشكل صحيح ليس مرتفعاً. كما أن تقلبات مستوى الإشارة نتيجة للانتشار متعدد المسارات تقلل أيضًا من احتمال فك تشفير معلومات النظام. لهذه الأسباب، للحصول على معرفات BS، من الضروري أن يقوم الماسح الضوئي بتجميع المعلومات خلال فترة تبلغ حوالي 10 دقائق. ولكن حتى في هذه الحالة، لا توفر جميع القنوات هذا المكانمستوى إشارة وجودة كافية لفك التشفير حتى بواسطة جهاز الاستقبال الأكثر مثالية. بالإضافة إلى ذلك، لا يتم استخدام جميع قنوات GSM للعمل وفقًا لمعيار GSM، كما هو موضح في الشكل أعلاه، فإن القنوات 975 - 1000 مشغولة بواسطة Megafon للعمل وفقًا لمعيار UMTS.
أثناء التشغيل، يضيف الماسح الضوئي معلومات النظام حول القنوات الجديدة التي تم فك تشفيرها إلى المجموعة العامة من المعلومات الموجودة على القنوات. لكن المعلومات المتعلقة بالقنوات التي تم فك تشفيرها مسبقًا لا يتم مسحها عندما لا يتم فك تشفير معلومات النظام في هذه الخطوة، وتبقى في المصفوفة. لمسح هذه المعلومات، استخدم الزر لمسح نتائج فك تشفير BS.
عند النقر على زر حفظ التقرير، يتم حفظ النتائج المتراكمة ملف نصيباسم مكون من اسم البرنامج وتاريخ ووقت حفظ البيانات. فيما يلي مثال لجزء من ملف التقرير:
تم تصميم الماسح الضوئي للعمل ضمن أنظمة التشغيل Windows 7 و8.1 و10. وتم اختبار العمل بثلاث نسخ من RTL-SDR مع موالف R820T، ولم يتم اختبار الأنواع الأخرى من الموالفات.
تم تجميع إصدار خاص من البرنامج للعمل ضمن نظام التشغيل Windows XP؛ وهو يعمل بشكل أبطأ عدة مرات من الإصدار القياسي.

تطوير.

يتم توفير برنامج الماسح الضوئي كما هو، دون أي ضمانات أو مسؤولية. إذا كانت لديك أفكار معقولة حول كيفية توسيع الوظيفة أو تحسين أداء الماسح الضوئي، فنحن على استعداد لمناقشة إمكانية تنفيذها.
يمكنك المشاركة في تطوير الماسح الضوئي؛ للقيام بذلك، قم بزيارة صفحة التطوير.
يتم التخطيط لمزيد من التطوير للماسح الضوئي GSM، ربما بمشاركتك.

هل تحتاج إلى مصدر زمني دقيق من GPS؟ ستوضح لك هذه المقالة كيفية استخدام وحدة GPS للحصول على الوقت والتاريخ والإحداثيات وكيفية عرضها على شاشة LCD باستخدام Arduino.

ما هو ضروري؟

  • جهاز كمبيوتر مثبت عليه Arduino IDE ؛
  • اردوينو (نستخدم اردوينو ميجا)؛
  • وحدة GPS (نستخدم EM-411، والبعض الآخر من الممكن أن يدعم ذلك بروتوكول نميا، على سبيل المثال، VK2828U7G5LF أو GY-NEO6MV2)؛
  • اللوح والوصلات ومقياس الجهد 5 كيلو أوم ؛
  • مكتبة TinyGPS (الرابط أدناه).

مقدمة

بدأ تطوير نظام تحديد المواقع العالمي (GPS) في أوائل السبعينيات. كل دولة (روسيا والولايات المتحدة الأمريكية والصين وغيرها) لديها نظامها الخاص، ولكن معظم مرافق الملاحة عبر الأقمار الصناعية في العالم تستخدم النظام الأمريكي.

يحتوي كل قمر صناعي في النظام على ساعة ذرية يتم مراقبتها وتعديلها بشكل مستمر بواسطة NORAD (قيادة الدفاع الجوي لأمريكا الشمالية) كل يوم.

بشكل أساسي، يستخدم المستقبل ساعته لقياس TOA (وقت الوصول) البالغ أربعة إشارات الأقمار الصناعية. بناءً على TOA وTOT (وقت الإرسال)، يقوم جهاز الاستقبال بحساب أربع قيم لوقت الرحلة (TOF)، تختلف عن بعضها البعض اعتمادًا على المسافة من القمر الصناعي إلى جهاز الاستقبال. ثم، من قيم TOF الأربع، يحسب جهاز الاستقبال موقعه في الفضاء ثلاثي الأبعاد وانحراف ساعته.

تبلغ دقة أجهزة استقبال GPS الأقل تكلفة حوالي 20 مترًا لمعظم الأماكن على وجه الأرض. الآن دعونا نرى كيفية إنشاء ساعة GPS الخاصة بك باستخدام Arduino.

المعدات

تحتوي وحدة GPS الخاصة بي على 6 منافذ: GND وVin وTx وRx وGND مرة أخرى. الدبوس السادس غير متصل في أي مكان. يتم توصيل طرف GND بالعلبة الموجودة على Arduino، ويتم توصيل Vin بالحافلة +5V على Arduino، ويتم توصيل Tx بالدبوس 10 على Arduino، كما أن منفذ Rx غير متصل في أي مكان، لأننا لن نرسل أي رسائل إلى وحدة GPS. تقوم وحدتي بنقل بيانات القمر الصناعي باستخدام واجهة RS-232 بسرعة 4800 بت في الثانية، والتي يستقبلها Arduino على المنفذ 10.

فيما يلي صورة لوحدة GPS:

وحدة GPS EM-411

ترسل الوحدة ما يعرف برسائل NMEA. هنا يمكنك رؤية مثال لرسالة NMEA وشرحها (مقتطف من الوصف الفني):

$GPGGA,161229.487,3723.2475,شمال,12158.3416,عرض,1.07,1.0,9.0,م,0000*18

تنسيق بيانات GGA
اسممثالالوحداتوصف
معرف الرسالة$GPGGA رأس بروتوكول GGA
التوقيت العالمي المنسق161229.487 hhmmss.sss (الساعات المكونة من رقمين، والدقائق المكونة من رقمين، ثم الثواني إلى أجزاء من الألف)
خط العرض3723.2475
علم N/Sن شمال - شمال، جنوب - جنوب
خط الطول12158.3416 ddmm.mmmm (أول رقمين هما الدرجات، ثم الدقائق إلى أقرب عشرة آلاف)
علم E/Wدبليو ه - الشرق، غرب - الغرب
مؤشر الموقع1
  • 0 - الموقع غير متاح أو غير صحيح؛
  • 1 - وضع GPS SPS، الموقع صحيح؛
  • 2 - GPS التفاضلي، وضع SPS، الموقع الصحيح؛
  • 3 - وضع GPS PPS، الموقع صحيح.
عدد الأقمار الصناعية المستخدمة07 تتراوح من 0 إلى 12
HDOP1.0 تدهور الدقة الأفقية
الارتفاع بالنسبة لمستوى سطح البحر9.0 متر
الوحداتممتر
الفرق الجيودي الفرق بين المجسم الإهليلجي الأرضي WGS-84 ومستوى سطح البحر (الجينويد)
الوحداتممتر
عمر بيانات GPS التفاضلية ثوانيالحقول الفارغة عند عدم استخدام DGPS
معرف المحطة التي ترسل التصحيحات التفاضلية0000
تحقق من المبلغ*18
نهاية الرسالة

يتم استقبال كل هذه البيانات بواسطة Arduino عبر الدبوس 10. تقرأ مكتبة TinyGPS رسائل GPGGA وGPRMC (لـ معلومات مفصلةحول GPRMC انظر الوصف الفني).

لا يظهر اردوينو في الرسم التخطيطي. يتصل الأجهزة الطرفيةوفقا للاتصالات الموقعة.


مخطط ساعة جي بي اسعلى اردوينو

برمجة

عند توصيل الطاقة، تستغرق وحدة GPS بعض الوقت للحصول على الموقع الصحيح من الأقمار الصناعية. عند استلام موقع ما، ترسل الوحدة رسائل NMEA إلى Arduino. تحتوي مكتبة TinyGPS على وظيفة للحصول على الوقت والتاريخ من رسالة GPRMC. يُطلق عليه اسم crack_datetime() ويأخذ سبعة مؤشرات للمتغيرات كمعلمات: year year، وmonthmonth، وday ofmonth day، وhourhour، وminute Min، وsecrets Second، ومئات من أجزاء الثانية من المائة. يبدو استدعاء الوظيفة كما يلي:

GPS.crack_datetime(&السنة، &الشهر، &اليوم، &الساعة، &الدقيقة، &الثانية، &المئات)؛

يؤدي استدعاء هذه الوظيفة إلى إرجاع القيم الصحيحة في المتغيرات طالما أن كل شيء على ما يرام مع الأجهزة.

للحصول على موقعك، يمكنك استدعاء الدالة f_get_position(). هذه الوظيفةيأخذ كمعلمات مؤشرين للمتغيرات: خط العرض وخط الطول وخط الطول. يبدو استدعاء هذه الوظيفة كما يلي:

Gps.f_get_position(&latitude, &longitude);

النص المصدر للبرنامج:

#يشمل #يشمل #يشمل # تحديد RXPIN 10 # تحديد TXPIN 9 # تعريف GPSBAUD 4800 # تحديد RS 2 # تحديد EN 3 # تحديد D4 4 # تحديد D5 5 # تحديد D6 6 # تعريف D7 7 TinyGPS gps; SoftwareSerial uart_gps(RXPIN, TXPIN); شاشات الكريستال السائل السائل (RS، EN، D4، D5، D6، D7)؛ // المتغيرات int ثواني؛ إزاحة الوقت int = 1؛ // يجب على المستخدم تغيير الوحدة إلى المنطقة الزمنية المناسبة. في المثال نستخدم التحول من +1 ساعة. // إعلان الوظائف. void getgps(TinyGPS &gps); // وظيفة الإعداد - تعمل فقط عند تشغيل void setup() ( Serial.begin(115200); // بدء تشغيل الواجهة التسلسلية لتصحيح الأخطاء uart_gps.begin(GPSBAUD); // بدء تشغيل جهاز استقبال UART لنظام تحديد المواقع العالمي LCD.begin(16) ,2) ؛ // إعلان LCD LCD.print("ساعة GPS"); // تأخير رسالة الترحيب (1000); // انتظر ثانية واحدة LCD.clear(); البرنامج الرئيسي- حلقة الفراغ () قيد التشغيل دائمًا ( while(uart_gps.available()) ( int c = uart_gps.read(); if(gps.encode(c)) ( getgps(gps); ) ) ) /* * هذه الوظيفة يستقبل البيانات من وحدة GPS * ويعرضها على شاشة LCD */ void getgps(TinyGPS &gps) ( int year; float latitude, longitude; بايت شهر، يوم، ساعة، دقيقة، ثانية، أجزاء من المئات؛ gps.f_get_position(&latitude, &longitude ); : ") ؛ إذا (ساعة<= 9) { lcd.print("0"); lcd.print(hour, DEC); } else { lcd.print(hour, DEC); } lcd.print(":"); if (minute <=9) { lcd.print("0"); lcd.print(minute, DEC); } else { lcd.print(minute, DEC); } lcd.print(":"); if (second <= 9) { lcd.print("0"); lcd.print(second, DEC); } else { lcd.print(second, DEC); } lcd.setCursor(0,1); lcd.print("Date: "); if (day <= 9) { lcd.print("0"); lcd.print(day, DEC); } else { lcd.print(day, DEC); } lcd.print("-"); if (month <= 9) { lcd.print(month, DEC); } else { lcd.print(month, DEC); } lcd.print("-"); lcd.print(year, DEC); delay(2000); lcd.clear(); lcd.print("Lat: "); lcd.print(latitude, DEC); lcd.setCursor(0,1); lcd.print("Lon: "); lcd.print(longitude, DEC); delay(2000); // Debugging purpose only. Serial.print(latitude, DEC); Serial.print(" - "); Serial.println(longitude, DEC); }

سنقوم اليوم بصنع جهاز GPS Tracker يعتمد على Arduino MKR FOX 1200 الذي يرسل بيانات GPS دقيقة عبر شبكة Sigfox.

وقد أصبح هذا الأمر أكثر أهمية بالنسبة للعديد من البلدان بسبب زيادة السيطرة على أي أجهزة تقنية مستوردة، وخاصة تلك المتعلقة بنظام تحديد المواقع العالمي (GPS).

الخطوة 1. ما سنحتاجه

مجموعة أجزاء هذا الدرس ليست كبيرة:

  • اردوينو MKR فوكس 1200×1
  • وحدة GPS (اختيارية، لكننا استخدمنا نسخة طبق الأصل من ublox NEO6m (ATGM332D) × 1
  • ترانزستور NPN للأغراض العامة (استخدمنا BC548) × 1
  • المقاوم 1 كيلو أوم × 1

الخطوة 2. معلومات المشروع

يستخدم جهاز التعقب وحدة GPS ATGM332 للحصول على موقع GPS بدقة أكبر من خدمات الموقع التي تقدمها Sigfox. يتم بعد ذلك إرسال بيانات العنصر على شكل "سلسلة" عبر شبكة Sigfox ويتم تسليمها أخيرًا عبر البريد الإلكتروني.

اردوينو MKR فوكس 1200

تشبه اللوحة Arduino Zero، والتي تعتمد على SAM D21 وتتضمن وحدة ATA8520 Sigfox. هذه لوحة منخفضة الطاقة تأتي مع اللوحة مع اشتراك مجاني لمدة عام في شبكة Sigfox (حتى 140 رسالة يوميًا)، بالإضافة إلى الوصول المجاني إلى خدمة تحديد الموقع ينقطها.

وحدة نظام تحديد المواقع ATGM332

تناسب وحدة GPS منخفضة التكلفة ومنخفضة الطاقة Arduino MKR FOX 1200 جيدًا لأنها تعمل فقط مع 2.7 فولت (3.3 فولت اسمي).

في البداية كان من المفترض أن أشتري وحدة NEO6m2، التي تحتوي على وضع الاستعداد، لكن كان علي استخدام NEO6. في الواقع كانت وحدة ATGM332. ونتيجة لذلك، لم يكن لديه وضع الاستعداد، لذلك كان من الضروري استخدام الترانزستور لتشغيل وحدة GPS عند الحاجة وإيقاف تشغيلها لتوفير البطارية. هدفنا هو الحصول على معلومات الموقع بشكل غير متكرر، أي 4 رسائل في الساعة، حيث أن Sigfox يسمح فقط بـ 140 رسالة في اليوم.

نستخدم مكتبة TinyGPS (https://github.com/mikalhart/TinyGPS) لفك تشفير إطارات GPS.

تبديل الترانزستور

كان من الضروري تشغيل نظام تحديد المواقع العالمي (GPS) وإيقافه عند الضرورة. تعد وحدات الترحيل ضخمة جدًا وقوية إذا كنت تحتاج فقط إلى تبديل حمل 3 فولت وبضعة مللي أمبير. أيضًا، تتطلب معظم وحدات الترحيل 5 فولت، لذا سيكون الترانزستور هو الحل الأفضل. بالإضافة إلى ذلك، يوفر MKR FOX 1200 7 مللي أمبير فقط على طرف الإدخال/الإخراج.

سيفي الترانزستور BC548 NPN بالغرض. عندما يتم تطبيق إشارة الصفر على قاعدة الترانزستور، فإنه ينطفئ، ويعمل كمفتاح مفتوح، ولا يتدفق تيار المجمع. عندما يتم تطبيق إشارة إيجابية على قاعدة الترانزستور، فإنه يصبح في وضع التشغيل، ويعمل كمفتاح مغلق، ويتدفق الحد الأقصى لتيار الدائرة عبر الجهاز.

الخطوة 3. مخطط الاتصال

مصدر الطاقة الوحيد هو بطاريتين AA بقدرة 1.5 فولت تعملان على تشغيل Arduino MKR FOX 1200. تستقبل وحدة GPS الطاقة من لوحة Arduino.

يتصل Arduino MKR FOX 1200 بوحدة GPS باستخدام المنفذ التسلسلي الثاني عبر المنفذين 13 و14، المسمى Serial1 في الكود. يتم توصيل إخراج بيانات TX لوحدة GPS بإدخال البيانات التسلسلية (دبوس 13) للوحة Arduino.

بالإضافة إلى ذلك، تستخدم لوحة Arduino PIN2 لتشغيل وإيقاف وحدة GPS، كما هو موضح أعلاه.

الخطوة 4. رمز المشروع

يمكنك تنزيل أو نسخ كود مشروعنا أدناه:

#يشمل #يشمل #يشمل // بما في ذلك TinyGPS #define WAITING_TIME 15 #define GPS_PIN 2 #define GPS_INFO_BUFFER_SIZE 128 bool debug = false; TinyGPS gps;// كائن GPS // متغيرات بيانات GPS int year; بايت الشهر، اليوم، الساعة، الدقيقة، الثانية، المئات؛ أحرف طويلة غير موقعة؛ الجمل القصيرة غير الموقعة، Fail_checksum؛ شار GPS_info_char; شار GPS_info_buffer; int غير الموقعة تلقى_شار؛ رسالة منطقية_بدء = خطأ؛ كثافة العمليات ط = 0؛ // بنية إحداثيات نظام تحديد المواقع العالمي (GPS)، حجم 12 بايت على منصات 32 بت struct gpscoord ( float a_latitude; // 4 بايت float a_longitude; // 4 بايت float a_altitude; // 4 بايت ); خط العرض العائم = 0.0f؛ تعويم خط الطول = 0.0f؛ ارتفاع تعويم = 0؛ //////////////// وظيفة الانتظار ////////////////// void Wait(int m, bool s) ( //m دقيقة لانتظار // نبضات LED البطيئة if (debug) ( Serial.print("Waiting: "); Serial.print(m); Serial.println(" min."); ) digitalWrite(LED_BUILTIN, LOW s)); (int seg = m * 30؛ for (int i = 0; i< seg; i++) { digitalWrite(LED_BUILTIN, HIGH); //LED on delay(1000); digitalWrite(LED_BUILTIN, LOW); //LED off delay(1000); } } else { int seg = m * 15; for (int i = 0; i < seg; i++) { digitalWrite(LED_BUILTIN, HIGH); //LED on delay(1000); digitalWrite(LED_BUILTIN, LOW); //LED off delay(3000); } } } /////////////////// Sigfox Send Data function //////////////// void SendSigfox(String data) { if (debug) { Serial.print("Sending: "); Serial.println(data); if (data.length() >12) ( Serial.println("الرسالة طويلة جدًا، سيتم إرسال أول 12 بايت فقط"); ) ) // إزالة EOL //data.trim(); // ابدأ الوحدة SigFox.begin(); // انتظر 30 مللي ثانية على الأقل بعد التكوين الأول (100 مللي ثانية قبل) تأخير(100); // مسح كافة المقاطعات المعلقة SigFox.status(); تأخير (1)؛ إذا (تصحيح) SigFox.debug(); تأخير (100)؛ SigFox.beginPacket(); SigFox.print(data); إذا (تصحيح) (int ret = SigFox.endPacket(true)؛ // إرسال المخزن المؤقت إلى شبكة SIGFOX وانتظر الاستجابة إذا (ret> 0) (Serial.println("لا يوجد إرسال"); ) آخر (Serial.println ("الإرسال موافق")؛ ) Serial.println(SigFox.status(SIGFOX)); if (SigFox.parsePacket()) (Serial.println("الاستجابة من الخادم:"); while (SigFox.available()) ( Serial.print("0x"); Serial.println(SigFox.read(), HEX ) ) else ( Serial.println("تعذر الحصول على أي استجابة من الخادم"); Serial.println("تحقق من SigFox" التغطية في منطقتك"); Serial.println("إذا كنت في الداخل، فتحقق من تغطية 20 ديسيبل أو تحرك بالقرب من النافذة"); ) Serial.println(); ) else ( SigFox.endPacket(); ) SigFox.end( ); ) ////////////////// تحويل وظيفة GPS ////////////////// /* تحويل بيانات GPS العائمة إلى بيانات Char * / String ConvertGPSdata(const void* data, uint8_t len) ( uint8_t* bytes = (uint8_t*)data; String cadena ; if (debug) ( Serial.print("Length: "); Serial.println(len); ) لـ (uint8_t i = len - 1؛ i< len; --i) { if (bytes[i] < 12) { cadena.concat(byte(0)); // Not tested } cadena.concat(char(bytes[i])); if (debug) Serial.print(bytes[i], HEX); } if (debug) { Serial.println(""); Serial.print("String to send: "); Serial.println(cadena); } return cadena; } ////////////////////////// Get GPS position function///////////////////// String GetGPSpositon() { int messages_count = 0; String pos; if (debug) Serial.println("GPS ON"); digitalWrite(GPS_PIN, HIGH); //Turn GPS on Wait(1, false); while (messages_count < 5000) { while (Serial1.available()) { int GPS_info_char = Serial1.read(); if (GPS_info_char == "$") messages_count ++; // start of message. Counting messages. if (debug) { if (GPS_info_char == "$") { // start of message message_started = true; received_char = 0; } else if (GPS_info_char == "*") { // end of message for (i = 0; i < received_char; i++) { Serial.write(GPS_info_buffer[i]); // writes the message to the PC once it has been completely received } Serial.println(); message_started = false; // ready for the new message } else if (message_started == true) { // the message is already started and I got a new character if (received_char <= GPS_INFO_BUFFER_SIZE) { // to avoid buffer overflow GPS_info_buffer = GPS_info_char; received_char++; } else { // resets everything (overflow happened) message_started = false; received_char = 0; } } } if (gps.encode(GPS_info_char)) { gps.f_get_position(&latitude, &longitude); altitud = gps.altitude() / 100; // Store coordinates into dedicated structure gpscoord coords = {altitud, longitude, latitude}; gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths); if (debug) { Serial.println(); Serial.println(); Serial.print("Latitud/Longitud: "); Serial.print(latitude, 5); Serial.print(", "); Serial.println(longitude, 5); Serial.println(); Serial.print("Fecha: "); Serial.print(day, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/"); Serial.print(year); Serial.print(" Hora: "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); Serial.print("."); Serial.println(hundredths, DEC); Serial.print("Altitud (metros): "); Serial.println(gps.f_altitude()); Serial.print("Rumbo (grados): "); Serial.println(gps.f_course()); Serial.print("Velocidad(kmph): "); Serial.println(gps.f_speed_kmph()); Serial.print("Satelites: "); Serial.println(gps.satellites()); Serial.println(); } gps.stats(&chars, &sentences, &failed_checksum); if (debug) Serial.println("GPS turned off"); digitalWrite(GPS_PIN, LOW); //GPS turned off pos = ConvertGPSdata(&coords, sizeof(gpscoord)); //Send data return pos; } } } pos = "No Signal"; } //////////////////SETUP/////////////////// void setup() { if (debug) { Serial.begin(9600); while (!Serial) {}// wait for serial port to connect. Needed for native USB port only Serial.println("Serial Connected"); } //Serial1 pins 13-14 for 3.3V connection to GPS. Serial1.begin(9600); while (!Serial1) {} if (debug) { Serial.println("GPS Connected"); } pinMode(GPS_PIN, OUTPUT); //pin de interruptor del GPS if (!SigFox.begin()) { Serial.println("Shield error or not present!"); return; } // Enable debug led and disable automatic deep sleep if (debug) { SigFox.debug(); } else { SigFox.end(); // Send the module to the deepest sleep } } //////////////////////LOOP//////////////////////// void loop() { String position_data; position_data = GetGPSpositon(); SendSigfox(position_data); Wait(WAITING_TIME, false); }

الخطوة 5: إرسال معلومات GPS عبر Sigfox

أردنا إرسال معلومات نظام تحديد المواقع العالمي (GPS) باستخدام البيانات العائمة، ولكن عندما حاولنا ذلك، حصلنا دائمًا على قيم فارغة.

أدى البحث على الإنترنت إلى هذا المشروع على GitHub - https://github.com/nicolsc/SmartEverything_SigFox_GPS بقلم نيكولاس ليسكوني. يستخدم أوامر AT لإرسال أي نوع من البيانات ويحول "تعويم" إلى "ست عشري". ومع ذلك، فإن Arduino MKR FOX 1200 لا يحتوي على وضع AT ولم نتمكن من تشغيله.

تم إجراء عشرات الاختبارات، ومن خلال تعديل كود نيكول، تم العثور على طريقة لإرسال "سلسلة" تم تحليلها بواسطة منصة Sigfox "float: 32" ويمكن استخدامها مباشرة دون أي تحويل.

تقتصر بيانات Sigfox على 12 بايت. البيانات التي يتم إرسالها إلى شبكة SigFox:

  • خط العرض، تعويم: 32 نوعًا (تعويم: 32 نوع)، 4 بايت.
  • خط الطول، تعويم: 32 نوع (تعويم: 32 نوع)، 4 بايت.
  • الارتفاع، التعويم: 32 نوعًا (تعويم: 32 نوع)، 4 بايت.

الخطوة 6: تكوين رد اتصال Sigfox

تكوين رد الاتصال المخصص لـ Sigfox:

اللات::float:32lng::float:32 البديل::float:32

سوف تتلقى رسالة بالبريد الإلكتروني:

لرؤية الموقع بسهولة، قمنا بتضمين عنوان URL في خرائط Google باستخدام المعلومات التي حصلنا عليها:

وأخيرًا، نتيجة جهاز التتبع Arduino GPS الخاص بنا:

هذا كل شيء، أتمنى لك مشاريع عظيمة!

يتم حفظ البيانات في جدول بيانات dataGPS.csv، والذي يتوافق تنسيقه مع متطلبات الخدمة جوجل خرائطي.

    لغة البرمجة: اردوينو (C++)

تعليمات الفيديو

ماذا تحتاج

كيفية التجميع

gps-tracker.ino // مكتبة للعمل مع الأجهزة عبر SPI#يشمل // مكتبة للعمل مع بطاقة SD#يشمل // مكتبة للعمل مع جهاز GPS#يشمل // قم بإنشاء كائن من فئة GPS وتمرير كائن Serial1 إليهنظام تحديد المواقع العالمي (المسلسل 1) ؛ // دبوس LED#define LED_PIN A0 // دبوس الزر #define BUTTON_PIN 13 // دبوس CS بطاقة مايكرو SD#تعريف CHIP_SELECT_PIN 9 // الفاصل الزمني لكتابة البيانات على البطاقة#تعريف الفاصل الزمني 5000 // قم بتعيين حجم المصفوفة للوقت والتاريخ وخط العرض وخط الطول#حدد MAX_SIZE_MASS 16 // مصفوفة لتخزين الوقت الحاليوقت الحرف[MAX_SIZE_MASS]؛ // حالة التسجيلحالة منطقيةRec = خطأ؛ // يتذكر الوقت الحاليبداية طويلةMillis = millis() ; الإعداد باطل() ( // افتح المنفذ التسلسلي لمراقبة الإجراءات في البرنامج Serial.begin(115200); // انتظر حتى يتم فتح شاشة المنفذ التسلسلي // لتتبع كافة الأحداث في البرنامج// while (!Serial) ( // ) Serial.print ("Serial init OK \r\n") ; // فتح اتصال تسلسلي مع وحدة GPS Serial1.begin(115200); // اضبط مؤشر LED على وضع الإخراج pinMode(LED_PIN, OUTPUT) ؛ // اضبط الزر على وضع تسجيل الدخول pinMode(BUTTON_PIN, INPUT_PULLUP) ; // إخراج معلومات حول التهيئة إلى المنفذ التسلسلي Serial.println("تهيئة بطاقة SD...") ; // تهيئة بطاقة SDبينما (! SD.begin (CHIP_SELECT_PIN) ) ( Serial.println ("فشلت البطاقة، أو غير موجودة" ) ; تأخير(1000 ) ; ) // إخراج المعلومات إلى المنفذ التسلسلي Serial.println("تمت تهيئة البطاقة"); // قم بإنشاء كائن dataFile من فئة File للعمل مع الملفاتملف dataFile = SD.open("dataGPS.csv" , FILE_WRITE) ; // إذا كان الملف موجوداإذا (ملف البيانات) ( // اكتب اسم البيانات المستقبلية على بطاقة الذاكرة dataFile.println("الوقت، الإحداثيات، السرعة")؛ // أغلق الملف dataFile. Close(); Serial.println("حفظ موافق"); ) آخر ( Serial.println ("حدث خطأ أثناء فتح test.csv" ) ; ) ) حلقة باطلة() ( // سجل الضغط على الزرإذا (! القراءة الرقمية (BUTTON_PIN) ) ( // تغيير حالة "التسجيل" / "عدم الكتابة" على بطاقة الذاكرةستيتريك =! StateRec; // تغيير حالة مؤشر LEDالكتابة الرقمية (LED_PIN، StateRec)؛ ) // إذا جاءت البيانات من وحدة GPSإذا (gps.available()) ( // قراءة البيانات وتحليلها gps.readParsing(); // تحقق من حالة وحدة GPSالتبديل (gps.getState () ) ( // كل شيء على ما يرام case GPS_OK: Serial.println ("GPS is OK"))؛ // إذا انقضى الفاصل الزمني المحددإذا (ملي () - startMillis > INTERVAL &&stateRec) ( // حفظ البيانات على بطاقة الذاكرة saveSD () ؛ // تذكر الوقت الحالي startMillis = millis() ; ) استراحة ؛ // حالة خطأ البيانات GPS_ERROR_DATA: Serial.println ("بيانات خطأ GPS")؛ استراحة ؛// لا يوجد اتصال بالأقمار الصناعية الحالة GPS_ERROR_SAT: Serial.println ("GPS لا يتصل بالأقمار الصناعية" ) ; استراحة ؛) ) ) // وظيفة حفظ البيانات على بطاقة الذاكرةإذا (ملف البيانات) ( باطلة saveSD () (ملف dataFile = SD.open("dataGPS.csv" , FILE_WRITE) ؛// إذا كان الملف موجودًا وتم فتحه // يقرأ الوقت الحالي gps.getTime(time, MAX_SIZE_MASS); \" " // اكتب الوقت على بطاقة الذاكرة \" " ملف البيانات.طباعة(" \" " ) ; ) ; dataFile.print(time); ملف البيانات.طباعة(") ; dataFile.print ("،")؛ ملف البيانات.طباعة(" \" " // قراءة وكتابة إحداثيات خطوط الطول والعرض على بطاقة الذاكرة

dataFile.print(gps.getLatitudeBase10(), 6); dataFile.print ("،")؛ dataFile.print(gps.getLongitudeBase10(), 6); ملف البيانات.طباعة("

) ; dataFile.print ("،")؛ dataFile.print(gps.getSpeedKm()); dataFile.println("كم/ساعة"); dataFile. Close(); Serial.println("حفظ موافق"); ) آخر ( Serial.println ("حدث خطأ أثناء فتح test.csv" ) ; ) )


مساء الخير (مساء/ليلة اختياري).

سيكون هناك اليوم مراجعة لجهاز استقبال GPS وتطبيقه عمليًا.

مقدمة

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

لم يكن هناك سوى عدد قليل من المراجعات الأكثر شمولاً لجهاز استقبال GPS هذا - حوالي 4، كان أحدهم جيدًا حقًا، وتم وصف الباقي بشكل عام. لن أكرر نفسي كثيرًا.

كالعادة تحذير:

أبعاد هذه الوحدة لا تزيد عن 35 × 24 ملم، ويمكن أن تجد مكانها ليس فقط في الأجهزة الإلكترونية القابلة للارتداء، ولكن أيضًا في أجهزة التحكم عن بعد.

تشتمل المجموعة على هوائي سلبي:

إذا رغبت في ذلك، يمكنك دائمًا استبدال العنصر النشط أو تصنيعه بنفسك باستخدام هذه الطريقة:

اليوم الوحدة ليست نموذجًا قديمًا، ويتم استخدامها بشكل نشط، + يوجد دعم من الشركة المصنعة.

في الشكل أدناه أوضحت الخطوط التي يجب توصيلها حيث يمكن اكتشاف نظام تحديد المواقع العالمي (GPS) في الكمبيوتر:

يبدو شيء من هذا القبيل:

ثم قم بتثبيت تطبيق U-center، الرابط الموضح أعلاه، وحدد المنفذ:

بشكل افتراضي، نتواصل عند 9600 باود.

وإليك كيف يعمل بشكل عام، كل شيء التقطته في الداخل:

ربط الوحدة بالاردوينو

لنعد المبرمج للبرامج الثابتة:

ثم نقوم بخياطة هذا الرسم في النانو:

معلومات إضافية

// ArduinoISP // حقوق الطبع والنشر © 2008-2011 Randall Bohn // إذا كنت بحاجة إلى ترخيص، راجع // http://www.opensource.org/licenses/bsd-license.php // // هذا الرسم يحول Arduino إلى AVRISP باستخدام أطراف Arduino التالية: // // يتم استخدام Pin 10 لإعادة ضبط وحدة التحكم الدقيقة المستهدفة. // // افتراضيًا، تُستخدم دبابيس SPI الخاصة بالأجهزة MISO وMOSI وSCK للتواصل // مع الهدف. في جميع أجهزة Arduino، يمكن العثور على هذه الأطراف // على رأس ICSP/SPI: // // MISO °. . 5V (!) تجنب هذا الدبوس عند Due، Zero... // SCK. . موسي // . . GND // // في بعض Arduinos (Uno،...)، تكون أطراف MOSI وMISO وSCK هي نفس أطراف // الرقمية 11 و12 و13 على التوالي. ولهذا السبب فإن العديد من البرامج التعليمية ترشدك إلى ربط الهدف بهذه الدبابيس. إذا وجدت أن هذه الأسلاك أكثر // عملية، فقم بتعريف USE_OLD_STYLE_WIRING. سيعمل هذا حتى في حالة عدم استخدام Uno. (في Uno هذا غير مطلوب). // // بدلاً من ذلك، يمكنك استخدام أي دبوس رقمي آخر عن طريق تكوين // برنامج ("BitBanged") SPI والحصول على تعريفات مناسبة لـ PIN_MOSI، // PIN_MISO وPIN_SCK. // // هام: عند استخدام Arduino الذي لا يتحمل 5V (Due، Zero، ...) باعتباره // المبرمج، تأكد من عدم تعريض أي من أطراف المبرمج إلى 5V // طريقة بسيطة للإنجاز هذا لتشغيل النظام بأكمله (المبرمج // والهدف) عند 3V3. // // ضع مؤشر LED (مع المقاوم) على الأطراف التالية: // 9: نبضات القلب - يوضح أن المبرمج قيد التشغيل // 8: خطأ - يضيء إذا حدث خطأ ما (استخدم اللون الأحمر إذا كان ذلك منطقيًا) // 7: البرمجة - في التواصل مع العبد // #include "Arduino.h" #undef SERIAL #define PROG_FLICKER true // تكوين ساعة SPI (في هرتز). // على سبيل المثال بالنسبة لـ ATtiny عند 128 كيلو هرتز: تنص ورقة البيانات على أن نبض ساعة SPI العالية والمنخفضة يجب أن يكون أكبر من دورتين لوحدة المعالجة المركزية، لذا خذ 3 دورات، أي قم بتقسيم الهدف // f_cpu على 6: // # تحديد SPI_CLOCK (128000/6) // // الساعة بطيئة بدرجة كافية لـ ATtiny85 @ 1 ميجاهرتز، وهي افتراضية معقولة: #define SPI_CLOCK (1000000/6) // حدد SPI للأجهزة أو البرامج، اعتمادًا على ساعة SPI حاليًا فقط بالنسبة لـ AVR، وبالنسبة للبنيات الأخرى (Due، Zero،...)، من المحتمل أن يكون SPI للأجهزة // سريعًا جدًا على أي حال. #if تعريف(ARDUINO_ARCH_AVR) #if SPI_CLOCK > (F_CPU / 128) #define USE_HARDWARE_SPI #endif #endif // تكوين المسامير التي سيتم استخدامها: // تكوين الدبوس القياسي. #ifndef ARDUINO_HOODLOADER2 #define RESET 10 // استخدم السن 10 لإعادة تعيين الهدف بدلاً من SS #define LED_HB 9 #define LED_ERR 8 #define LED_PMODE 7 // قم بإلغاء التعليق على السطر التالي لاستخدام أسلاك نمط Uno القديم // (باستخدام السن 11، 12 و13 بدلاً من رأس SPI) على ليوناردو، بسبب. .. // #define USE_OLD_STYLE_WIRING #ifdef USE_OLD_STYLE_WIRING #define PIN_MOSI 11 #define PIN_MISO 12 #define PIN_SCK 13 #endif // HOODLOADER2 يعني تشغيل الرسومات على رقائق المحول التسلسلي ATmega16U2 // على لوحات Uno أو Mega. يجب أن نستخدم الأطراف المكسورة: #else #define RESET 4 #define LED_HB 7 #define LED_ERR 6 #define LED_PMODE 5 #endif // بشكل افتراضي، استخدم دبابيس SPI للأجهزة: #ifndef PIN_MOSI #define PIN_MOSI MOSI #endif #ifndef PIN_MISO #define PIN_MISO MISO #endif #ifndef PIN_SCK #define PIN_SCK SCK #endif // فرض bitbanged SPI في حالة عدم استخدام دبابيس SPI للأجهزة: #if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK) #undef USE_HARDWARE_SPI #endif // تكوين المنفذ التسلسلي المراد استخدامه. // // تفضل منفذ USB التسلسلي الظاهري (المعروف أيضًا باسم منفذ USB الأصلي)، إذا كان Arduino يحتوي على واحد: // - لا تتم إعادة التعيين تلقائيًا (باستثناء معدل الباود السحري البالغ 1200). // - إنه أكثر موثوقية بسبب مصافحة USB. // // ليوناردو وما شابه لها منفذ تسلسلي افتراضي USB: "Serial". // Due وZero لهما منفذ تسلسلي افتراضي USB: "SerialUSB". // // في Due وZero، يمكن استخدام "Serial" أيضًا، بشرط تعطيل إعادة الضبط التلقائي. // لاستخدام "Serial": #define SERIAL Serial #ifdef SERIAL_PORT_USBVIRTUAL #define SERIAL_PORT_USBVIRTUAL #else #define SERIAL Serial #endif // تكوين معدل الباود: #define BAUDRATE 19200 // #define BAUDRATE 115200 // #define BAUDRATE 1000000 #define HWVER 2 #define SWMAJ 1 #define SWMIN 18 // تعريفات STK #define STK_OK 0x10 #define STK_FAILED 0x11 #define STK_UNKNOWN 0x12 #define STK_INSYNC 0x14 #define STK_NOSYNC 0x15 #define CRC_EOP 0x20 // حسنًا إنها مسافة ... نبض باطلة (دبوس كثافة العمليات، مرات كثافة العمليات)؛ #ifdef USE_HARDWARE_SPI #include "SPI.h" #else #define SPI_MODE0 0x00 class SPISettings ( public: // الساعة بالهرتز SPISettings(uint32_t Clock, uint8_t bitOrder, uint8_t dataMode) : Clock(clock) ( (void) bitOrder; ( void) dataMode Private: uint32_t Clock؛ فئة BitBangedSPI (عام: بداية باطلة () (digitalWrite (PIN_SCK، LOW)؛ digitalWrite (PIN_MOSI، LOW)؛ pinMode (PIN_SCK، OUTPUT)؛ pinMode (PIN_MOSI، OUTPUT)؛ pinMode (PIN_MISO، INPUT)؛) بداية المعاملات الباطلة (SPISettings) الإعدادات) ( عرض النبض = (500000 + الإعدادات. الساعة - 1) / الإعدادات. الساعة؛ إذا (عرض النبض == 0) عرض النبض = 1؛) نهاية باطلة () () نقل uint8_t (uint8_t b) (لـ (غير موقع int i = 0;< 8; ++i) { digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH: LOW); digitalWrite(PIN_SCK, HIGH); delayMicroseconds(pulseWidth); b = (b << 1) | digitalRead(PIN_MISO); digitalWrite(PIN_SCK, LOW); // slow pulse delayMicroseconds(pulseWidth); } return b; } private: unsigned long pulseWidth; // in microseconds }; static BitBangedSPI SPI; #endif void setup() { SERIAL.begin(BAUDRATE); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); pulse(LED_ERR, 2); pinMode(LED_HB, OUTPUT); pulse(LED_HB, 2); } int error = 0; int pmode = 0; // address for reading and writing, set by "U" command unsigned int here; uint8_t buff; // global block storage #define beget16(addr) (*addr * 256 + *(addr+1)) typedef struct param { uint8_t devicecode; uint8_t revision; uint8_t progtype; uint8_t parmode; uint8_t polling; uint8_t selftimed; uint8_t lockbytes; uint8_t fusebytes; uint8_t flashpoll; uint16_t eeprompoll; uint16_t pagesize; uint16_t eepromsize; uint32_t flashsize; } parameter; parameter param; // this provides a heartbeat on pin 9, so you can tell the software is running. uint8_t hbval = 128; int8_t hbdelta = 8; void heartbeat() { static unsigned long last_time = 0; unsigned long now = millis(); if ((now - last_time) < 40) return; last_time = now; if (hbval >192) هبدلتا = -هبدلتا؛ إذا (هبفال< 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); } static bool rst_active_high; void reset_target(bool reset) { digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH: LOW); } void loop(void) { // is pmode active? if (pmode) { digitalWrite(LED_PMODE, HIGH); } else { digitalWrite(LED_PMODE, LOW); } // is there an error? if (error) { digitalWrite(LED_ERR, HIGH); } else { digitalWrite(LED_ERR, LOW); } // light the heartbeat LED heartbeat(); if (SERIAL.available()) { avrisp(); } } uint8_t getch() { while (!SERIAL.available()); return SERIAL.read(); } void fill(int n) { for (int x = 0; x < n; x++) { buff[x] = getch(); } } #define PTIME 30 void pulse(int pin, int times) { do { digitalWrite(pin, HIGH); delay(PTIME); digitalWrite(pin, LOW); delay(PTIME); } while (times--); } void prog_lamp(int state) { if (PROG_FLICKER) { digitalWrite(LED_PMODE, state); } } uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { SPI.transfer(a); SPI.transfer(b); SPI.transfer©; return SPI.transfer(d); } void empty_reply() { if (CRC_EOP == getch()) { SERIAL.print((char)STK_INSYNC); SERIAL.print((char)STK_OK); } else { error++; SERIAL.print((char)STK_NOSYNC); } } void breply(uint8_t b) { if (CRC_EOP == getch()) { SERIAL.print((char)STK_INSYNC); SERIAL.print((char)b); SERIAL.print((char)STK_OK); } else { error++; SERIAL.print((char)STK_NOSYNC); } } void get_version(uint8_t c) { switch © { case 0x80: breply(HWVER); break; case 0x81: breply(SWMAJ); break; case 0x82: breply(SWMIN); break; case 0x93: breply("S"); // serial programmer break; default: breply(0); } } void set_parameters() { // call this after reading parameter packet into buff param.devicecode = buff; param.revision = buff; param.progtype = buff; param.parmode = buff; param.polling = buff; param.selftimed = buff; param.lockbytes = buff; param.fusebytes = buff; param.flashpoll = buff; // ignore buff (= buff) // following are 16 bits (big endian) param.eeprompoll = beget16(&buff); param.pagesize = beget16(&buff); param.eepromsize = beget16(&buff); // 32 bits flashsize (big endian) param.flashsize = buff * 0x01000000 + buff * 0x00010000 + buff * 0x00000100 + buff; // AVR devices have active low reset, AT89Sx are active high rst_active_high = (param.devicecode >= 0xe0); ) void start_pmode() ( // إعادة تعيين الهدف قبل القيادة PIN_SCK أو PIN_MOSI // SPI.begin() سوف يقوم بتكوين SS كمخرج، لذلك يتم تحديد الوضع الرئيسي SPI. // لقد حددنا RESET على أنه الدبوس 10، وهو بالنسبة للعديد من Arduinos ليس دبوس SS. // لذلك يتعين علينا تكوين RESET كإخراج هنا، // (reset_target () يعين المستوى الصحيح أولاً)set_target(true); (SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); ، الفصل "خوارزمية برمجة SERIAL_PRG": // إعادة تعيين النبض بعد أن يكون PIN_SCK منخفضًا: digitalWrite(PIN_SCK, LOW); القيمة التي تم اختيارها بشكل تعسفيset_target(false); // سرعات أعلى من 20 كيلو هرتز تأخير ميكروثانية (100)؛ // أرسل أمر تمكين البرمجة: تأخير (50)؛ // ورقة البيانات: يجب أن تكون> 20 مللي ثانية spi_transaction(0xAC, 0x53, 0x00, 0x00); .end(); // نحن على وشك إخراج الهدف من إعادة التعيين، لذا قم بتكوين منافذ SPI كإدخال pinMode(PIN_MOSI, INPUT); pinMode(PIN_SCK, INPUT); Reset_target(false); pinMode(RESET, INPUT); بمود = 0؛ ) void Universal() ( uint8_t ch; fill(4); ch = spi_transaction(buff, buff, buff, buff); breply(ch); ) void flash(uint8_t hilo, unsigned int addr, uint8_t data) ( spi_transaction(0x40) + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data) ) التزام باطلة(unsigned int addr) ( if (PROG_FLICKER) ( prog_lamp(LOW); ) spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); if (PROG_FLICKER) ( تأخير(PTIME); prog_lamp(HIGH); ) ) int current_page() غير موقعة ( if (param.pagesize == 32) ( العودة هنا & 0xFFFFFFF0; ) إذا ( param.pagesize == 64) ( ارجع هنا & 0xFFFFFFFE0; ) إذا (param.pagesize == 128) ( ارجع هنا & 0xFFFFFFFC0; ) إذا (param.pagesize == 256) ( ارجع هنا & 0xFFFFFF80; ) ارجع هنا؛ write_flash(int length) ( fill(length); if (CRC_EOP == getch()) ( SERIAL.print((char) STK_INSYNC); SERIAL.print((char) write_flash_pages(length)); ) else ( error++; SERIAL .print((char) STK_NOSYNC); ) ) uint8_t write_flash_pages(int length) ( int x = 0; unsigned int page = current_page(); بينما (x< length) { if (page != current_page()) { commit(page); page = current_page(); } flash(LOW, here, buff); flash(HIGH, here, buff); here++; } commit(page); return STK_OK; } #define EECHUNK (32) uint8_t write_eeprom(unsigned int length) { // here is a word address, get the byte address unsigned int start = here * 2; unsigned int remaining = length; if (length >param.eepromsize) ( error++; return STK_FAILED; ) while (remaining > EECHUNK) ( write_eeprom_chunk(start, EECHUNK); start += EECHUNK; Result -= EECHUNK; ) write_eeprom_chunk(start, المتبقي); إرجاع STK_OK؛ ) // كتابة (طول) بايت، (بدء) هو عنوان بايت uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) ( // هذا يكتب بايت بايت، قد تكون كتابة الصفحة أسرع (4 بايت في المرة الواحدة) fill(length); prog_lamp(LOW);< length; x++) { unsigned int addr = start + x; spi_transaction(0xC0, (addr >> 8) & 0xFF، العنوان & 0xFF، برتقالي[x])؛ تأخير (45)؛ ) prog_lamp(HIGH); إرجاع STK_OK؛ ) برنامج باطلة () (نتيجة char = (char) STK_FAILED؛ طول int غير الموقع = 256 * getch ()؛ length += getch ()؛ char memtype = getch ()؛ // ذاكرة فلاش @ هنا، (الطول) بايت إذا (memtype == "F") ( write_flash(length); return; ) if (memtype == "E") ( result = (char)write_eeprom(length); if (CRC_EOP == getch()) ( SERIAL.print ((char) STK_INSYNC)؛ SERIAL.print(result); else ( error++; SERIAL.print((char) STK_NOSYNC); ) SERIAL.print((char)STK_FAILED); (0x20 + hilo * 8, (addr >> 8) & 0xFF, addr & 0xFF, 0) char flash_read_page(int length) ( for (int x = 0; x< length; x += 2) { uint8_t low = flash_read(LOW, here); SERIAL.print((char) low); uint8_t high = flash_read(HIGH, here); SERIAL.print((char) high); here++; } return STK_OK; } char eeprom_read_page(int length) { // here again we have a word address int start = here * 2; for (int x = 0; x < length; x++) { int addr = start + x; uint8_t ee = spi_transaction(0xA0, (addr >> 8) و0xFF، العنوان و0xFF، 0xFF)؛ SERIAL.print((شار)ee); ) إرجاع STK_OK؛ ) قراءة باطلة () (نتيجة char = (char)STK_FAILED؛ طول int = 256 * getch()؛ length += getch()؛ char memtype = getch(); if (CRC_EOP != getch()) ( error++; SERIAL .print((char) STK_NOSYNC); return; ) SERIAL.print((char) STK_INSYNC); if (memtype == "F") result = flash_read_page(length); (الطول)؛ SERIAL.print(result);) void read_signature() ( if (CRC_EOP != getch()) ( error++; SERIAL.print((char) STK_NOSYNC); return;) SERIAL.print((char) STK_INSYNC ); uint8_t High = spi_transaction(0x30, 0x00, 0x00, 0x00); ///////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// /// /////////////////////////// void avrisp() ( uint8_t ch = getch (); التبديل (ch) (الحالة "0": // خطأ في تسجيل الدخول = 0؛ فارغ_reply()؛ فاصل؛ الحالة "1": if (getch() == CRC_EOP) ( SERIAL.print((char) STK_INSYNC); SERIAL. print("AVR ISP"); ": fill(20);empty_reply(); الحالة "E": // المعلمات الموسعة - تجاهل الآن فارغ_reply(); (!pmode) start_pmode(); فاصل; الحالة "U": // تعيين العنوان (كلمة) هنا += 256 * getch(); // STK_PROG_FLASH getch(); // STK_READ_PAGE "t"; read_page(); حالة "V": //0x51 خطأ = 0؛ الحالة 0x75: //STK_READ_SIGN "u" read_signature(); استراحة؛

بعد ذلك، حدد وحدة التحكم Pro Mini الخاصة بك، وحدد مبرمج ArduinoISP وقم بخياطة وحدة التحكم باستخدام الأمر رسم -> تحميل عبر مبرمجواضغط على زر إعادة الضبط في جهاز Pro mini، وسيبدأ البرنامج الثابت لوحدة التحكم في الوميض (بالنسبة لي، يعمل فقط في المحاولة الثانية، أحتاج إلى التحلي بالصبر):

كما قلت أعلاه، أحب حقًا إرفاق شاشات بجميع أنواع الأدوات، حسنًا، إنه أمر مخيف، لذلك هذا "مشروع"رغبتي لم تمر مرور الكرام.

ماذا نحتاج لكل هذا:

بشكل عام، قمت بجمع كل القمامة التي كانت ملقاة حول:

1. وحدة بطاقة SD، ضخمة جدًا، لذا حاولت التخلص منها في أسرع وقت ممكن.

2. تعتمد الشاشة على وحدة التحكم PCD8544، وهي شاشة Nokia الشهيرة.

3. بطاقة ذاكرة بسعة 1 جيجابايت، مع معيار MiniSD الذي لا يحظى بشعبية، لم يكن لدي أي فكرة عن مكان توصيلها، ولكني أردت تشغيل كل شيء، لذا دعها تعمل لصالح التنقل.

4. سوف تحتاج إلى دماغ، دماغ Pro Mini كبير على شريحة 328P.

كما كتبت أعلاه، سنقوم بالخياطة من خلال Arduino Nano مع أداة تحميل التشغيل المُثبتة فيه.

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

5. بالطبع الوحدة نفسها + الهوائي، كما كتبت أعلاه، يمكنك صنعها بنفسك.

6. أوه نعم، لقد نسيت تقريبًا أنك ستحتاج إلى حافظة أخرى، وإلا ما هو نوع الجهاز الذي لا يحتوي على حافظة.

في هذه الحالة، تم شراؤها مرة أخرى، ولكن في شكل فضي، للاختبار. سأقول هذا، لم يعجبني اللون الفضي على الإطلاق، فالأسود يبدو أفضل.

عندما تكون جميع المكونات متاحة، يمكنك توصيلها وبرمجتها كلها.

نقوم بالاتصال بـ Pro Mini وفقًا للمخطط التالي:

عرض:

RST-D6
م - د7
دي سي-D5
دين-D4
كلك-D3
VCC - 5 فولت (اختياري في حالتي، وفي حالات أخرى 3.3 فولت)
الضوء - GND
غند - غند

لم أكن بحاجة إلى الإضاءة الخلفية، لذلك لم أقوم بتوصيلها.

CS-D10
موسي-D11
ميسو-D12
إس كيه-D13
غند - غند
5V - VCC (اختياري في حالتي، في بعض الحالات مع محول نتصل بـ 3.3V)

وحدة نظام تحديد المواقع:

آر إكس-D8
تكس-D2
غند - غند
VCC-3.3 (3.3 هو الحد الأقصى!)

لا تنس توصيل الهوائي بالوحدة، لقد أخذت الطاقة من Nano Tk. تم توصيله لتصحيح الأخطاء، ثم سيتم تحويل كل شيء إلى البطارية.

عرض تقريبي:

الكود بسيط ومباشر؛ لاستخدامه ربما تحتاج إلى . إضافي . الباقي مدمج. وفقًا للكود، الخط هو الوقت*0.000001+5، لقد قمت بشكل أساسي بإحضار الوقت إلى نموذج سهل الهضم وأضفت منطقة زمنية. يمكنك تخطي هذا والحصول على نتائج نظيفة.

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

إذا كان هناك خطأ في قراءة ملف أو لم يكن هناك إمكانية الوصول إلى بطاقة SD، فسيتم عرض رسالة SD-، في حالات أخرى اس دي+.

#يشمل #يشمل #يشمل #يشمل //CS-D10، MOSI-D11، MISO-D12، SCK-D13، GND - GND، 5V - VCC (اختياري في حالتي، في بعض الحالات نتصل بـ 3.3 فولت إذا لم يكن هناك محول) File GPS_file; نظام تحديد المواقع TinyGPS. SoftwareSerial gpsSerial (2، 8)؛ // RX - 8 pin، TX - 2 pin static PCD8544 LCD؛ // RST - D6، CE - D7، DC - D5، DIN - D4، CLK - D3، VCC - 5V (اختياري، إذا كان هناك محول على خط 3.3 فولت)، Light - GND، GND - GND bool newdata = خطأ شنيع؛ بداية طويلة غير موقعة؛ خط العرض الطويل، خط الطول؛ وقت طويل غير موقع، تاريخ؛ إعداد الفراغ () (lcd.begin(84, 48); gpsSerial.begin(9600); Serial.begin(9600); pinMode(10, OUTPUT); if (!SD.begin(10))( lcd.setCursor( 0, 0);lcd.println("SD-");return;)lcd.setCursor(0, 0);lcd.println("SD+"); .txt..."); GPS_file.print("LATITUDE"); GPS_file.print("،); GPS_file.print("LONGITUDE"); GPS_file .print("،); GPS_file.print("DATE" "); GPS_file.print("TIME"); "); GPS_file.println(); Serial.println("done.");"); "); )lcd.setCursor(0,3) ;lcd.print("ALT: ");lcd.print("SPD: ");lcd.print("LAT: "); .setCursor(0,5) ; &lon gps.get_datetime(&date, &time); شاشات الكريستال السائل.setCursor(55,0); طباعة شاشات الكريستال السائل (الوقت * 0.000001+5)؛ شاشات الكريستال السائل.setCursor(22, 4); شاشات الكريستال السائل. طباعة (لات)؛ شاشات الكريستال السائل.setCursor(22, 5); شاشات الكريستال السائل. طباعة (لون)؛ شاشات الكريستال السائل.setCursor(22, 2); lcd.print(gps.f_speed_kmph()); شاشات الكريستال السائل.setCursor(22, 3); lcd.print(gps.f_altitude()); ) ) GPS_file = SD.open("GPSLOG.txt", FILE_WRITE); إذا (GPS_file) ( GPS_file.print (lat)؛ GPS_file.print ("،)؛ GPS_file.print (lon)؛ GPS_file.print ("،)؛ GPS_file.print (date)؛ GPS_file.print ("، "); GPS_file.print(time*0.000001+5); GPS_file.print("،); GPS_file.print(gps.f_altitude()); GPS_file.println(); GPS_file.إغلاق(); )else( شاشات الكريستال السائل .setCursor(0, 0);lcd.println("SD-"); bool readgps())( while (gpsSerial.available())( int b = gpsSerial.read(); if("\r" ! = ب)( إذا (gps.encode(b)) يُرجع صحيحًا؛)) يُرجع خطأ؛)

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

يمكنك اللعب بترتيب العناصر، كان هناك مثل هذا الخيار، لكنني أدركت أن حساب متوسط ​​الإحداثيات ينتج عنه خطأ كبير ورفضت.

بالنسبة للبطاريات التي أستخدمها بطارية ليثيوم أيون. أشتري بطاريات لكاميرات الحركة بكميات كبيرة وأستخدمها في أعمالي اليدوية، بالإضافة إلى أنها يمكن أن تكون دائمًا مفيدة لكاميرا الحركة التي أستخدمها أثناء التنزه. .

استخدام اللوح، ضع كل شيء معا:

لقد قمت بلصق قطعة من الشريط الكهربائي على علبة بطاقة الذاكرة، لأنها على اتصال بجهات اتصال شاحن البطارية. نقوم بفلاش بطاقة الذاكرة في FAT16.

ثم نبدأ ونتحقق، دون أن ننسى تشغيل المفتاح:

معالجة النتائج

يتم عرض النتائج كملف نصي:

اضبط فاصل الأعمدة على فاصلة:

ثم يمكنك تحميل كل شيء في البرنامج جوجل إيرثبرو باستخدام علامة التبويب ملف -> فتح، افتح ملفنا وحدد الأعمدة المسؤولة عن خطوط الطول والعرض واحصل على مسار مماثل (بما أنني كنت في مكان واحد، حصلت على نقاط متناثرة):

يمكنك تحديد نقطة وعرض العدد الكامل للنقاط المقابلة لها:

الحد الأدنى

بشكل عام، يعمل المسجل، يمكنك كتابة المسار، ثم التحرير على الخريطة. ايضا في برمجةمن Google، يمكن حفظ المسار بتنسيق أكثر شيوعًا تدعمه الخرائط الأخرى.

أنا أكثر من راضية فضولي.

الجانب السلبي هو أنه هوائي صغير؛ في بعض الأحيان يمكن أن تستغرق البداية الباردة ما يصل إلى 10 دقائق (اعتمادًا على مدى الغيوم والوقت من اليوم). يمكن استبدال الهوائي، بالطبع، محلي الصنع، أو شراؤها بالإضافة إلى ذلك؛ هناك عدد غير قليل من الهوائيات النشطة في السوق.

شكرا على وقتك.

التحديث من 22/05/18

1. استبدلت السكن وصنعت هوائيًا من الرابط الذي قدمته. (تقليل وقت البدء البارد، والعثور على الأقمار الصناعية بشكل أسرع وأسرع بكثير.)

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

3. لتقليل المساحة المأهولة، قمت بتفكيك الشاشة ولحامها بها.

حتى الآن هذا هو الرأي.

التخطيط لشراء +129 اضافة الى المفضلة اعجبني الاستعراض +170 +299