LED مكعب + ثعبان

مقدمة


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

الصورة

تحضير


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

قم بإنشاء مكعب LED الخاص بك


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

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

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

الصورة

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

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

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

الصورة

الصورة

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

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

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

الصورة

الصورة

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

بعد القيام بكل هذه الإجراءات ، ستحصل على مكعب LED الذي جمعته وعدد قليل من الأصابع المحروقة ، ولكن هذا يعتمد بالفعل على دقتك.

الصورة

الصورة

تصميم الدوائر


لتنفيذ أفكارنا ، كنا بحاجة إلى نوع من وحدة التحكم الدقيقة. قررنا البقاء على متحكم اردوينو ليوناردو. لم نرغب في الإزعاج من المبرمجين والبرامج الضرورية ، ولكننا لا نحتاج إلى معالج قوي لمهامنا. بعد الانتهاء من الجهاز ، أدركنا أنه من الممكن استخدام Nano ، ولكن هذا ليس بالغ الأهمية. للتحكم في المكعب ، قررنا استخدام هاتف متصل بـ Arduino عبر Bluetooth ، وفي حالتنا يتم استخدام HC-05 ، ولكن يمكنك استخدام أي هاتف آخر.

الصورة

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

الصورة

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

الصورة

الصورة

ضع المكعب معًا


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

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

الصورة

قرروا تجميع النموذج الأولي على التخطيط المستخدم في اللحام.

الصورة

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

الصورة

يجب ألا يكون هناك ضوء!


هناك مكعب ، يبقى لجعله يتوهج. بعد ذلك ، سيتم وصف أوضاع (أوضاع) المكعب المختلفة ، للتبديل بين البلوتوث + Android الذي تم استخدامه. تمت كتابة تطبيق الهاتف باستخدام Cordova. لن يتم وصف رمز التطبيق هنا ، ولكن يتم عرض رابط المستودع في الخاتمة.

خوارزمية المكعب


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

الخوارزمية هي كما يلي:

  1. الطبقة الحالية هي 0.
  2. تسجيل القناع للطبقة الحالية
  3. أغلق الترانزستور للطبقة السابقة. إذا كانت الطبقة الحالية صفرًا ، فإن الطبقة السابقة هي الطبقة السابعة
  4. نضغط القيم في السجلات. تظهر القيمة على مخرجات السجلات
  5. افتح الترانزستور للطبقة الحالية. مرحى ، طبقة واحدة تتوهج!
  6. الطبقة الحالية ++. اذهب: 2

في المجموع ، تتكرر هذه الخوارزمية بسرعة كبيرة ، مما يعطينا الوهم بأن جميع مصابيح LED مضاءة في وقت واحد (لكننا نعلم أن هذا ليس كذلك). يتم تخزين الأقنعة في صفيف 64 × 8 بايت.

تعديل الكتابة

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

أشعل المكعب
void Mode_2_Init() {
	for (byte z = 0; z < CUBE_EDGE_SIZE; z++) {
		for (byte y = 0; y < CUBE_EDGE_SIZE; y++) {
			for (byte x = 0; x < CUBE_EDGE_SIZE; x++) {
				cube->data[z * CUBE_LEVEL_SIZE + y * CUBE_EDGE_SIZE + x] = 1;
			}
		}
	}
}


وزارة الدفاع "لزجة"

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

رمز ثابت
void Mode_0() {
	byte positionToMove = random(CUBE_LEVEL_SIZE);
	byte fromLevel = cube->data[positionToMove] == 1 ? 0 : 7;
	bool top = fromLevel == 0;
	cube->ShowDataXTimes(5);
	while (true) {
		byte toLevel = top ? fromLevel + 1 : fromLevel - 1;
		if (toLevel >= CUBE_EDGE_SIZE || toLevel < 0) break;
		cube->data[fromLevel * CUBE_LEVEL_SIZE + positionToMove] = 0;
		cube->data[toLevel * CUBE_LEVEL_SIZE + positionToMove] = 1;
		cube->ShowDataXTimes(2);
		fromLevel = toLevel;
	}
}

void Mode_0_Init() {
	cube->Clear();
	for (byte i = 0; i < CUBE_LEVEL_SIZE; i++) {
		byte value = random(0, 2);  // max - 1
		cube->data[i] = value;  //first level
		cube->data[i + (CUBE_EDGE_SIZE - 1) * CUBE_LEVEL_SIZE] = !value;  //last level
	}
}


كيف تبدو في الحياة:



"تعديل آخر لزجة"

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

رمز لزجة آخر
void Mode_3_Init() {
	cube->Clear();
	positions->clear();
	new_positions->clear();
	mode_3_direction = NORMAL;
	for (short y = 0; y < CUBE_LEVEL_SIZE * CUBE_EDGE_SIZE; y += CUBE_LEVEL_SIZE) {
		for (byte x = 0; x < CUBE_EDGE_SIZE; x++) {
			cube->data[x + y] = 1;
			positions->push_back(x + y);
		}		
	}
}

void Mode_3() {
	if (positions->size() == 0) {
		delete positions;
		positions = new_positions;
		new_positions = new SimpleList<short>();
		mode_3_direction = mode_3_direction == NORMAL ? INVERSE : NORMAL;
	}
	byte item = random(0, positions->size());
	short position = *((*positions)[item]);
	positions->erase(positions->begin() + item);
	byte i = 1;
	while(i++ < CUBE_EDGE_SIZE ) {
		cube->data[position] = 0;
		if(mode_3_direction == NORMAL) position += CUBE_EDGE_SIZE;
		else position -= CUBE_EDGE_SIZE;
		cube->data[position] = 1;
		cube->ShowDataXTimes(1);
	}
	new_positions->push_back(position);
}




مكعب داخل مكعب

فكرة: تضيء مصابيح LED داخل المكعب على شكل وجوه مكعبات بأحجام من 1 إلى 8 مصابيح LED والعكس صحيح.

مكعب داخل مكعب
void Mode_1() {
	cube->Clear();
	for (byte cube_size = 0; cube_size < CUBE_EDGE_SIZE; cube_size++) {
		for (byte level = 0; level <= cube_size; level++) {
			for (byte x = 0; x <= cube_size; x++) {
				for (byte y = 0; y <= cube_size; y ++) {
					cube->data[level * CUBE_LEVEL_SIZE + y * CUBE_EDGE_SIZE + x] =
						(y % cube_size == 0 || x % cube_size == 0)
						&& level % cube_size == 0 ||
						(y % cube_size == 0) && (x % cube_size == 0) ? 1 : 0;
				}
			}
		}
		cube->ShowDataXTimes(5);
	}
	for (byte cube_size = CUBE_EDGE_SIZE - 1; cube_size > 0; cube_size--) {
		for (byte level = 0; level <= cube_size; level++) {
			for (byte x = 0; x <= cube_size; x++) {
				for (byte y = 0; y <= cube_size; y++) {
					cube->data[level * CUBE_LEVEL_SIZE + (CUBE_EDGE_SIZE - 1 - y) * CUBE_EDGE_SIZE + (CUBE_EDGE_SIZE - 1 - x)] =
						(((y % (cube_size - 1) == 0 || x % (cube_size - 1) == 0) && (level % (cube_size - 1) == 0))
						|| ((y % (cube_size - 1) == 0) && (x % (cube_size - 1) == 0) && level % cube_size != 0))
						&& x < (cube_size) && y < (cube_size) ? 1 : 0;
				}
			}
		}
		cube->ShowDataXTimes(5);
	}
}


كيف تبدو:



وأخيرا الأفعى

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

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

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

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

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

كود التوجيه
void Snake::ApplyUp() {
	switch (direction) {
	case X:
	case Y:
		direction = Z;
		directionType = NORMAL;
		break;
	case Z:
		direction = X;
		directionType = INVERSE;
	}
}

void Snake::ApplyDown() {
	switch (direction) {
	case X:
	case Y:
		direction = Z;
		directionType = INVERSE;
		break;
	case Z:
		direction = X;
		directionType = NORMAL;
	}
}

void Snake::ApplyLeft() {
	switch (direction) {
	case X:
		direction = Y;
		directionType = directionType == NORMAL ? INVERSE : NORMAL;
		break;
	case Y:
		direction = X;
		directionType = directionType;
		break;
	
	case Z:
		direction = Y;
		directionType = NORMAL;
	}
}

void Snake::ApplyRight() {
	switch (direction) {
	case X:
		direction = Y;
		directionType = directionType;
		break;
	case Y:
		direction = X;
		directionType = directionType == NORMAL ? INVERSE : NORMAL;
		break;
	case Z:
		direction = Y;
		directionType = INVERSE;
	}
}

void Snake::ChangeDirection(KEY key) {
	switch(key) {
	case UP:
		ApplyUp();
		break;
	case LEFT:
		ApplyLeft();
		break;
	case RIGHT:
		ApplyRight();
		break;
	case DOWN:
		ApplyDown();
		break;
	}
}


نتيجة البرنامج:





روابط إلى الكود المصدر للبرنامج الثابت والتطبيق الخاص بالهاتف: البرنامج الثابت

للتطبيق


النتيجة


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

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


All Articles