چراغ راهنمایی یکی از چیزهایی است که به نظر میرسد یکی از وسایل روزمره زندگی ما شده است. هر جایی که به میزان متوسطی اتومبیل وجود داشته باشد احتمالا باید یکی از این چراغهای راهنمایی هم وجود داشته باشد. چراغ های راهنمایی مدرن از نظر ساختمان داخلی بسیار پیچیده هستند و از همه نوع سنسور ، تایمر و حتی از سیستم مانیتورینگ ترافیک که برای نظارت بر کنترل نرخ ترافیک استفاده میشود بهره برده است.
ما الان قصد ساخت یک چراغ راهنمایی واقعی را نداریم اما میخواهیم عملکرد آن را با آردواینو شبیهسازی کنیم. انجام دادن این کار یک راه عالی جهت کار کردن راحتتر با آردواینو وآشنایی با مهمترین دستورات رایج آن است. همچنین اینکار میتواند به ما در حل یک مسئله کمک کند. نتیجه آنکه ، این پروژه به ما کمک میکند که عملکرد پایه ای یک چراغ راهنمایی را بفهمیم.
-سخت افزار لازم:
-نرم افزار لازم
تئوری:
ایده اولیه و پایهای چراغهای راهنمایی ، کنترل نرخ ترافیک است. همانطور که قبلا گفته شد، چراغ های مدرن ترافیک امروزی امکان نظارت و مانیتورینگ ترافیک را دارند. عوض شدن مدت دوره ای چراغ ها وابسته به درخواست عابران پیاده برای عبور از خیابان و یا افزایش ترافیک در خیابان و …. است.
در این پروژه، ما تقاطع یک چهارراه را بر اساس فواصل زمانی ثابت برای هر چراغ پیادهسازی میکنیم. چراغ ما هیچ فیدبکی ندارد و خیلی ساده بدون اینکه به حجم ترافیک نگاه کند کار میکند. حتی اگر چراغها هوشمند نباشند ما میتوانیم به طور هوشمندانه ای این سیستم را پیادهسازی نماییم. شاید مقداری پول باید برای اینکار ذخیره نماییم!
برای مثال ، ما یک چهار راه داریم که از دو خیابان یک طرفه (الف) و (ب) ایجاد شده است. با توجه به تجربه پلیس محله ، خیابان (الف) از (ب) شلوغتر است. از آنجایی که ما از جریان ترافیکی تقاطع اطلاع داریم، یک تایمر ساده برای اینکار مناسب است. (فرض بر این است که)اضافه کردن هر ویژگی دیگهای در اینجا سبب اتلاف هزینه است که شهر توان پرداخت آن را ندارد!
چیزی که ما جهت شبیهسازی احتیاج داریم این است که چراغهای راهنماییمان را معرفی کنیم که اینکار با LED ها ممکن است. عملیات کنترل و منطقی و باقی کارها را آردواینو انجام میدهد. آردواینو به عنوان کنترل و تایمر هوشمند به ما کمک میکند. به این معنی که آردواینو هر چراغی را روشن و خاموش میکند و مدت زمان روشن بودن هر چراغ را نیز شمارش میکند.
-توالی حلقه چراغها:
یک چراغ راهنمایی ساده شامل چراغ های زرد و سبز و قرمز میشود. توالی چراغها به صورت زیر است:
آنچه که در بالا گفته شد البته برای یک خیابان است. جهت تقاطع دیگر (چهارراه) نیز باید به خوبی فکر شود. برای اینکه موضوع را بهتر نشان دهیم ، ما از یک جدول زمانی که توالی چراغ ها را بهتر نشان میدهد استفاده میکنیم.
بیایید فرض کنیم که خیابان (الف) باید به میزان ۱۲ ثانیه و خیابان (ب) به میزان ۴ ثانیه سبز باشند. برای هر دو خیابان چراغ زرد رنگ به میزان ۳ ثانیه روشن باشد. چراغهای قرمز رنگ نیز مستقیما تحت تاثیر زمان چراغ سبز و زرد هستند. مطالعه جدول زیر سبب فهم موضوع میشه:
همانطور که میبینید این جدول فهم موضوع را آسانتر میکند.کل چرخه زمانی ۲۶ ثانیه است. موقعی که به انتهای این جدول میرسید، دوباره کل روند از ابتدا شروع میشود. اگر به دقت نگاه کنید میبیند که در آن هر دو چراغ قرمز است. قبل از آنکه ادامه مطلب را مطالعه کنید سعی کنید درباره علت اینگونه طراحی تامل و فکر کنید.
اگر شما فکر کنید که جهت دقت بهتر باید بلافاصله بعد از آنکه این چراغ قرمز شد، چراغ دیگری سبز شود احتمالا تصادف را خواهید داشت. البته این موضوع به عرض خیابان ، حد مجاز سرعت و دیگر عوامل بستگی دارد. اما جهت اطمینان ما میتوانیم فرض کنیم که شخصی در یک طرف خیابان هنگام زرد شدن چراغ در لحظه نایستد، و از چراغ عبور کند در حالی که آن چراغ قرمز شده است و اگر در طرف دیگر خیابان توجه نشود ، ممکن است سبب تصادف هولناک شخص شود. بهتر است که در هر دو طرف چراغ قرمز بشود تا این مشکلات حل و فصل شود و در شرایط قابل پیشبینیتر و با ثباتتر کار صورت گیرد.
بخش سخت افزار این پروژه اصلا پیچیده نیست و به هیچ برد بوردی احتیاج ندارد ; حتی به یک قطعه سیم هم احتیاجی نیست.
ما سیم بندی چراغ راهنمایی اول را آغاز میکنیم.
پایه مثبت LED قرمز را به پین ۳۱ وارد میشود. پایه مثبت LED معمولا بلندتر است، اما اگر هر دو پایه هم اندازه بودند آن پایهای که از دید پوشش بیرونی تختتر است، منفیست.
حالا یک مقاومت بین ۳۳۰ اهم تا ۱ کیلو اهم برداشته و به پین ۳۰ وصل میکنیم. سپس سمت دیگر مقاوت را به پایه دیگر LED لحیم میکنیم، که طرف منفی آن خواهد بود. پین ۳۰ را زمین مدارمان قرار میدهیم.
این گام ها رو مطابق بالا برای LEDهای دیگر با توجه به نقشه زیر انجام دهید:
تصویر LED لحیم شده به مقاومت
و بالاخره مدار ما باید چیزی شبیه زیر باشه
و برای رسمیت بیشتر شماتیک مدار به صورت زیر است:
کد آردواینو:
کد آردواینو نوشته شده دارای توضیحات کامل به صورت کامنت است:
/* ================================================================================ File........... Traffic Light Controller Test Code Purpose........ To simulate traffic lights ================================================================================ Notes ================================================================================ - Please visit www.texinlab.com to search for complete article! ================================================================================ Updates ================================================================================ */ //=============================================================================== // Header Files //=============================================================================== //=============================================================================== // Constants //=============================================================================== const int TRAFFIC_LIGHT_STYLE = ۱; // Used to pick the style traffic light const int GREEN_LIGHT = ۱۲; // Green light time in seconds const int AMBER_LIGHT = ۳; // Amber light time in seconds const int DEAD_LIGHT = ۲; // Dead light time in seconds const int RED_AMBER_LIGHT = ۱; // Red/Amber light time in seconds // I know what you are thinking, why the defalut values? It becomes clearer // later on in the code. I basically compute Lazy Tortoise Ave's cycle from // the cycle times from Busy Bunny Lane's values. Keep reading! //=============================================================================== // Variables //=============================================================================== //=============================================================================== // Pin Declarations //=============================================================================== //Inputs: // You could put in a switch to go back and forth to usa and uk modes if // are feeling ambitious! //Outputs: int greenBusyBunnyLane = ۳۰; // Green light output: Busy Bunny Lane int amberBusyBunnyLane = ۳۲; // Amber light output: Busy Bunny Lane int redBusyBunnyLane = ۳۴; // Red light output: Busy Bunny Lane int greenBusyBunnyLaneGnd = ۳۱; // Green light ground: Busy Bunny Lane int amberBusyBunnyLaneGnd = ۳۳; // Amber light ground: Busy Bunny Lane int redBusyBunnyLaneGnd = ۳۵; // Red light ground: Busy Bunny Lane int greenLazyTortoiseAve = ۴۸; // Green light output: Lazy Tortoise Ave int amberLazyTortoiseAve = ۵۰; // Amber light output: Lazy Tortoise Ave int redLazyTortoiseAve = ۵۲; // Red light output: Lazy Tortoise Ave int greenLazyTortoiseAveGnd = 49; // Green light ground: Lazy Tortoise Ave int amberLazyTortoiseAveGnd = 51; // Amber light ground: Lazy Tortoise Ave int redLazyTortoiseAveGnd = ۵۳; // Red light ground: Lazy Tortoise Ave //=============================================================================== // Initialization //=============================================================================== void setup() { // Set appropriate pin light outputs for Busy Bunny Lane pinMode(greenBusyBunnyLane, OUTPUT); pinMode(amberBusyBunnyLane, OUTPUT); pinMode(redBusyBunnyLane, OUTPUT); pinMode(greenBusyBunnyLaneGnd, OUTPUT); pinMode(amberBusyBunnyLaneGnd, OUTPUT); pinMode(redBusyBunnyLaneGnd, OUTPUT); // Set appropriate pin light outputs for Lazy Tortoise Ave pinMode(greenLazyTortoiseAve, OUTPUT); pinMode(amberLazyTortoiseAve, OUTPUT); pinMode(redLazyTortoiseAve, OUTPUT); pinMode(greenLazyTortoiseAveGnd, OUTPUT); pinMode(amberLazyTortoiseAveGnd, OUTPUT); pinMode(redLazyTortoiseAveGnd, OUTPUT); // Set initial states digitalWrite(greenBusyBunnyLane,LOW); digitalWrite(amberBusyBunnyLane,LOW); digitalWrite(redBusyBunnyLane,LOW); digitalWrite(greenBusyBunnyLaneGnd,LOW); digitalWrite(amberBusyBunnyLaneGnd,LOW); digitalWrite(redBusyBunnyLaneGnd,LOW); digitalWrite(greenLazyTortoiseAve,LOW); digitalWrite(amberLazyTortoiseAve,LOW); digitalWrite(redLazyTortoiseAve,LOW); digitalWrite(greenLazyTortoiseAveGnd,LOW); digitalWrite(amberLazyTortoiseAveGnd,LOW); digitalWrite(redLazyTortoiseAveGnd,LOW); } //=============================================================================== // Main //=============================================================================== void loop() { // To decide which traffic light style to be ran in this program, we need a // way to decide this. Fortunately, at the top of this program, under Constants, // we reserved TRAFFIC_LIGHT_STYLE for this very purpose. Now we can just use // the SWITCH CASE conditional statements below to choose which one to execute // for the life of this program. You can always add more as well if you would // like! switch (TRAFFIC_LIGHT_STYLE) { case 0: usaTrafficLight(); break; case 1: ukTrafficLight(); break; default: break; } } //=============================================================================== // Functions //=============================================================================== ///////////////////// // usaTrafficLight // ///////////////////// void usaTrafficLight() { // Remember to consult texinlab.com for the timing table! This will // be really helpful in figuring out why the code exists below. Now this is // only one way of making this whole cycle happen. When I code, I like to // make everything as readable as possible. And if I do not need the extra // computing speed, I will re-introduce statements for the sake of remembering // what the last condition was. So if you think to yourself "hey, he turned // on the red light, then off, and then on!", you are right! I just wanted // to make things easier to read! // First have Busy Bunny Lane have its green light on. And according to the // chart, Lazy Tortoise Ave is Red. I will be using FOR LOOPs in one second // increments since this will help maintain logical continuity from the timing // table. Do not forget to turn the lights off after each cycle! for (int seconds = 0; seconds < GREEN_LIGHT; seconds++) { digitalWrite(greenBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(greenBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Now that the green light time has elapsed for Busy Bunny Lane, we can // move onto our amber light time. for (int seconds = 0; seconds < AMBER_LIGHT; seconds++) { digitalWrite(amberBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(amberBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Dead zone up ahead to prevent our traffic accidents. for (int seconds = 0; seconds < DEAD_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Finally Lazy Tortoise Ave gets its turn for green! for (int seconds = 0; seconds < (GREEN_LIGHT / 3); seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(greenLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(greenLazyTortoiseAve,LOW); // Lazy Tortoise Ave now goes into amber light. for (int seconds = 0; seconds < AMBER_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(amberLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(amberLazyTortoiseAve,LOW); // Once again, a dead zone for (int seconds = 0; seconds < DEAD_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Cycle is over! } //////////////////// // ukTrafficLight // //////////////////// void ukTrafficLight() { // This will be very similar to the TrafficLight // First have Busy Bunny Lane have its green light on. And according to the // chart, Lazy Tortoise Ave is Red. I will be using FOR LOOPs in one second // increments since this will help maintain logical continuity from the timing // table. Do not forget to turn the lights off after each cycle! for (int seconds = 0; seconds < GREEN_LIGHT; seconds++) { digitalWrite(greenBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(greenBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Now that the green light time has elapsed for Busy Bunny Lane, we can // move onto our amber light time. for (int seconds = 0; seconds < AMBER_LIGHT; seconds++) { digitalWrite(amberBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(amberBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Dead zone up ahead to prevent our traffic accidents. for (int seconds = 0; seconds < DEAD_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Here is where the uk light differs! for (int seconds = 0; seconds < RED_AMBER_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); digitalWrite(amberLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); digitalWrite(amberLazyTortoiseAve,LOW); // Finally Lazy Tortoise Ave gets its turn for green! for (int seconds = 0; seconds < (GREEN_LIGHT / 3); seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(greenLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(greenLazyTortoiseAve,LOW); // Lazy Tortoise Ave now goes into amber light. for (int seconds = 0; seconds < AMBER_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(amberLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(amberLazyTortoiseAve,LOW); // Once again, a dead zone for (int seconds = 0; seconds < DEAD_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Here is where the uk light differs, again! for (int seconds = 0; seconds < RED_AMBER_LIGHT; seconds++) { digitalWrite(redBusyBunnyLane,HIGH); digitalWrite(amberBusyBunnyLane,HIGH); digitalWrite(redLazyTortoiseAve,HIGH); delay(1000); } digitalWrite(redBusyBunnyLane,LOW); digitalWrite(amberBusyBunnyLane,LOW); digitalWrite(redLazyTortoiseAve,LOW); // Cycle is over! }
گامهای احتمالی آینده:
اگر شما خواهان گسترش این پروژه باشید، ممکن است که بخواهید یک چراغ راهنمایی واقعی را بخرید و آن را سیمبندی کنید که البته شما باید با ولتاژهای متوسط(مثلا ۱۲۰ ولت ac در آمریکا یا ۲۲۰ ولت ac در ایران) کار کنید؛ که اگر با آن راحت نباشید باید بیخیالش بشید!
شما به وسیلهای به نام رله نیاز دارید. البته باید به طریقی نیز یک چراغ راهنمایی واقعی تهیه کنید. اگر توانستید، با توجه به راهنمایی های این مقاله کار را پیش ببرید.
البته همه این تلاشها برای این است که چگونگی ترتیب و زمانبندی چراغها را فرا بگیرید تا فقط به چراغ راهنمایی متوقف نشوید. شما میتوانید از جدول زمانی استفاده کنید که به کل فرآیند کمک کند. شما میتوانید از این پروژه به عنوان یک تایمر آماده بهره ببرید و در خاموش و روشن کردن چیزهای دیگری که غالبا تاخیر بیشتری دارند مثل پمپ استخر و روشنایی حیاط و راهپله ها و…. استفاده کنید. اصولا هر کاربردی که نیاز داشته باشد طبق یک جدول زمانی مشخص کار کنه اما خیلی دقیق نباشه رو میشه به این شیوه پیادهسازی کرد. اینطوری میتوان قدرت تصور را برای کار با چیزهای دیگری فراتر از چراغ راهنمایی تقویت کرد.
موفق باشید