جهاز لمنع النوم على الظهر والتحكم في وضعية جهاز تحديد وضعية UPSNS-KO



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

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

ولكن لا تتخلص من وحدات التحكم الدقيقة التي تم شراؤها بالفعل ، وأجهزة قياس التسارع والأفكار الرائعة التي تستعبد العقل ، أليس كذلك؟

بالمناسبة ، كان هناك محرضين آخرين. بدءًا من خيار المتشددين:



وتنتهي بتصحيحات الموقف الفاتنة تمامًا ، التي تعلمتها بصراحة بعد رؤيتي.

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

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

بشكل عام ، كسرت ماكينة حلاقة أوكام عندما بدأت في طحن ملامح المنبه في المستقبل. والذي كشف فجأة عن مواهب أخرى محتملة ، وهي: السيطرة على الموقف والتحذير [العوالق المكتبية] من الجمود الطويل. والسبب في توسيع الوظائف أمر شائع - كان من المؤسف أن نرى كيف تختفي الموارد حتى أقوى متحكم ، لكنها لا تزال خطيرة للغاية.

كيف تعمل


كما تعلم ، فإن جهاز Positioner لديه ثلاثة أوضاع للتشغيل:

1) منع النوم على الظهر (جيدًا ، أو في أي وضع آخر ، لا يهمه)
2) التحكم في الوضع
3) تحذير من ضعف الحركة

، وكما لا زلت لا تعرف ، زر واحد فقط ، الذي يؤدي وظيفة إعادة تعيين متحكم.

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

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

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

وبعبارة أخرى ، خمّن القارئ اليقظ بالفعل أن قراءات مقياس التسارع تستخدم لتحديد الوضع ، وما زلت أنتشر عبر الشجرة.

هنا ، يمكنك أن ترى كيف يعمل على مثال نموذج أولي على لوحة توصيل:



كما ترى ، كل شيء بسيط للغاية.

في إصدار نهائي أكثر أو أقل ، يعمل المنبه على النحو التالي:

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

2) في وضع التحكم في الوضع ، يضمن Positioner الحفاظ على الوضع الصحيح لحوالي 60 ٪ من الوقت من فاصل زمني مدته 5 دقائق. خلاف ذلك ، يبدأ في الاهتزاز حتى تعود إلى الوضع الصحيح.

3) في وضع التحذير من الحركة المنخفضة ، يتأكد Positioner من تخصيص 8 ٪ على الأقل من الوقت من فترة 30 دقيقة للحركة. إذا لم يكن الأمر كذلك ، فإنها تنتج مرة واحدة سلسلة من 10 إشارات ، والتي لا تنقطع وتبدأ في العد التنازلي لفاصل زمني جديد.

بالطبع ، يمكن مقاطعة المنبه في أي وضع بالضغط على زر إعادة الضبط.

أما الفترات والإشعارات التي قد تبدو غريبة فقد تابعت ما يلي. دقيقة على الظهر من وجهة نظري طويلة بما فيه الكفاية ، و 8 إشارات دون انقطاع (واحتمال تلقي نفس المبلغ بشكل متكرر) تبدو سببًا كافيًا للاستيقاظ.

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

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

بالطبع ، كل هذه الفترات ليست عقيدة ويمكن تغييرها بسهولة. ستكون رغبة.

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

في الفترات الفاصلة بين تحديد الموقع ، تكون وحدة التحكم في وضع إيقاف التشغيل ، حيث يكون الاستهلاك مشابهًا لوضع السكون الخاص بالموضع - 4 μA. تستيقظ وحدة التحكم بواسطة مؤقت كل 8 ثوانٍ تقريبًا - هذا في نفس الوقت هو أقصى توفير للبطارية ومقبول للتشغيل الصحيح إلى حد ما لجميع الأوضاع.



لسوء الحظ ، لا يمكنني حساب الاستقلالية الكاملة ، لأنني لا أعرف كيف.

كيف يتم ذلك


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

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

1) ATtiny85 متحكم (على سبيل المثال، مثل )
2) التسارع ADXL335 تجميعها (على سبيل المثال، هذا أو مباشرة مع 3.3V امدادات الطاقة)
3) اهتزاز المحرك من الهاتف المحمول (حصلت على الكثير من الإصلاحات لإصلاح)
4) زر (أخذت من جهاز تحكم عن بعد مفكك)
5) 2.2Kohm المقاوم
6) النوع 1N4007 ديود (لدي شيء مثل KD522
7) ترانزستور NPN ، على سبيل المثال 2N2222 (أخذت شيئًا من قرص DVD مكسور)
8) بطارية (CR2032)
9) حالة مناسبة

المخطط على النحو التالي: سرقت



بصدق الجزء المتعلق بتوصيل المحرك في مشروع ELSE مثير للاهتمام .

بالمناسبة ، أوصي بشدة بهذه الصورة الجميلة من Sparkfun بحيث يستحيل عدم الاقتباس منها:



هناك خدعة أخرى. خلاصة القول هي أن هناك إصداران على الأقل من الألواح مع مقياس تسارع ADXL335: 3.3V وحتى 5V. في الواقع ، يتراوح نطاق جهد التشغيل لمقياس التسارع من 1.8 فولت إلى 3.6 فولت ، لذلك تختلف النسخة الثانية عن الأولى من خلال وجود مثبت جهد.

. هنا واحد مع استقرار (صرصور ثلاثي الأرجل على يسار مقياس التسارع). صورة فوتوغرافيةTinydeal


. وهذا بدون مثبت. تصوير هواية للالكترونيات


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


لدي الآن لوحة مزودة بمثبت يعمل على حد سواء من 5V ، وهو ليس مفاجئًا ، ومن 3.3V (راجعت). ولكن بما أنني لا أرى أي سبب لتسخين المثبت ، وبالتالي ، نفقد البطارية دون جدوى ، في النسخة النهائية من الجهاز ، قمت بتوصيل طاقة التسارع مباشرة بنفسي ، متجاوزًا المثبت.

. لتجاوز المثبت ، يمكنك التنقل في كل من اللوحة وعلى ورقة بيانات ADXL335


ربما لا يزال من المنطقي أن نتحدث عن حقيقة أن أجهزة التحكم الدقيقة ATtiny85 مختلفة أيضًا. غالبًا ما تكون الرقائق التي تحمل علامات من نوع ATtiny85-20 وأرخص في المتاجر ، و ATtiny85-10 أقل وأقل تكلفة. من وجهة نظر تصنيع جهاز تحديد المواقع (ووفقًا لورقة البيانات ) ، فإن الاختلاف الأهم هو أن ATtiny85-20 يعمل في نطاق الجهد 2.7V - 5.5V ، و ATtiny85-10 - في النطاق 1.8V - 5.5V. أولئك. والثاني هو أكثر تفضيلاً من وجهة نظر الاستخدام الكامل لسعة البطارية.

والفرق الثاني هو تردد الساعة 20 ميجا هرتز مقابل 10 ميجا هرتز. على الرغم من أن Positioner هذا ، بشكل عام ، غير مهم: فهو يعمل عند 1 MHz ولا يشكو من الحياة. ولكن بما أنني التقطت أول شيء ظهر وأرخص ، فلدي فقط ATtiny85-20.

أخيرًا ، إذا كان الأمر غامضًا بالنسبة إلى شخص ما ، فقد قمت بتوصيل مقياس التسارع بوحدة التحكم لسبب أنه من الأسهل إيقاف تشغيله (مقياس التسارع) في وضع السكون الخاص بالموضع. خلاف ذلك ، سوف نتسرب باستمرار حتى 350 μA (وفقًا لورقة بيانات ADXL335).

