
ابني "مدمن مخدرات" بقوة على
البناء المغناطيسي Magformers . بمجرد
الاطلاع على
سلسلة من Fixiks حيث تم عرض المنشئ نفسه ، سأل الطفل: "يا أبي ، لماذا تحتوي أدوات الإصلاح على تفاصيل تتألق ، لكننا لا نفعل ذلك؟".
اتضح أن هناك بالفعل "Magformers Neon LED Set" ، حيث يوجد بالإضافة إلى لبنات البناء المعتادة ، عنصر مع LED. نظرًا لأننا بحلول هذا الوقت قد جمعنا بالفعل صندوقًا كاملًا من المغناطيس بجميع الأشكال والأحجام الممكنة (كما هو الحال بالنسبة لي ، فإن
صانعي الشعارات الصينية ليسوا أدنى من الأصل على الإطلاق) ، لم أكن أريد
بطريقة ما شراء مجموعة أخرى لمجرد استخدام مصباح كهربائي. علاوة على ذلك ، تكلف هذه المجموعة أكثر بكثير من مجموعة مماثلة دون الإضاءة الخلفية.
بعد أن قدرت أنه لا يوجد سوى بضعة دولارات في المكونات ، والتي كان لدي معظمها بالفعل ، فقد قررت أن أحصل على مورغولكا. نعم ، مع الآثار التي لم يكن لديك الأصلي.
تحت القط ، ستجد خيار الوامض على ATTiny85 ولوحة LED في WS8212 LEDs. سأتحدث عن الدوائر الكهربائية ، وكيف قمت بتشغيل هذا الشيء برمته من البطارية ، بالإضافة إلى المشكلات غير الواضحة التي جرفتها على طول الطريق. سأتحدث أيضًا بالتفصيل عن مكون البرنامج في المشروع.
الخطوات الأولى
يبدو لي أن التوهج على LED العادية (حتى RGB) ممل ومبتذلة. ولكن الشعور بشيء مثل WS8212 بدا مثيرًا للاهتمام. على ebee ، تم تقديم كل من LEDs والمصفوفات الفردية حتى حجم 16x16. بعد أن اشترى عدة وحدات مختلفة ، قررت على مصفوفة 4X4. هناك الكثير من مصابيح LED لتنغمس في المؤثرات البصرية المختلفة ، في حين أن الوحدة قابلة للمقارنة في حجمها مع نافذة الكتلة المربعة للمصمم.

للتحكم في مصفوفة LED ، يكفي وجود دبوس واحد فقط من المتحكم الدقيق ، لذا يبدو أن نانو اردوينو تبدو وكأنها تمثال نصفي (إلى جانب ذلك ، لن يتناسب مع هذه الحالة). ولكن تبين أن استنساخ digispark الموجود على وحدة التحكم ATTiny85 كان صحيحًا تمامًا - فهو لا يحتوي على الكثير من الذاكرة والدبابيس ، ولكن أكثر من كافية لمصباح LED الوامض. تتكامل الوحدة بشكل مثالي مع Arduino IDE وتحتوي على أداة تحميل USB على متن الطائرة ، لذلك فإن برمجة هذه الوحدة بسيطة ومريحة للغاية. لقد أردت منذ فترة طويلة لمحاولة ذلك.
بدأت مع أبسط مخطط.

في هذا النموذج ، كان من الممكن تصحيح جميع خوارزميات التوهج / وميض بسرعة (حولها أدناه) بسرعة. لكن اللعبة التي تعمل بالطاقة السلكية ليست هي الحالة - تحتاج إلى التفكير في طاقة البطارية. علاوة على ذلك ، من أجل عدم الإفلاس على بطاريات الأصابع (والتي ، علاوة على ذلك ، لا تنسجم مع المغلف) ، فقد تقرر استخدام الليثيوم. ونظرًا لوجود بطارية ليثيوم ، فأنت بحاجة إلى التفكير في كيفية شحنها. في الصناديق ، وجدنا للتو
وحدة تحكم شحن "شائعة" على رقاقة TP4056 التي تم شراؤها في هذه المناسبة.
لكنها لم تنجح على الفور. لم يتم تصميم دائرة وحدة Digispark ATTiny85 جدًا لهذا الغرض - فهناك إما طاقة USB ، ولكن بعد ذلك يتم تزويد الطاقة مباشرة إلى المتحكم الدقيق (عبر ناقل +5) ، أو من دخل VIN ، ولكن بعد ذلك تمر الطاقة عبر مثبت الخطي 7805. الخيار عند وحدة شحن الليثيوم لم يتم توفير إدراجها في الفجوة بين موصل USB وجهاز التحكم. اضطررت إلى تعديل الدائرة قليلاً وإزالة التفاصيل الإضافية.

لذلك ، يتم الآن تزويد USB بالطاقة إلى دبوس VIN ومن ثم يذهب إلى إدخال الشاحن. خرج الشاحن (في الواقع ، يتم توصيل البطارية مباشرة) يعود إلى اللوحة من خلال القدم 5V. وعلى الرغم من أنه سيكون هناك في الواقع من 3 إلى 4.2 فولت (الجهد البطارية) هذا أمر طبيعي للغاية - نطاق الجهد التشغيل من متحكم هو 1.8-5.5V. وحتى وحدة LED تعمل بشكل طبيعي من 2.7V ، على الرغم من أن 3.2V أقل من الصمام الضوئي الأزرق والألوان "تطفو" قليلاً باللون الأصفر.
لتوفير الطاقة ، اختفى أيضًا مصباح D2 LED الذي يعمل دائمًا. المخطط العام يبدو الآن مثل هذا

سيكون من الممكن تغذية الدائرة من خلال موصل USB في الشاحن ، ولكن بعد ذلك ستفقد القدرة على تحميل البرامج الثابتة عبر موصل USB على لوحة التحكم. قد يكون من الممكن ترك موصلي USB لأغراض متعددة - أحدهما للشحن ، والآخر للبرامج الثابتة ، لكن هذا خطأ إلى حد ما.
لقد اشتريت بطارية بحجم 6 × 25 × 35 على موقع ebay ، لكن تبين أنها إما معيبة ، أو قتلتها باستخدام دائرة كهربائية قصيرة أو تيار شحن كبير (افتراضياً ، يتم ضبط تيار الشحن على 1A وتحتاج إلى لحام مقاوم واحد لتقليل التيار). في أي حال ، عندما يكون الحمل متصلاً ، حتى عند 10 مللي أمبير ، انخفض الجهد على البطارية إلى 1 فولت. في وقت الاختبار ، تحولت إلى بطارية LiPo نصف ميتة من quadrocopter صغير. بعد ذلك بقليل ، طلبت البطارية من بائع آخر واتضح أنها جيدة.
من حيث المبدأ ، سيكون من الممكن التوقف عند هذا ، لحام أسلاك التوصيل ودفع كل شيء بلطف في نوع من السكن ، لكنني قررت قياس استهلاك الدائرة. ثم بكيت. حسنًا ، في حالة صالحة للعمل (عندما تلمع المصابيح بالكامل) ، فإن هذا الشيء يأكل ما يصل إلى 130 مللي أمبير ، لذا في الاستهلاك ، الاستهلاك أكثر من 25 مللي أمبير! أي هذا الوامض يأكل بطاريتي 600 مللي أمبير في أقل من يوم!
اتضح أن حوالي 10 مللي أمبير تستهلك المصابيح. حتى إذا لم يضيءوا ، لا يزال متحكم يعمل في كل منهم وينتظر الأمر. أي تحتاج إلى الخروج بدائرة الطاقة لأسفل للمصابيح.
يتم استهلاك ما تبقى من 15 مللي أمبير من قبل متحكم. نعم ، يمكن وضعه في الفراش ووفقًا لورقة البيانات ، سيتم قياس الاستهلاك بواسطة microamps ، ولكن في الواقع لم يكن من الممكن الحصول على أقل من 1 مللي أمبير. أغلقت ADC وترجمت المسامير إلى مدخلات. يبدو أن هناك تسربًا في مكان ما في الدائرة ، لكن معرفتي المتواضعة بالإلكترونيات ليست كافية للعثور عليه وفهمه.
نحن تعقيد المخطط
ثم تذكرت أنني اشتريت رقاقة PT1502 للاختبار. هذه الرقاقة عبارة عن وحدة تحكم لشحن بطارية الليثيوم مع مزود طاقة مزود بعدة مدخلات تحكم. تكمن الصعوبة الوحيدة في أن الدائرة المصغرة تأتي في حزمة QFN20 4 × 4 مم وتتطلب بعض الربط. لحام هذا في المنزل صعب ولكنه ممكن. الرسوم صعبة بالنسبة لطرف منتظم ويجب طلبها من الصينيين. لكننا لسنا خائفين من الصعوبات ، أليس كذلك؟
في العديد من الصناديق ، يمكن وصف المخطط على النحو التالي.

