القنفذ - طائر يتحدث [إذا كان مع مشغل MP3]



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

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

ونذهب بعيدا.



لتوضيح ماذا وأين ذهب ، عرض القنفذ في أوضاع مختلفة.

عبارات مسلية أثناء الانتظار:



تبديل القصص ، تشغيل الصوت وإيقافه باستخدام البطاقات والاهتزاز:



الشحن اللاسلكي:



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

لذا ، بعد بحث ومقارنة وجيزة ، تحولت إلى Ebay ، حيث حصلت على ما أريده - لاعبًا مزودًا بشريحة فك JQ6500 ، و 4 ميجابايت من الذاكرة الداخلية وفتحة microSD .



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

الصورة

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

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

لذلك ، أضفنا هنا أبسط مستشعر الاهتزاز SW-18010P وقارئ بطاقات RC522 المعروف.

الصورة

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

الصورة

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

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

لذلك ، بينما كنت أفكر ، في هذه الأثناء أخرجت وحدة تحكم ATmega328p من الأسهم ، وقمت بلصقها على لوحة التوصيل وميض برنامج تحميل Adruino من خلال Arduino Mega 2560.

الصورة

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

تم لحام مثبت 3.3V أيضًا بجواره ، نظرًا لأن RC522 ، بسبب سوء الفهم ، يتم تشغيله بواسطة هذا الجهد ، في حين أن بقية المكونات تشعر بالارتياح على 5V العالمي ، والذي توقعت أن أتناوله من بنك طاقة بسيط على 18650 بطارية.

الصورة

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

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

قد يلاحظ القارئ اليقظ أن المشغل يمكن تشغيله بواسطة دبوس تحكم رقمي ، والذي سيكون جيدًا تمامًا في وضع التشغيل والإيقاف. أرغب في ذلك بنفسي ، ولكن في وضع الاستعداد فقط يستهلك اللاعب 16 مللي أمبير. وعندما تكون الموسيقى ، فإنها تستهلك بسهولة أكثر من 100 مللي أمبير ، وهو بالفعل ضعف سعة ATmega. لذلك ، أخذت "أي" ترانزستور npn بتيار جامع 300 مللي أمبير وأحضره إلى الدبوس الرقمي لوحدة التحكم من خلال المقاوم حوالي 200 أوم.

لكن قارئ البطاقة يستهلك في غضون 40 مللي أمبير ، وبالتالي يمكن توصيل المثبت الذي يغذيه بدبوس التحكم الرقمي. فعل ذلك ، ولكن لا يزال لا يعمل ، والتي حول - في النهاية.

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

بقي تافه ، أي مرآة الروح. وهو أسهل من صنع مصابيح LED المتصلة في سلسلة. لم أتناول اللون الأحمر الوحشي - إنه أمر مخيف للغاية. ولكن العيون ذات اللون الأصفر الكهرماني - هذا كل ما في الأمر.

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

لذلك ، بادئ ذي بدء ، بدأت في البحث عن مرشح أكثر بأسعار معقولة للزراعة. وتم العثور على واحد: القنفذ الساحر إيفلين ، الذي يباع في عالم الأطفال.

الصورة

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



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



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

ويجب أن أقول ، إن القنفذ الذي يخرج من عينه مثقاب هو مشهد جهنمي.

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

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

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

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

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

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

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

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

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

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

في الوقت نفسه ، إذا قمت بتعيين LOW فقط ، فإن LED لقارئ البطاقة "يضيء" تمامًا ، فإن الجهد عند خرج المثبت الذي يزود القارئ بحوالي فولت. إذا كان دخل جهاز التحكم ، عندئذٍ ، يتم إدخال هذا الجهد إلى حوالي 3 فولت.

من المثير للاهتمام أنه إذا قمت أولاً بتعيين دبابيس وحدة التحكم المتصلة بقارئ SS و RST على LOW و INPUT ، ثم وضعت دبوس الطاقة الخاص بوحدة التحكم في نفس الموضع ، يتم إيقاف تشغيل القارئ. وحتى بعد ذلك يتم تشغيله بعد النوم ، إذا تم نقل دبوس الطاقة إلى OUTPUT و HIGH.

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

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

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

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

برنامج العمل
/*  A0 -   MP3 (  )
 *  pin 0, 1 -   ()
 *  pin 2 -   
 *  pin 4 -   MP3 ( )
 *  pin 5 - 
 *  pin 6 -  
 *  pin 7, 8 -  MP3
 *  pin 9 -  
 *  pin 10 -  
 *  pin 11, 12, 13 - SPI 
 */ 


