Giải thuật lấy mẫu ADC sân thi đấuLấy mẫu ADC sân thi đấu là một phương án rất hiệu quả trong dò đường, lấy mẫu ADC giúp tiết kiệm thời gian lấy mẫu sân so với phương pháp dùng mạch so sánh ngày xưa. Ngoài ra lấy mẫu ADC còn rất xác hơn, có thể thích hợp với mọi loại sân thi đấu mà không sợ trường hợp ở nhà robot chạy 1 kiểu lên sân thi đấu robot lại chạy kiểu khác. Nó giúp phần thiết kế mạch đỡ cồng kềnh hơn, và vì thế robot chạy ổn định hơn. Có nhiều cách để lấy mẫu ADC sân thi đấu phục vụ dò đường. Duới đây là 1 bài viết về cách lấy mẫu ADC mà tôi học được từ đàn anh đí trứơc. Nếu ai muốn nhanh mà tiện có thể mua sẵn module LTM02 của phòng nghiên cứu HLAP (http://hlab.com.vn). Với module này có 2 nút lấy mẫu sân và lấy mẫu vạch, chủ cần nhấn nút là xong. Tôi sẽ không bàn luận về phương pháp này, mà hôm nay tôi sẽ trình bày phương pháp lấy mẫu sân thi đấu tự động. Có nghĩa là robot sẽ tự động so sánh màu sân thi đấu sau đó tự động lấy ngưỡng và so sánh ngưỡng. Từ đó robot sẽ biết được đâu là vạch trắng đâu là sân. Chúng ta sẽ cần 1 nút để lưu cảm biến (CB) trong bàn phím điều khiển robot. Khi lấy mẫu các bạn đưa robot của mình đến vị trí có cả vạch trằng cả sân (nên lấy mẫu ở vị trí sân có màu gần với màu của vạch nhất). Sau đó cho robot đi một đoạn sao cho tất cả sensor đi hết qua cả vạch trắng cả nền sân. như vậy giá trị mẫu ADC đã đựợc phân tích và lưu lại.
Robot dò đường
Giải thuật lấy mẫu ADC dò đường đơn kênh
Hình trên là 1 lưu đồ thuật toán về việc lấy trung bình giá trị ADC phục vụ dò đường của 1 kênh đơn (1 sensor), giá trị này sẽ được sao lưu vào eeprom trong suốt quá trình thi đấu. Với mỗi sân khác nhau giá trị này cũng khác nhau. Sử dụng ADC giúp tiết kiệm thời gian lấy mẫu sân và chính xác hơn phương pháp dùng mạch so sánh thông thường.
Lấy mẫu sân thi đấu là lấy giá trị trung bình ADC của điểm có giá trị ADC nhỏ nhât với điểm có giá trị ADC lớn nhất. Để chống nhiễu khi lấy giá trị ADC quá trình này được lặp đi lặp lại 8 lần. Sau đó được lặp lại thêm 100 lần nữa nhằm lấy mẫu được một khoảng sân dài hơn và giá trị ADC khi đó cũng chính xác hơn. Sau 100 lần lặp này thu được giá trị max_cb và min_cb. Tiếp theo toàn bộ quá trình lại được lặp lại với số lần bằng giá trị được truyền vào thông qua biến solan. Qua mỗi vòng lặp lần thứ 3 giá trị max_cb lại được cộng dồn và lưu vào biến MAX. Thoát khỏi vòng lặp, giá trị trung bình của n vòng lặp lại được lưu vào biến KQ_MAX, KQ_MAX là giá trị lớn nhất của ADC sau rất nhiều vòng sàng lọc. Sau khi đã lấy được các giá trị lớn nhất và nhỏ nhất của ADC là KQ_MAX và cb_min sẽ tiếp tục lấy trung bình 2 giá trị này để tạo ra ngưỡng so sánh ADC.
So sánh ngưỡng ADC
void TB_ADC(int so_lan)
{
int i=0,j=0,n=0;
int max_cb[8]={0,0,0,0,0,0,0,0};
int min_cb[8]={255,255,255,255,255,255,255,255};
int MAX[8] ={0,0,0,0,0,0,0,0};
int KQ_MAX[8]={0,0,0,0,0,0,0,0};
for(n=0;n<so_lan;n++)
{
for(j=0;j<100;j++)
{
doc_cam_bien();
for(i=0;i<8;i++)
{
/////////////////////////////// Lấy giá trị cb_max và cb_min ////////////////////////
if(max_cb[0]<L[0])
{max_cb[0]=L[0];}
if(min_cb[0]>L[0])
{min_cb[0]=L[0];}
if(max_cb[1]<L[1])
{max_cb[1]=L[1];}
if(min_cb[1]>L[1])
{min_cb[1]=L[1];}
if(max_cb[2]<L[2])
{max_cb[2]=L[2];}
if(min_cb[2]>L[2])
{min_cb[2]=L[2];}
if(max_cb[3]<L[3])
{max_cb[3]=L[3];}
if(min_cb[3]>L[3])
{min_cb[3]=L[3];}
if(max_cb[4]<L[4])
{max_cb[4]=L[4];}
if(min_cb[4]>L[4])
{min_cb[4]=L[4];}
if(max_cb[5]<L[5])
{max_cb[5]=L[5];}
if(min_cb[5]>L[5])
{min_cb[5]=L[5];}
if(max_cb[6]<L[6])
{max_cb[6]=L[6];}
if(min_cb[6]>L[6])
{min_cb[6]=L[6];}
if(max_cb[7]<L[7])
{max_cb[7]=L[7];}
if(min_cb[7]>L[7])
{min_cb[7]=L[7];}
/////////////////////////////////////////////////////////////////////////
}
}
/////////////Cộng dồn giá trị cb_max ////////////////////////////////////////
MAX[0] = max_cb[0]+ MAX[0];
MAX[1] = max_cb[1]+ MAX[1];
MAX[2] = max_cb[2]+ MAX[2];
MAX[3] = max_cb[3]+ MAX[3];
MAX[4] = max_cb[4]+ MAX[4];
MAX[5] = max_cb[5]+ MAX[5];
MAX[6] = max_cb[6]+ MAX[6];
MAX[7] = max_cb[7]+ MAX[7];
///////////////////////////////////////////////////////////////////////
}
for(i=0;i<n;i++)
{
KQ_MAX[i] = MAX[i]/n; // Lấy trung bình giá trị cb_max sau 800 lần lặp
MAX[i]=0;
}
for(i=0;i<8;i++)
{
erom_ADC[i]=(KQ_MAX[i] + min_cb[i])/2; //Approximation ADC
}
luu_CB(); // Luu ngưỡng giá trị cảm biên vào eeprom
}
Việc so sánh ngưỡng ADC sẽ quyết định xem đâu là vạch trắng đâu là nền sân, từ đó quyết định đâu là mức 1 đâu là mức 0.
Giải thuật lưu sensor ADC trong dò đường
void cam_bien()// Thoi gian de doc duoc ham nay la 276us
{
int i=0;
sensor=0B00000000;
L[0]=read_adc(7);
L[1]=read_adc(6);
L[2]=read_adc(5);
L[3]=read_adc(4);
L[4]=read_adc(3);
L[5]=read_adc(2);
L[6]=read_adc(1);
L[7]=read_adc(0);
for(i=0;i<8;i++)
{
if(L[i]<=ADC[i])
{
sensor |= w[7-i];
}
else sensor |= 0;
}
// return sensor;
}
sensor là biến lưu vị trí các cảm biến trên giàn dò. Khi có 1 cảm biến chạm vào vạch, thì bit ở vị trí tương ứng với vị trí của cảm biến đó được đưa lên thành mức 1.
Giải thuật dò đường
Bắt đầu chương trình biến sensor được đưa về 0, sau đó tiến hành đọc tất cả các đầu vào cảm biến. Sau khi đọc xong, các giá trị này được lấy ra lần lượt và so sánh với mẫu ADC đã được lưu trong eeprom. Nếu giá trị ADC của cảm biến này nhỏ hơn giá trị mẫu ADC thì quyết định đó là vạch trắng và bit tương ứng trong biến sensor sẽ được nhờ phép toán hoặc bit (sensor |= w[7-i]) đưa lên thành mức 1.
Mảng w[8] gồm có các phần tử: {1, 2, 4, 8, 16, 32, 64, 128}.
Ví dụ: LED ngoài cùng phía bên trái (i=0) chạm vạch tương ứng với vị trí R7 khi đó:
So sánh L[0] < ADC[0] nên sẽ thực hiện phép toán:
sensor |= w[7-i] ó sensor = sensor | 128
ó sensor = 00000000b | 10000000 = 10000000
ó sensor = 10000000. (R7)
Như vậy, bit tương ứng với LED ngoài cùng bên trái đã được đưa lên thành mức 1. Toàn bộ quá trình này chỉ tốn 276us.