فیڈ بیک ایکچویٹرز کے لئے سیریل کنٹرول کے افعال

اپنے ایکٹیویٹر کو کنٹرول کرنے کے لئے پی ایل سی کا پروگرام بنانا ایک مشکل منصوبوں میں سے ایک ہوسکتا ہے۔ اس کے لئے آزمائش اور غلطی ، جانچ اور صبر کا ڈھیر درکار ہے۔ اگرچہ نتائج ناقابل یقین حد تک فعال اور فائدہ مند ہوسکتے ہیں۔

اس ٹیوٹوریل میں کوڈ ایک فنکشنل کے لئے ایک مکمل پروگرام ہے سیریل ذمہ دار ایکچوایٹر. اپنے PLC کے ساتھ سیریل مانیٹر کا استعمال آپ کو دوسرے کمپیوٹرز ، ماڈیولز یا آٹومیشن سسٹم کے ساتھ اپنے اردوینو سسٹم کو انٹرفیس کرنے کی اجازت دے گا۔

ہم جاتے وقت کوڈ کے ہر فنکشن اور سیکشن کا جائزہ لیں گے ، لہذا آپ اس ٹیوٹوریل سے مخصوص افعال کھینچ سکتے ہیں۔ براہ کرم نوٹ کریں ، کچھ افعال دوسرے افعال پر کال کرتے ہیں جو ایک ہی کوڈ بلاک میں شامل نہیں ہیں ، لہذا آپ کو اپنے کوڈ کو چیک کرنے کی ضرورت ہوگی تاکہ یہ یقینی بنایا جاسکے کہ یہ صحیح طریقے سے انجام دے گا۔

مکمل کوڈ اس مضمون کے آخر میں پوسٹ کیا جائے گا۔ اگر آپ مکمل کوڈ استعمال کرنا چاہتے ہیں تو ، اسے کاپی کریں اور اسے اپنے IDE سافٹ ویئر میں چسپاں کریں۔

پروگرام کا جائزہ

جب شروع کیا جائے تو ، یہ پروگرام گھر اور آپ کے ایکٹیویٹرز کو کیلیبریٹ کرے گا ، جس سے یونٹ کے لئے حرکت کا خاتمہ ہوگا۔ اس کے بعد مزید احکامات کا انتظار کرنے کے لئے یہ ایکچواٹر کو اسٹروک کے درمیانی نقطہ پر لے جاتا ہے۔ اس کے بعد آپ کسی نمبر کو اپنے سیریل مانیٹر (اپنے کمپیوٹر سے) میں داخل کرسکتے ہیں اور ایکٹیویٹر اس پوزیشن پر منتقل ہوجائے گا۔ یہ پروگرام اسٹروک کے آخر میں شٹ آف سے الجھن میں نہیں پڑتا ہے ، اور کسی بھی ہال اثر سینسر یا آپٹیکل سینسر ایکچوایٹر کے ساتھ کام کرتا ہے۔

حصوں کی فہرست

A (*) والے اجزاء میں شامل ہیں ارڈینو اسٹارٹر کٹ

افعال

افعال کا خلاصہ

  1. void setup(): پنوں کی ابتداء ، سیریل مواصلات شروع کرتا ہے ، اور ہومنگ اور انشانکن کے معمولات چلتا ہے۔
  2. void homingRoutine().
  3. void calibrateActuator(): انشانکن کا آغاز کرتا ہے ، ایکچویٹر کو مکمل توسیع میں منتقل کرتا ہے ، اور زیادہ سے زیادہ فالج طے کرتا ہے۔
  4. void loop(): سیریل ان پٹ کے لئے چیک ، ہدف کی پوزیشن کو اپ ڈیٹ کرتا ہے ، اور ایکچوایٹر کی نقل و حرکت کو کنٹرول کرتا ہے۔
  5. void movement(): ہدف کی پوزیشن کی بنیاد پر ایکٹیویٹر تحریک کی سمت کو کنٹرول کرتا ہے۔
  6. void readSensor(): سینسر کی اقدار ، اپ ڈیٹ کی پوزیشن ، اور سینسر ریڈنگ پرنٹس پڑھتا ہے۔
  7. void stopMotor(): ایکٹیویٹر تحریک کو روکتا ہے۔
  8. bool isEndOfStroke(): فالج کے حالات کے خاتمے اور ٹائم آؤٹ کو سنبھالنے کے لئے چیک۔

