المؤقتات الزمنية و التحكم اللحظي بمنافذ الأردوينو
السلام عليكم ورحمة الله تعالى وبركاته .
كيف تجعل منافذ الأردوينو أكثر إستجابة ؟؟ ذا السؤال الذي طالما يطرح علي في رسائل المتابعين على صفحتي الشخصية ، فهل يمكنني ذلك ؟؟ هل يمكنني ربط حساسات كثيرة مثل الالتراسونيك و الاشعة تحت الحمراء و المحركات مع الأردوينو و جعلها تعمل بشكل واحد و بدون تأخير زمني ملحوظ ؟
في البداية يجب أن أشير إلى أن المتحكمات الأصغرية MCU برمجتها تعتمد على الأوامر السلمية Ladder أي تنفيذ البرامج يكون بالترتيب حسب موضع التعليمة بالكود , من الأعلى للأسفل , هناك استثناءات الأ وهي المقاطعات Interrupts و المؤقتات Timers.
لكن نرجع للسؤال الأهم ، هل يمكنهم كلهم العمل مع الأردوينو دون تأخير زمني ملحوظ ؟؟
الجواب نعم
كيف ؟ هذا ما سنتعرف عليه سويا في هذه التدوينة .
أبسط أوامر التأخير الزمني في الأردوينو هو delay هذا الأمر يسهل على المبتدئين معرفة معنى التأخير الزمني و كيفية تطبيقه على المداخل و المخارج .
كأبسط مثال , برنامج Blink الذي يطبق على الباعث الضوئي LED المربوط على المدخل D13 يضيء لثانية واحده و يطفى لثانية واحدة
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
This example code is in the public domain.
*/
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
هذا الأمر فيه عدة عيوب , منها أنه لا نستطيع عمل أي شيء خلال زمن التأخير , لا نستطيع مثلاً قراءة حالة مدخل معين خلال هذا الوقت او التحكم في حالة مدخل آخر , إلا بعد انتهاء زمن التأخير كما أن زمن التأخير لا يكون بالضبط بنفس القيمة المحددة , في المثل السابق التأخير الزمني هو 1000 ملي ثانية لكن فعلياً التأخير يزيد بقليل عن هذه القيمة , و اذا تم تشغيل هذا البرنامج لفترة طويلة سيكون واضحاً جداً ان التأخير الزمني بين عمليه الأنارة و الأطفاء تزيد عن 1000 ملي ثانية بوضوح تام !
الحل يكون باستخدام الأمر millis ففي الأردوينو يمكن تشغيل المؤقتات باستخدام هذا الأمر و ان يكون زمن الأضاءة و الأغلاق للباعث الضوئي LED بالضبط هو 1000ملي ثانية حتى و لو استمر البرنامج بالعمل لفترة طويلة , هذا رائع :)
هذا البرنامج مثال موجود ضمن ملفات الأردوينو يوضح طريقة العمل لهذا الأمر و بنفس مخرجات البرنامج السابق .
/* Blink without Delay
Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.
The circuit:
* LED attached from pin 13 to ground.
* Note: on most Arduinos, there is already an LED on the board
that's attached to pin 13, so no hardware is needed for this example.
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop()
{
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
ممتاز هذا رائع , لكن لو اردنا عمل برامج معقدة سيكون وضع الكود بهذه الطريقة أمراً مربكاً للمبرمج , فالحل يكون بوجود مكتبة .
لحسن الحظ فالمهتمين بالأردوينو قاموا بكتابة عشرات المكتبات لتسهل على المستخدمين التعامل مع المداخل و المخارج بصورة سريعة و بدقة عالية , منها مكتبة Metro .
هذه المكتبة تعتمد بشكل أساسي على الأمر millis و تسهل على المبرمج الحصول على برنامج يحتوي العديد من البرامج ذات تأخير زمني ثابت بين كل وظيفة و الأخرى .
اولاً يمكن تحميل المكتبة من هنا
أوامرها جداً سهلة و يمكن أن ترى عدة أمثلة مرفقه مع المكتبة .
مثلاً لو أردنا تشغيل 3 مداخل في الأردوينو بحيث يكون :
1)واحد منهم يعمل لأضاءة - اطفاء ضوء لمدة2000ملي ثانية
2)يعمل كتعديل نبضي PWM بحيث يقوم بزيادة طول النبضة الفعالة "زيادة توهج ال LED " مرة كل 10 ملي ثانية.
3) يعمل كمدخل قراءة لحساس تماثلي "مقاومة متغيرة" يقوم بالتحقق منها كل 200ملي ثانية و يزيد توهج LED مربوط على مدخل رقمي بتناسب طردي مع قيمة المقاومة المقروءة .
القطع المستخدمة في التجربة :
1) بطاقة أردوينو
2) مقاومة متغيرة Potentiometer
3) LED باعث ضوئي عدد 3
4)مقاومات عدد 3 "ان تكون قيمتها أقل من 1كيلو اوم"
5) اسلاك توصيل
6) Bread Board .
المخطط :
البرنامج :
// Metro Library code
//Written By : MBARK TiЭSTO
//http://www.mbarktiesto.com
// 18/12/2015
//....................................
#include <Metro.h> // Include the Metro library
//first , Blink Led for 150ms
Metro LED_flasher = Metro(2000);
boolean LEDState=true;
//second , Increase dimming For Led by 1 each time
Metro PWM_Cycle = Metro(10);
int i=0;
int Factor=1; //or -1
// third , Read Potentiometer and control the bright
//of led connect to another PWM Pin
Metro Sensor=Metro(200);
const int LED=13;
const int pwmPin=6;
const int sensorPin=A0;
const int pwmPin2=3;
void setup() {
// put your setup code here, to run once:
pinMode( LED ,OUTPUT);
pinMode( pwmPin ,OUTPUT);
pinMode( pwmPin2 ,OUTPUT);
pinMode( sensorPin ,INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (LED_flasher.check() == 1) { // check if the metro has passed its interval .
digitalWrite(LED,LEDState);
LEDState=!LEDState;
}
if (PWM_Cycle.check() == 1) { // check if the metro has passed its interval .
analogWrite(pwmPin,i);
if(i==0){Factor=1;}
if(i>255){Factor=-1;}
i+=Factor;
}
if (Sensor.check() == 1) { // check if the metro has passed its interval .
int SensorValue=analogRead(A0);
analogWrite(pwmPin2,SensorValue/4);
}
}
هذه أحدى الطرق لزيادة فاعلية برنامجك , حاول دائماً ان لا تستخدم ال delay بشكل كبير خصوصاً عندما تحتوي مشاريعك على العديد من القطع او التعليمات التي تحتاج دقة في الوقت .
المصدر MBARK TiЭSTO Blog
{[['
']]}

المؤقتات الزمنية و التحكم اللحظي بمنافذ الأردوينو
مراجعة MBARK T3STO
يوم
6:11 م
التقييم:

ليست هناك تعليقات: