ในส่วนต่อไปคือโปรแกรมในการเคลื่อนที่นั้นนอกจากจะใช้ encoder ในการวัดระยะในการเคลื่อนที่แล้ว ยังสามารถนำมาควบคุมความเร็วในการเคลื่อนที่ได้อีกด้วย โดยจะใช้หลักการนับสัญญาณพัลส์ได้กี่พัลส์ใน 100 มิลลิเซค (ms)
ยกตัวอย่าง :: ถ้ามอเตอร์หมุนและส่งสัญญาณพัลส์ได้ 10 พัลส์ต่อ 100 มิลลิเซค ถ้ารับสัญญาณพัลส์ได้ น้อยกว่า 10 พัลส์จะทำการเพิ่มความเร็วมอเตอร์ แต่ถ้ารับสัญญาณพัลส์ได้มากกว่า 10 จะลดความเร็วมอเตอร์
ถ้าในระหว่างการสำรวจเส้นทางถ้าหุ่นยนต์เกิดการเอียงจะใช้ Ultrasonic ในการช่วยตรวจสอบและปรับความเร็วมอเตอร์ได้ โดยการที่เราแบ่งช่วงเซ็นเซอร์ของ Ultrasonic เป็นระยะใกล้ กลาง ไกล จะเทียบกับกำแพง ถ้าวัดได้ระยะใกล้จะทำการเพิ่มความเร็วมอเตอร์ข้างซ้าย
ถ้าวัดได้ระยะกลางจะทำการปรับความเร็วมอเตอร์ทั้ง 2 ข้างเท่ากัน
ถ้าวัดได้ระยะไกลจะทำการเพิ่มความเร็วมอเตอร์ข้างขวา
การติดต่อสื่อสารระหว่างหุ่นยนต์กับคอมพิวเตอร์
การสื่อสารระหว่างหุ่นยนต์และคอมพิวเตอร์ จะอาศัย การสื่อสารแบบไร้สายระยะใกล้ คือ การใช้
บลูทูท (Bluetooth) ส่งข้อความหรือ ตัวเลขเพื่อสื่อสารกัน
1. การส่งข้อมูลของคอมพิวเตอร์ถึง หุ่นยนต์
ใน หุ่นยนต์ สามารถเคลื่อนที่ได้ 4 ลักษณะ คือ การเดินไปข้างหน้า การหันไปทางซ้าย การหันไปทางขวา และการหันกลับหลัง
ดังนั้นเมื่อถึงเวลาที่ต้องสำรวจ (Exploration) จะต้องส่งคำสั่งให้กับหุ่น รหัสการสั่งมีดังนี้
รหัสเลข 0 จะเป็นคำสั่งให้หุ่นเคลื่อนไปข้างหน้า
รหัสเลข 1 จะเป็นคำสั่งให้หุ่นเคลื่อนถอยหลัง
รหัสเลข 2 เป็นคำสั่งให้เลี้ยวซ้าย
รหัสเลข 3 เป็นคำสั่งให้เลี้ยวขวา
รหัสเลข 4 เป็นคำสั่งให้หันกลับหลัง
รหัส 0 1 2 3 4 นั้นมีประโยชน์ต่อการโปรแกรม ในภาษา ซี อันเนื่องจาก คุณสมบัติของ enumeration ซึ่งสามารถใช้ตัวเลข เพื่อเรียก ข้อความที่อยู่ในฟังก์ชัน enum ทำให้สะดวกต่อการเรียกใช้และประมวลผลของโปรแกรมจากคอมพิวเตอร์
รหัส 0 1 2 3 4 นั้นมีประโยชน์ต่อการโปรแกรม ในภาษา ซี อันเนื่องจาก คุณสมบัติของ enumeration ซึ่งสามารถใช้ตัวเลข เพื่อเรียก ข้อความที่อยู่ในฟังก์ชัน enum ทำให้สะดวกต่อการเรียกใช้และประมวลผลของโปรแกรมจากคอมพิวเตอร์
2. การส่งข้อมูลของหุ่นยนต์ไปยังคอมพิวเตอร์
เนื่องจากว่า สิ่งกีดขวางของหุ่นประกอบไปตามเซ็นเซอร์อัลตราโซนิก ซึ่งติดตั้งในหุ่น ทำให้หุ่นสามารถตรวจจับสิ่งกีดขวาง รวมถึงมี กล้องจับสีภาพ PIXY ช่วยในการจับสีที่กล้องตรวจจับได้
สิ่งกีดขวางที่เป็นไปได้คือ กำแพง ด้านต่างๆ ซึ่งประกอบไปด้วย กำแพงด้านซ้าย ด้านขวา และข้างหน้า
ดังรูปที่ 1 สิ่งกีดขวาง หรือ พื้นที่ว่าง ดังรูปที่่ 2
ดังรูปที่ 1 สิ่งกีดขวาง หรือ พื้นที่ว่าง ดังรูปที่่ 2
รูปที่ 1 รูปแสดงตำแหน่งการติดตั้งของอุปกรณ์ตรวจจับ หรือ เซนเซอร์อัลตราโซนิก
ค่าที่ตรวจจับ หากเป็นกำแพง จะส่งค่าที่เป็น 1 มาทำให้ทราบว่ามีสิ่งกีดขวาง
ค่าที่ถูกตรวจจับ หากเป็นช่องว่าง จะส่งค่าที่เป็น 0 มาทำให้ทราบว่าบริเวณนั้นเป็นทางที่สามารถเดินได้
ตามตัวอย่าง ดังรูปที่ 3
ตามตัวอย่าง ดังรูปที่ 3
ค่าเหล่านี้ก็จะถูกส่งกลับไปยัง คอมพิวเตอร์เพื่อสร้างแผนที่ที่ สำรวจ
การจับสีภาพของกล้อง pixy นั้นจะสามารถทำได้โดยการกำหนด หาก สีเป็นดังต่อไปนี้
รหัสสี 0 หมายถึง สีขาว
รหัสสี R หมายถึง สีแดง
รหัสสี G หมายถึง สีเขียว
รหัสสี B หมายถึง สีน้ำเงิน
รูปที่ 4 รูปแสดง รหัสของการตรวจจับสี โดยกล้อง pixy
Source Code #
#include <AFMotor.h>
float dir = 0.0, error = 0.0, no_wall = 40;
int sl = 0, sr = 0, spd_l = 200, spd_r = 250, sl_c = 0, sr_c = 0;
enum Wallcolor {white, red, green, blue, orange};
enum direct {forw, left, right, retn, right2, left2};
enum command {fow, lef, rgt, rtn, none, rtn2};
enum ck_sen {clr, ct_sen, sd_data, ct_rtn, ct_fw};
int en1 = 21, en2 = 20; //180//180
int n = 0, clr_n = 0, start2 = 0;
char p1 = ' ', p = ' ';
char test[128];
int n_reval = 0, kk = 0;
unsigned de = 0;
unsigned int ti, ti_pre = 0;
int mode1 = 0, mode = 0, mode2 = 0 , mode3 = 0 , n_sf = 0;
char p3;
String data;
String sm[3];
int sen[3], sd[3];
int nn = 0;
int Scut = 0;
ck_sen ck_sn;
direct dirt;
command cmd;
AF_DCMotor m1(1);
AF_DCMotor m2(2);
void setup()
{
pinMode(en1, INPUT);
pinMode(en2, INPUT);
pinMode(32, OUTPUT);
attachInterrupt(digitalPinToInterrupt(en1), en_l, RISING );
attachInterrupt(digitalPinToInterrupt(en2), en_r, RISING );
Serial.begin(9600);
Serial1.begin(9600); // For uno
Serial2.begin(9600); //For Bluetooth
m1.setSpeed(199);
m2.setSpeed(245);
mode = 0; clr_en();
m_stp();
delay(2000); p1 = ' '; p = ' '; cmd = none; ck_sn = clr;
digitalWrite(32, HIGH);
delay(20);
digitalWrite(32, LOW); //m_for();
// Serial2.println("R");
}
void loop()
{
//Serial.println(test);
if (sen[0] <= 13 )
{
if ((sen[0] > 0 && sen[0] < 8) && (sen[2] < 38 && sen[2] > 16))
{
dirt = right;
}
else if ((sen[0] > 0 && sen[0] <= 13) && sen[2] > 38)
{
dirt = forw;
}
else if ((sen[0] > 0 && sen[0] < 8) && sen[2] < 16 && sen[2] > 9)
{
dirt = right2;
}
else
{
dirt = forw;
}
}
else if (sen[0] > 16)
{
if ((sen[2] > 0 && sen[2] < 8 ) && (sen[0] < 38 && sen[0] > 16))
{
dirt = left;
}
else if ((sen[2] > 0 && sen[2] < 8 ) && sen[0] > 38)
{
dirt = forw;
}
else if ((sen[2] > 0 && sen[2] < 8 ) && sen[0] < 16 && sen[0] > 9)
{
dirt = left2;
}
else
{
dirt = forw;
}
}
////////////////////////////
if (ck_sn == ct_sen)
{ if (sd[0] == 1 && sd[1] == 1 && sd[2] == 1)
{
digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
}
else
{
digitalWrite(32, LOW); delay(50);
}/*
Serial.print(sd[0]); Serial.print(","); Serial.print(sd[1]); Serial.print(","); Serial.print(sd[2]);
Serial.print(","); Serial.println(white);*/
de++;
if (de > 28)
{
de = 0;
ck_sn = sd_data;
}
}
else if (ck_sn == sd_data)
{ de++; delay(50);
if (de > 15)
{ de = 0;
clr_en();
if (sen[1] < 14)
{
ck_sn = ct_rtn; de = 0;
}
else if (sen[1] < 37 && sen[1] > 20)
{
ck_sn = ct_fw; de = 0;
}
else
{
Serial2.print(sd[0]); Serial2.print(","); Serial2.print(sd[1]); Serial2.print(","); Serial2.print(sd[2]);
Serial2.print(","); Serial2.println(white);
digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
clr_en(); ck_sn = clr;
de = 0;
}
}
}
else if (ck_sn == ct_rtn)
{ // Serial2.println(sen[1]);
m_re(); de = 0;
if (sl > 12 && sr > 12)
{ Serial.print("yyy "); Serial.println(ck_sn);
de = 0;
m_stp();
delay(800);
clr_en(); ck_sn = ct_sen;
}
}
else if (ck_sn == ct_fw)
{
m_for();
de = 0;
if (sl > 12 && sr > 12)
{ Serial.print("yyy "); Serial.println(ck_sn);
de = 0;
m_stp();
delay(800);
clr_en(); ck_sn = ct_sen;
}
}
if (p1 == '0' || cmd == fow )//
{ m_for(); ck_spd(); de++;
/* sprintf(test, " S1 =%d S2=%d spd_l %d spd_r %d %s|", sen[0], sen[2], spd_l, spd_r, dirt);
Serial2.println(test);*/
// Serial2.print(test); Serial2.print(" error" ); Serial2.print(error); Serial2.print(" dir "); Serial2.println(dir);
if (sl > 116 && sr > 116 )
{
m_stp();
clr_en(); p1 = ' '; de = 0;
cmd = none;
ck_sn = ct_sen;
}
ck_local();
}
else if (p1 == '2' || cmd == rgt) //2
{ m_rr();
if (sl >= 73)
{
n = 1;
m_stp();
delay(800);
// Serial2.println(sl);
//delay(1200);
if (sl > 80 && sl <= 100)
{
mode2 = 1;
n_sf = sl - 80;
}
else if ( sl <= 75 && sl > 63)
{
n_sf = 78 - sl;
mode2 = 2;
}
else
{ mode2 = 0; clr_en();
m_stp();
delay(800);
}
clr_en();
if (mode2 != 0)
{
while (1)
{
if (mode2 == 1)
{
m_rr_re();
if (sl >= n_sf)
{
m_stp();
delay(800);
break;
}
}
else if (mode2 == 2)
{
m_rr();
if (sl >= n_sf)
{
m_stp();
delay(800);
break;
}
}
}
p1 = ' ';
mode2 = 0;
}
if (mode2 == 0)
{
cmd = none; p1 = ' '; Serial2.println("R"); Serial.println("R"); digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
clr_en();
ck_local();
}
}
}
else if (p1 == '1' || cmd == lef)
{
m_ll();
if (sr >= 70)
{
n = 1;
m_stp();
delay(800);
// Serial2.println(sr);
if (sr > 82 && sr <= 100)
{
mode3 = 1;
n_sf = sr - 82;
}
else if ( sr >= 64 && sr < 70)
{
n_sf = 70 - sr;
mode3 = 2;
}
else
{
mode3 = 0; clr_en();
m_stp();
delay(800);
}
clr_en();
if (mode3 != 0)
{
while (1)
{
if (mode3 == 1)
{
m_ll_re();
if (sr >= n_sf)
{
m_stp();
delay(800);
break;
}
}
else if (mode3 == 2)
{
m_ll();
if (sr >= n_sf)
{
m_stp();
delay(800);
break;
}
}
}
mode3 = 0; clr_en(); p1 = ' ';
}
if (mode3 == 0)
{
cmd = none; Serial2.println("R"); Serial.println("R"); digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
clr_en(); p1 = ' '; //spd_l = 165; spd_r = 230;
n_reval = 1;
ck_local();
}
}
}
else if (p1 == '3' || cmd == rtn)
{
m_r();// return
if (sl > 68)
{
m1.setSpeed(0);
}
if (sr > 72)
{
m2.setSpeed(0);
}
if (sl > 70 && sr > 71)
{
m_stp();
delay(800);
if (sr > 90)
{ n_sf = sr - 84; clr_en();
m_ll();
while (sr < n_sf)
{
m_ll();
} m_stp(); delay(500);
}
// Serial2.print(sl); Serial.print(" "); Serial2.println(sr);
Serial2.println("R"); Serial.println("R"); digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
cmd = none; clr_en(); p1 = ' ';
// spd_l = 214; spd_r = 230;
n_reval = 1;ck_local();
}
}
else if ( cmd == rtn2)
{
m_l();// return
if (sl > 68)
{
m1.setSpeed(0);
}
if (sr > 72)
{
m2.setSpeed(0);
}
if (sl > 66 && sr > 69)
{
m_stp();
delay(800);
if (sl > 90)
{ n_sf = sl - 84;
clr_en();
while (sl < n_sf)
{ //Serial2.println("ee");
m_rr();
} m_stp(); delay(500);
}
// Serial2.print(sl); Serial.print(" "); Serial2.println(sr);
Serial2.println("R"); Serial.println("R"); digitalWrite(32, HIGH);
delay(50);
digitalWrite(32, LOW);
cmd = none; clr_en(); p1 = ' ';
spd_l = 220; spd_r = 230; n_reval = 1;
}
}
else if (p1 == '5' )
{
m_re(); Serial.println(sen[1]);
if (sl > 15 && sr > 15)
{
m_stp();
delay(800);
clr_en(); p1 = ' ';
}
}
}
void m_for()
{
m1.run(FORWARD);
m2.run(FORWARD);
}
void m_re()
{ m1.setSpeed(199);
m2.setSpeed(245);
m1.run(BACKWARD);
m2.run(BACKWARD);
}
void m_rr()
{
m1.setSpeed(199);
m2.setSpeed(245);
m1.run(FORWARD);
m2.run(RELEASE);
}
void m_rr_re()
{
m1.run(BACKWARD);
m2.run(RELEASE);
}
void m_r()
{
m1.setSpeed(240);
m2.setSpeed(255);
m1.run(FORWARD);
m2.run(BACKWARD);
}
void m_l()
{
m1.setSpeed(230);
m2.setSpeed(255);
m2.run(FORWARD);
m1.run(BACKWARD);
}
void m_ll()
{
m1.setSpeed(199);
m2.setSpeed(245);
m2.run(FORWARD);
m1.run(RELEASE);
}
void m_ll_re()
{
m2.run(BACKWARD);
m1.run(RELEASE);
}
void m_stp()
{
m1.run(RELEASE);
m2.run(RELEASE);
}
void en_l()
{
sl++; sl_c++;
}
void en_r()
{ sr++; sr_c++;
}
void clr_en()
{
sl = 0; sr = 0;
}
void clr_en_spd()
{
sl_c = 0; sr_c = 0;
}
void ck_local()
{
if (sen[0] > 0 && sen[0] < 8)
{
spd_l = 230; spd_r = 200;
}
else if (sen[2] > 0 && sen[2] < 8)
{
spd_l = 175; spd_r = 255;
}
else
{
spd_l = 193; spd_r = 245;
}
}
void ck_spd()
{
ti = millis() - ti_pre;
if (ti >= 100)
{ ti_pre = millis();
if (dirt == forw)
{ /*
spd_l = 199;
spd_r = 245;*/
// Serial.print("fowww ");
//Serial.println(test);
//spd_r = 245;
if (n_reval == 0)
{ spd_r = 245;
spd_l = 194;
}
else if (n_reval >= 3)
{
n_reval = 0;
}
else
{
n_reval++;
}
if (sl_c > 12)
{
spd_l -= 4;
}
else if (sl_c < 10)
{
spd_l += 4;
}
limit_spd();
}
else if (dirt == right)
{ //Serial.print("rigt ");
n_reval = 0;
spd_l += 6;
spd_r = 210;
limit_spd();
}
else if (dirt == right2)
{
n_reval = 0;
spd_l += 3;
spd_r = 228;
limit_spd();
}
else if (dirt == left)
{ //Serial.print("left ");
n_reval = 0;
spd_l = 170;
spd_r += 6;
limit_spd();
}
else if (dirt == left2)
{ //Serial.print("left ");
n_reval = 0;
spd_l = 185;
spd_r += 3;
limit_spd();
}
m1.setSpeed(spd_l);
m2.setSpeed(spd_r);
clr_en_spd();
}
}
void limit_spd()
{
if (spd_l > 255)
{
spd_l = 255;
}
else if (spd_l < 140)
{
spd_l = 140;
}
if (spd_r > 255)
{
spd_r = 255;
}
else if (spd_r < 200)
{
spd_r = 200;
}
}
void serialEvent2()
{
while (Serial2.available())
{
p1 = Serial2.read();
}
if (p1 == 'S')
{
Serial.println("CMP!! ");
Serial2.print("1,0,1,"); Serial2.println(white);
p1 = ' ';
}
if (p1 == '3')
{
p1 = ' ';
if (sen[0] > sen[2])
{
// Serial2.println("111");
cmd = rtn;
}
else
{ //Serial2.println("222");
cmd = rtn2;
}
}
digitalWrite(32, HIGH);
delay(300);
digitalWrite(32, LOW);
}
void serialEvent1()
{
while (Serial1.available())
{ p = Serial1.read();
if (p == ']')
{
Scut = 1;
} else
{
data += p;
}
}
if (Scut == 1)
{
Strcut();
Scut = 2;
con_step();
Scut = 0; data = "";
}
}
void Strcut()
{
while (1)
{ int check = data.indexOf(',');
if (check != -1)
{
sm[nn] = data.substring(0, check);
data = data.substring(check + 1, data.length());
nn++;
}
else
{
sm[nn] = data;
mode = 1;
nn = 0;
break;
}
}
}
void con_step()
{
sen[0] = sm[0].toInt();
sen[1] = sm[1].toInt();
sen[2] = sm[2].toInt();
if (sen[0] > 45)
{
sd[0] = 0;
}
else
{
sd[0] = 1;
}
if (sen[1] > 37)
{
sd[1] = 0;
}
else
{
sd[1] = 1;
}
if (sen[2] >= 45)
{
sd[2] = 0;
}
else
{
sd[2] = 1;
}
}
void serialEvent()
{
while (Serial.available())
{
p = Serial.read();
}
if (p == '0')
{
//p1 = '0';
p = ' ';
cmd = fow;
}
if (p == '1')
{
//p1 = '1';
p = ' ';
cmd = lef;
}
if (p == '2')
{
//p1 = '2';
p = ' ';
cmd = rgt;
}
if (p == '3')
{
// p1 = '3';
p = ' ';
cmd = rtn;
}
if (p == '4')
{
cmd = rtn2;
}
if (p == '5')
{
p = ' ';
p1 = '5';
}
}