متغیر

آپ کے کوڈ میں متغیرات کو استعمال کرنے سے پہلے بلایا جانا چاہئے۔ بہترین پروگرامنگ پریکٹس یہ ہے کہ آپ اپنے متغیرات کو اپنے کوڈ کے اوپری حصے میں تفویض اور سیٹ کریں ، تاکہ آپ کے متغیرات میں ترمیم یا 'ٹیوننگ' آسان بنائیں۔

یہ اس کوڈ کے لئے استعمال ہونے والے متغیرات ہیں ، جس میں ایک تبصرہ ان کے فنکشن اور ممکنہ حد کی وضاحت کرتا ہے۔

//Actuator Specifications
int maxStroke; // Leave undefined, set during calibration
int minStroke; // Leave undefined, set during homing
// Input Variables (Pins) - Change to match your pinout
const int Xpin=10;
const int Rpin=11;
// Sensor Read Pin 1
const int sensorPin=3;
// Hall Effect Sensor Input (Sensor Read pin 2) - Change to match your pinout
const int sensorPin2=4;
int sensorCount2;
// Position Target Function Variables
int targetNumber;
int currentPosition;
int lastPosition=0;
// Motor Control Variables
bool active = false; // Actuator On / Off toggle flag
bool EOSFlag=false; // End of Stroke Flag
// Sensor Readings
int sensorValue;
int lastSensorValue = LOW;
int sensorValue2;
int lastSensorValue2 = LOW;
// Variables for Debounce and End of Stroke Sensing
const unsigned long motionTimeout = 2000;  
// Adjust this value based on your requirements (in milliseconds) 2000=2s
const unsigned long CALIBRATION_TIMEOUT=3000;
// Adjust this value based on your requirements (in milliseconds) 3000=3s
unsigned long lastMotionTime = millis(); //Timer function for EOS function
// Position Variables
unsigned long pulseCount = 0; 
int direction = 0;  // Used for incremental movement count
// 0: Stopped, 1: Moving Forward, -1: Moving Backward

سیٹ اپ/ابتدا

باطل سیٹ اپ () ؛ فنکشن ایک بیس ارڈوینو فنکشن ہے جو پی ایل سی کو شروع کرتا ہے ، سیریل مانیٹر شروع کرتا ہے ، اور بطور پروگرامڈ ان پٹ اور آؤٹ پٹ تفویض کرتا ہے۔

یہ سیٹ اپ فنکشن 4 پنوں کو آدانوں یا آؤٹ پٹ کے طور پر تفویض کرتا ہے ، پھر ہومنگ اور انشانکن کے معمولات چلاتا ہے۔

void setup() {
  pinMode(Xpin, OUTPUT);
  pinMode(Rpin, OUTPUT);
  pinMode(sensorPin, INPUT_PULLUP);
  pinMode(sensorPin2, INPUT_PULLUP);
  Serial.begin(115200);

  homingRoutine();
  calibrateActuator();
}

ہومنگ روٹین

یہ کوڈ کا ٹکڑا آپ کے تاثرات کو ایکچوایٹرز کے لئے کام کرنے کا کام ہے۔ یہ کوڈ اسٹروک کے اختتام کا پتہ لگانے تک آپ کے ایکٹیویٹر کو پیچھے ہٹائے گا ، اور اس پوزیشن کو "0" کی قیمت تفویض کرے گا - پھر یہ انشانکن فنکشن کو شروع کرتا ہے۔

مکمل پروگرام میں ، ہومنگ اور انشانکن افعال ایک بار ، اسٹارٹ اپ کے دوران چلائے جاتے ہیں ، اور دوبارہ فون نہیں کیا جاتا ہے۔

یہ کوڈ اسنیپٹ کال کرتا ہے اضافی فنکشن (زبانیں) جو اس بلاک میں شامل نہیں ہیں۔

void homingRoutine() {
  active=true;
  Serial.println("Homing Initiated");
  digitalWrite(Xpin, LOW);
  digitalWrite(Rpin, HIGH);
  while (!EOSFlag) {
    direction=-1;
    readSensor();
    isEndOfStroke();
    // Move actuator to full retraction
    
  }
  direction=0;
  minStroke=currentPosition;
  Serial.println("Homing Completed");
}

انشانکن کا معمول

اگلا ، ہمارے پاس انشانکن کا معمول ہے۔ ہومنگ فنکشن کے یونٹ کو مکمل طور پر پیچھے ہٹانے کے بعد یہ فنکشن آپ کے ایکٹیویٹر کو مکمل طور پر بڑھا دے گا۔ اس معمول کا مقصد سینسر کی دالوں کو ایکچوایٹر کے فالج کے ایک سرے سے دوسرے سے گننا ہے۔ اس کے بعد اس قدر کو میکس اسٹروک متغیر کے طور پر محفوظ کیا جاتا ہے اور اسے پوزیشننگ کے لئے استعمال کیا جاتا ہے۔ اس کوڈ کو دالوں کی گنتی کے بجائے وولٹیج کی نقشہ سازی کے ذریعہ پوٹینومیٹر آراء پر کارروائی کرنے کے لئے ترمیم کی جاسکتی ہے۔

یہ کوڈ اسنیپٹ کال کرتا ہے اضافی فنکشن (زبانیں) جو اس بلاک میں شامل نہیں ہیں۔

void calibrateActuator() {
  Serial.println("Calibration Initiated");
  active = true;
  // Reset variables
  pulseCount = 0;
  currentPosition = 0;
  lastMotionTime=millis();

  // Move actuator to full extension
  digitalWrite(Xpin, HIGH);
  digitalWrite(Rpin, LOW);
  direction=1;

  // Wait until the end of stroke is reached during calibration
  while (!isEndOfStroke()) {
    readSensor();

    // Add a timeout condition to avoid infinite loop
    if (millis() - lastMotionTime > motionTimeout) {
      Serial.println("Calibration Timeout");
      stopMotor();
      maxStroke=currentPosition;
      direction=0;
      // Print the calibration results
        Serial.print("Calibration Complete. Minimum Stroke: ");
        Serial.print(minStroke);
        Serial.print(" Maximum Stroke: ");
        Serial.println(maxStroke);
        targetNumber=((maxStroke+minStroke)/2);
        break;
    }
  }
}

 

لوپ

باطل لوپ () فنکشن ہے مرکزی جسم آپ کے اردوینو کوڈ کا۔ پروگرام کے دوران لوپ () فنکشن کے اندر لکھی گئی کسی بھی چیز کو بار بار عمل میں لایا جائے گا۔

پروگرامرز نوٹ: مجھے ذاتی طور پر لوپ فنکشن کو ہر ممکن حد تک آسان رکھنا آسان لگتا ہے۔ یہ کوڈ کا وہ حصہ ہے جو کال کرے گا زیادہ تر دوسرے افعال کوڈ میں ، اور نہیں کر سکتے باقی کوڈ کے بغیر اٹھایا جائے۔

اس لوپ فنکشن میں ، پروگرام ان پٹ کے لئے سیریل مانیٹر کی جانچ پڑتال کرتا ہے ، آپ کے کمانڈ کے ساتھ ہدف کی پوزیشن کو اپ ڈیٹ کرتا ہے ، اور تحریک کی تقریب کو کال کرتا ہے۔ پی ایل سی سیریل مانیٹر کو بھیجنے والے زیادہ تر پیغامات اس کوڈ کے ٹکڑے سے آتے ہیں۔

