logo-site-sefid
Search
Close this search box.
راه اندازی ماژول HC-12 با آردوینو

راه اندازی ماژول HC-12 با آردوینو

آردوینو و ماژول مخابراتی بی‌سیم برد بالای HC-12

در این آموزش آردوینو، قصد آموزش نحوه‌ی راه اندازی ماژول HC-12 با آردوینو را آموزش دهیم. این ماژول قادر به برقراری ارتباط بی‌سیم با برد طولانی بین چندین برد آردوینو با مسافت حداکثر 1.8 کیلومتر است. برای دریافت اطلاعات بیشتر در این باره، متن زیر برای شما آماده شده است.

بررسی اجمالی راه اندازی ماژول HC-12 با آردوینو

برای این آموزش دو مثال ساده برای توضیح نحوه‌ی اتصال به ماژول HC-12 و تولید ارتباط بین دو آردوینو و یک مثال اضافی که از یک حسگر شتاب‌سنج در اولین آردوینو استفاده می‌کند و موقعیت استپر به‌صورت بی‌سیم در آردوینوی دوم کنترل می‌شود، آورده شده است.

ماژول مخابراتی بی‌سیم HC-12

ابتدا نگاهی دقیق‌تر به پورت سریال ماژول مخابراتی HC-12 خواهیم داشت. در اینجا برخی مشخصات مربوطه آورده شده است.

  • وایرلس این ماژول در محدوده‌ی 433.4 تا 473 مگاهرتز کار می‌کند.

  • در کل 100 کانال با گام 400 کیلوهرتز برای هر کانال برای این ماژول وجود دارد.

  • توان انتقالی آن از 1DbM (79mW) تا 20dBm (100mW) است.

  • حساسیت دریافت (Receiving Sensivity) آن از 117dBm تا 100dBm است.

این مقادیر در واقع وابسته به سریال انتخابی و نرخ باود (Baud) در هوا است که در جدول زیر نمایش‌داده‌شده است.

نرخ باود (Baud) در هوا و سریال انتخابی
نرخ باود (Baud) در هوا و سریال انتخابی

 ماژول HC-12 یک ریزپردازنده دارد که در واقع قابلیت برنامه‌نویسی توسط کاربر ندارد. برای پیکربندی ماژول به‌سادگی از دستور AT استفاده می‌کنیم که می‌تواند از آردوینو، یک کامپیوتر یا هر ریزپردازنده‌ی دیگری که از پورت سریال استفاده می‌کند، ارسال شود. برای ورود به حالت دستور AT کافی است تا پین “Set” ماژول را با سطح پایین لاجیک تنظیم کنیم.

آردوینو و HC-12

حالا زمان اتصال ماژول HC-12 به آردوینو و انجام مثال اول فرارسیده است. در اینجا شماتیک مداری لازم نشان داده شده است. ولتاژ کاری ماژول از 3.2 ولت تا 5.5 ولت است و برای ایجاد شرایط کاری پایدار پیشنهاد می‌شود که از یک خازن تزویج و منبع تغذیه‌ی خارجی استفاده شود. به هر حال، در این آموزش برای هر سه مثال از USB کامپیوتر به‌عنوان منبع تغذیه استفاده شده است و مشکلی در این خصوص وجود نداشت.

اتصال ماژول به آردوینو UNO
اتصال ماژول به آردوینو UNO

اولین ماژول را به یک آردوینو UNO متصل می‌کنیم و دومین ماژول را نیز به یک آردوینو MEGA وصل می‌کنیم، البته شما می‌توانید از هر برد دلخواه خود استفاده کنید.

کد آردوینوی مثال 1

در اینجا کد آردوینوی مربوط به اولین مثال آورده شده است که از یک ارتباط پایه‌ای بین دو ماژول با استفاده از مانیتور سریال برخوردار است.

/*    Arduino Long Range Wireless Communication using HC-12
                      Example 01
*/

#include <SoftwareSerial.h>

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12

}

void loop() {
  while (HC12.available()) {        // If HC-12 has data
    Serial.write(HC12.read());      // Send the data to Serial monitor
  }
  while (Serial.available()) {      // If Serial monitor has data
    HC12.write(Serial.read());      // Send that data to HC-12
  }
}

کد مشابهی برای هر دو آردوینو استفاده شده است. می‌توانیم دو آردوینو را به دو کامپیوتر جداگانه متصل کنیم اما استفاده از یک کامپیوتر هم مشکلی ایجاد نمی‌کند.

اتصال آردوینو به کامپیوتر
اتصال آردوینو به کامپیوتر

در آن حالت، به محض اتصال اولین آردوینو به کامپیوتر، نیاز به انتخاب مدل و پورت COM خواهیم داشت و پس از آن کد را در آردوینو بارگذاری می‌کنیم. سپس، دومین آردوینو را وصل می‌کنیم و آردوینوی IDE را مجدداً راه‌اندازی می‌کنیم تا قادر به انتخاب پورت COM دیگری باشد که آردوینوی دوم به آن متصل است و همان کد را مجدداً در آن بارگذاری می‌کنیم.

بنابراین، هنگامی‌که دو آردوینوی IDE در حال اجرا هستند، می‌توانیم مانیتورهای سریال را راه‌اندازی و آزمایش کنیم که آیا این ارتباطات به درستی کار می‌کند یا خیر. هر چیز دیگری که در مانیتور سریال بنویسیم نیز از یک آردوینو به دیگری ارسال خواهد شد.

راه‌اندازی مانیتور سریال
راه‌اندازی مانیتور سریال

نحوه‌ی عملکرد کد: بنابراین، به محض اینکه چیزی در مانیتور سریال بنویسیم و دکمه‌ی ارسال را بزنیم، در آردوینوی اول، حلقه‌ی while با تابع Serial.available() به تحقق خواهد پیوست و با استفاده از تابع HC12.write() داده‌ها را از مانیتور سریال به ماژول HC-12 ارسال خواهیم کرد. این ماژول داده‌ها را به صورت بی‌سیم به دومین ماژول HC-12 منتقل می‌کند، پس در دومین آردوینو، حلقه‌ی while با تابع HC12.available() اجرا خواهد شد و با تابع Serial.write() داده‌ها به مانیتور سریال ارسال خواهند شد.

می‌توانیم از کد مشابهی برای ارسال دستورات AT استفاده کنیم و پارامترهای ماژول را مقداردهی کنیم. تمام کاری که باید انجام دهیم این است که پین “Set” ماژول را به زمین یا هر پین دیجیتال آردوینو با سطح لاجیک پایین (صفر) متصل کنیم.

ست کردن پین‌ها
ست کردن پین‌ها

برای آزمایش اینکه آیا با موفقیت وارد حالت کاری موردنظر شده‌ایم یا خیر، در مانیتور سریال می‌توانیم “AT” را تایپ کنیم و در این صورت باید پیغام “OK” را دریافت کنیم. در کل 12 دستور AT وجود دارد و برای تغییر پارامترهای مختلف مثل نرخ باود، کانال، توان انتقالی یا … مورد استفاده قرار می‌گیرند. به طور مثال، اگر عبارت “AT+B38400” را بنویسیم، نرخ باود ماژول 38400 تنظیم می‌گردد.

دستورات  AT:

  1. AT- دستور آزمایش.

    مثال: “AT” را به ماژول بفرستید، ماژول باید پاسخ “OK” بدهد.

  2. AT+Bxxxx- تغییر نرخ باود پورت سریال

    نرخ‌های در دسترس باود: 1200، 2400، 4800، 9600، 19200، 38400، 57600 و 115200 بیت بر ثانیه. مقدار پیش‌فرض: 9600 بیت بر ثانیه.

    مثال: با ارسال “AT+B38400” به ماژول و دریافت پاسخ “OK+B19200” از ماژول.

  3. AT+Cxxxx- تغییر کانال مخابراتی بی‌سیم از 001 تا 100.

    مقدار پیش‌فرض: کانال 001 با فرکانس کاری 433.4 مگاهرتز. کانال‌های بعدی با گام 400 کیلوهرتز تغییر می‌کنند.

    مثال: اگر بخواهیم ماژول را در کانال 006 تنظیم کنیم، نیاز به ارسال کد “AT+C006” به ماژول داریم و ماژول باید پاسخ “OK+C006” را برای ما بفرستد. فرکانس کاری جدید در این صورت، 435.4 مگاهرتز خواهد بود.

مثال 2

حال می‌خواهیم به بررسی دومین مثال بپردازیم. در اینجا از دو دکمه برای انتخاب کانال‌های مخابراتی متفاوت استفاده می‌کنیم و روش متفاوتی برای ذخیره سازی داده‌های ورودی مشاهده خواهید کرد.

نکته: پین‌های “Set” هر دو ماژول HC-12 به پین شماره 6 دو آردوینو متصل شده است و دو کلید به پین‌های 3 و 4 آردوینوی اول وصل شده است.

کد آردوینوی اول:

/*    Arduino Long Range Wireless Communication using HC-12
    Example 02 - Changing channels using push buttons - Buttons side
*/

#include <SoftwareSerial.h>

#define setPin 6
#define button1 4
#define button2 3

SoftwareSerial HC12(10, 11);         // HC-12 TX Pin, HC-12 RX Pin

byte incomingByte;
String readBuffer = "";

int button1State = 0;
int button1Pressed = 0;
int button2State = 0;
int button2Pressed = 0;

void setup() {
  Serial.begin(9600);                   // Open serial port to computer
  HC12.begin(9600);                     // Open serial port to HC12
  pinMode(setPin, OUTPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  digitalWrite(setPin, HIGH);           // HC-12 normal, transparent mode
}

void loop() {
  // ==== Storing the incoming data into a String variable
  while (HC12.available()) {             // If HC-12 has data
    incomingByte = HC12.read();          // Store each icoming byte from HC-12
    readBuffer += char(incomingByte);    // Add each byte to ReadBuffer string variable
  }
  delay(100);
  // ==== Sending data from one HC-12 to another via the Serial Monitor
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

  // ==== If button 1 is pressed, set the channel 01
  button1State = digitalRead(button1);
  if (button1State == HIGH & button1Pressed == LOW) {
    button1Pressed = HIGH;
    delay(20);
  }
  if (button1Pressed == HIGH) {
    HC12.print("AT+C001");               // Send the AT Command to the other module
    delay(100);
    //Set AT Command Mode
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(100);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print("AT+C001");               // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);          // Exit AT Command mode
    button1Pressed = LOW;
  }
  
  // ====  If button 2 is pressed, set the channel 02
  button2State = digitalRead(button2);
  if (button2State == HIGH & button2Pressed == LOW) {
    button2Pressed = HIGH;
    delay(100);
  }
  if (button2Pressed == HIGH) {
    HC12.print("AT+C002"); // Send the AT Command to the other module
    delay(100);
    //Set AT Command Mode
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(100);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print("AT+C002");               // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);
    button2Pressed = LOW;
  }
  checkATCommand();
  readBuffer = "";                       // Clear readBuffer
}
// ==== Custom function - Check whether we have received an AT Command via the Serial Monitor
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // Check whether the String starts with "AT"
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(200);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print(readBuffer);              // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    digitalWrite(setPin, HIGH);          // Exit AT Command mode
  }
}

کد آردوینوی دوم:

/*    Arduino Long Range Wireless Communication using HC-12
        Example 02 - Changing channels using push buttons
*/

#include <SoftwareSerial.h>

#define setPin 6

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

byte incomingByte;
String readBuffer = "";

void setup() {
  Serial.begin(9600);             // Open serial port to computer
  HC12.begin(9600);               // Open serial port to HC12
  pinMode(setPin, OUTPUT);
  digitalWrite(setPin, HIGH);     // HC-12 normal mode
}

void loop() {
  // ==== Storing the incoming data into a String variable
  while (HC12.available()) {             // If HC-12 has data
    incomingByte = HC12.read();          // Store each icoming byte from HC-12
    readBuffer += char(incomingByte);    // Add each byte to ReadBuffer string variable
  }
  delay(100);
  // ==== Sending data from one HC-12 to another via the Serial Monitor
  while (Serial.available()) {
    HC12.write(Serial.read());
  }
  // === If button 1 is pressed, set channel 01
  if (readBuffer == "AT+C001") {
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(100);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print(readBuffer);              // Send AT Command to HC-12 ("AT+C001")
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);          // Exit AT Command mode
    readBuffer = "";
  }
  // === If button 2 is pressed, set channel 02
  if (readBuffer == "AT+C002") {
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(100);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print(readBuffer);              // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);          // Exit AT Command mode

    readBuffer = "";
  }
  checkATCommand();
  readBuffer = "";                       // Clear readBuffer
}
// ==== Custom function - Check whether we have received an AT Command via the Serial Monitor
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // Check whether the String starts with "AT"
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(100);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print(readBuffer);              // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    digitalWrite(setPin, HIGH);          // Exit AT Command mode
  }