في حالة إيقاف التشغيل ، لا يتم توفير الطاقة إلى وحدة التحكم ومصابيح LED. يحتوي الجهاز على زر "الطاقة" الذي يقوم بتشغيل الوامض (يقوم أيضًا بتبديل الأوضاع). على سبيل المثال ، يضيء مصباح LED ، وإذا لم يكن هناك نشاط للمستخدم (لا أحد يضغط على زر) ، فإن الجهاز ينطفئ. أي إن الأمر لا يتعلق بالنوم فقط ، ولكنه يوقف تشغيل الطاقة عن طريق إشارة Power Hold. وتطفئ كل شيء في وقت واحد - كل من متحكم ومصابيح LED. يتم تشغيل وظيفة التشغيل والإيقاف داخل رقاقة PT1502
كل ما تبقى هو رسم رسم تخطيطي للدوائر وعمل لوحة دوائر. يتم تركيب الدوائر ، في معظمها ، مع ورقة بيانات PT1502 ، وكذلك وحدة Digispark ATTiny85. يتم تقسيم الدائرة الدقيقة لوحدة التحكم في الطاقة PT1502 وظيفيًا إلى عدة أجزاء ، وبالتالي يتم تقسيمها إلى كتل في الدائرة.

هذا ، في الواقع ، هو وحدة تحكم شحن بطارية الليثيوم مع تسخير الخاصة به. يشير المصباح LED1 إلى حالة الشحن - بعد ذلك ، تكون الشحنة قيد التشغيل. يقوم المقاوم R6 بتعيين الشحنة الحالية إلى 470 مللي أمبير. بما أن لدي بطارية 600mAh ، من حيث المبدأ ، يمكنك زيادة التيار ووضع المقاوم في 780-800 أوم يصل إلى 600mA. ومع ذلك ، لست متأكدًا من الجودة الخاصة لبطاريتي - فمن الأفضل أن يتم الشحن ببطء أكثر ، لكنه سيستمر لفترة أطول.
النظر في خطة الطاقة

يعمل زر SW1 على بدء تشغيل النظام بالكامل - تستيقظ رقاقة PT1502 نفسها ثم تبدأ تشغيل جميع مصادر الطاقة (التي تحتوي على 3). عند تثبيت الطاقة ، سيبدأ الدارة الدقيقة وحدة التحكم عن طريق تحرير إشارة RESET. لسهولة تصحيح الأخطاء ، أضفت أيضًا زر إعادة تعيين منفصل.
يتم استخدام إشارة HOLD لإيقاف النظام بأكمله. عندما يبدأ المتحكم الدقيق ، يجب عليه ضبط الوحدة على هذا الخط. عندما يحين وقت التقريب ، فإن المتحكم الدقيق يضبط الصفر على خط HOLD وسيقوم رقاقة الطاقة PT1502 بإيقاف جميع مصادر الطاقة.
قد لا يزال من الممكن تتبع انخفاض شحن البطارية باستخدام إخراج BAT_LOW ، ولكن في هذا المقال سجلته - لن تحتاج إلى حفظ أي بيانات ولن ينفجر شيء إذا لم تلاحظ وجود بطارية ميتة في الوقت المناسب. يموت حتى يموت. ولكن فقط في حالة ذلك ، قام مجلس الإدارة بتوفير جهة الاتصال لهذا العمل.
دعنا نعود إلى زر SW1 لثانية واحدة. قررت عدم إجراء 2 أزرار منفصلة لتشغيل والتحكم. لذلك ، يتم توصيل الزر نفسه أيضًا بـ ATTiny85 ، ويقوم أثناء التشغيل بتبديل أوضاع الوامض. يتم تحديد قيم الفاصل R7-R8 حتى لا يتم حرق منفذ متحكم PB2. لجميع نطاقات الجهد البطارية (3.3 - 4.2V) ، سيتم توفير الجهد إلى سفح وحدة التحكم داخل حدود ورقة البيانات المحددة (0.7 * VCC - VCC + 0.5V)
النظر في مصدر الطاقة

هذا محول DC-DC نابض. يتم ضبط الجهد الناتج بواسطة المقاومات R10-R11 ، وفقا للصيغة من ورقة البيانات ، يتم تعيين إلى 3.3V. كل شيء آخر هو ضخم الربط.
للأبد ، ليس هناك حاجة فعلية لمصدر الطاقة المنقطع التدريجي هذا - سيكون من الممكن تشغيل المتحكم بشكل عام مباشرةً من البطارية. إن هذا المصدر تم تنفيذه بالفعل في شريحة PT1502 ويمكن تشغيله / إيقافه عندما نحتاج إليه - لماذا لا نستخدمه؟

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

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

لا يوجد شيء مثير للاهتمام في ربط متحكم.
اللمسة النهائية هي الموصل

