[IPST-SE] แนวการเขียนโปรแกรม STEM FESTIVAL 2016 EP.2

ตอนที่ 2 การเคลื่อนที่ในเขาวงกต

DSC_2724_thumb.jpg

Stem battle

จากตอนที่ 1 การอ่าน Barcode มาสู่ตอนที่ 2 การเคลื่อนที่ในเขาวงกตโดยไม่มีเส้นกำกับ จะต้องมีอุปกรณ์อื่นๆ เข้ามาช่วย โดยในงานนี้ให้ใช้ โมดูลเข็มทิศ HMC5983

โมดูลเข็มทิศ HMC5983

hmc5983

โมดูลเข็มทิศดิจิตอล HMC5983 เป็นตัวตรวจจับสนามแม่เหล็กโลก จึงนำมาประยุกต์เป็นตัวตรวจจับทิศทางเพื่อช่วยกำหนดทิศทางการเคลื่อนที่ของหุ่นยนต์ได้  เหมาะกับพื้นที่สนามที่ไม่มีเส้นกำกับ

install Compass sensor

การติดตั้งโมดูล

จากรูปโครงสร้างทั้งหมดเป็นพลาสติก ไม่เกิดการรบกวนทำงานของเข็มทิศ  และต้องติดตั้งให้สูงเหนือตัวหุ่นยนต์ขึ้นไป

P60906-132016

 

การเชื่อมต่อ

โมดูลเข็มทิศ HMC5983 มีการสื่อสารด้วยระบบบัส I2C ประกอบด้วยขา SDA (ข้อรับส่งข้อมูล) SCL (ขาสัญญาณนาฬิกา)  ซึ่งขาทั้งสองมีติดตั้งอยู่ที่บอร์ด IPST-SE เรียบร้อยแล้ว
 

P60906-132053

 

ชุดคำสั่งสำหรับการติดต่อกับ HMC5983

เมื่อใช้งาน IPST-SE กับซอฟต์แวร์ Arduino เวอร์ชั่นล่าสุด จะสามารถใช้งานคำสั่งติดต่อกับเข็มทิศ HMC5983 ได้ทันที โดยมีคำสั่งที่ต้องใช้งานกับกิจกรรมนี้เพียงคำสั่งเดียวคือ

compass_read()

โดยฟังก์ชั่นนี้จะคืนค่า ทิศในช่วง 0-359 ออกมา

ตัวอย่างการอ่านค่าแสดงผลที่ glcd  

  setTextSize(2); glcdMode(1);
      glcd(2, 0, "%d  ", compass_read());

 การใช้งานเข็มทิศนั้น ก็เพื่อให้หุ่นยนต์เคลื่อนที่ตรงไปยังทิศทางที่ต้องการ และให้หุ่นยนต์หมุนตัวตรงไปยังทิศทางที่ต้องการ ดังนั้นก่อนการใช้งานโปรแกรม จำเป็นต้องสำรวจทิศ ของสนามก่อน โดยกำหนดเป็นตัวแปรขึ้นมาดังนี้

int N=50,E=122,S=168,W=300; โดยค่าเหล่านี้ ระบุทิศทั้ง 4 ที่เราเคลื่อนที่ โดยค่าจะไม่เป็นเชิงเส้นมากนัก และสำหรับค่าที่เกิดขึ้น อาจจะไม่เท่ากันทุกจุดในสนาม จะต้องมีการปรับจูน บวกลบค่าเพิ่มเติมจากค่าเหล่านี้ด้วย จากนั้น สร้างฟังกํชั่นเพื่อทำภารกิจต่างๆ

DSC_2723

สำหรับฟังก์ชั่นที่เกี่ยวข้องกับการใช้งานเข็มทิศ ต้องยกเครดิตให้ ครูนัฎฐิกา หลอดแก้ว แห่งโรงเรียนบางปลาม้า “สูงสุมารผดุงวิทย์” ที่อนุเคราะห์รูปแบบการเขียนโค้ดที่ดูเข้าใจง่าย แต่ทำงานได้อย่างมีประสิทธิภาพ 

ฟังก์ชั่นหมุนตัวไปจนกระทั่งถึงทิศที่ต้องการ

 

void rightUntil(int c) {
  while (compass_read()<c){sr(40);}
}
void leftUntil(int c) {
  while (compass_read()>c){sl(40);}
}

หลักการเขียนโปรแกรมง่ายๆ คือ ใช้ while ตรวจสอบเงื่อนไขการหมุนตัว โดยหมุนไปจนกระทั่งถึงทิศทางที่ต้องการ การหมุนจะต้องมีทั้งการหมุนทางซ้าย (leftUntil()) และหมุนทางขวา (rightUntil() ) เพื่อป้องกันการเคลื่อนที่ผ่านจุด 0 องศา ซึ่งจะทำให้การตรวจสอบทิศผิดพลาด

ตัวอย่าง

ปัจจุบันหุ่นยนต์อยู่ที่ตำแหน่ง 300 องศา(ทิศตะวันตก :W )  จะเคลื่อนที่ไปที่ตำแหน่ง 50 องศา (ทิศเหนือ : N) โดยปกติเราอาจจะเคลื่อนที่ทางขวา ช่วงเวลาสั้นๆ ได้ แต่ เพื่อไม่ให้ผ่านจุด 0 องศา เราจึงต้องใช้วิธีการเคลื่อนที่หมุนตัวทางซ้ายเพื่อไปที่ตำแหน่ง 50  องศาแทนโดยเขียนได้เป็น

leftUntil(50);

ฟังก์ชั่นเดินตรงไปตามทิศทางที่ต้องการ

DSC_2724

สำหรับฟังก์ชั่นนี้ จะเดินตรงไปเรื่อย ๆจนกว่าจะชนกำแพงดังนั้นจะต้องติดตั้งสวิตช์ที่ด้านหน้าหุ่นยนต์ด้วยดังรูป  โดยสวิตช์จะติดทั้งด้านหน้าและด้านหลัง เพื่อ ใช้ตรวจสอบทั้งการเดินหน้าและถอยหลัง

จากรูปสวิตช์ด้านหน้าต่อที่ขา 27 และสวิตช์ด้านหลังต่อที่ขา 30

void trackWallCompass(int c){   //แทร็กเข็มทิศ
    while(in(27)){
      if(compass_read()<=c+2&&compass_read()>=c-2){fd(40); }
      else if (compass_read()<c+2){tr(40);}
      else if (compass_read()>c-2){tl(40);}
    }ao();
  }

void trackWallBackCompass(int c) {   
  while (in(30)) {
    if (compass_read()<=c+2&&compass_read()>=c-2){bk(40);}
    else if (compass_read()<c+2){bk2(0,40);}
    else if (compass_read()>c-2){bk2(40,0);}
  } 
  ao();
}

การทำงานของโปรแกรมคือ ทำงานไปเรื่อยๆ จนเจอกำแพง โดยการอ่านค่าทิศทาง ถ้าค่าทิศทางอยู่ในช่วงผิดพลาดไม่เกิน +/- 2 องศาก็ให้หุ่นยนต์เดินตรงไป ถ้าเอียงไปด้านซ้ายก็ให้เลี้ยวซ้าย เอียงไปด้านขวาก็ให้เลี้ยวขวา

ฟังก์ชั่น เดินตรงด้วยเข็มทิศหยุดการเคลื่อนที่ด้วยเวลา

ฟังก์ชั่นนี้ใช้ในกรณีที่เดินตรงไป แล้วหยุดด้วยระยะทางที่กำหนด  เนื่องจากเราไม่มี encoder ช่วยระบุเวลาที่กำหนดได้ จึงจำเป็นต้องใช้ ฟังก์ชั่น millis() ซึ่งเป็นค่าเวลาของระบบเข้ามาช่วย  โดยฟังก์ชั่นนี้จะทำงานอยู่เบื้องหลังและให้ค่าเวลาส่งกลับมาให้เราตลอดเวลา ในหน่วยเป็นมิลลิวินาที ซึ่งนำค่านี้มาใช้จับเวลาการเคลื่อนที่ที่แม่นยำได้

void trackTimeCompass(int c,long t){ //แทร็กเข็มทิศด้วยเวลา
    long m=millis(); 
    while(millis()<(m+t)){
      if(compass_read()<=c+2&&compass_read()>=c-2){fd(40); }
      else if (compass_read()<c+2){tr(40);}
      else if (compass_read()>c-2){tl(40);}
    }ao();
}
void trackTimeBackCompass(int c,long t){ //แทร็กเข็มทิศ หยุดเมื่อหมดเวลา
    long m=millis(); 
    while(millis()<(m+t)){
      if(compass_read()<=c+2&&compass_read()>=c-2){bk(40); }
      else if (compass_read()<c+2){bk2(0,40);}
      else if (compass_read()>c-2){bk2(40,0);}
    }ao();
}

การทำงานของโปรแกรมจะเคลื่อนที่ตรงไปจนกว่าค่าเวลาจะมากกว่าค่าที่ตั้งไว้

 

 

 

จากฟังก์ชั่นทั้งหมดสามารถนำมาเขียนรูปแบบการเคลื่อนที่ในเขาวงกตได้ดังนี้

void MazeRight() {
  trackWallCompass(N);
  bk(30); delay(200); ao();
  rightUntil(W);
  trackWallCompass(W);  // ใข่ใบที่ 1
  bk(30); delay(200); ao();
  leftUntil(N);
  trackWallCompass(N);   
  bk(30); delay(200); ao();
  rightUntil(E);
  trackWallCompass(E);   // ใข่ใบที่ 2
  trackTimeBackCompass(E,2700);
  leftUntil(N+12);
  trackWallCompass(N+12);   // ใข่ใบที่ 3
  trackTimeBackCompass(N+12,900);
  rightUntil(E);
  trackTimeBackCompass(E,2300);
  leftUntil(N+12);
  trackWallCompass(N+12);   // ใข่ใบที่ 4
  trackWallBackCompass(N+12);
  fd(40);delay(200);ao();
  rightUntil(E);
  trackWallBackCompass(E);  
  fd(40);delay(200);ao();
  leftUntil(N);
  trackWallBackCompass(N);
  trackTimeCompass(N,1500);
  rightUntil(E);
  trackTimeCompass(E,2000);
  rightUntil(S+15);
  trackWallCompass(S+15);
  bk(40); delay(250); ao();
  rightUntil(W);
  trackWallCompass(W);  // ใขใบที่ 5
  bk(40); delay(250); ao();
  leftUntil(S+19);
  trackTimeCompass(S+19,3000);
  bk(40); delay(250); ao();
  }

 

void MazeLeft() {
  bk(30); delay(100);
  trackWallCompass(N);
  bk(30); delay(300); ao();
  rightUntil(E);
  trackWallCompass(E);
  bk(30); delay(300); ao();
  leftUntil(N);
  trackWallCompass(N);
  bk(30); delay(250); ao();
  rightUntil(W);
  trackWallCompass(W);
  bk(30); delay(300); ao();
  leftUntil(S);
  trackWallCompass(S);  //  ใข่ใบที่ 1
  trackWallBackCompass(S);
  fd(30); delay(250); ao();
  leftUntil(E);
  trackTimeCompass(E, 1000);
  leftUntil(N);
  trackWallCompass(N);
  bk(30); delay(150); ao();
  rightUntil(W);
  trackWallCompass(W);
  bk(30); delay(100); ao();
  leftUntil(N);
  trackWallCompass(N);   // ใข่ใบที่ 2
  trackWallBackCompass(N);
  fd(30); delay(250); ao();
  rightUntil(E);
  trackWallCompass(E);
  bk(30); delay(100); ao();
  leftUntil(N);
  trackWallCompass(N);
  bk(30); delay(150); ao();
  rightUntil(E);
  trackWallCompass(E);  // ใข่ใบที่ 3
  trackTimeBackCompass(E, 1000);
  rightUntil(S);
  trackWallCompass(S);
  bk(30); delay(150); ao();
  rightUntil(W);
  trackWallCompass(W);  // ใข่ใบที่ 4
  bk(30); delay(1000); ao();
  trackTimeBackCompass(W, 1000);
  leftUntil(S);
  trackWallCompass(S);
  bk(30); delay(1000); ao(); // ใข่ใบที่ 5
  leftUntil(E);
  trackWallCompass(E);
  bk(30); delay(100); ao();
  rightUntil(S);
  trackTimeCompass(S, 3000);
  LLL(); ao();
}

 

DSC_2724

Facebook Comments