توضیحات لازم در مورد کدها:

در ابتدا به تعریف پین‌ها و تنظیم پین “Set” با مقدار بالای (1) لاجیک نیاز داریم تا ماژول در حالت عادی ترنسپرنت کار کند. با اولین حلقه‌ی while داده‌های ورودی را در یک رشته‌ی متغیر ذخیره خواهیم کرد. به این ترتیب امکان مدیریت بهتری وجود خواهد داشت.

 

// ==== Storing the incoming data into a String variable
  while (HC12.available()) {             // If HC-12 has data
    incomingByte = HC12.read();          // Store each icoming byte from HC-12
    readBuffer += char(incomingByte);    // Add each byte to ReadBuffer string variable
  }

داده‌های ورودی همیشه و در هر بار با یک بایت می‌رسند بنابراین برای ارسال رشته‌ی “Test123” از دومین آردوینو، حلقه‌ی while هفت تکرار خواهد داشت. هر تکرار، از تابع HC12.read() استفاده می‌کند و هر بایت یا کاراکتر ورودی که خوانده می‌شود، به یک رشته که مخصوص متغیرهاست با نام “readBuffer” اضافه می‌شود.

در گام بعدی، به این موضوع پرداخته می‌شود که چگونه می‌توانیم کانال مخابراتی را با استفاده از اولین دکمه تغییر دهیم؛ بنابراین اگر اولین دکمه را بفشاریم، با استفاده از تابع HC12.print() رشته‌ی “AT+C001” را به ماژول HC-12 یا دومین آردوینو ارسال خواهیم کرد.

// ==== Custom function - Check whether we have received an AT Command via the Serial Monitor
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // Check whether the String starts with "AT"
    digitalWrite(setPin, LOW);           // Set HC-12 into AT Command mode
    delay(200);                          // Wait for the HC-12 to enter AT Command mode
    HC12.print(readBuffer);              // Send AT Command to HC-12
    delay(200);
    while (HC12.available()) {           // If HC-12 has data (the AT Command response)
      Serial.write(HC12.read());         // Send the data to Serial monitor
    }
    digitalWrite(setPin, HIGH);          // Exit AT Command mode
  }
}

ارتباط بی‌سیم HC-12: کنترل موتور استپر با استفاده از یک شتاب‌سنج

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

استپر موتور و آردوینو
استپر موتور و آردوینو

این مدار همچنین شامل یک میکروسوئیچ برای پیدا کردن موقعیت اول موتور استپر در 0 درجه است.

کنترل استپر موتور با شتاب‌سنج
کنترل استپر موتور با شتاب‌سنج

آردوینوی اول- کد انتقال‌دهنده:

/*   Arduino Long Range Wireless Communication using HC-12
     Example 03 - Stepper Motor Control using Accelerometer - Transmitter, Accelerometer
*/

#include <SoftwareSerial.h>
#include <Wire.h>

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

float angle;
int lastAngle = 0;
int count = 0;
int angleSum = 0;

//--- Accelerometer Register Addresses
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53;  //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
float Xa, Ya, Za;