في الواقع ، حصلت على لوحة تصحيح الأخطاء هذه بنفسي على ATTiny85 بدعم USB ووحدة تحكم طاقة مع بطارية ليثيوم. لذلك ، لم أحدد نفسي فقط بإخراج الخط إلى LED. بدلاً من ذلك ، أحضرت جميع خطوط المتحكم الدقيق إلى المشط - وفي الوقت نفسه ، من المريح الاتصال بالمبرمج.
ودع جميع الخطوط تقيد بشكل صارم بوظائف معينة (PB1 - خط تعليق ، PB2 - زر طاقة ، PB3 / PB4 - USB ، PB5 - إعادة ضبط) في المستقبل سيكون من الممكن تجاوز بعض الحدود. على سبيل المثال ، لا تقم بتوصيل كبل USB ثم حرر خطوط PB3 / PB4. أو ، على سبيل المثال ، رفض إعادة تعيين ثم حرر PB5. في غضون ذلك ، يبقى PB0 فقط مجانيًا - وقم بتوصيل LED الخاص بنا به.
نحن نمر الى المجلس. نظرًا للقيود المفروضة على حجم اللوحة في 40 × 40 مم ، وعدد المكونات وحاوية QFN20 من رقاقة PT1502 ، لم أكن حتى أفكر في تصنيع اللوحة في المنزل. لذلك ، بدأت على الفور في إنتاج اللوحة المدمجة من طبقتين. هذا ما حصلت عليه

لسهولة الاستخدام ، في الجانب العكسي ، وقعت على جميع وظائف الإخراج الممكنة (حصلت على الفكرة من لوحة Digispark)

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

السكن
حان الوقت للانتقال إلى الهيكل. لقد طبعتها على طابعة ثلاثية الأبعاد. تصميم بدون زخرفة - صندوق وزر. يتم توفير خطافات خاصة في المربع لتثبيت اليراع في الوحدة النمطية للمربع المصمم.

اللوحة الرئيسية والبطارية تعيش في هذه القضية.


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

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

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


البرامج الثابتة
بالنسبة لمصابيح LED الوامضة ، لا تحتاج إلى الغوص بشكل خاص في محيط المتحكم الدقيق - فقط بضع وظائف للعمل مع GPIO كافية. ولكن بما أن الوحدة النمطية مثبتة في منصة Arduino ، فلماذا لا تستفيد من ذلك؟
أولاً ، بعض التعاريف والثوابت
يحدد هذا عدد وحدات البكسل في مصفوفة وأرقام الدبوس والحد الأقصى من سطوع مصابيح LED (أثناء تصحيح الأخطاء ، كان من المناسب ضبطها على 50 حتى لا تغمض عيني)
يتم ترتيب المصابيح في مصفوفة بلدي بطريقة غير واضحة إلى حد ما - متعرج. لذلك ، لتأثيرات مختلفة ، اضطررت إلى إعادة ترقيم.
للتحكم في LEDs ، لم
أعد اختراع العجلة وأخذت
مكتبة جاهزة للعمل مع WS8211 LEDs . واجهة المكتبة بيضاء قليلاً. تم تعليق بعض الوظائف المساعدة (على سبيل المثال ، تحويل HSV إلى RGB) هناك.
أولاً ، يجب تهيئة اللوحة ومكتبة WS8211.
بادئ ذي بدء ، تحتاج إلى ضبط إشارة POWER HOLD على الوحدة - وستكون هذه إشارة إلى شريحة PT1502 التي انتهى إليها المتحكم الصغير ويعمل بشكل صحيح. في المقابل ، سوف تقوم الدائرة الكهربائية الصغيرة بدورها بتزويد التيار الكهربائي إلى متحكم المصابيح ومصابيح LED طالما أن إشارة HOLD مضبوطة على الوحدة.
بعد ذلك ، يتم تكوين أرجل التحكم في مؤشر LED في الإخراج والأزرار الموجودة على الإدخال. بعد ذلك ، يمكنك تهيئة مكتبة WS8211.
نظرًا لأن هذا الجهاز مستقل إلى حد ما ، فمن المستحيل السماح للتحكم الدقيق بالالتصاق في حالة غير مفهومة واستيعاب البطارية بأكملها. للقيام بذلك ، أبدأ مؤقت الوكالة الدولية للطاقة لمدة 2 ثانية. سيتم إعادة تشغيل المؤقت في حلقة البرنامج الرئيسي.
أنت الآن بحاجة إلى تحديد بضع وظائف مساعدة. مكتبة WS8211 بتخزين مخزن مؤقت مع قيم الألوان لكل LED. العمل مع المخزن المؤقت بشكل مباشر ليس ملائمًا للغاية ، لأنني كتبت وظيفة بسيطة لكتابة قيم RGB إلى مؤشر LED محدد
void setRgb(uint8_t led_idx, uint8_t r, uint8_t g, uint8_t b) { CRGB * leds = ws2811.getRGBData(); leds[led_idx].r = r; leds[led_idx].g = g; leds[led_idx].b = b; }
لكن في معظم الحالات ، في نموذج ألوان RGB ، يعد عد الألوان غير مناسب للغاية ، أو حتى مستحيل. على سبيل المثال ، عند رسم أي نوع من أنواع قوس قزح ، يكون أكثر ملاءمة للعمل مع
طراز ألوان HSV . يتم ضبط لون كل بكسل من خلال قيمة نغمة اللون والسطوع. تم حذف التشبع للبساطة (يتم استخدام الحد الأقصى). يتم تقليل قيم تدرج الألوان إلى نطاق من 0-255 (بدلاً من المعيار 0-359).
void setHue(uint8_t led_idx, int hue, int brightness) {
هذه الوظيفة مأخوذة من مكتبة Ai_WS8211 ويتم حفظها قليلاً. في الإصدار الأصلي من هذه الوظيفة من المكتبة ، كان هناك بعض الأخطاء التي ظهر بسببها اللون الموجود على أقواس قزح مع الهزات.
دعنا ننتقل إلى تنفيذ الآثار المختلفة. يتم استدعاء كل وظيفة من الحلقة الرئيسية لرسم "إطار" واحد. لأن كل تأثير يعمل مع معلمات مختلفة بين المكالمات ، يتم تخزينها في متغيرات ثابتة.
هذا هو أبسط تأثير - جميع المصابيح مملوءة بلون واحد ، والذي يتغير بسلاسة.
void rainbow() { static uint8_t hue = 0; hue++; for (int led = 0; led < NUM_HW_PIXELS; led++) setHue(led, hue, MAX_VAL); ws2811.sendLedData(); delay(80); }
التأثير التالي أكثر إثارة للاهتمام - يعرض قوس قزح على طول محيط المصفوفة ، وتتحول الألوان الموجودة في قوس قزح تدريجياً في دائرة.
void slidingRainbow() { static uint8_t pos = 0; pos++; for (int led = 0; led < ARRAY_SIZE(circleLEDIndexes); led++) { int hue = (pos + led*256/ARRAY_SIZE(circleLEDIndexes)) % 256; setHue(circleLEDIndexes[led], hue, MAX_VAL); } ws2811.sendLedData(); delay(10); }
وهذا التأثير يملأ المصفوفة بأكملها بلون عشوائي ، يضيء أولاً بسلاسة ، ثم يخرج بسلاسة أيضًا.
void randomColorsFadeInOut() { static uint8_t color = 0; static bool goesUp = false; static uint8_t curLevel = 0; if(curLevel == 0 && !goesUp) { color = rand() % 256; goesUp = true; } if(curLevel == MAX_VAL && goesUp) { goesUp = false; } for(int led = 0; led < NUM_HW_PIXELS; led++) setHue(led, color, curLevel); if(goesUp) curLevel++; else curLevel--; ws2811.sendLedData(); delay(10); }
المجموعة التالية من التأثيرات ترسم إشارات وميض مختلفة. لذلك ، على سبيل المثال ، يحب الطفل بناء جرافة خارج المغناطيس ، وسوف يكون المتعري البرتقالي مفيدًا جدًا هناك.
void orangeBeacon() { const int ORANGE_HUE = 17; static uint8_t pos = 0; pos+=3; for (int led = 0; led < ARRAY_SIZE(circleLEDIndexes); led++) { int brightness = brightnessByPos(pos, led*255/ARRAY_SIZE(circleLEDIndexes), 70); setHue(circleLEDIndexes[led], ORANGE_HUE, brightness); } ws2811.sendLedData(); delay(1); }
من الناحية الفنية ، يبدو التأثير وكأنه نقطة مضيئة تتحرك على طول المصفوفة. ولكن لجعلها تبدو جميلة ، تتلاشى المصابيح المجاورة تدريجياً وأنت تتحرك بعيدًا عن النقطة الرئيسية. لذلك ، كنت بحاجة إلى وظيفة تحسب نفس السطوع.
int brightnessByPos(int pos, int ledPos, int delta) { int diff = abs(pos - ledPos); if(diff > 127) diff = abs(256-diff); int brightness = MAX_VAL - constrain(MAX_VAL*diff/delta, 0, MAX_VAL); return brightness; }
Pos هي موضع شرطي معين لنقطة السطوع المضيئة ، يتم تعيينها على نطاق الاسترجاع من 0-255. ledPos هو موضع مؤشر LED (المعروض على نفس النطاق) الذي تحتاج إلى حساب سطوعه. إذا كان الفرق في الموضع أكبر من الدلتا ، فلن يضيء مؤشر LED ، وكلما اقترب من الموضع ، زاد سطوعه.
أو ، على سبيل المثال ، ضوء أحمر وامض للشرطة
void policeBeacon() { const int RED_HUE = 0; const int BLUE_HUE = 170; static uint8_t pos = 0; pos += 2; for (int led = 0; led < ARRAY_SIZE(policeLEDIndexes); led++) { int ledPos = led*255/ARRAY_SIZE(policeLEDIndexes); int brightness = brightnessByPos(pos, ledPos, 50); setHue(policeLEDIndexes[led], RED_HUE, brightness); if(brightness == 0) { brightness = brightnessByPos((pos+100) % 256, ledPos, 50); setHue(policeLEDIndexes[led], BLUE_HUE, brightness); } } ws2811.sendLedData(); delay(1); }
بما أننا نتحدث عن السيارات ، فإن إشارة المرور هنا ليست مشكلة في التنفيذ.
هذه هي الوظائف التي تشمل إشارات المرور المختلفة في مواقع مختلفة.
void clearPixels() { for(int i=0; i<NUM_HW_PIXELS; i++) { setRgb(i, 0, 0, 0); } } void redTrafficLights() { for(int i=0; i<4; i++) setRgb(i, MAX_VAL, 0, 0); ws2811.sendLedData(); } void yellowTrafficLights() { for(int i=4; i<8; i++) setRgb(i, MAX_VAL, MAX_VAL, 0); ws2811.sendLedData(); } void greenTrafficLights() { for(int i=8; i<16; i++) setRgb(i, 0, MAX_VAL, 0); ws2811.sendLedData(); }
حان الوقت لإحياء ذلك. تعمل إشارة المرور وفقًا لبرنامج خاص محدد في نوع من الرمز الفرعي. تصف اللوحة الوضع والوقت الذي يجب فيه تشغيل هذا الوضع.
enum TRAFFIC_LIGHTS { NONE, RED, YELLOW, GREEN }; struct trafficLightState { uint8_t state; uint16_t duration; }; const trafficLightState trafficLightStates[] = { {NONE, 1},
في الواقع وظيفة أن يعالج كل شيء
void trafficLights() { static uint8_t curStateIdx = 0; static unsigned long curStateTimeStamp = 0;
عند الوصول إلى الفاصل الزمني المحدد ، يتم تشغيل وضع إشارة المرور التالي ويبدأ العد التنازلي مرة أخرى.
التأثير الأخير الذي كان فيه خيالي كافيًا هو العلامات النجمية. 5 مصابيح LED عشوائية تضيء وسطوع عشوائي ، ثم أطفئها بسلاسة. إذا خرج أحد النجوم ، فسيضيء نجم آخر في مكان عشوائي.
void stars() { const uint8_t numleds = 5; static uint8_t ledIndexes[numleds] = {0}; static uint8_t curVal[numleds] = {0}; static uint8_t maxVal[numleds] = {0}; for(int i=0; i<numleds; i++) { if(ledIndexes[i] == 0) { uint8_t led = rand() % (NUM_HW_PIXELS+1); CRGB * leds = ws2811.getRGBData(); if(leds[led].r == 0) { ledIndexes[i] = led; maxVal[i] = rand() % (MAX_VAL-1) + 1; curVal[i] = 0; } } else { uint8_t led = ledIndexes[i]; if(curVal[i] < maxVal[i]) curVal[i]++; else if(curVal[i] == maxVal[i]) maxVal[i] = 0; else if(curVal[i] == 0 || --curVal[i] == 0) ledIndexes[i] = 0; setRgb(led-1, curVal[i], curVal[i], curVal[i]); } } ws2811.sendLedData(); delay(80); }
في مكان ما هنا تسللت حشرة شريرة فيها. في بعض الأحيان تضيء النجوم بحدة ، أو بالعكس تنفجر فجأة. ولكي أكون صادقًا ، كنت كسولًا للغاية لاكتشاف ذلك - يبدو الأمر طبيعيًا جدًا.
حان الوقت للتفكير في توفير البطارية. لقد أعطيت بالفعل قيم الاستهلاك لهذا الشيء كله. إذا كنت لا تفكر في إيقاف تشغيل الطاقة ، فإن مصابيح LED ستأكل البطارية في غضون ساعتين. هذه الوظيفة مسؤولة عن إيقاف تشغيل الطاقة بعد 90 ثانية من عدم النشاط. في البداية ، كان 60 ثانية ، ولكن مع لعبة حقيقية لم يكن هذا كافياً ، و 2 دقيقة كانت طويلة إلى حد ما.
void shutdownOnTimeOut(bool resetTimer = false) { static unsigned long periodStartTime = 0; if(periodStartTime == 0 || resetTimer) { periodStartTime = millis(); return; } if(millis() - periodStartTime >= 90000UL) { periodStartTime = 0; shutDown(); } }
في الواقع خارج السلطة يحدث على النحو التالي.
void shutDown() { clearPixels(); ws2811.sendLedData(); wdt_disable(); digitalWrite(POWER_EN_PIN, LOW);
إذا ضغط المستخدم على الأزرار ، تتم إعادة ضبط المؤقت. بعد مرور الوقت المحدد ، تقوم الوظيفة بتعيين إشارة HOLD على صفر ، وهو أمر PT1502 لإيقاف الطاقة. بالمناسبة ، يجب أيضًا إيقاف تشغيل الوكالة الدولية للطاقة ، وإلا بعد 2 ثانية ستستيقظ على النظام وتقوم بتشغيل الطاقة مرة أخرى.
وأخيرا ، الحلقة الرئيسية التي تبدأ كل شيء
يؤدي الضغط على الزر إلى تبديل الأوضاع وإعادة ضبط مؤقت إيقاف التشغيل التلقائي. اعتمادًا على الوضع الحالي ، يتم تشغيل إحدى وظائف التأثير من قائمة الأوضاع. في كل دورة ، تتم إعادة تعيين الوكالة الدولية للطاقة أيضًا.
إذا كان الطفل ، على سبيل المثال ، يلعب سيارة تابعة للشرطة وبعد 1.5 دقيقة منطفأ ضوء الطوارئ ، فعلى الأرجح بعد الانعطاف الثاني على الابن أن يستمر في لعب سيارة الشرطة. للقيام بذلك ، يتم حفظ الوضع المحدد في EEPROM (يتم تحديد الخلية رقم 10 من الجرافة).
إليك مقطع فيديو يوضح كيفية عمل كل شيء.
محمل الإقلاع
تقريبا كل شيء جاهز. ولكن هناك شيء آخر يحتاج إلى رفع - أداة تحميل التشغيل. الحقيقة هي أن أداة تحميل التشغيل القياسية لا تناسبنا.
أولاً ، عند تشغيل الطاقة ، فإنها تنتظر لمدة تصل إلى 6 ثوان - ربما ستبدأ البرامج الثابتة في التدفق عليها. فقط بعد نقل عنصر التحكم هذا إلى البرامج الثابتة الرئيسية. هذا مناسب في مرحلة التطوير ، ولكنه سيكون مزعجًا في الجهاز النهائي.
وثانيا ، لا يعرف محمل الإقلاع القياسي شيئًا عن شريحة PT1502 ، والتي سيكون من الجميل إعطاء إشارة HOLD. بدون هذه الإشارة ، تعتقد الدائرة الدقيقة أن المتحكم الدقيق إما لم يبدأ ، أو على العكس من ذلك ، يريد إيقافه. وإذا كان الأمر كذلك ، فبعد بضع ميلي ثانية سيقطع PT1502 الطاقة عن الدائرة بأكملها.
الاستفادة من حل كل المشاكل ليست صعبة. يستخدم digispark ATTiny85
محمل الإقلاع الصغير . أداة تحميل التشغيل هذه سهلة بما يكفي لتقديمها لاحتياجاتنا. من الضروري فقط تصحيح التعريفات المقابلة في ملف التكوين.
بادئ ذي بدء ، قمت بنسخ التكوين الثابت \ configuration \ t85_default القياسي إلى الدليل الخاص بي وقمت بالفعل بإجراء جميع التغييرات فيه. لذلك سيكون في هذه الحالة من السهل التراجع إلى محمل الإقلاع الأصلي.
في ملف bootloaderconfig.h ، هناك خيار من طريقة إدخال أداة تحميل التشغيل. من بين ما يتم تقديمه خارج الصندوق ، لا يوجد شيء يناسبنا ، ولكن الخيار الأقرب هو ENTRY_JUMPER. في هذا الخيار ، لا يمكن الوصول إلى محمل الإقلاع إلا في حالة ظهور مستوى معين على دبوس محدد (يتم إغلاق العبور على اللوحة).
#define ENTRYMODE ENTRY_JUMPER
ليس لدينا رابط ، ولكن يوجد زر على سفح PB2. دع محمل الإقلاع يدخل إذا كان الزر مثبتًا لمدة تتراوح بين 5 و 7 ثوان عند تشغيل الطاقة. ولكن إذا تم الضغط عليه وإصداره ، فسيحدث الانتقال إلى البرنامج الثابت الرئيسي على الفور.
نحتاج إلى تحديد 3 وظائف - التهيئة ، وإلغاء التهيئة ، والتحقق فعليًا من أن الوقت قد حان لدخول محمل الإقلاع. في الأصل ، كلها بسيطة وتنفيذها مع وحدات الماكرو. فقط 2 الأولى ستكون بسيطة
#define HOLD_PIN PB1 #define JUMPER_PIN PB2 #define JUMPER_PORT PORTB #define JUMPER_DDR DDRB #define JUMPER_INP PINB #define bootLoaderInit() {JUMPER_DDR &= ~_BV(JUMPER_PIN); JUMPER_DDR |= _BV(HOLD_PIN); JUMPER_PORT &= ~_BV(JUMPER_PIN); JUMPER_PORT |= _BV(HOLD_PIN); _delay_ms(1);} #define bootLoaderExit() {;}
يقوم bootLoaderInit () بتهيئة دبوس الزر (JUMPER_PIN) للإدخال وإيقاف تشغيل جهاز التعليق عليه. لدينا بالفعل سحب على اللوحة ، وعلى الأرض ، وعندما تضغط على زر على الدبوس ، على العكس سيكون هناك زر. في الوقت نفسه ، يمكنك تهيئة إشارة HOLD على الفور لإخراجها وتعيين الوحدة عليها ...
للحصول على شرح لحساب البت ، على سبيل المثال ، اذهب
هنا ، ويمكن الحصول على فهم لسجلات إعداد GPIO في وحدات التحكم AVR ، على سبيل المثال ،
من هنا .
وظيفة bootLoaderExit () فارغة لأن التكوين المكشوف مناسب تمامًا للانتقال اللاحق إلى البرامج الثابتة الرئيسية
إن وظيفة bootLoaderStartCondition () ، المسؤولة عن إدخال محمل الإقلاع بتنسيق الماكرو ، لم تكن مناسبة ، وبالتالي أصبحت وظيفة كاملة
#ifndef __ASSEMBLER__
وظيفة في غضون ثوان قليلة (في الواقع حوالي 6-7) يتحقق حالة الزر. إذا تم إصدار الزر مسبقًا ، فلن نحتاج إلى إدخال أداة تحميل التشغيل. يُسمح للمريض والمستمر بالدخول إلى أداة تحميل التشغيل.
كما اتضح فيما بعد ، فإن ملف bootloaderconfig.h متورط في عملية تجميع ملفات المجمّع ويتسبب الرمز في هذا الملف في حدوث أخطاء. اضطررت إلى وضع الوظيفة في كتلة #ifndef __ASSEMBLER__
هناك معلمة أخرى قمت بتعديلها تخبر محمل الإقلاع بما يجب فعله إذا لم يكن متصلاً بـ USB - الخروج بعد ثانية واحدة. والحقيقة هي أنه خلال فترة الاستراحة ، ضغط الابن على الزر ودخل بطريق الخطأ إلى محمل الإقلاع. لا أعرف مدى معجزة ، لكن إذا لم يشاهد أداة تحميل التشغيل اتصال USB ، فقد يؤدي ذلك إلى الكتابة فوق بعض صفحات الذاكرة عن طريق الخطأ. لذلك ، إذا لم يكن هناك اتصال ، فسنقوم ببساطة بالخروج من البرنامج الرئيسي.
#define AUTO_EXIT_NO_USB_MS 1000
نحن نجمع ... ونحصل على خطأ بأن الشفرة لا تنسجم مع مساحة أداة تحميل التشغيل المخصصة لها. نظرًا لأن ذاكرة الفلاش في وحدة التحكم صغيرة جدًا ، يتم ضغط أداة تحميل الإقلاع إلى الحد الأقصى من أجل ترك مساحة أكبر للبرنامج الرئيسي. ولكن تم إصلاح هذا بسهولة في ملف Makefile.inc باتباع الإرشادات.
ثم قمت فقط بتقليل عنوان بدء أداة تحميل التشغيل إلى صفحة واحدة (64 بايت) ، وبالتالي زيادة مساحة أداة تحميل التشغيل.
خلاف ذلك ، لم يكن تجميع وتحميل أداة تحميل الإقلاع باستخدام مبرمج USBAsp مشكلة.
الخاتمة
لقد كانت طريقة مثيرة للاهتمام للغاية من النموذج الأولي على اللوح إلى الجهاز النهائي. يبدو الأمر وكأنه وميض عادي من درس اردوينو ، لكن في الواقع ، كان عليّ أن أعمل أثناء عملية العمل على حل مجموعة كاملة من المشاكل المثيرة للاهتمام - هنا هي الصراع مع الاستهلاك ، واختيار قاعدة العنصر ، وتصميم الحالة ، ووضع البرنامج الثابت مع أداة تحميل bootloader في الاعتبار. آمل مخلصًا أن تكون تجربتي مفيدة لشخص ما.
يمكن أن يكون أسهل؟ بالطبع يمكنك ذلك. أعتقد أن كل شيء يمكن القيام به باستخدام الترانزستور. لسوء الحظ
، قرأت
هذا المقال بعد أن ألحقت اللوحة. أود أن أرى المقال في وقت سابق - سأفعل كل شيء على نفس الطراز TP4056 الشهير - من الأسهل التلاعب به. على أي حال ، محول DC-DC ، الموجود داخل PT1502 في هذا الجهاز ، للأبد ، ليس مطلوبًا. ومع ذلك ، فإن دراسة عملية حول الدائرة الدقيقة PT1502 مفيدة بالنسبة لي في مشروعي الآخر ، وكذلك القدرة على لحام الدوائر الدقيقة في حزمة QFN20.
أخيرًا ، إليك الروابط إلى مشروعي:
رمز البرنامج الثابتالدائرة والمجلسنموذج الإسكان والناشرنماذج STL جاهزة للطباعة