#include <Arduino.h>
#include <SoftwareSerial.h>
#include <JQ6500_Serial.h>
#include <avr/pgmspace.h> //  PROGMEM
#include <SPI.h>
#include <MFRC522.h>
#include <avr/sleep.h>
#include <avr/power.h>

#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off) 
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC

#define RST_PIN 9
#define SS_PIN 10
#define mp3Pin 4
#define mp3Busy A0
#define readerPin 6
#define tonePin 5
#define ledPin 3
#define offDelay 70000 //  
#define winkStep 1500 //   
#define on 150 //  ""
#define off 80 //  ""
#define tOut1 0 //         (x - / x1 -  )
#define tOut11 500
#define tOut2 14000
#define tOut21 15000
#define tOut3 29000
#define tOut31 30000
#define tOut4 44000
#define tOut41 45000
#define tOut5 60000
#define tOut51 65000
#define tShake 2000 //     
#define nShakeQ 10 //     
#define introQ 5 //  -
#define minVol 18 //  
#define midVol  22 //  
#define maxVol 25 //  


unsigned long dimDelay, winkStepDelay, onDelay, ledOffDelay, tShakeDelay;
boolean ledOn, ledOff, eyes, pwm;
int wink;
int pwmVal;

boolean playON = false;
boolean pwmUp = false;
byte pwmStep = 1;


unsigned int playFile;

MFRC522 mfrc522(SS_PIN, RST_PIN);       //  MFRC522
unsigned long uidDec, uidDecTemp; //       
byte bCounter, readBit, nShake, rnd;
byte vol = midVol; //     
unsigned long ticketNumber;
unsigned long offTimeOut = 0; //   
boolean mp3ON = false; //   
boolean isInt = false; //   

byte ticketQ = 32; //     (  -  )
byte fileQ = 0; //  MP3-

//    (  ,    ),         .   ,    
PROGMEM const uint32_t ticketSet[]  = {2515217196, 2540548337, 2490970856, 2486466332, 2485920633, 35870611, 37836807, 37836806, 2377004330, 2522873668, 2514304566, 23472725, 2485702426, 2374853555, 2374391583, 2492957469, 2486467162, 2489280075, 2488031661, 2491726641, 2491720188, 2490968782, 2490968783, 2488900952, 2489969016, 2506562651, 2375447052, 2375449579, 2489276180, 2483389692, 2486466331, 2484789326};

JQ6500_Serial mp3(8,7); //  

void enterSleep()
{
 mp3.playFileNumberInFolderNumber(01, 005); // -
 mp3.playFileNumberInFolderNumber(01, 005); // -
 delay(2500);
 tone(tonePin, 800, 500);
 delay(500); 
 digitalWrite(readerPin, LOW); 
 digitalWrite(mp3Pin, LOW);
 digitalWrite(ledPin, LOW);
 pinMode(ledPin, INPUT);
 pinMode(readerPin, INPUT);
 pinMode(mp3Pin, INPUT);
 
  adc_disable();

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  
  sleep_enable();
  
  sleep_mode();
  
 sleep_disable();
 power_all_enable();

 adc_enable();
 tone(tonePin, 450, 500);
 pinMode(ledPin, OUTPUT);
 pinMode(readerPin, OUTPUT);
 pinMode(mp3Pin, OUTPUT);
 digitalWrite(ledPin, LOW);
 digitalWrite(readerPin, HIGH); 
 digitalWrite(mp3Pin, HIGH);
 SPI.begin();            //  SPI
 mfrc522.PCD_Init();     //  MFRC522
 mp3Init();
 offTimeOut = millis();
 ledOffDelay = millis();
 mp3.playFileNumberInFolderNumber(01, 001); // -
 mp3.playFileNumberInFolderNumber(01, 001); // -
 delay(500);
 playON = false; 
 mp3ON = true;
}

void wakeUp() {
   detachInterrupt(0);
   ledOffDelay = millis();
   if (isInt == false) { //  
    isInt = true;
   }
   attachInterrupt(0, wakeUp, LOW); 
}

void setup() {
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, wakeUp, LOW);
  pinMode(readerPin, OUTPUT);  
  digitalWrite(readerPin, HIGH);
  SPI.begin();            //  SPI
  mfrc522.PCD_Init();     //  MFRC522
  pinMode(mp3Pin, OUTPUT);
  mp3Init();
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  eyes = false;
  ledOn = false;
  ledOff = false;
  dimDelay = millis();
  winkStepDelay = millis();
  wink = 0;
  pwmUp = true; //    
  pwmVal = 0;
  ledOffDelay = millis();
  offTimeOut = millis();  
  mp3.playFileNumberInFolderNumber(01, 001); // -
  mp3.playFileNumberInFolderNumber(01, 001); // -
  delay(500);
  playON = false; 
  mp3ON = true;
}

void loop() {

rnd = random(1, fileQ-1);

if ((millis() - offTimeOut) > offDelay) { //  

     enterSleep();

 } else { 

 ledWink(); //   


 if (isInt == true) {
  
  offTimeOut = millis(); //    -  ,    

  if (nShake == 0) {
    tShakeDelay = millis();
  }
  
  if ((millis() - tShakeDelay) < tShake){
    nShake = nShake + 1;
  } else {
    tShakeDelay = millis();
    nShake = 0;
  }

   isInt = false;
 }

 if (nShake > nShakeQ) {
  playRandom();
  nShake = 0;
 }

//    

playPreset(); //     


//   
  if (mp3ON == true) {
   
   if (playON == true) { //  ,   
    offTimeOut = millis(); //   
   }

   nShake = 0;

   eyesPWM(); //  
   

    //  MP3
    if(analogRead(mp3Busy) < 250) { //    -  ,  
     mp3ON = false; 
     playON = false;
     digitalWrite(ledPin, LOW);
    }
  }
  
 scanPlay(); //   
 
 }
}


void setBitsForGood(byte daBeat) {


  
        if (daBeat == 1) {
                bitSet(ticketNumber, bCounter);
                bCounter=bCounter+1;
                }
        else {
                bitClear(ticketNumber, bCounter);
                bCounter=bCounter+1;
        }
}

//    MP3
void mp3Init() {
  digitalWrite(mp3Pin, HIGH);
  delay(100);
  mp3.begin(9600);
  mp3.reset();
  mp3.setVolume(vol);
  mp3.setLoopMode(MP3_LOOP_NONE);

  fileQ = mp3.countFiles(MP3_SRC_SDCARD); //    
  fileQ = fileQ - introQ; //  

}


//   
void playRandom() {
   tone(tonePin, 450, 500);
   delay(500);  
   playFile = rnd;
   mp3ON = true;
   playON = true;
   mp3.playFileByIndexNumber(playFile);
   mp3.playFileByIndexNumber(playFile);
   mp3.playFileByIndexNumber(playFile);  
   delay(500);
}

// 
void ledWink() {

 //     
if ((millis() - winkStepDelay) > winkStep) { //  

// 
  if (eyes == true) { //   

    if (ledOn == false) {
      onDelay = millis(); //  
        ledOn = true; //  ,   
    }
 
    if ((millis() - onDelay) > on) { //   
      digitalWrite(ledPin, LOW); //   
      eyes = false; //   
    }

  }

// 
  if (eyes == false) { //   
    
    if (ledOff == false) {
      ledOffDelay = millis(); //  
        ledOff = true; //  ,   
    }

    if ((millis() - ledOffDelay) > off) { //   
      digitalWrite(ledPin, HIGH); //  
      eyes = true; //   
    }
  }

  if (ledOn == true && ledOff == true) { //    (  /)
    wink = wink+1;
    ledOn = false;
    ledOff = false;    
  }

  if (wink == 4) { //   /
     winkStepDelay = millis();
     wink = 0;
 }

 }

}

//     
void playPreset() {

 if (mp3ON == false) {
  
  if ((millis() - offTimeOut) > tOut2 && (millis() - offTimeOut) < tOut21) {
    mp3.playFileNumberInFolderNumber(01, 002); //   /001/002.mp3      tOut21 .
    mp3ON = true; 
    delay(500);
  }

  if ((millis() - offTimeOut) > tOut3 && (millis() - offTimeOut) < tOut31) {
    mp3.playFileNumberInFolderNumber(01, 003); //   /001/003.mp3      tOut31 .
    mp3ON = true;
    delay(500);
   }  

  if ((millis() - offTimeOut) > tOut4 && (millis() - offTimeOut) < tOut41) {
    mp3.playFileNumberInFolderNumber(01, 004); //   /001/004.mp3      tOut41 .
    mp3ON = true;  
    delay(500); 
  }    

    
 }
  
}


// 
void eyesPWM(){

 if ((millis() - winkStepDelay) > (pwmStep)/4) {
   //     MP3 
    if (pwmUp == true) {
      if (pwmVal < 128) { //   254 -    (    255,      )
        analogWrite(ledPin, pwmVal);
        pwmVal = pwmVal + 1;
        pwmStep = pwmStep - 1;
        winkStepDelay = millis();
      } else {
            pwmUp = false;
            pwmStep = 1;
            pwmVal = 128;
      } 
    }
    
    if (pwmUp == false) {
      if (pwmVal > pwmStep) {
        analogWrite(ledPin, pwmVal);
        pwmVal = pwmVal - 1;
        pwmStep = pwmStep +1 ;
        winkStepDelay = millis();
      } else {
            pwmUp = true;
            pwmStep = 128;
            pwmVal = 1;
      } 
    }
    }
  
}

//   
void scanPlay() {

 if (fileQ > 0) {
          //   
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
                return;
        }

        //  
        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        uidDec = 0;

//   ,   

        byte status;
        byte byteCount;
        byte buffer[18]; //   (16  + 2   ) 
        byte pages[2]={4, 8}; //   
        byte pageByte; //   
        
        byteCount = sizeof(buffer);
        byte bCount=0;
                

        mfrc522.MIFARE_Read(4, buffer, &byteCount);
        
          
                                bCounter = 0; // 32-   
                                
                                //  0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[6], (bCount+4));
                                        setBitsForGood(readBit);
                                }

                                //  4 - 27
                                for (pageByte=5; pageByte > 2; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }

                                //  28-31
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[2], bCount);
                                        setBitsForGood(readBit);
                                }

                               for (byte ticketNum = 0; ticketNum < ticketQ; ticketNum++) {
                                unsigned long ticketTemp = pgm_read_dword_near(ticketSet + ticketNum);
                                if (ticketTemp == ticketNumber) {
                                  tone(tonePin, 450, 500);
                                  delay(500); 
                                  if (ticketNum < (ticketQ - 2)) {
                                    if ((ticketNum+1) < fileQ) {
                                      digitalWrite(ledPin, HIGH);
                                       playFile = ticketNum+1;
                                      mp3ON = true;
                                      playON = true;
                                      mp3.playFileByIndexNumber(playFile);
                                      mp3.playFileByIndexNumber(playFile);
                                      mp3.playFileByIndexNumber(playFile);
                                      delay(500);
                                      }
                                      return;
                                  } else {
                                    if (ticketNum == ticketQ-1) {
                                      enterSleep(); // 
                                    }
                                    if (ticketNum == ticketQ-2) {
                                      setVol(); //  
                                    }
                                  }
                                  
                                }
                               }
                        // }
                
        // Halt PICC
    mfrc522.PICC_HaltA();    


  }
  
}

//    
void setVol() {

  switch (vol) {
    case maxVol:
      vol = minVol;
      break;
    case midVol:
      vol = maxVol;
      break;
    case minVol:
      vol = midVol;
      break;
  } 

  mp3.setVolume(vol);
  
}




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





هنا:

  • U1 = ATmega328p
  • UHT7333 = HT7333
  • C1 = 0,1
  • R2 = ~50
  • R3 = 220
  • R4 = 1
  • M1 =
  • R4 = 1
  • SP1 = 8
  • Piezo =
  • T1 = NPN- 0,3
  • U2 = JQ6500 : 1 — TX, 2 — RX, 3 — GND, 4 — VCC, 5 — BUSY, 6 — SPK+, 7 — SPK -


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



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

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

  • اللاعب: 8.9
  • ATmega328p: 1.1
  • مجلس التنمية: 0.28
  • القارئ RC522: 2.21
  • رأس ديناميكي: 0.99
  • باعث Piezoceramic: 0.77
  • المصابيح: 0.12
  • الترانزستور: 0.14
  • موازن: 0.13
  • مستشعر الاهتزاز: 0.13
  • صحن الصابون: 0.99
  • بنك الطاقة: 0.75
  • 18650 بطارية: 3.9
  • محول شحن Qi: 1.65
  • بطاقة الذاكرة: 3
  • القنفذ إيفلين: 6


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

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

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

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


All Articles