ایک ہے a لائن کی لائن پر تبصرہ کیا گیا ذیل میں - جب شامل ہے تو ، کوڈ کی اس لائن نے ایکٹیویٹر کو 0-100 کے ان پٹ کا نقشہ بنادیا ہے۔ یعنی آپ کا ان پٹ اب ایکچواٹر کے فالج کا ایک فیصد ہے۔ اسی لائن کو اسی طرح کے نقشے کی شکل میں دوسرے آدانوں کو استعمال کرنے کے لئے بھی ترمیم کی جاسکتی ہے۔

اس کوڈ کا ٹکڑا اضافی فنکشن (زبانیں) کو کال کرتا ہے جو اس بلاک میں شامل نہیں ہیں۔

void loop() {
if (!active && Serial.available() > 0) {
  String serialInput = Serial.readStringUntil('\n');
  Serial.print("Received: ");
  Serial.println(serialInput);
  if (serialInput.length() > 0) {
    targetNumber = serialInput.toInt();
    //targetNumber = map(targetNumber, 0, 100, minStroke, maxStroke);

/*If the above line is active, you will input a value between 0-100,
The program will use this input as a % of stroke.*/
Serial.print("Target number: "); Serial.println(targetNumber); EOSFlag = false; } // Clear the serial buffer while (Serial.available()) { Serial.read(); } } if (targetNumber != currentPosition) { active = true; movement(); } /* if (!active) { Serial.println("Waiting for Input"); return; } */ if (active && targetNumber == currentPosition) { stopMotor(); Serial.println("Target Met"); } }

 

تحریک

تحریک کا فنکشن ہدف کی پوزیشن کی بنیاد پر ایکچوایٹر موومنٹ کی سمت کو کنٹرول کرتا ہے۔ اس پروگرام میں یہ واحد فنکشن ہے جو موٹر ڈرائیور کو ایکچوایٹر کو منتقل کرنے کے لئے کہتا ہے۔ 

اس کوڈ کا ٹکڑا اضافی فنکشن (زبانیں) کو کال کرتا ہے جو اس بلاک میں شامل نہیں ہیں۔

void movement() {
  if (targetNumber > currentPosition) {
    digitalWrite(Xpin,HIGH);
    digitalWrite(Rpin,LOW);
    //Serial.println(" Extending");
    direction = 1;
  } else if (targetNumber < currentPosition) {
    digitalWrite(Rpin,HIGH);
    digitalWrite(Xpin,LOW);
    direction = -1;
    //Serial.println("Retracting");
  } else if (targetNumber == currentPosition) {
    stopMotor();
    delay(10);
  }
  if(active) {
    readSensor();
  }
  if (isEndOfStroke()) {
    return;  // Skip further movement actions
  }
}

سینسر پڑھیں

سینسر پروسیسنگ کا فنکشن سینسر کی اقدار ، اپ ڈیٹ کی پوزیشن ، اور سیریل مانیٹر پر سینسر ریڈنگ پرنٹ کرتا ہے۔ سیریل کمانڈز ڈیبگنگ کے لئے استعمال کی جاسکتی ہیں ، یا کم بوسی ریڈ آؤٹ کے لئے تبصرہ کرتے ہیں۔

اس کوڈ کا ٹکڑا کسی بھی پروگرام میں استعمال کیا جاسکتا ہے اور تاثرات سینسر سے دالوں کی درست پڑھنے کو دے گا۔

void readSensor() {
  sensorValue = digitalRead(sensorPin);
  if(lastSensorValue != sensorValue) {
    lastSensorValue = sensorValue;
    pulseCount = pulseCount + direction;
    Serial.print("Sensor 1: ");
    Serial.println(pulseCount);
  }
  sensorValue2 = digitalRead(sensorPin2);
  if(lastSensorValue2 != sensorValue2) {
    lastSensorValue2 = sensorValue2;
    sensorCount2=sensorCount2+direction;
    pulseCount = pulseCount + direction;
    Serial.print("Sensor 2: ");
    Serial.println(sensorCount2);
    Serial.print("Current Position: ");
    Serial.println(currentPosition);
  }
  currentPosition = pulseCount;
}

موٹر رکنے اور غیر فعال کرنا

ایکچوایٹر موومنٹ کو روکتا ہے اور مزید کمانڈوں کے لئے سیریل مانیٹر کو پڑھنے کے لئے یونٹ کو دوبارہ اہل بناتا ہے۔ اس پروگرام میں یہ واحد کوڈ کا ٹکڑا ہے جو ایکچواٹر کی تحریک کو روک دے گا۔

اس کوڈ کا ٹکڑا کسی بھی پروگرام میں کسی بھی ایکٹوئٹر کے ساتھ استعمال کیا جاسکتا ہے ، کیونکہ یہ موٹر کو بند کردیتا ہے اور 'فعال' حالت کو تبدیل کرتا ہے۔

void stopMotor() {
 if (active) {
   active=false;
   digitalWrite(Xpin,LOW);
   digitalWrite(Rpin,LOW);
  }
}

اسٹروک چیک کا اختتام

فالج کے حالات کے خاتمے اور ٹائم آؤٹ کو سنبھالنے کے لئے چیک۔ جب ایکچواٹر اسٹروک کے اختتام سے ٹکرا جاتا ہے اور حرکت کرنا چھوڑ دیتا ہے تو ، یہ فنکشن نئے کمانڈ ان پٹ کے لئے ایکچوایٹر کو متحرک اور دوبارہ ترتیب دے گا ، یہاں تک کہ اگر ابھی تک ہدف نمبر نہیں پہنچا ہے۔

یہ کوڈ اسنیپٹ کال کرتا ہے اضافی فنکشن (زبانیں) جو اس بلاک میں شامل نہیں ہیں۔

bool isEndOfStroke() {
  // Check if there is motion (changes in the pulse count)
  if (active && (currentPosition != lastPosition)) {
    lastMotionTime = millis();  // Update the time of the last motion
    lastPosition = currentPosition;
    EOSFlag=false;
  }

  // Check if there is no motion for the specified timeout
  if (active && ((millis() - lastMotionTime) > motionTimeout)) {
    if(EOSFlag!=true) {
      Serial.print("Timeout - ");
      Serial.println("At limit");
      EOSFlag=true;
    }
    direction=0;
    stopMotor();
    return true;
  }
  return false;
}

مکمل کوڈ

//Actuator Specifications
int maxStroke;
int minStroke;

// Input Variables (Pins)
const int Xpin=10;
const int Rpin=11;
const int sensorPin=3;
// Hall Effect Sensor Input
const int sensorPin2=4;
int sensorCount2;


// Motor Function Variables
int targetNumber;
int currentPosition;
int lastPosition=0;
bool active = false;
bool EOSFlag=false;

// Sensor Readings
int sensorValue;
int lastSensorValue = LOW;
int sensorValue2;
int lastSensorValue2 = LOW;

// Variables for Debounce
const unsigned long motionTimeout = 2000;  // Adjust this value based on your requirements (in milliseconds)
const unsigned long CALIBRATION_TIMEOUT=3000; // Adjust this value based on your requirements (in milliseconds)
unsigned long lastMotionTime = millis();

// Position Variables
unsigned long pulseCount = 0;
int direction = 0;  // 0: Stopped, 1: Moving Forward, -1: Moving Backward




void setup() {
  pinMode(Xpin, OUTPUT);
  pinMode(Rpin, OUTPUT);
  pinMode(sensorPin, INPUT_PULLUP);
  pinMode(sensorPin2, INPUT_PULLUP);
  Serial.begin(115200);

  homingRoutine();
  calibrateActuator();
}

void homingRoutine() {
  active=true;
  Serial.println("Homing Initiated");
  digitalWrite(Xpin, LOW);
  digitalWrite(Rpin, HIGH);
  while (!EOSFlag) {
    direction=-1;
    readSensor();
    isEndOfStroke();
    // Move actuator to full retraction
    
  }
  direction=0;
  minStroke=currentPosition;
  Serial.println("Homing Completed");
}

void calibrateActuator() {
  Serial.println("Calibration Initiated");
  active = true;
  // Reset variables
  pulseCount = 0;
  currentPosition = 0;
  lastMotionTime=millis();

  // Move actuator to full extension
  digitalWrite(Xpin, HIGH);
  digitalWrite(Rpin, LOW);
  direction=1;

  // Wait until the end of stroke is reached during calibration
  while (!isEndOfStroke()) {
    readSensor();

    // Add a timeout condition to avoid infinite loop
    if (millis() - lastMotionTime > motionTimeout) {
      Serial.println("Calibration Timeout");
      stopMotor();
      maxStroke=currentPosition;
      direction=0;
      // Print the calibration results
        Serial.print("Calibration Complete. Minimum Stroke: ");
        Serial.print(minStroke);
        Serial.print(" Maximum Stroke: ");
        Serial.println(maxStroke);
        targetNumber=((maxStroke+minStroke)/2);
        break;
    }
  }
}

void loop() {
if (!active && Serial.available() > 0) {
  String serialInput = Serial.readStringUntil('\n');
  Serial.print("Received: ");
  Serial.println(serialInput);
  if (serialInput.length() > 0) {
    targetNumber = serialInput.toInt();
    Serial.print("Target number: ");
    Serial.println(targetNumber);
    EOSFlag = false;
  }
  // Clear the serial buffer
  while (Serial.available()) {
    Serial.read();
  }
}

  if (targetNumber != currentPosition) {
    active = true;
    movement();
  } 
  /*
  if (!active) {
   Serial.println("Waiting for Input"); 
   return;
  } */
  if (active && targetNumber == currentPosition) {
   stopMotor();
   Serial.println("Target Met");
  }
}

void movement() {
  if (targetNumber > currentPosition) {
    digitalWrite(Xpin,HIGH);
    digitalWrite(Rpin,LOW);
    //Serial.println(" Extending");
    direction = 1;
  } else if (targetNumber < currentPosition) {
    digitalWrite(Rpin,HIGH);
    digitalWrite(Xpin,LOW);
    direction = -1;
    //Serial.println("Retracting");
  } else if (targetNumber == currentPosition) {
    stopMotor();
    delay(10);
  }
  if(active) {
    readSensor();
  }
  if (isEndOfStroke()) {
    return;  // Skip further movement actions
  }
}

void readSensor() {
  sensorValue = digitalRead(sensorPin);
  if(lastSensorValue != sensorValue) {
    lastSensorValue = sensorValue;
    pulseCount = pulseCount + direction;
    Serial.print("Sensor 1: ");
    Serial.println(pulseCount);
  }
  sensorValue2 = digitalRead(sensorPin2);
  if(lastSensorValue2 != sensorValue2) {
    lastSensorValue2 = sensorValue2;
    sensorCount2=sensorCount2+direction;
    pulseCount = pulseCount + direction;
    Serial.print("Sensor 2: ");
    Serial.println(sensorCount2);
    Serial.print("Current Position: ");
    Serial.println(currentPosition);
  }
  currentPosition = pulseCount;
}


void stopMotor() {
 if (active) {
   active=false;
   digitalWrite(Xpin,LOW);
   digitalWrite(Rpin,LOW);
  }
}

bool isEndOfStroke() {
  // Check if there is motion (changes in the pulse count)
  if (active && (currentPosition != lastPosition)) {
    lastMotionTime = millis();  // Update the time of the last motion
    lastPosition = currentPosition;
    EOSFlag=false;
  }

  // Check if there is no motion for the specified timeout
  if (active && ((millis() - lastMotionTime) > motionTimeout)) {
    if(EOSFlag!=true) {
      Serial.print("Timeout - ");
      Serial.println("At limit");
      EOSFlag=true;
    }
    direction=0;
    stopMotor();
    return true;
  }
  return false;
}
Share This Article
Tags: