نظام التحكم التلقائي في حوض السمك في اردوينو

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



فكرة إنشاء حوض مائي


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

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

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

التعرف على الإلكترونيات الدقيقة


لقد بدأت رحلتي مع مجموعة جاهزة لتعلم Arduino. على الأرجح ، جمع الجميع شيئًا مشابهًا عندما تعرّف على هذه المنصة:



مصباح كهربائي عادي (LED) ، مقاوم 220 أوم. يتحكم أردوينو في اللمبة باستخدام خوارزمية C ++. قم بالحجز على الفور بعد شراء أي مجموعة جاهزة من Arduino أو نظيرتها ، فمن المستحيل تجميع شيء مفيد إلى حد ما. حسنًا ، باستثناء مكبر الصوت أو ، على سبيل المثال ، ميزان حرارة منزلي. من الممكن تعلم المنصة نفسها من خلال الدروس ، ولكن ليس أكثر. لأشياء مفيدة ، كان علي أن أتعلم اللحام ولوحات الدوائر المطبوعة وتصميم لوحات الدوائر المطبوعة والمسرات الإلكترونية الأخرى.

بناء النموذج الأولي الخاص بك حوض السمك


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

يجب على الحوض:

  1. , , ;
  2. , , ( ) ;
  3. ( ) ;
  4. , , ;
  5. « »
  6. ;
  7. . , 9:00 AM;
  8. , ;
  9. .
  10. يجب إبراز الشاشة التي بها تاريخ الضغط على الزر الموجود على جهاز التحكم عن بعد. إذا لم يتم الضغط على أي شيء في غضون 5 ثوانٍ ، فاخرج.

قررت البدء باستكشاف تشغيل شاشة LCD و Arduino.

قم بإنشاء القائمة الرئيسية. عملية LCD


بالنسبة لشاشات الكريستال السائل ، قررت استخدام مكتبة LiquidCrystal. من قبيل الصدفة ، بالإضافة إلى Arduino ، كان لدي أيضًا شاشة LCD في حقيبتي. يمكنه إخراج النص والأرقام. كان ذلك كافيًا ، وبدأت في دراسة اتصال هذه الشاشة بـ Arduino. أخذت معلومات الاتصال الأساسية من هنا . هناك أيضًا أمثلة على رمز إخراج "Hello World".

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

  1. معلومات اساسية؛
  2. تحديد الوقت ؛
  3. إعداد التاريخ
  4. درجة الحرارة؛
  5. مناخ؛
  6. الإضاءة الخلفية
  7. الأجهزة

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

في الواقع ، تم كتابة الفئة الأساسية في C ++ ، والتي سيتم وراثتها جميع القوائم الفرعية الأخرى.

 class qQuariumMode
{
protected:
	LiquidCrystal* LcdLink;
public:

	//    ,   bool  isLcdUpdated.
	bool isLcdUpdated = false;
    
	//     .
	void exit();
	
	//  loop      . ,      
	//   .        .
	virtual void loop();

	// ,    virtual,      
	// . 
	virtual void OkClick();
	virtual void CancelClick();
	virtual void LeftClick();
	virtual void RightClick();
};

على سبيل المثال ، بالنسبة لقائمة "الأجهزة" ، سيبدو تنفيذ الفئة الأساسية qQuariumMode كما يلي:

#include "qQuariumMode.h"
class qQuariumDevicesMode :
	public qQuariumMode
{
private:

	int deviceCategoryLastIndex = 4;
	
	//    
	enum DeviceCategory
	{
		MainLight, //   
		Aeration, //  
		Compressor, //  
		Vulcanius, //  
		Pump //  
	};
	
	DeviceCategory CurrentDeviceCategory = MainLight;

	char* headerDeviceCategoryText = NULL;

	//   "",      
	BaseOnOfDeviceHelper* GetDeviceHelper();

public:
	void loop();
	void OkClick();
	void CancelClick();
	void LeftClick();
	void RightClick();
};

إليكم نتيجة تنفيذ المستوى الأول من القائمة:



جزء الأجهزة. الفروق الدقيقة في توصيل المكونات


أريد أن أقول بضع كلمات حول أجهزة وحدة تحكم الحوض. للتشغيل العادي لوحدة التحكم ، اضطررت إلى شراء:

  1. 1 × اردوينو أونو / ميجا. في وقت لاحق قرر العمل مع Mego.
  2. 1 × ساعة الوقت الحقيقي ، على سبيل المثال DS1307 ؛
  3. 2 x RTD14005, , .. 220 ;
  4. 1 x ;
  5. 1 x ;
  6. 5 x IRF-530 MOSFET N . (3 RGB , 1 , 1 );
  7. 1 x RGB . , . ;
  8. 1 x White ;
  9. 1 x LCD ;
  10. 1 x . DS18B20;
  11. 1 x . DHT11;

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

تلف المكونات


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

شريط RGB LED


نشأت صعوبات خاصة مع شرائط LED. حاولت تنفيذ المخطط التالي:



عند الاتصال بـ Arduino ، استخدمت الدبابيس التي تدعم PWM (تعديل عرض النبض). أثناء تشغيل الجهد الأقصى لجميع دبابيس 3 في نفس الوقت ، كان الشريط الخاص بي ساخنًا جدًا. ونتيجة لذلك ، إذا تركتها لمدة ساعة أو ساعتين ، فقد توقفت بعض المصابيح عن التوهج. أعتقد أن هذا كان بسبب فشل بعض المقاومات. عيب آخر لهذا المخطط هو السطوع المختلف لشريط LED لكل لون. على سبيل المثال ، إذا وضعت الحد الأقصى للجهد على المكون الأحمر للشريط ، فإنني أحصل على السطوع المشروط للشريط الأحمر عند 255 وحدة. إذا قمت بتشغيل كل من المكونين الأحمر والأزرق بالجهد الأقصى ، فسيكون السطوع مساويًا لـ 255 + 255 = 510 وحدة ، وسيكون اللون أرجوانيًا. بشكل عام ، هذا الحل لم يناسبني.

تقرر تطبيق الخوارزمية التالية:

void LedRgbHelper::Show(RGBColorHelper colorToShow)
{	
	// RGBColorHelper         . 
	//  ,     
	int sumColorParts = colorToShow.RedPart + colorToShow.GreenPart + colorToShow.BluePart;

	//      
	float rK = 0;
	float gK = 0;
	float bK = 0;

	if (sumColorParts != 0)
	{
		float redPartAsFloat = (float)colorToShow.RedPart;
		float greenPartAsFloat = (float)colorToShow.GreenPart;
		float bluePartAsFloat = (float)colorToShow.BluePart;

		float sumColorPartsAsFloat = (float)sumColorParts;

		int brightness = colorToShow.Brightness;
		

		//       .
		rK = redPartAsFloat / sumColorPartsAsFloat;
		gK = greenPartAsFloat / sumColorPartsAsFloat;
		bK = bluePartAsFloat / sumColorPartsAsFloat;
		
		//      
		rK = rK*brightness;
		gK = gK*brightness;
		bK = bK*brightness;
	}
		
	uint8_t totalCParts = (uint8_t)rK + (uint8_t)gK + (uint8_t)bK;
	
	if (totalCParts <= 255){
		//      .        255 .
		analogWrite(RedPinNum, (uint8_t)rK);
		analogWrite(GreenPinNum, (uint8_t)gK);
		analogWrite(BluePinNum, (uint8_t)bK);
	}	
}

في هذا النموذج ، كان للون الأحمر واللون البنفسجي نفس السطوع. أولئك. توهج أضواء LED الحمراء في الحالة الأولى بسطوع 255 وحدة ، ولون بنفسجي ، كان الأحمر بسطوع 127 وحدة وأزرق بسطوع 127 وحدة ، وهو في النهاية يساوي تقريبًا 255 وحدة:



شريط إضاءة LED أبيض


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

لتطبيق هذه الفكرة ، قمت بتطبيق خوارزمية خطية لتغيير سطوع شريط LED أبيض.

void MainLightHelper::HandleState()
{
	if (!IsFadeWasComplete)
	{
		unsigned long currentMillis = millis();
		if (currentMillis - previousMillis > 50) {
			previousMillis = currentMillis;

			switch (CurrentLevel)
			{
			case MainLightHelper::Off:
			{
				//    ,          .
				if (currentBright != 0)
				{
					if (currentBright > 0)
					{
						currentBright--;
					}
					else
					{
						currentBright++;
					}
				}
				else
				{
					//    ,     .
					currentBright = 0;
					IsFadeWasComplete = true;
				}
				break;
			}
			case MainLightHelper::Low:
			case MainLightHelper::Medium:
			case MainLightHelper::High:
			{
				//      ,         
				if (currentBright != CurrentLevel)
				{
					if (currentBright > CurrentLevel)
					{
						currentBright--;
					}
					else
					{
						currentBright++;
					}
				}
				else
				{
					currentBright = CurrentLevel;
					IsFadeWasComplete = true;
				}
			}
			break;
			}
			
			//         .
			analogWrite(PinNum, currentBright);
		}
	}
}

تموج "بركان"


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



يأتي مع محول ، خرجه 12V DC ، والمدخلات 220V AC. لم أكن بحاجة إلى محول ، لأنني طبقت قوة البركان وسطوعه من خلال Arduino.

تم تنفيذ نبض البركان على النحو التالي:

long time = 0;
int periode = 10000;

void VulcanusHelper::HandleState()
{
	if (IsActive){
		// time -  cos     . 
		//   -       
		time = millis();
		int value = 160 + 95 * cos(2 * PI / periode*time);

		analogWrite(PinNum, value);
	}
	else
	{
		analogWrite(PinNum, 0);
	}
}

يضيء البركان الحوض بشكل مثالي في المساء ، وتبدو التموج نفسها جميلة جدًا:



مضخة مياه. استبدال مياه الحوض


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


اختبرت المضخة عند الحامل:



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

منفذ الأشعة تحت الحمراء والرغبة في استبداله


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

void ButtonHandler::Learn(IRrecv* irrecvLink, LiquidCrystal* lcdLink)
{
	//      
	irrecvLink->enableIRIn();
	
	//       
	decode_results irDecodeResults;
	...
	...
		while (true) {
		//       
		if (irrecvLink->decode(&irDecodeResults)) {
						
			//   
			irrecvLink->resume();

			//     .
			if (irDecodeResults.bits >= 16 && 
				irDecodeResults.value != 0xC53A9966// fix for Pioneer DVD
				) {
			
				lcdLink->setCursor(0, 1);
				//        HEX
				lcdLink->print(irDecodeResults.value, HEX);
				
				//     Arduino  
				irRemoteButtonId = irDecodeResults.value;
				
				...
				...

في وقت لاحق توصلت إلى استنتاج مفاده أن جهاز التحكم عن بعد غير مريح. فقط لأنك تحتاج إلى البحث عنه وهذا جهاز إضافي في المنزل. من الأفضل تنفيذ التحكم من خلال الهاتف المحمول أو الكمبيوتر اللوحي. كانت لدي فكرة لاستخدام الكمبيوتر الصغير Raspberry PI لرفع تطبيق الويب ASP.NET MVC 5 عليه من خلال Mono و NancyFX. بعد ذلك ، استخدم إطار عمل jquery mobile لتطبيقات الويب عبر الأنظمة الأساسية. من خلال Raspberry ، تواصل مع Arduino عبر WiFi ، أو LAN. في هذه الحالة ، يمكنك حتى التخلي عن شاشة LCD ، لأنه يمكن عرض جميع المعلومات الضرورية على الهاتف الذكي أو الكمبيوتر اللوحي. لكن هذا المشروع في رأسي فقط.

لوحة الدوائر المطبوعة وتصنيعها


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

التجميع على لوحات الدوائر (التي يستخدمها Arduino Uno):



لقد طورت ثنائي الفينيل متعدد الكلور أحادي الطبقة في برنامج Fritzing. اتضح ما يلي (باستخدام Arduino Mega):



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

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



كان التجميع نفسه بسيطًا أيضًا - كان يكفي لحام المكونات الرئيسية للوحة: على



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

استنتاج


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

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


All Articles