قام بتجميع كل شيء مع تركيب مثبت على الحائط ، وربط العناصر بسلك مطلي بالمينا 0.1 مم (مميز بسلك توصيل) ، زوج من الملفات التي أعطاني إياها الصينيون الجيدون مع محطة لحام. والتي لم أكن أعرفها منذ عام ، إلى أين أذهب. اتضح تمامًا: تمزق السلك تمامًا بمكواة لحام 300C مع الصنوبري التقليدي ، وهو ملائم بما يكفي لحام كل من ATtiny85 والترانزستور في حزمة SOT23.

وينتج عن هذا المشهد النفعية إلى حد ما:

. ما هي المكونات - وتعيين. من غير المربح جدًا شراء قطعة واحدة في كل مرة في متجر B & D


الخوارزمية والرمز



الخوارزمية الأساسية لعمل Positioner هي كالتالي:



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

بالنسبة للرمز ، يجب أن أقدم بعض التعليقات.

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

هنا اخترت مرة أخرى أسهل طريقة. وهي - غوغل ما هو مطلوب. الأول هو رمز وضع ATtiny85 في أعمق وضع نوم مع الاستيقاظ من قبل جهاز ضبط الوقت .

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

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

بعد إيقاف تشغيل ADC أثناء وضع السكون ، أصبح مزود الطاقة من Positioner متناغمًا بقدر ما أستطيع جوجل على الإطلاق. أي ، كما كتبت أعلاه ، فإن الحد الأدنى للاستهلاك هو 4 μA ، أثناء الاستيقاظ أثناء القياس - عشرات أو مئات من الميكرامترات ، مع تشغيل المحرك الاهتزازي يمكن أن يتجاوز 2 مللي أمبير.

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

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

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

تم تحميل الرمز إلى ATtiny85 عبر Arduino Mega وفقًا للتعليمات الشائعة. أولئك. تم تنزيل دعم ATtiny لأول مرة لإصداره من بيئة Arduino هنا .

وكالعادة ، قام بتفريغ محتويات الأرشيف (دليل صغير يحتوي على جميع المحتويات) في مجلد الأجهزة في دليل Arduino الخاص به:



ثم انتقلت إلى هذا الدليل ، ووفقًا للتعليمات ، قمت بإنشاء ملف boards.txt الذي نسخت فيه ملفات Prospective Boards.txt من الملف الموجود ما احتاجه - على سبيل المثال وصف ATtiny 1 ميجاهرتز ، وفي حالة 8 ميجاهرتز فقط.

هنا هو boards.txt
attiny85at8.name=ATtiny85 @ 8 MHz  (internal oscillator; BOD disabled)

# The following do NOT work...
# attiny85at8.upload.using=avrispv2
# attiny85at8.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny85at8.upload.using=arduino:arduinoisp
# attiny85at8.upload.protocol=avrispv2
# attiny85at8.upload.using=pololu

attiny85at8.upload.maximum_size=8192

# Default clock (slowly rising power; long delay to clock; 8 MHz internal)
# Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value
# Brown-out detection disabled; [BODLEVEL=111]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

attiny85at8.bootloader.low_fuses=0xE2
attiny85at8.bootloader.high_fuses=0xD7
attiny85at8.bootloader.extended_fuses=0xFF
attiny85at8.bootloader.path=empty
attiny85at8.bootloader.file=empty85at8.hex

attiny85at8.build.mcu=attiny85
attiny85at8.build.f_cpu=8000000L
attiny85at8.build.core=tiny
 
###########################################################################
###########################################################################

attiny85at1.name=ATtiny85 @ 1 MHz  (internal oscillator; BOD disabled)

# The following do NOT work...
# attiny85at1.upload.using=avrispv2
# attiny85at1.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny85at1.upload.using=arduino:arduinoisp
# attiny85at1.upload.protocol=avrispv2
# attiny85at1.upload.using=pololu

attiny85at1.upload.maximum_size=8192

# Default clock (slowly rising power; long delay to clock; 8 MHz internal; divide clock by 8)
# Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value
# Divide clock by 8 internally; [CKDIV8=0]
# Brown-out detection disabled; [BODLEVEL=111]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

attiny85at1.bootloader.low_fuses=0x62
attiny85at1.bootloader.high_fuses=0xD7
attiny85at1.bootloader.extended_fuses=0xFF
attiny85at1.bootloader.path=empty
attiny85at1.bootloader.file=empty85at1.hex

attiny85at1.build.mcu=attiny85
attiny85at1.build.f_cpu=1000000L
attiny85at1.build.core=tiny
 
###########################################################################
###########################################################################



بعد أن بدأت Arduino ، تأكدت من ظهور ATtiny الضروري في قائمة Service - Board: لقد



اتصلت (وبالطبع اخترت اللوحة اليمنى) Arduino Mega 2560 ، كتب رسم Arduino ISP منه من الأمثلة:



ثم قمت بتوصيل ATtiny بـ Mega ، مسترشدًا بـ Mega 2560 pinout والتعليمات من رسم اردوينو ISP:

// pin name:    not-mega:         mega(1280 and 2560)
// slave reset: 10:               53 
// MOSI:        11:               51 
// MISO:        12:               50 
// SCK:         13:               52 


بالطبع ، قمت بتوصيل ATtiny بالطاقة والأرض ، في حالتي تم مشاركة كلا الخطين مع المبرمج ، أي ميجا 2560 ، على الرغم من أننا ندرك جميعًا أن الحد الأدنى الضروري من الإجمالي هو SPI وخطوط إعادة تعيين وخطوط أرضية.

وعندما كان كل شيء جاهزًا ، ثم أولاً (مع عدم نسيان اختيار لوحة ATtiny85) ، كتب محمل التمهيد:



وبعده - في الواقع رسم
// 
// http://donalmorrissey.blogspot.ru/2010/04/sleeping-arduino-part-5-wake-up-via.html
// http://www.technoblogy.com/show?KX0

/* 
 . 			
 - . 		
 - ..		
 - ...		
 - 			    
 ...			 
 --			, 
 .......... 	
 */


#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

volatile int f_wdt=1;

#define xPin A1 //   X
#define yPin A2 //   Y
#define zPin A3 //   Z
#define alPin 0 //   
#define posPowPin 1 //   
#define timeLimit 10000 //    
 #define posCountSleep 9 //      (*8 ) 8
#define posCountMove 231 //      (*8 ) 230
#define posCountBack 41 //      40
#define tresholdSleep 25 //     
#define tresholdMove 25 //    
#define tresholdBack 20 //     
#define movPercentMove 92 //   ( %)   
#define movPercentBack 40 //    ( %)   
#define startTimeOut 5000//         
#define motionTimeOut 1500//        

unsigned long timeOut; //    
byte treshold = 15; //    
int posCounter = 1; //    
byte posMode = 0; //   (  -  = 0;    - 1;  - 2;  - 3)
int posTolerance = 0; //         ( 009b).
int x, y, z, x1, y1, z1; // 
int relX, relY, relZ; //    
int posCount; //     
boolean alarmRaised = false; //  
boolean standBy = false; //    

// http://www.technoblogy.com/show?KX0
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off) 
#define adc_enable()  (ADCSRA |=  (1<<ADEN)) // re-enable ADC

ISR(WDT_vect)
{
  if(f_wdt == 0)
  {
    f_wdt=1;
  }
}

void enterSleep(void)
{
  pinMode(alPin, INPUT);
  pinMode(posPowPin, INPUT);

  adc_disable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  

  sleep_enable();

  sleep_mode();

  sleep_disable(); 

  power_all_enable();
  adc_enable();

  pinMode(alPin, OUTPUT);
  digitalWrite(alPin, LOW);

  pinMode(posPowPin, OUTPUT);
  digitalWrite(posPowPin, LOW);
}


void setup() {

  /*** Setup the WDT ***/

  /* Clear the reset flag. */
  MCUSR &= ~(1<<WDRF);

  /* In order to change WDE or the prescaler, we need to
   * set WDCE (This will allow updates for 4 clock cycles).
   */
  WDTCR |= (1<<WDCE) | (1<<WDE);

  /* set new watchdog timeout prescaler value */
  WDTCR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */

  /* Enable the WD interrupt (note no reset). */
  WDTCR |= _BV(WDIE);

  //   
  pinMode(alPin, OUTPUT);
  digitalWrite(alPin, LOW);

  //   
  pinMode(posPowPin, OUTPUT);
  digitalWrite(posPowPin, LOW);

  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(zPin, INPUT);

  delay(1000); // -
  blinker(500, 1); //   

  if (motionDetect(startTimeOut) == true) {

    getPos(); //  	

    if (abs(x1-y1) > abs(x1-z1)) {
      if (abs(x1-z1) > abs(y1-z1)) {
        selectX(); // x
      } 
      else {
        posMode = 2; // y
        posCount = posCountMove; //   
        treshold = tresholdMove;		
        blinker(1000, 1);
        blinker(500, 2);  
      }
    } 
    else {
      if (abs(x1-y1) > abs(z1-y1)) {
        selectX(); //x
      } 
      else {
        posMode = 1; // z
        posCount = posCountSleep; //    		
        treshold = tresholdSleep;
        blinker(1000, 1);
        blinker(500, 1);    
      }
    }
  }

  if (posMode > 0) {

    getPos(); //  
    x = x1; //  
    y = y1;
    z = z1;
    timeOut = millis();	

    while ((millis() - timeOut) < timeLimit) {
      getPos();
      if (comparePos(x, y, z, x1, y1, z1) == false) { //    -  
        blinker(1000, 1); //    
        x = x1; 
        y = y1; 
        z = z1;
        timeOut = millis();
      }
    }

    //       
    standBy = true;
    blinker(500, 3); //   
  }
  else {
    blinker(1500, 2);
  }	


}

void loop() {

  if(f_wdt == 1) {

    if (posMode == 0) {
      /* Don't forget to clear the flag. */
      f_wdt = 0;

      /* Re-enter sleep mode. */
      enterSleep();
    }
    else {

      getPos();

      if (posCounter <= posCount && alarmRaised == false) { //          
      
      if (posMode == 2) { //    
        if (motionDetect(motionTimeOut) == true) { //      
          posTolerance = posTolerance++; //   
        }

        if ((posCounter - posTolerance) > (posCount*movPercentMove)/100) { //      %   
          alarmRaised = true; //   
        } 

      } else { //   
          if (comparePos(x, y, z, x1, y1, z1) == true) { //    
            posTolerance = posTolerance++; //   ""  (       )
          }
        }
      
        
        if (posMode == 1) { //   
          if (posTolerance >= (posCount - 1)) { //     
            alarmRaised = true; //   
          } 
        }

        if (posMode == 3) { //    
          if ((posCounter - posTolerance) > (posCount*movPercentBack)/100) { //       %   
            alarmRaised = true; //   
          } 
        }

       posCounter++;

      } 
      else { //    

       posCounter = 1; //   
       posTolerance = 0;
       
      }

      if (alarmRaised == true) { //   

        if (posMode == 1) { //   
          blinker(500, 8); // 8  ...
          getPos(); 
          if (comparePos(x, y, z, x1, y1, z1) == false) { // ... 
            alarmRaised = false; //  
            posCounter = 0;
          }
        }

        if (posMode == 2) { //   
          blinker(500, 10); // 10 
          alarmRaised = false; //   
          posCounter = 0;
        } 

        if (posMode == 3) { //   
          blinker(500, 1); //    ...
          getPos();
          if (comparePos(x, y, z, x1, y1, z1) == true) { // ...  
            alarmRaised = false; //   
            posCounter = 0;
          }
        }
        
        posTolerance = 0; //    
      } 
      else {
        /* Don't forget to clear the flag. */
        f_wdt = 0;

        /* Re-enter sleep mode. */
        enterSleep();
      }
    } // posMode == 0
  } // wdt
} // loop

// 

void blinker(unsigned int impulse, byte times) {

  for (byte ttimes = 0; ttimes < times; ttimes++) {

    digitalWrite(alPin, HIGH);
    delay(impulse);
    digitalWrite(alPin, LOW);
    delay(impulse);

  }

}


//     
boolean comparePos(int xOne, int yOne, int zOne, int xTwo, int yTwo, int zTwo) {

  boolean compareRes = false;

  relX = xOne - xTwo;
  relY = yOne - yTwo;
  relZ = zOne - zTwo;

  if (abs(relX) < treshold && abs(relY) < treshold && abs(relZ) < treshold) {
    compareRes = true; //      
  }
  return compareRes;

}

boolean motionDetect(int detectTimeOut) {
 
  boolean motionDetected = false;
  
  getPos();
  x = x1; y = y1; z = z1; //   ,       ,    
  timeOut = millis();
  
  while (((millis() - timeOut) < detectTimeOut)) { //    detectTimeOut ,       
   if (motionDetected == false) { //    
    if (comparePos(x, y, z, x1, y1, z1) == false) { //     
      motionDetected = true; //   
    } 
    else {
      getPos();
    }
   }
  }
  
  return motionDetected;
}

//   
void getPos(){

  digitalWrite(posPowPin, HIGH);
  delay(10);

  byte i;
  unsigned int posX = 0;
  unsigned int posY = 0;
  unsigned int posZ = 0;

  for (i = 0; i < 100; i++) {
    posX = posX + analogRead(xPin);
    posY = posY + analogRead(yPin);
    posZ = posZ + analogRead(zPin);
  }

  x1 = posX/100;
  y1 = posY/100;
  z1 = posZ/100;

  digitalWrite(posPowPin, LOW); 
}

void selectX() {
  posMode = 3;
  posCount = posCountBack; //   		
  treshold = tresholdBack;
  blinker(1000, 1);
  blinker(500, 3);
}






الإسكان


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

ومع ذلك ، تلاشت حماسي قليلاً بعد أن قطعت غطاءًا من البوليسترين المحدد (بسمك 1.5 مم فقط) للتجسد الثاني لـ Eulampia . اتضح أنه صعب - قطع من البوليسترين بسكين واحد فقط من السجاد.

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

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

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

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

. شيء من هذا القبيل في هذه العملية


. وهكذا بعد أن اضطررت إلى تفكيك الجسم الملصق بالفعل


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

بعد أن تم تحريك إطار العلبة بطريقة ما ، قلصت الحواف قليلاً بسكين. وبعد تجربة المكونات ، اكتشفت أن هذا الصلصال # $٪ & * # ليس متصلبًا كما ينبغي فحسب ، بل أيضًا "مقلي" في عملية الخبز. لذلك ، اضطررت إلى توسيع القواطع بعناية. لحسن الحظ ، لم تكن المادة الناتجة حجرًا.

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

. مشهد مفجع




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

بالمناسبة ، لا أوصي بالانكماش الأبيض إذا اتبعت خطوتي: أنيقة ، بالطبع ، لكنها تتسخ بسرعة كبيرة.

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

والبلاستيك في كل مرة يعاد طباعتها. على الرغم من أنني لا أجادل ، إلا أنها ستكون أكثر برودة من نسختي من Redneck 3D-modelling.

الضمان تنويه


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

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

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

خلاف ذلك ، لا فائدة.

أوافق على أنه سيكون من الممكن استخدام وحدة تحكم أخرى ومقياس تسارع آخر ، سيكون من الممكن الحصول على المزيد من C ++ ، والمزيد مع أدمغتي الخاصة و ... لذلك لا أمنع - افعل ذلك ، جربه. أنا متأكد من أنك ستنجح ، أفضل مني.

في الواقع ، لهذا السبب أكتب على Geek ، وليس على Habré. إذا جاز التعبير ، لا المساومة على الأخير ، وهو في الواقع الأول.

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


All Articles