void setup() {
  HC12.begin(9600);               // Open serial port to HC12
  Wire.begin(); // Initiate the Wire library
  Serial.begin(9600);
  delay(100);

  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register); // Power_CTL Register
  // Enable measurement
  Wire.write(8); // Bit D3 High for measuring enable (0000 1000)
  Wire.endTransmission();
}
void loop() {
  // X-axis
  Wire.beginTransmission(ADXAddress); // Begin transmission to the Sensor
  //Ask the particular registers for data
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
  Wire.requestFrom(ADXAddress, 2); // Request the transmitted two bytes from the two registers
  if (Wire.available() <= 2) { //
    X0 = Wire.read(); // Reads the data from the register
    X1 = Wire.read();
    /* Converting the raw data of the X-Axis into X-Axis Acceleration
      - The output data is Two's complement
      - X0 as the least significant byte
      - X1 as the most significant byte */
    X1 = X1 << 8;
    X_out = X0 + X1;
    Xa = X_out / 256.0; // Xa = output value from -1 to +1, Gravity acceleration acting on the X-Axis
  }
  //Serial.print("Xa= ");
  //Serial.println(X_out);

  // Y-Axis
  Wire.beginTransmission(ADXAddress);
  Wire.write(Y_Axis_Register_DATAY0);
  Wire.write(Y_Axis_Register_DATAY1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2) {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1 << 8;
    Y_out = Y0 + Y1;
    Ya = Y_out / 256.0;
  }

  // Combine X and Y values for getting the angle value from 0 to 180 degrees
  if (Y_out > 0) {
    angle = map(Y_out, 0, 256, 90, 0);
  }
  else if (Y_out < 0) {
    angle = map(Y_out, 256, 0, 90, 0);
    angle = 90 - angle;
  }
  if (X_out < 0 & Y_out < 0) {
    angle = 180;
  }
  if (X_out < 0 & Y_out >0) {
    angle = 0;
  }
  
  // float to int
  int angleInt = int(angle);
  // Makes 100 accelerometer readings and sends the average for smoother result
  angleSum = angleSum + angleInt;
  count++;
  if (count >= 100) {
    angleInt = angleSum / 100;
    angleSum = 0;
    count = 0;
    // Some more smoothing of acceleromter reading - sends the new angle only if it differes from the previous one by +-2
    if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
      Serial.println(angleInt);
      String angleString = String(angleInt);
      //sends the angle value with start marker "s" and end marker "e"
      HC12.print("s" + angleString + "e");
      delay(10);
      lastAngle = angleInt;
      angleSum = 0;
      count = 0;
    }
  }
}

دومین آردوینو – کد دریافت‌کننده:

/*   Arduino Long Range Wireless Communication using HC-12
     Example 03 - Stepper Motor Control using Accelerometer - Receiver, Stepper Motor
*/
#include <SoftwareSerial.h>

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

char incomingByte;
String readBuffer = "";

// defines pins numbers
const int dirPin = 4;
const int stepPin = 3;
const int button = 2;

int currentAngle = 0;
int lastAngle = 0;
int rotate = 0;

void setup() {
  Serial.begin(9600);             // Open serial port to computer
  HC12.begin(9600);               // Open serial port to HC12

  // Sets the two pins as Outputs
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  // Microswitch input, with internal pull-up resistor activated
  pinMode(button, INPUT_PULLUP);
  delay(10);
  digitalWrite(dirPin, HIGH);
  boolean startingPosition = true;
  while (startingPosition) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(200);
    if (digitalRead(button) == LOW) {
      startingPosition = false;
    }
  }
  delay(100);
}
void loop() {
  readBuffer = "";
  boolean start = false;
  // Reads the incoming angle
  while (HC12.available()) {             // If HC-12 has data
    incomingByte = HC12.read();          // Store each icoming byte from HC-12
    delay(5);
    // Reads the data between the start "s" and end marker "e"
    if (start == true) {
      if (incomingByte != 'e') {
        readBuffer += char(incomingByte);    // Add each byte to ReadBuffer string variable
      }
      else {
        start = false;
      }
    }
    // Checks whether the received message statrs with the start marker "s"
    else if ( incomingByte == 's') {
      start = true; // If true start reading the message
    }
  }
  // Converts the string into integer
  currentAngle = readBuffer.toInt();
  // Makes sure it uses angles between 0 and 180
  if (currentAngle > 0 && currentAngle < 180) {
    // Convert angle value to steps (depending on the selected step resolution)
    // A cycle = 200 steps, 180deg = 100 steps ; Resolution: Sixteenth step x16
    currentAngle = map(currentAngle, 0, 180, 0, 1600); 
    //Serial.println(currentAngle); // Prints the angle on the serial monitor
    digitalWrite(dirPin, LOW); // Enables the motor to move in a particular direction
    // Rotates the motor the amount of steps that differs from the previous positon
    if (currentAngle != lastAngle) {
      if (currentAngle > lastAngle) {
        rotate = currentAngle - lastAngle;
        for (int x = 0; x < rotate; x++) {
          digitalWrite(stepPin, HIGH);
          delayMicroseconds(400);
          digitalWrite(stepPin, LOW);
          delayMicroseconds(400);
        }
      }
      // rotate the other way
      if (currentAngle < lastAngle) {
        rotate = lastAngle - currentAngle;
        digitalWrite(dirPin, HIGH);        //Changes the rotations direction
        for (int x = 0; x < rotate; x++) {
          digitalWrite(stepPin, HIGH);
          delayMicroseconds(400);
          digitalWrite(stepPin, LOW);
          delayMicroseconds(400);
        }
      }
    }
    lastAngle = currentAngle;  // Remembers the current/ last positon
  }
}

توضیحاتی در مورد کدها:

در ابتدا به تعریف پین‌ها و مقداردهی اولیه‌ی ماژول‌ها در بخش تنظیمات می‌پردازیم. سپس مقادیر محورهای X و Y شتاب‌سنج را می‌خوانیم و آن‌ها را به مقادیری از 0 تا 180 درجه نگاشت می‌کنیم. مقادیری که از شتاب‌سنج به دست می‌آیند گاهی اوقات ناپایدار هستند، بنابراین برای نرم کردن نتایج از مقدار متوسط صد مقدار خوانده شده استفاده شده است.

// Makes 100 accelerometer readings and sends the average for smoother result
  angleSum = angleSum + angleInt;
  count++;
  if (count >= 100) {
    angleInt = angleSum / 100;
    angleSum = 0;
    count = 0;
    // Some more smoothing of acceleromter reading - sends the new angle only if it differes from the previous one by +-2
    if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
      Serial.println(angleInt);
      String angleString = String(angleInt);
      //sends the angle value with start marker "s" and end marker "e"
      HC12.print("s" + angleString + "e");
      delay(10);
      lastAngle = angleInt;
      angleSum = 0;
      count = 0;
    }
  }

برای نرم کردن بیشتر خروجی، مقدار جدید زاویه را تنها اگر 2 درجه با مقدار قبلی متفاوت باشد، ارسال خواهیم کرد. در اینجا باید به این نکته توجه داشت که هنگام ارسال زاویه به ماژول HC-12، کاراکتر “s” پیش از آن و کاراکتر “s” پس از آن ارسال می‌شود که به ما در هنگام دریافت داده‌ها در آردوینوی دوم کمک می‌کند.

در دومین آردوینو، تا زمانی که نشانگر شروع با “s” آغاز شود صبر می‌کنیم. سپس، مقدار زاویه را تا زمانی که نشانگر پایان به “e” ختم شود، می‌خوانیم. به این روش مطمئن می‌شویم که تنها مقادیر زاویه دریافت شده است.

// Reads the incoming angle
  while (HC12.available()) {             // If HC-12 has data
    incomingByte = HC12.read();          // Store each icoming byte from HC-12
    delay(5);
    // Reads the data between the start "s" and end marker "e"
    if (start == true) {
      if (incomingByte != 'e') {
        readBuffer += char(incomingByte);    // Add each byte to ReadBuffer string variable
      }
      else {
        start = false;
      }
    }
    // Checks whether the received message statrs with the start marker "s"
    else if ( incomingByte == 's') {
      start = true; // If true start reading the message
    }
  }

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

به این ترتیب آموزش این بخش در آردوینو نیز تکمیل شد.

رضا قنبری
متخصص آموزش رباتیک

رضا قنبری هستم متخصص آموزش رباتیک با بیش از 10 سال سابقه فعالیت در ایران

این مطلب را به اشتراک بگذارید

دسته بندی نشده

ماژول سنسور مجاورت نوری

ماژول سنسور مجاورت نوری قبل از خواندن این مقاله بهتر است در نظر داشته باشید مقالاتی که با عنوان ماژول در سایت قرار گرفته اند

ماژول کاهنده

ماژول كاهنده قبل از خواندن مقاله ماژول كاهنده بهتر است در نظر داشته باشید مقالاتی که با عنوان ماژول در سایت قرار گرفته اند از

دیدگاه‌ خود را بنویسید

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