ساخت یک چراغ راهنمایی با برد آردواینو MEGA

چراغ راهنمایی یکی از چیزهایی است که به نظر می‌رسد یکی از وسایل روزمره زندگی ما شده است. هر جایی که به میزان متوسطی اتومبیل وجود داشته باشد احتمالا باید یکی از این چراغهای راهنمایی هم وجود داشته باشد. چراغ های راهنمایی مدرن از نظر ساختمان داخلی بسیار پیچیده هستند و از همه نوع سنسور ، تایمر و حتی از سیستم مانیتورینگ ترافیک که برای نظارت بر کنترل نرخ ترافیک استفاده می‌شود بهره برده است.

trafficlightJPG

ما الان قصد ساخت یک چراغ راهنمایی واقعی را نداریم اما میخواهیم عملکرد آن را با آردواینو شبیه‌سازی کنیم. انجام دادن این کار یک راه عالی جهت کار کردن راحت‌تر با آردواینو وآشنایی با مهمترین دستورات رایج آن است. همچنین این‌کار میتواند به ما در حل یک مسئله کمک کند. نتیجه آنکه ، این پروژه به ما کمک می‌کند که عملکرد پایه ای یک چراغ راهنمایی را بفهمیم.

-سخت افزار لازم:

  • چراغ‌های LED (2 تا قزمز، ۲ تا سبز، ۲ تا زرد)
  • مقاوت الکتریکی(مقاومت هایی در بازه ۳۳۰ اهم تا ۱کیلو اهم برای هر چراغ)
  • یک برد آردواینو (هر نوعی از آن میتواند این کار را انجام دهد اما ما اینجا با MEGA کار کردیم)
  • دستگاه لحیم
  • دم باریک یا سیم چین

-نرم افزار لازم

  • نرم افزار آردواینو (Arduino IDE)

 

تئوری:

ایده اولیه و پایه‌ای چراغ‌های راهنمایی ، کنترل نرخ ترافیک است. همانطور که قبلا گفته شد، چراغ های مدرن ترافیک امروزی امکان نظارت و مانیتورینگ ترافیک را دارند. عوض شدن مدت دوره ای چراغ ها وابسته به درخواست عابران پیاده برای عبور از خیابان و یا افزایش ترافیک در خیابان و …. است.

در این پروژه، ما تقاطع یک چهارراه را بر اساس فواصل زمانی ثابت برای هر چراغ پیاده‌سازی می‌کنیم. چراغ ما هیچ فیدبکی ندارد و خیلی ساده بدون اینکه به حجم ترافیک نگاه کند کار می‌کند. حتی اگر چراغها هوشمند نباشند ما میتوانیم به طور هوشمندانه ای این سیستم را پیاده‌سازی نماییم. شاید مقداری پول باید برای اینکار ذخیره نماییم!

برای مثال ، ما یک چهار راه داریم که از دو خیابان یک طرفه (الف) و (ب) ایجاد شده است. با توجه به تجربه پلیس محله ، خیابان (الف) از (ب) شلوغ‌تر است. از آنجایی که ما از جریان ترافیکی تقاطع اطلاع داریم، یک تایمر ساده برای اینکار مناسب است. (فرض بر این است که)اضافه کردن هر ویژگی دیگه‌ای در اینجا سبب اتلاف هزینه است که شهر توان پرداخت آن را ندارد!

چیزی که ما جهت شبیه‌سازی احتیاج داریم این است که چراغهای راهنماییمان را معرفی کنیم که اینکار با LED ها ممکن است. عملیات کنترل و منطقی و باقی کارها را آردواینو انجام می‌دهد. آردواینو به عنوان کنترل و تایمر هوشمند به ما کمک می‌کند. به این معنی که آردواینو هر چراغی را روشن و خاموش می‌کند و مدت زمان روشن بودن هر چراغ را نیز شمارش می‌کند.

-توالی حلقه چراغ‌ها:

یک چراغ راهنمایی ساده شامل چراغ های زرد و سبز و قرمز می‌شود. توالی چراغها به صورت زیر است:

  • سبز جهت حرکت ایمن
  • زرد جهت کاهش سرعت و اخطار قرمز شدن چراغ
  • قرمز جهت ایست

 

آنچه که در بالا گفته شد البته برای یک خیابان است. جهت تقاطع دیگر (چهارراه) نیز باید به خوبی فکر شود. برای اینکه موضوع را بهتر نشان دهیم ، ما از یک جدول زمانی که توالی چراغ ها را بهتر نشان می‌دهد استفاده می‌کنیم.

