
ESP-0806
قابل استفاده برای تمامی مدلهای ESP-08
در این آموزش با نحوه استفاده از دستور espElapsedTime برای استفاده در کنترل روند برنامه در پی ال سی ایرانی ESP-0806 آشنا می شوید.
تابع espElapsedTime یک تابع زمانسنجی است که بررسی میکند آیا زمان مشخصی از یک نقطه شروع گذشته است یا خیر. این تابع برای کنترل زمانبندی بدون بلوک کردن برنامه استفاده میشود.
ساختار کلی دستور
تعریف دستور espElapsedTime
bool espElapsedTime(uint32_t startTime, uint32_t duration);
پارامترها
startTime: زمان شروع (به میلیثانیه)
duration: مدت زمان مورد نظر (به میلیثانیه)
مقدار بازگشتی
bool: true اگر زمان گذشته باشد، false اگر هنوز نگذشته باشد
روشهای استفاده
1- بررسی ساده گذشت زمان
// بررسی گذشت 5 ثانیه uint32_t startTime = espGetCurrentTime(); if (espElapsedTime(startTime, 5000)) { // 5 ثانیه گذشته SetQ(0, 0); }
2- کنترل عملیات دوره ای
// کنترل عملیات هر 2 ثانیه
static uint32_t lastOperationTime = 0;
if (espElapsedTime(lastOperationTime, 2000)) {
// انجام عملیات
performOperation();
lastOperationTime = espGetCurrentTime();
}
مثالهای کاربردی
مثال 1- کنترل LED چشمک زن
// LED چشمکزن با espElapsedTime
void blinkLED() {
static uint32_t lastToggleTime = 0;
static bool ledState = false;
if (espElapsedTime(lastToggleTime, 500)) { // هر 500 میلیثانیه
if (ledState) {
ResetQ(0, 0); // خاموش کردن LED
} else {
SetQ(0, 0); // روشن کردن LED
}
ledState = !ledState;
lastToggleTime = espGetCurrentTime();
}
}
مثال 2- کنترل موتور با زمان بندی
// کنترل موتور با زمانبندی دقیق
void motorTimeControl() {
static uint32_t motorStartTime = 0;
static bool motorRunning = false;
if (!motorRunning && I0[0].Value) {
// شروع موتور
SetQ(0, 0);
motorStartTime = espGetCurrentTime();
motorRunning = true;
}
if (motorRunning && espElapsedTime(motorStartTime, 10000)) {
// توقف موتور بعد از 10 ثانیه
ResetQ(0, 0);
motorRunning = false;
}
}
مثال3- تولید پالس با زمان بندی
// تولید پالس با زمانبندی دقیق
void generateTimedPulse() {
static uint32_t pulseStartTime = 0;
static bool pulseActive = false;
if (!pulseActive && I0[0].Value) {
// شروع پالس
SetQ(0, 1);
pulseStartTime = espGetCurrentTime();
pulseActive = true;
}
if (pulseActive && espElapsedTime(pulseStartTime, 1000)) {
// پایان پالس بعد از 1 ثانیه
ResetQ(0, 1);
pulseActive = false;
}
}
مثال4- کنترل توالی عملیات
// کنترل توالی با زمانبندی
void timedSequence() {
static uint32_t sequenceStartTime = 0;
static uint8_t currentStep = 0;
static bool sequenceActive = false;
if (!sequenceActive && I0[0].Value) {
// شروع توالی
sequenceStartTime = espGetCurrentTime();
currentStep = 0;
sequenceActive = true;
}
if (sequenceActive) {
switch (currentStep) {
case 0: // مرحله 1: 0 تا 2 ثانیه
SetQ(0, 0);
if (espElapsedTime(sequenceStartTime, 2000)) {
currentStep = 1;
}
break;
case 1: // مرحله 2: 2 تا 4 ثانیه
ResetQ(0, 0);
SetQ(0, 1);
if (espElapsedTime(sequenceStartTime, 4000)) {
currentStep = 2;
}
break;
case 2: // مرحله 3: 4 تا 6 ثانیه
ResetQ(0, 1);
SetQ(0, 2);
if (espElapsedTime(sequenceStartTime, 6000)) {
currentStep = 3;
}
break;
case 3: // پایان توالی
ResetQ(0, 2);
sequenceActive = false;
break;
}
}
}
مثال 5- کنترل چندین تایمر همزمان
// کنترل چندین تایمر همزمان
void multiTimerControl() {
static uint32_t timer1Start = 0;
static uint32_t timer2Start = 0;
static uint32_t timer3Start = 0;
// تایمر 1: هر 1 ثانیه
if (espElapsedTime(timer1Start, 1000)) {
SetQ(0, 0);
timer1Start = espGetCurrentTime();
}
// تایمر 2: هر 2 ثانیه
if (espElapsedTime(timer2Start, 2000)) {
SetQ(0, 1);
timer2Start = espGetCurrentTime();
}
// تایمر 3: هر 5 ثانیه
if (espElapsedTime(timer3Start, 5000)) {
SetQ(0, 2);
timer3Start = espGetCurrentTime();
}
}
مثال 6- کنترل با تاخیر متغیر
// کنترل با تاخیر متغیر
void variableDelayControl() {
static uint32_t lastTime = 0;
static uint16_t currentDelay = 1000;
if (espElapsedTime(lastTime, currentDelay)) {
// انجام عملیات
SetQ(0, 0);
Delay(100); // تاخیر کوتاه
ResetQ(0, 0);
// تغییر تاخیر برای بار بعد
currentDelay = (currentDelay == 1000) ? 2000 : 1000;
lastTime = espGetCurrentTime();
}
}
مثال7 - کنترل با زمان بندی نسبی
// کنترل با زمانبندی نسبی
void relativeTimingControl() {
static uint32_t baseTime = 0;
uint32_t currentTime = espGetCurrentTime();
if (baseTime == 0) {
baseTime = currentTime;
}
// عملیات در زمانهای نسبی
if (espElapsedTime(baseTime, 1000) && !espElapsedTime(baseTime, 1100)) {
// 100 میلیثانیه اول هر ثانیه
SetQ(0, 0);
} else {
ResetQ(0, 0);
}
}
توابع کمکی
تابع تاخیر غیر بلوک کننده
// تاخیر غیربلوک کننده
bool nonBlockingDelay(uint32_t startTime, uint32_t delayTime) {
return espElapsedTime(startTime, delayTime);
}
// استفاده
uint32_t startTime = espGetCurrentTime();
if (nonBlockingDelay(startTime, 5000)) {
// 5 ثانیه گذشته
}
تابع بررسی زمان باقیمانده
// بررسی زمان باقیمانده
uint32_t espRemainingTime(uint32_t startTime, uint32_t duration) {
uint32_t elapsed = espGetCurrentTime() - startTime;
if (elapsed >= duration) {
return 0; // زمان تمام شده
}
return duration - elapsed;
}
// استفاده
uint32_t startTime = espGetCurrentTime();
uint32_t remaining = espRemainingTime(startTime, 10000);
if (remaining > 0) {
// هنوز زمان باقیمانده
}
تابع تاخیر با بررسی شرط
// تاخیر با بررسی شرط
bool espDelayWithCondition(uint32_t startTime, uint32_t delayTime, bool (*condition)(void)) {
if (espElapsedTime(startTime, delayTime)) {
return true; // زمان تمام شده
}
if (condition != NULL && condition()) {
return true; // شرط برقرار شده
}
return false; // هنوز منتظر
}
// استفاده
bool checkEmergencyStop(void) {
return I0[0].Value;
}
uint32_t startTime = espGetCurrentTime();
if (espDelayWithCondition(startTime, 5000, checkEmergencyStop)) {
// زمان تمام شده یا توقف اضطراری
}
مدیریت خطا و ایمنی
بررسی سرریز زمان
// بررسی سرریز زمان
bool espTimeOverflow(uint32_t oldTime, uint32_t newTime) {
return newTime < oldTime;
}
// استفاده ایمن با espElapsedTime
bool safeElapsedTime(uint32_t startTime, uint32_t duration) {
uint32_t currentTime = espGetCurrentTime();
if (espTimeOverflow(startTime, currentTime)) {
// سرریز رخ داده
uint32_t elapsedTime = (0xFFFFFFFF - startTime) + currentTime;
return elapsedTime >= duration;
} else {
// محاسبه عادی
return espElapsedTime(startTime, duration);
}
}
تابع تاخیر ایمن
// تاخیر ایمن با بررسی شرایط
bool espSafeDelay(uint32_t startTime, uint32_t delayTime) {
if (espElapsedTime(startTime, delayTime)) {
return true; // زمان تمام شده
}
// بررسی شرایط ایمنی
if (emergencyStopCondition()) {
return true; // خروج در صورت توقف اضطراری
}
return false; // هنوز منتظر
}
مثال کامل سیستم کنترل
// تعریف متغیرهای زمانسنجی
uint32_t systemStartTime;
uint32_t lastOperationTime;
uint32_t lastMaintenanceTime;
uint32_t lastStatusCheckTime;
void initializeTimeSystem() {
systemStartTime = espGetCurrentTime();
lastOperationTime = systemStartTime;
lastMaintenanceTime = systemStartTime;
lastStatusCheckTime = systemStartTime;
}
void mainTimeControl() {
uint32_t currentTime = espGetCurrentTime();
// عملیات هر 10 ثانیه
if (espElapsedTime(lastOperationTime, 10000)) {
performOperation();
lastOperationTime = currentTime;
}
// نگهداری هر 5 دقیقه
if (espElapsedTime(lastMaintenanceTime, 300000)) {
performMaintenance();
lastMaintenanceTime = currentTime;
}
// بررسی وضعیت هر 1 ثانیه
if (espElapsedTime(lastStatusCheckTime, 1000)) {
checkSystemStatus();
lastStatusCheckTime = currentTime;
}
// بررسی زمان کارکرد سیستم
if (espElapsedTime(systemStartTime, 86400000)) { // 24 ساعت
systemRestart();
}
}
void performOperation() {
SetQ(0, 0);
Delay(100); // تاخیر کوتاه
ResetQ(0, 0);
}
void performMaintenance() {
SetQ(0, 1);
Delay(1000); // تاخیر نگهداری
ResetQ(0, 1);
}
void checkSystemStatus() {
// بررسی وضعیت سیستم
if (I0[0].Value) {
SetQ(0, 2); // نشانگر وضعیت
} else {
ResetQ(0, 2);
}
}
void systemRestart() {
ResetQ(0, 0);
ResetQ(0, 1);
ResetQ(0, 2);
Delay(5000); // تاخیر راهاندازی مجدد
// راهاندازی مجدد سیستم
}
نکات مهم:
دقت: زمانسنجی بر اساس تایمر سیستم است
سرریز: هر 49.7 روز یک بار سرریز رخ میدهد
غیربلوک کننده: برنامه را متوقف نمیکند
کارایی: بررسی سریع زمان
ایمنی: همیشه سرریز را در محاسبات طولانی بررسی کنید