การใช้งาน ZX-BLE ร่วมกับชุด POP-BOT32i Rover Kit Plus

ZX-BLE มินิบอร์ดสื่อสารข้อมูลอนุกรมไร้สายผ่านบลูทูธกำลังงานต่ำ

คุณสมบัติของ ZX-BLE

  • ใช้ไมโครคอนโทรลเลอร์ ESP32-C3 ให้ทำงานในโหมดบลูทูธพลังงานต่ำหรือ BLE (Bluetooth Low Energy)
  • ติดต่อกับบอร์ดไมโครคอนโทรลเลอร์ได้ทุกรุ่นที่มีพอร์ตสื่อสารข้อมูลอนุกรม UART
  • อัตราบอด 115,200 บิตต่อวินาที ในรูปแบบข้อมูล 8N1 (8 บิตข้อมูล, ไม่มีการตรวจสอบบิตพาริตี้ และ 1 บิตหยุด)
  • ใช้ไฟเลี้ยง 3.3V ต้องการกระแสไฟฟ้า 20mA ขณะรับส่งข้อมูล
  • มีจุดต่อ RxDและ TxDเป็นคอนเน็กเตอร์ JST ตัวผู้ 2.0 มิลลิเมตร 3 ขา
  • มี LED แสดงสถานะไฟเลี้ยงและการสื่อสารข้อมูล
  • มีจุดต่อพอร์ต USB-C สำหรับติดต่อกับคอมพิวเตอร์เพื่อตั้งค่าอัตราบอดและชื่ออุปกรณ์สำหรับการจับคู่อุปกรณ์ BLE

รูปที่ 1 แสดงส่วนประกอบของมินิบอร์ด

แนะนำแอปพลิเคชั่น V7RC

V7RC เป็นแอปพลิเคชั่นสำหรับการควบคุมอุปกรณ์ระบบสมองกลฝังตัวผ่านคลื่นวิทยุด้วยบลูทูธพลังงานต่ำหรือ BLE บนสมาร์ตโฟน ที่พัฒนาโดย V7 Media จากไต้หวัน โดยใช้งานเป็นได้ทั้งรีโมตคอนโทรลแบบไร้สาย ส่วนแสดงผลภาพนิ่งและวิดีโอระยะไกล และยังรองรับการพัฒนาระบบควบคุมด้วยเทคโนโลยีปัญญาประดิษฐ์ผ่านฮาร์ดแวร์ของสมาร์ตโฟนสมัยใหม่ ช่วยให้ผู้เรียนและผู้ใช้งานสามารถเรียนรู้ เขียนโค้ด และทดลองใช้งานเทคโนโลยี AI ได้ทุกที่ ทุกเวลา ด้วยฟังก์ชันที่ครบถ้วนและใช้งานง่าย มีหน้าต่างหลักแสดงดังรูปที่ 2

รูปที่ 2 หน้าต่างหลักของแอปพลิเคชั่น V7RC

รูปแบบข้อมูลปุ่มกดของแอปพลิเคชั่น V7RC

ชุดข้อมูลหรือแพ็กเก็ตข้อมูลของ BLE มีขนาด 20 ไบต์ ในแอปพลิเคชั่น V7RC กำหนดรูปแบบของชุดข้อมูลดังนี้

รูปที่ 3 รูปแบบของชุดข้อมูล

  • 3 ไบต์แรกเก็บข้อมูลโหลดการทำงาน มีด้วยกัน 3 รหัสคือ
    • SRV สำหรับโหมด CAR ควบคุมมอเตอร์ขับเคลื่อน 2 ตัว
    • SRT สำหรับโหมด TANK ควบคุมมอเตอร์ขับเคลื่อน 4 ตัว
    • SS8 สำหรับโหมด PRO ควบคุมมอเตอร์ขับเคลื่อน 2 ตัว, เซอร์โวมอเตอร์หลัก 2 ตัว, มอเตอร์ไฟตรงเสริม (AUX) 2 ตัว และเซอร์โวมอเตอร์เสริม 2 ตัว รวมสูงสุด 8 ตัว
  • 16 ไบต์ต่อมาสำหรับคำสั่ง SRV และ SRT เป็นข้อมูลสำหรับนำไปใช้สร้างสัญญาณ PWM ให้กับวงจรขับมอเตอร์บนไมโครคอนโทรลเลอร์
    • ไบต์ที่ 4 ถึง 7 ข้อมูลสำหรับสร้างสัญญาณ PWM ให้กับวงจรขับมอเตอร์ช่องที่ 1
    • ไบต์ที่ 8 ถึง 11 ข้อมูลสำหรับสร้างสัญญาณ PWM ให้กับวงจรขับมอเตอร์ช่องที่ 2
    • ไบต์ที่ 12 ถึง 15 ข้อมูลสำหรับสร้างสัญญาณ PWM ให้กับวงจรขับมอเตอร์ช่องที่ 3
    • ไบต์ที่ 16 ถึง 19 ข้อมูลสำหรับสร้างสัญญาณ PWM ให้กับวงจรขับมอเตอร์ช่องที่ 3
  • สำหรับ 16 ไบต์ต่อมาสำหรับคำสั่ง SS8 ข้อมูลที่ใช้ในการกำหนดค่าสัญญาณ PWM จะเป็นเลขฐานสิบหก 8 ชุด ชุดละ 2 ไบต์
  • ไบต์สุดท้ายเป็นรหัสปิด ซึ่งใช้อักขระ #

รูปที่ 4 ตัวอย่างรูปแบบชุดข้อมูลและหน้าต่างของแอป V7RC ในแต่ละโหมด

การตั้งค่าและชื่ออุปกรณ์บลูทูธให้กับมินิบอร์ด ZX-BLE

  • สิ่งที่ต้องเตรียม
    • มินิบอร์ด ZX-BLE
    • สาย USB-C สำหรับเชื่อมต่อกับคอมพิวเตอร์
    • คอมพิวเตอร์ที่ติดตั้งระบบปฏิบัติการวินโดวส์ และติดตั้งโปรแกรม ZX-BLE Config ( ดาวน์โหลดได้ที่ https://inex.co.th/store/ZXBLE_Config.zip )
  • ขั้นตอนการตั้งชื่ออุปกรณ์บลูทูธให้กับมินิบอร์ด ZX-BLE
    • ดาวน์โหลดโปรแกรมจาก https://inex.co.th/store/ZXBLE_Config.zip 
    • แตกไฟล์ .zip แล้วดับเบิ้ลคลิกไฟล์ ZX-BLE_Config.exe
    • หน้าต่างของโปรแกรม ZX-BLE Config ปรากฏขึ้นมาดังรูปที่  ทำการกำหนดชื่อที่ต้องการตั้งให้กับมินิบอร์ด ZX-BLE ที่ช่อง BLE Name โดยกำหนดชื่อเป็นภาษาอังกฤษได้ยาวถึง 15 ตัวอักษร ในทีนี้ตั้งชื่อเปฌน ZX-BLE ID-001

รูปที่ 5 แสดงส่วนประกอบของโปรแกรม ZX-BLE Config

    • เชื่อมต่อมินิบอร์ด ZX-BLE เข้ากับพอร์ต USB ของคอมพิวเตอร์โดยใช้สาย USB-C ดังรูปที่ 6
    • รอครู่หนึ่ง เพื่อให้การเชื่อมต่ออุปกรณ์ USB สำเร็จ

รูปที่ 6 แสดงการเชื่อมต่อมินิบอร์ด ZX-BLE กับคอมพิวเตอร์

    • ตรวจสอบตำแหน่งพอร์ต COM PORT ของมินิบอร์ด ZX-BLE โดยคลิกเมาส์ปุ่มขวาที่เครื่องหมาย Windows แล้วเลือก Device Manager ดังรูปที่ 7
    • ที่หน้าต่าง Device Manager คลิกเลือกหัวข้อ Port (COM & LPT) จะเห็นรายการ USB Serial Device (COM xx)  จำหมายเลข COM ไปใช้ในการตั้งค่าที่โปรแกรม ZX-BLE Config จากตัวอย่างคือ COM18

    • กลับมายังโปรแกรม ZX-BLE Config เลือกพอร์ตเชื่อมต่อเป็น COM18 ดังรูป
    • กดปุ่ม Read ที่หน้าต่างของโปรแกรมจะแสดงหมายเลข COM Port ที่เชื่อมต่ออยู่ ดังรูป แสดงข้อความ ZX-BLE name read ครู่หนึ่ง หมายความว่าโปรแกรมสามารถอ่านชื่ออุปกรณ์ของ ZX-BLE สำเร็จ

    • ทดลองเปลี่ยนเป็นชื่ออื่นๆ จากนั้นกดปุ่ม Write เพื่อบันทึกชื่อใหม่ให้กับมินิบอร์ด ZX-BLE 
    • เมื่อตั้งค่าสำเร็จจะแจ้งด้วยข้อความ Write completed
    • ทำการทดสอบให้มั่นใจ ว่ามินิบอร์ด ZX-BLE ได้ถูกทำการเปลี่ยนชื่อโดยการกดปุ่ม Read อีกครั้ง ชื่อของอุปกรณ์จะกลับมาแสดงที่ช่อง BLE Name
    • ชื่อที่ปรากฏยังคงเป็น ZX-BLE 108 แสดงว่าการเปลี่ยนชื่อเสร็จสมบูรณ์
    • นำมินิบอร์ด ZX-BLE ไปเชื่อมต่อกับบอร์ด ไมโครคอนโทรลเลอร์ที่ต้องการใช้งาน ในที่นี้คือบอร์ด POP32i 
    • เมื่อทำการค้นหามินิบอร์ด ZX-BLE ในแอป V7RC จะพบชื่อของอุปกรณ์บลูทูธตามที่ตั้งชื่อไว้ ทำการจับคู่ เพื่อเริ่มต้นการใช้งาน

วิธีการใช้งาน ZX-BLE ร่วมกับ POP-BOT32i : Rover Kit Plus

          1. เตรียมอุปกรณ์

    • ชุด POP-BOT32i : Rover Kit Plus และ ZX-BLE
    • สาย USB สำหรับเชื่อมต่อบอร์ดกับคอมพิวเตอร์
    • ซอร์ฟแวร์ Arduino IDE สำหรับเขียนและอัพโหลดโค้ด
    • แอปพลิเคชั่น V7RC ( คลิกเพื่อติดตั้ง Android / IOS )
    • ไลบรารี่ที่เกี่ยวข้อง

          2. เชื่อมต่อ ZX-BLE กับแอปพลิเคชั่น V7RC

    • เชื่อมต่อมินิบอร์ด ZX-BLE กับบอร์ด POP-32i ที่ใช้ในชุดหุ่นยนต์ POP-BOT32i Rover Kit Plus โดยต่อขา RxD ของ ZX-BLE เข้าที่จุดต่อ TxD และต่อขา TxD ของ ZX-BLE เข้าที่จุดต่อ RxD ดังรูปที่ 2.1

รูปที่ 2.1 เชื่อมต่อ ZX-BLE กับบอร์ด POP-32i

    • เปิดแอปพลิเคชั่น V7RC แล้วแตะที่ไอคอนฟันเฟืองเพื่อเข้าสู่หน้าต่าง CONTROL CENTER
    • ที่หน้าต่าง CONTROL CENTER สังเกตที่กรอบข้อความหลังคำว่า LANGUAGE ให้เลือกภาษา ENGLISH ดังรูปที่ 2.2

รูปที่ 2.2 ตั้งค่าภาษาของแอปพลิเคชชั่น V7RC

    • จากนั้นที่หน้าต่าง CONTROL CENTER ตรวจสอบที่ช่อง NETWORK จะแสดงตัวเลือก BLE และ WIFI ให้เลือก BLE
    • และสังเกตในช่อง DEVICE ให้แตะเข้าไปที่ช่อง No device ดังรูปที่ 2.3 

รูปที่ 2.3 เชื่อมต่อ Device ของ ZX-BLE

    • จากนั้นจะแสดงหน้าต่าง BLUETOOTH โดยจะแสดงรายละเอียดของอุปกรณ์ สังเกตชื่อของอุปกรณ์ที่ตรงกับที่ตั้งค่าไว้ ในที่นี้คือ ZX-BLE ID-001 จากนั้นกดปุ่ม LINK เพื่อเริ่มการเชื่อมต่อ ระบบจะแสดงสถานะกำลังเชื่อมต่อด้วยการแสดงไอคอนรูปเฟือง จากนั้น ไอคอนจะหายไปหากการเชื่อมต่อไม่สำเร็จ ให้กดปุ่ม LINK ซ้ำจนกว่าการเชื่อมต่อจะสำเร็จ
    • เมื่อเชื่อมต่อได้สำเร็จ ให้กดปุ่มย้อนกลับ 2 ครั้ง เพื่อกลับไปยัังหน้าต่าง CONTROL CENTER 
    • ที่หน้าต่าง CONTROL CENTER จะแสดงสถานะการเชื่อมต่อสำเร็จ โดยดูที่ช่อง Device จะปรากฎชื่อของอุปกรณ์ ZX-BLE ที่เชื่อมต่อได้ ดังรูปที่ 2.4 แล้วกดปุ่มย้อนกลับอีกครั้ง
    • หน้าต่างหลักของแอป V7RC ปรากฎขึ้น ที่ช่อง Device name จะแสดงชื่ออุปกรณ์ตรงกันกับที่แสดงในเมนู Device ในหน้าต่าง CONTROL CRETER ถ้าได้ตามนี้ แอป V7RC จะเชื่อมต่อกับ ZX-BLE เรียบร้อยพร้อมใช้และทำงานร่วมกัน ดังรูปที่ 2.4

รูปที่ 2.4 หน้าต่างหลักของแอป V7RC ที่แสดงชื่ออุปกรณ์ที่เชื่อมต่อสำเร็จ

          3. เชื่อมต่อมอเตอร์และเซอร์โวเข้ากับบอร์ด POP-32i

    • เชื่อมต่อมอเตอร์ฝั่งซ้าย เข้าที่ช่อง Motor 1 และเชื่อมต่อมอเตอร์ฝั่งขวา เข้าที่ช่อง Motor 2 ดังรูปที่ 3.1
    • เชื่อมต่อเซอร์โวส่วนสำหรับยกและวางของ Gripper-X เข้าที่ช่อง Servo 1 และเชื่อมต่อเซอร์โวส่วนแขนจับของ Gripper-X เข้าที่ช่อง Servo 2 ดังรูป 3.1

รูปที่ 3.1 เชื่อมต่อมอเตอร์และเซอร์โวเข้ากับบอร์ด POP-32i

ตัวอย่างโปรแกรมสำหรับบอร์ด POP-32i เพื่อทำงานร่วมกับ ZX-BLE ในการติดต่อกับแอปพลิเคชั่น V7RC

//
//  Mode CAR 2 motors :  M2 = Left , M1 = Right
//  Mode TANK 4 motors : M3 M4 = Left , M2 M1 = Right
//  Mode PRO  Drive 2 motors : M2 = Left , M1 = Right , Main 2 servos : S1 S2 = P2 P3,
//            Aux. 2 motors M3 M4 = P4 P5 control , Aux. 2 servos S3 S4 = P6 P7
//
#include <POP32.h>
//#define DEBUG   // Remove // remark when Debuggung V7RC Command bytes
#define SERVO_DEFAULT_VALUE 1500
#define SERVO_DEFAULT_MAX_VALUE 2000
#define SERVO_DEFAULT_MIN_VALUE 1000
#define PACKET_LENGTH 20
#define SERIAL_BAUDRATE 115200
#define DEFAULT_PERIOD_TIME 30
#define LOST_SIGNAL_MAX_TIME 500  // Maximum signal loss time;
#define DEFAULT_LOOP_TIMES 33
//const int failSaveLED = 8; // Fail status shown (not used)
long startProcessTime = 0;
long endProcessTime = 0;
int currentLostSignalTime = 0;
char readBuffer[PACKET_LENGTH];
int bufferIndex = 0;
long loopStart, loopEnd;
static boolean ledStatus = LOW;
static int loopProcessCheck = 0;
static int failSafeCheckTime = 0;  // Check if the information has been received
static bool ifLostSignal = true;
int leftWheel = 0;
int rightWheel = 0;
#define SERIAL2_RX PB7
#define SERIAL2_TX PB6
HardwareSerial Serial2(SERIAL2_RX, SERIAL2_TX);
void setup() {
  Serial.begin(SERIAL_BAUDRATE);
  Serial2.begin(SERIAL_BAUDRATE);
  delay(100);
  Serial2.println("AT+RESET");
  delay(1000);
  oled.text(0, 0, "V7RC ZX-BLE");
  oled.show();
  String str;
  if (Serial2.available() > 0) {
    Serial2.readStringUntil('N');
    Serial2.readStringUntil('A');
    Serial2.readStringUntil('M');
    Serial2.readStringUntil('E');
    Serial2.readStringUntil('=');
    str = Serial2.readStringUntil('#');
    const char* cc = str.c_str();
    oled.text(2, 0, "Name:");
    oled.text(2, 5, cc);
    oled.show();
    Serial.print(cc);
  }
}
void loop() {
  loopStart = millis();
  if (loopProcessCheck > DEFAULT_LOOP_TIMES) {
    // Serial.println("init loopProcessCheck:" + String(loopProcessCheck));
    // Serial.println("loopProcessCheck:" + String(loopProcessCheck));
    if (ledStatus == LOW) {
      ledStatus = HIGH;
    } else {
      ledStatus = LOW;
    }
    if (ledStatus) {
      pinMode(PC13, OUTPUT);
      digitalWrite(PC13, LOW);
    } else {
      pinMode(PC13, INPUT_PULLUP);
    }
    //    digitalWrite(led, ledStatus);
    loopProcessCheck = 0;
  }
  int bufferLength = Serial2.available();
  while (bufferLength > 0) {
    char tempBuffer[bufferLength];
    Serial2.readBytes(tempBuffer, bufferLength);
    // Serial.print("getValue:");
    // Serial.println(bufferLength);
    for (int i = 0; i < bufferLength; i++) {
      readBuffer[bufferIndex] = tempBuffer[i];
      bufferIndex++;
      //Data length = 20
      if (bufferIndex >= PACKET_LENGTH) {
        //convert char[] to String
        if (readBuffer[19] == '#') {

          String command = String(readBuffer);
          //Command Process
          V7RCCommand(command);

#ifdef DEBUG
          // DEBUG command bytes
          Serial.print(command);
          Serial.print(" ");
#endif
          ifLostSignal = false;
          failSafeCheckTime = 0;
          //digitalWrite(failSaveLED, HIGH);

        } else {

#ifdef DEBUG
          Serial.print("invaild Value :");
          Serial.println(readBuffer[19]);
#endif
        }
        bufferIndex = 0;
      }
      if (i == bufferLength - 1) {
        bufferIndex = 0;
      }
    }
    bufferLength = Serial2.available();
  }
  loopEnd = millis();
  //if delay time less then 30 microsecond
  int needDelay = loopEnd - loopStart;
  needDelay = DEFAULT_PERIOD_TIME - needDelay;
  failSafeCheckTime += DEFAULT_PERIOD_TIME;
  // Serial.print("failSafeCheckTime:");
  // Serial.println(failSafeCheckTime);
  if (failSafeCheckTime > LOST_SIGNAL_MAX_TIME) {
    processFailSave();
    failSafeCheckTime = LOST_SIGNAL_MAX_TIME;
    ifLostSignal = true;
  } else {
  }
  if (needDelay > 0) {
    delay(needDelay);
  }
  loopProcessCheck += 1;
}
void V7RCCommand(String bufferString) {
  // Serial.println(bufferString);
  String P0str;
  String P1str;
  String P2str;
  String P3str;
  String P4str;
  String P5str;
  String P6str;
  String P7str;
  int P0Value = 1500;
  int P1Value = 1500;
  int P2Value = 1500;
  int P3Value = 1500;
  int P4Value = 1500;
  int P5Value = 1500;
  int P6Value = 1500;
  int P7Value = 1500;
  int Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7;
  if (bufferString.substring(0, 3) == "SRV")  // CAR, Game pad , Game pad 2 Mode
  {
    P0Value = (bufferString.substring(3, 7)).toInt();
    P1Value = (bufferString.substring(7, 11)).toInt();
    P2Value = (bufferString.substring(11, 15)).toInt();
    P3Value = (bufferString.substring(15, 19)).toInt();
    Value0 = map(P0Value, 1000, 2000, -100, 100);
    Value1 = map(P1Value, 1000, 2000, -100, 100);
    if (Value1 == 0)  // spin
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, -50, 50);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, -50, 50);
    } else if (Value1 > 0)  // forward
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, 0, 100);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, 0, 100);
    } else  // Backward
    {
      leftWheel = Value1 + Value0;
      leftWheel = constrain(leftWheel, -100, 0);
      rightWheel = Value1 - Value0;
      rightWheel = constrain(rightWheel, -100, 0);
    }
    POP32_ModeCAR(leftWheel, rightWheel);
  } else if (bufferString.substring(0, 3) == "SRT") {  // TANK Mode
    int Tank0 = 1500;
    int Tank1 = 1500;
    P0Value = (bufferString.substring(3, 7)).toInt();
    P1Value = (bufferString.substring(7, 11)).toInt();
    P2Value = (bufferString.substring(11, 15)).toInt();
    P3Value = (bufferString.substring(15, 19)).toInt();
    Value0 = map(P0Value, 1000, 2000, -100, 100);
    Value1 = map(P1Value, 1000, 2000, -100, 100);
    if (Value1 == 0)  // spin
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, -50, 50);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, -50, 50);
    } else if (Value1 > 0)  // forward
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, 0, 100);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, 0, 100);
    } else  // Backward
    {
      leftWheel = Value1 + Value0;
      leftWheel = constrain(leftWheel, -100, 0);
      rightWheel = Value1 - Value0;
      rightWheel = constrain(rightWheel, -100, 0);
    }
    POP32_ModeTANK(leftWheel, leftWheel, rightWheel, rightWheel);
  } else if (bufferString.substring(0, 3) == "SS8")  // PRO , BOT , BOT 2 Mode
  {
    P0str = bufferString.substring(3, 5);
    P0Value = strtol(P0str.c_str(), nullptr, 16);
    P1str = bufferString.substring(5, 7);
    P1Value = strtol(P1str.c_str(), nullptr, 16);
    P2str = bufferString.substring(7, 9);
    P2Value = strtol(P2str.c_str(), nullptr, 16);
    P3str = bufferString.substring(9, 11);
    P3Value = strtol(P3str.c_str(), nullptr, 16);
    P4str = bufferString.substring(11, 13);
    P4Value = strtol(P4str.c_str(), nullptr, 16);
    P5str = bufferString.substring(13, 15);
    P5Value = strtol(P5str.c_str(), nullptr, 16);
    P6str = bufferString.substring(15, 17);
    P6Value = strtol(P6str.c_str(), nullptr, 16);
    P7str = bufferString.substring(17, 19);
    P7Value = strtol(P7str.c_str(), nullptr, 16);
#ifdef DEBUG
    Serial.print(P0Value, DEC); Serial.print(" ");
    Serial.print(P1Value, DEC); Serial.print(" ");
    Serial.print(P2Value, DEC); Serial.print(" ");
    Serial.print(P3Value, DEC); Serial.print(" ");
    Serial.print(P4Value, DEC); Serial.print(" ");
    Serial.print(P5Value, DEC); Serial.print(" ");
    Serial.print(P6Value, DEC); Serial.print(" ");
    Serial.print(P7Value, DEC); Serial.println(" ");
#endif
    Value0 = map(P0Value, 100, 200, -100, 100);
    Value1 = map(P1Value, 100, 200, -100, 100);
    Value2 = map(P2Value, 100, 200, 0, 180);
    Value3 = map(P3Value, 100, 200, 0, 180);
    Value4 = map(P4Value, 100, 200, -100, 100);
    Value5 = map(P5Value, 100, 200, -100, 100);
    Value6 = map(P6Value, 100, 200, 0, 180);
    Value7 = map(P7Value, 100, 200, 0, 180);
    if (Value1 == 0)  // spin
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, -50, 50);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, -50, 50);
    } else if (Value1 > 0)  // forward
    {
      leftWheel = Value1 - Value0;
      leftWheel = constrain(leftWheel, 0, 100);
      rightWheel = Value1 + Value0;
      rightWheel = constrain(rightWheel, 0, 100);
    } else  // Backward
    {
      leftWheel = Value1 + Value0;
      leftWheel = constrain(leftWheel, -100, 0);
      rightWheel = Value1 - Value0;
      rightWheel = constrain(rightWheel, -100, 0);
    }
    POP32_ModePRO(leftWheel, rightWheel, Value2, Value3, Value4, Value5, Value6, Value7);
  } else {
    // Serial.write("ERROR");
  }
}
void POP32_ModeCAR(int Wheel1, int Wheel2) {
  motor(1, Wheel1);
  motor(2, Wheel2);
}
void POP32_ModeTANK(int Wheel1, int Wheel2, int Wheel3, int Wheel4) {
  motor(1, Wheel1);
  motor(2, Wheel2);
  motor(3, Wheel3);
  motor(4, Wheel4);
}
void POP32_ModePRO(int Wheel1, int Wheel2, int Arm1, int Arm2, int Wheel3, int Wheel4, int Arm3, int Arm4) {
  motor(1, Wheel1);
  motor(2, Wheel2);
  servo(1, Arm1);
  servo(2, Arm2);
  motor(3, Wheel3);
  motor(4, Wheel4);
  servo(3, Arm3);
  servo(4, Arm4);
}
// When no data is received, return to the preset value;
void processFailSave() {
  // Stop all motors;
  AO();
}

อธิบายโปรแกรม

โปรแกรมนี้ถูกออกแบบมาเพื่อใช้กับบอร์ด POP32 สำหรับรับคำสั่งควบคุมจากแอปพลิเคชัน V7RC ผ่านบลูทูธ โดยเมื่อเริ่มทำงานจะแสดงชื่ออุปกรณ์ที่เชื่อมต่อผ่านหน้าจอ OLED และเข้าสู่ระบบการรอรับชุดข้อมูลขนาด 20 ตัวอักษรอย่างต่อเนื่อง

หัวใจหลักของโปรแกรมคือฟังก์ชัน V7RCCommand ที่ทำหน้าที่แยกแยะโหมดการทำงานตามที่ผู้ใช้เลือกในแอป หากเลือกโหมด CAR หรือ TANK โปรแกรมจะเน้นไปที่การคำนวณทิศทางเพื่อควบคุมมอเตอร์ขับเคลื่อนให้เดินหน้า ถอยหลัง หรือหมุนตัว แต่หากเลือกโหมด PRO โปรแกรมจะปลดล็อกการควบคุมที่ละเอียดขึ้น โดยสามารถสั่งการมอเตอร์ได้ 4 ตัว และเซอร์โวมอเตอร์ได้อีก 4 ตัวพร้อมกัน ซึ่งเหมาะสำหรับหุ่นยนต์ที่มีระบบแขนกลหรืออุปกรณ์เสริมหลายส่วน

นอกจากนี้ โปรแกรมยังมีระบบความปลอดภัยที่เรียกว่า Fail-Safe ซึ่งจะคอยตรวจสอบสัญญาณอยู่ตลอดเวลา หากสัญญาณขาดหายเกิน 0.5 วินาที โปรแกรมจะสั่งหยุดการทำงานของมอเตอร์ทั้งหมดทันที

ในการทดลองนี้จะเลือกใช้โหมด PRO เนื่องจากที่หน้าต่างควบคุมของโหมด PRO สามารถควบคุมมอเตอร์ได้ 4 ตัว และเซอร์โวมอเตอร์ได้อีก 4 ตัวเช่นกัน จึงเหมาะในการนำมาใช้งานเพื่อควบคุมการทำงานของชุด POP-BOT32i Rover Kit Plus

ตัวอย่างการใช้งาน V7RC ร่วมกับชุด POP-BOT32i Rover Kit Plus

Facebook Comments Box