بیایید فرض کنیم که خیابان (الف) باید به میزان ۱۲ ثانیه و خیابان (ب) به میزان ۴ ثانیه سبز باشند. برای هر دو خیابان چراغ زرد رنگ به میزان ۳ ثانیه روشن باشد. چراغهای قرمز رنگ نیز مستقیما تحت تاثیر زمان چراغ سبز و زرد هستند. مطالعه جدول زیر سبب فهم موضوع میشه:

trafficchartUSAJPG

همانطور که می‌بینید این جدول فهم موضوع را آسانتر می‌کند.کل چرخه زمانی ۲۶ ثانیه است. موقعی که به انتهای این جدول می‌رسید، دوباره کل روند از ابتدا شروع می‌شود. اگر به دقت نگاه کنید می‌بیند که در آن هر دو چراغ قرمز است. قبل از آنکه ادامه مطلب را مطالعه کنید سعی کنید درباره علت اینگونه طراحی تامل و فکر کنید.

اگر شما فکر کنید که جهت دقت بهتر باید بلافاصله بعد از آنکه این چراغ قرمز شد، چراغ دیگری سبز شود احتمالا تصادف را خواهید داشت. البته این موضوع به عرض خیابان ، حد مجاز سرعت و دیگر عوامل بستگی دارد. اما جهت اطمینان ما می‌توانیم فرض کنیم که شخصی در یک طرف خیابان هنگام زرد شدن چراغ در لحظه نایستد، و از چراغ عبور کند در حالی که آن چراغ قرمز شده است و اگر در طرف دیگر خیابان توجه نشود ، ممکن است سبب تصادف هولناک شخص شود. بهتر است که در هر دو طرف چراغ قرمز بشود تا این مشکلات حل و فصل شود و در شرایط قابل پیش‌بینی‌تر و با ثبات‌تر کار صورت گیرد.

 

بخش سخت افزار این پروژه اصلا پیچیده نیست و به هیچ برد بوردی احتیاج ندارد ; حتی به یک قطعه سیم هم احتیاجی نیست.

ما سیم بندی چراغ راهنمایی اول را آغاز می‌کنیم.

پایه مثبت LED قرمز را به پین ۳۱ وارد می‌شود. پایه مثبت LED معمولا بلندتر است، اما اگر هر دو پایه هم اندازه بودند آن پایه‌ای که از دید پوشش بیرونی تخت‌تر است، منفی‌ست.

حالا یک مقاومت بین ۳۳۰ اهم تا ۱ کیلو اهم برداشته و به پین ۳۰ وصل می‌کنیم. سپس سمت دیگر مقاوت را به پایه دیگر LED لحیم می‌کنیم، که طرف منفی آن خواهد بود. پین ۳۰ را زمین مدارمان قرار می‌دهیم.

این گام ها رو مطابق بالا برای LEDهای دیگر با توجه به نقشه زیر انجام دهید:

ledlazybusyJPG

Joe1

تصویر LED لحیم شده به مقاومت

 

 

و بالاخره مدار ما باید چیزی شبیه زیر باشه

DSCF7086

 

 

و برای رسمیت بیشتر شماتیک مدار به صورت زیر است:

 

Corleto_arduino-traffic-light

کد آردواینو:

کد آردواینو نوشته شده دارای توضیحات کامل به صورت کامنت است:

/*
================================================================================

    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 در ایران) کار کنید؛ که اگر با آن راحت نباشید باید بیخیالش بشید!

شما به وسیله‌ای به نام رله نیاز دارید. البته باید به طریقی نیز یک چراغ راهنمایی واقعی تهیه کنید. اگر توانستید، با توجه به راهنمایی های این مقاله کار را پیش ببرید.

البته همه این تلاش‌ها برای این است که چگونگی ترتیب و زمان‌بندی چراغها را فرا بگیرید تا فقط به چراغ راهنمایی متوقف نشوید. شما می‌توانید از جدول زمانی استفاده کنید که به کل فرآیند کمک کند. شما می‌توانید از این پروژه به عنوان یک تایمر آماده بهره ببرید و در خاموش و روشن کردن چیزهای دیگری که غالبا تاخیر بیشتری دارند مثل پمپ استخر و روشنایی حیاط و راه‌پله ها و…. استفاده کنید. اصولا هر کاربردی که نیاز داشته باشد طبق یک جدول زمانی مشخص کار کنه اما خیلی دقیق نباشه رو میشه به این شیوه پیاده‌سازی کرد. اینطوری میتوان قدرت تصور را برای کار با چیزهای دیگری فراتر از چراغ راهنمایی تقویت کرد.

موفق باشید

خیلی بدضعیفمتوسطخوبخیلی عالی (1 نظر, امتیاز کل: 2,00 از 5)
Loading...

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *