Kết quả thử nghiệm với môi môi trường động

Một phần của tài liệu Nghiên cứu thiết kế và chế tạo robot vượt địa hình, bám đối tượng sử dụng công nghệ xử lý ảnh (Trang 82 - 124)

· Môi trường động webcam có độ phân giải (160x120) kết quả có 116 lần bị mất đối

tượng trong 1 phút.

· Môi trường động webcam có độ phân giải (176x144) kết quả có 97 lần mất đối tượng trong 1 phút.

Biểu đồ 6: Giá trị toạ độ tâm đối tượng môi trường động (176x144)

· Môi trường động webcam có độ phân giải (320x240) kết quả có 91 lần bị mất đối

tượng trong 1 phút.

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

· Môi trường động webcam có độ phân giải (640x480) kết quả 89 lần bị mất đối

tượng trong 1 phút.

Biểu đồ 8: Giá trị toạ độ tâm đối tượng môi trường động (640x480)

· Môi trường động đối tượng di chuyển ở tốc độ vừa phải phù hợp với tốc độ động

Biểu đồ 9: Giá trị tọa độ tâm đối tượng trong môi trường động tốc độ không đổi.

Nhận xét: Số lần mất đối tượng biểu hiện rõ nhất trên biểu đồ của của môi trường động, giống như nhận xét tổng quan lúc đầu các thuật toán trong môi trường tĩnh thực sự đã bỏ khá xa trong môi trường động. Biểu hiện cụ thể trong các thử nghiệm trên (ví dụ: webcam có độ phân giải (640x480) trong môi trường tĩnh có 17 lần bị mất đối tượng trong 1 phút, trong môi trường động là 89 lần trong 1 phút).

Có nhiều nguyên nhân, tuy nhiên trong trường hợp này phần lớn là do tốc độ động cơ 1 chiều được chọn quá chậm không đáp ứng kịp yêu cầu của phần mềm điều khiển. Cụ thể lúc theo dõi đối tượng ở tốc độ đối tượng ở mức độ phù hợp với tốc độ động cơ thì hệ thống làm việc rất tốt, số lần mất đối tượng trong môi trương động lúc này chỉ là 9.

Hệ thống đã được thử nghiệm ở nhiều trường hợp, trong hầu hết các tình huống khi điều kiện ánh sáng phù hợp, rô bốt có thể theo dõi đối tượng trên đường thẳng và các ngã rẽ, nếu đối tượng dừng lại rô bốt luôn điều chỉnh được đối tượng nằm ở vị trí mong muốn trên mặt phẳng ảnh. Tuy nhiên nếu trường hợp đối tượng di chuyển quá nhanh thì hệ thống gặp một ít vấn đề do tốc độ hệ thống không đáp ứng kịp.

Do tầm nhìn và tốc độ của webcam còn hạn chế, tốc độ đáp ứng của hệ thống không cao, do đó nếu đối tượng chuyển động quá nhanh hoặc hướng di chuyển thay đổi quá nhanh thì hệ thống sẽ bị mất đối tượng.

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

Hệ thống làm việc tốt dưới điều kiện ánh sáng vừa phải, nếu môi trường có độ sáng quá cao như ánh sáng mặt trời thì hệ làm việc rất kém do màu và độ sáng của đối tượng luôn thay đổi khi đối tượng thay đổi hướng.

KẾT LUẬN:

Đánh giá kết quả đạt được

Thứ nhất là thử nghiệm rô bốt trên một số địa hình ( đường ghồ ghề, mặt phẳng nghiêng có độ dốc lớn,...), rô bốt chạy ổn định và vượt qua một số địa hình phức tạp một cách dễ dàng.

Thứ hai báo cáo này mô tả hệ thống rô bốt di động bám đối tượng sử dụng thư viện xử lý ảnh OpenCV của Intel. Thuật toán sử dụng để nhận hình ảnh từ webcam tiến hành khử nhiễu, histogram, sử dụng thuật toán CamShift, tính toán tọa độ tâm, kích cỡ, góc, thiết kế khối giao tiếp RS232 sử dụng Microsoft Communication Version 6.0. Thiết kế mạch điều khiển động cơ sử dụng ATMEGA32. Dưới những điều kiện ánh sáng nhất định đối tượng có thể được tìm ra nhanh chóng chính xác mà ít bị ảnh hưởng của nhiễu.

Hoàn chỉnh được cả phần cứng và phần mềm của rô bốt, tiến hành chạy thử trên nhiều dạng môi trường khác nhau, ban đêm, ban ngày, ánh sáng mạnh, ánh sáng yếu, đường thẳng, đường vòng…kết quả, rô bốt luôn bám theo giữ đối tượng nằm ở trên một phần của mặt phẳng ảnh mà ta chọn.

Tuy nhiên chương trình còn hạn chế trong thiết kế phần cứng (khung xe), phần này còn yếu nên gây khó khăn trong việc di chuyển và động cơ của rô bốt di chuyển tốc độ chậm do đó không đáp ứng được tốc độ của webcam của rô bốt. Xử lý ảnh phụ thuộc rất nhiều vào chất lượng hình ảnh và tốc độ chụp hình của webcam. Tốc độ của rô bốt là cố định do chưa xây dựng thuật toán điều khiển tốc độ rô bốt phù hợp tốc độ dịch chuyển của đối tượng đang theo dõi.

Chương trình có thể được cải thiện bằng cách thêm một số hàm liên quan đến xử lý ảnh như đã trình bày ở trên. Tốc độ theo dõi đối tượng của thuật toán CamShift là tương

di chuyển quá nhanh. Nhược điểm của thuật toán CamShift có thể được cải thiện bằng thuật toán lọc Kalman. Điều này chưa được nghiên cứu do thời gian có hạn.

Chương trình điều khiển mới được thử nghiệm trên một số môi trường nhất định kết quả đạt được là tương đối tốt. Tuy nhiên trong xử lý ảnh vấn đề nhiễu trong môi trường rất quan trọng do đó cần có thêm nhiều thử nghiệm nữa mới có thể đánh giá được độ tin cậy của kết quả đạt được.

Webcam đang sử dụng có khả năng lọc nhiễu tương đối tốt. Tuy nhiên thời gian tính toán của rô bốt sẽ tăng lên nếu độ tương phản của webcam tăng lên. Trong ứng dụng này em sử dụng webcam có độ phân giải có thể điều chỉnh được cụ thể như sau (160x120, 176x144, 320x240, 640x480). Kết quả thực hiện cho thấy việc xử lý nhiễu khó khăn hơn với các webcam có độ phân giải tăng dần do nhiễu ảnh không cần thiết tăng lên, gần như không có thay đổi nhiều. Tuy nhiên với webcam có độ phân giải cao hơn thì chưa được kiểm nghiệm.

Các hàm lọc nhiễu có thể loại bỏ nhiễu gần như hoàn toàn, nhưng nó phải quét bức ảnh quá nhiều lần, do đó nó sẽ làm tăng thời gian tính toán của chương trình, các hàm này cần được cải thiện và tối ưu hơn.

Rô bốt được xây dựng để di chuyển trong trường hợp webcam đặt ở vị trí cao hơn so với đối tượng.

Hướng phát triển của đồ án (adsbygoogle = window.adsbygoogle || []).push({});

Rô bốt chỉ được thử nghiệm trên hệ thống có tốc độ thay đổi chậm, cần phải được thử nghiệm với hệ thống có tốc độ nhanh hơn.

Qua thử nghiệm cho thấy rô bốt hoạt động tốt. Thay vì dò tìm một vùng đặc biệt trên đối tượng như đường tròn màu đỏ, màu xanh v..v. Hệ thống cần được cải thiện để dò tìm đối tượng trực tiếp dựa vào các vùng đặc biệt trên đối tượng. Không chỉ màu sắc của đối tượng được sử dụng mà cần quan tâm đến các đặc điểm của cạnh, góc, như vậy sẽ tăng được độ tin cậy cho việc dò tìm đối tượng.

Phần xử lý ảnh nên bổ sung thêm bộ lọc Kalman để theo dõi những đối tượng chuyển động nhanh, kích thước bé sẽ khắc phục được nhược điểm của thuật toán CamShift.

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

Phần cứng cần bổ sung thêm thuật toán tăng, giảm tốc độ theo sự thay đổi tốc độ của đối tượng.

Kết quả thử nghiệm còn mang tính trực quan do đó cần xây dựng được khối phục vụ riêng cho việc thử nghiệm kết quả trong xử lý ảnh.

PHỤ LỤC A CHƯƠNG TRÌNH XỬ LÝ ẢNH //--- // Chương trình xử lý ảnh sử dụng trong đồ án // Ngày 31/05/2011. // Ngôn ngữ C++ //--- #include"stdafx.h" #include"afx.h" #include"cv.h" #include"highgui.h" #include"stdio.h" #include"cxcore.h" #include<windows.h> #include<tchar.h>

#include<iostream> #include<fstream>

IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0, *gray; CvHistogram *hist = 0; int backproject_mode = 0; int select_object = 0; int track_object = 0; int show_hist = 1; CvPoint origin; CvRect selection; CvRect track_window; CvBox2D track_box; CvConnectedComp track_comp; int hdims = 16; float hranges_arr[] = {0,180}; float* hranges = hranges_arr;

int vmin = 10, vmax = 256, smin = 30, count; CvPoint boxcenter,h;

int d2, d3,count1=0, dem=0; int high_switch_value = 256; int highInt = 0;

int low_switch_value = 0; int lowInt = 0;

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ int d0=0;

CvPoint seed_point = cvPoint(305,195); CvScalar color = CV_RGB(250,255,255); int g_switch_value = 0;

int filterInt = 0; int lastfilterInt = -1; //int position;

void switch_callback(int position ){ if( position == 0 ){

cvSmooth( backproject, backproject, CV_GAUSSIAN,3,3 );

}else if(position==1){

cvSmooth( backproject, backproject, CV_GAUSSIAN,5,5 );

}else if(position==2){

cvSmooth( backproject, backproject, CV_GAUSSIAN, 7, 7 );

}else if(position==3){ cvSmooth(backproject,backproject,CV_BLUR,7,7); }else if (position==4){ cvSmooth(backproject,backproject,CV_MEDIAN,7,7); } } IplConvKernel* element = 0;

int element_shape = CV_SHAPE_RECT;

//the address of variable which receives trackbar position update int open_pos=0, close_pos=0, erode_pos=0, dilate_pos=0;

COleVariant tmp(data_send_RS232); void Opening(int pos)

{

element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );

cvErode(backproject,backproject,element,1); cvDilate(backproject,backproject,element,1); cvReleaseStructuringElement(&element); }

void Closing(int pos) {

element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 ); (adsbygoogle = window.adsbygoogle || []).push({});

cvDilate(backproject,backproject,element,1); cvErode(backproject,backproject,element,1); cvReleaseStructuringElement(&element); }

void Erosion(int pos) {

element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );

cvErode(backproject,backproject,element,1); cvReleaseStructuringElement(&element); }

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

element = cvCreateStructuringElementEx( pos*2+1, pos*2+1, pos, pos, element_shape, 0 );

cvDilate(backproject,backproject,element,1); cvReleaseStructuringElement(&element); }

void on_mouse(int event,int x,int y,int flags,void* param ) { if( !image ) return; if( image->origin ) y = image->height - y; if( select_object ) { selection.x = MIN(x,origin.x); selection.y = MIN(y,origin.y);

selection.width = selection.x + CV_IABS(x - origin.x); selection.height = selection.y + CV_IABS(y - origin.y); selection.x = MAX( selection.x, 0 );

selection.y = MAX( selection.y, 0 );

selection.width = MIN( selection.width, image->width ); selection.height = MIN( selection.height, image->height ); selection.width -= selection.x;

switch(event ) { case CV_EVENT_LBUTTONDOWN: origin = cvPoint(x,y); selection = cvRect(x,y,0,0); select_object = 1; break; case CV_EVENT_LBUTTONUP: select_object = 0;

if( selection.width > 0 && selection.height > 0 ) track_object = -1;

break; }

}

// Chuyen doi tu khoang gian mau HSV den RGB

CvScalar hsv2rgb(float hue )

{

int rgb[3], p, sector;

static const int sector_data[][3]=

{{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}}; hue *= 0.033333333333333333333333333333333f; sector = cvFloor(hue); p = cvRound(255*(hue - sector)); p ^= sector & 1 ? 255 : 0; rgb[sector_data[sector][0]] = 255;

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ rgb[sector_data[sector][1]] = 0; rgb[sector_data[sector][2]] = p; return cvScalar(rgb[2], rgb[1], rgb[0],0); } void CTUBODlg::OnBnClickedButtonAuto() { FILE * xFile; FILE * yFile; FILE * demFile;

fopen_s (&demFile,"dem.txt","w"); fopen_s (&xFile,"X.txt","w");

fopen_s (&yFile,"Y.txt","w");

UpdateData(true); Setting(); CvCapture* capture = 0; capture = cvCaptureFromCAM(0); if( !capture ) {

fprintf(stderr,"Could not initialize capturing...\n"); // return -1;

}

printf("Hot keys: \n"

"\tESC - quit the program\n" "\tc - stop the tracking\n"

"\th - show/hide object histogram\n" (adsbygoogle = window.adsbygoogle || []).push({});

"To initialize tracking, select the object with mouse\n" ); // Tao track_bar.

cvNamedWindow("Histogram", 1 ); cvNamedWindow("MobileRobot", 1 );

cvSetMouseCallback("MobileRobot", on_mouse, 0 );

cvCreateTrackbar("Vmin","MobileRobot", &vmin, 256, 0 ); cvCreateTrackbar("Vmax","MobileRobot", &vmax, 256, 0 ); cvCreateTrackbar("Smin","MobileRobot", &smin, 256, 0 );

cvCreateTrackbar("Dilate","MobileRobot",&dilate_pos,10,Dilation); cvCreateTrackbar("Erode","MobileRobot",&erode_pos,10,Erosion);

cvCreateTrackbar("Filter","MobileRobot", &g_switch_value, 5, switch_callback ); //start:

for(;;) {

IplImage* frame = 0; int i, bin_w, c;

frame = cvQueryFrame( capture ); if( !frame )

break; if( !image ) {

/* allocate all the buffers */

image = cvCreateImage( cvGetSize(frame), 8, 3 );

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

cvFloodFill( image, seed_point, color, cvScalarAll(5.0),

cvScalarAll(5.0), NULL, 4, NULL );

hsv = cvCreateImage( cvGetSize(frame), 8, 3 ); hue = cvCreateImage( cvGetSize(frame), 8, 1 );

mask = cvCreateImage( cvGetSize(frame), 8, 1 );

gray = cvCreateImage( cvSize(320,240), 8, 1 );

backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); //cvThreshHist(hist,0);

hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );

histimg = cvCreateImage( cvSize(320,200), 8, 3 );

cvThreshold(histimg,histimg,low_switch_value,high_switch_value,CV_THRESH _BINARY);

cvZero( histimg ); }

cvCopy( frame, image, 0 );

cvCvtColor( image, hsv, CV_BGR2HSV ); if( track_object )

{

int _vmin = vmin, _vmax = vmax;

cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0), cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); cvSplit( hsv, hue, 0, 0, 0 ); if( track_object < 0 ) { float max_val = 0.f;

cvSetImageROI( hue, selection );

cvSetImageROI( mask, selection ); (adsbygoogle = window.adsbygoogle || []).push({});

cvCalcHist( &hue, hist, 0, mask );

cvNormalizeHist(hist,20*255);

cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );

cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); cvResetImageROI( hue );

cvResetImageROI( mask ); track_window = selection; track_object = 1;

cvZero( histimg );

bin_w = histimg->width / hdims; for( i = 0; i < hdims; i++ )

{

int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); CvScalar color = hsv2rgb(i*180.f/hdims);

cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), cvPoint((i+1)*bin_w,histimg->height - val), color, -1, 8, 0 );

} }

cvCalcBackProject( &hue, backproject, hist );

cvFloodFill( backproject, seed_point, color, cvScalarAll(5.0),

cvScalarAll(5.0), NULL, 4, NULL );

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/

cvEqualizeHist( backproject, backproject );

switch_callback(g_switch_value);

Erosion(erode_pos);

Dilation(dilate_pos);

//Closing(close_pos);

cvAnd( backproject, mask, backproject, 0 );

cvCamShift( backproject, track_window,

cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),

&track_comp, &track_box ); track_window = track_comp.rect;

if( backproject_mode )

cvCvtColor( backproject, image, CV_GRAY2BGR ); if(!image->origin)

track_box.angle = -track_box.angle;

cvCircle( image, boxcenter, 50, CV_RGB(255,0,0), 1, 8,0);\

track_box.angle = -track_box.angle;

CvPoint2D32f dcenter=track_box.center; (adsbygoogle = window.adsbygoogle || []).push({});

boxcenter=cvPointFrom32f(dcenter);

m_IntX=boxcenter.x;

m_IntY=boxcenter.y;

fprintf (xFile," %4d\n",m_IntX);

fprintf (yFile," %4d\n",m_IntY);

float s=h*w;

m_floatkichthuoc=s;

m_floatGoc=track_box.angle;

cvCircle( image, boxcenter, 3, CV_RGB(0,255,0), -1, 8,0);

} int d=(boxcenter.x); int d1=(boxcenter.y); count1 +=1; if(count1==5){ if ((d!=d2)||(d1!=d3)){ d2=d; d3=d1; if ((115<=d)&& (d<=185)&&(150<=d1)&& (d1<=200)) { data_send_RS232="f"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } else if(d1>200) { data_send_RS232="r"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } else if((d1>0)&&(d1<150)&&(115<=d)&&(d<=185))

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ { data_send_RS232="l"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } else if((d>185)&&(d1>0)&&(d1<=200)) { data_send_RS232="c"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } else if((d>0)&&(d<115)&&(d1>0)&&(d1<=200)) { data_send_RS232="x"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } } else if (((d==d2)&&(d1==d3)&&(d!=0)&&(d1!=0))&&((d1<100)||(d1>200)||(d<115)||(d>185))) { dem= dem+1; data_send_RS232="s"; m_mscomm1.put_Output(COleVariant(data_send_RS232));//strOutput)); } count1=0; }

{

cvSetImageROI( image,selection );

cvXorS( image, cvScalarAll(255), image, 0 ); cvResetImageROI( image );

}

cvSaveImage("image.jpg",image); cvSaveImage("histimg.jpg",histimg);

cvSaveImage("backproject.jpg",backproject); cvShowImage("MobileRobot", image );

cvShowImage("Histogram", histimg );

cvShowImage("backproject",backproject);

c = cvWaitKey(10); if( (char) c == 27 ) break; switch( (char) c ) { case'b': backproject_mode ^= 1; break; case'c': track_object = 0; cvZero( histimg ); break; case'h': show_hist ^= 1;

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ if( !show_hist ) cvDestroyWindow("Histogram" ); else cvNamedWindow("Histogram", 1 ); break; default: ; } } cvDestroyWindow("backproject"); cvDestroyWindow("Histogram"); cvDestroyWindow("MobileRobot"); cvReleaseImage(&image); cvReleaseImage(&histimg); cvReleaseCapture( &capture ); cvReleaseImage( &backproject); fprintf(demFile," %4d\n",dem); fclose (xFile); fclose (yFile); fclose (demFile)

PHỤ LỤC B

CHƯƠNG TRÌNH ĐIỀU KHIỂN ROBOT

//--- // Khối điều khiển Robot sử dụng Atmega32

// Ngày 31/05/2011 // Ngôn ngữ: C //--- #include <mega32.h> #include <delay.h> /********************************* // Bien dieu khien dong co

#define En_dc1 PORTA.0 #define En_dc2 PORTA.1 #define En_dc3 PORTA.2 #define En_dc4 PORTA.3 #define En_dc5 PORTA.4 #define En_dc6 PORTA.5 #define speed0 0

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ bit temp1,temp2,temp3,temp4,temp5; #define RXB8 1 #define TXB8 0 #define UPE 2 #define OVR 3 #define FE 4 #define UDRE 5 #define RXC 7

#define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<OVR)

#define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC)

// USART Receiver buffer #define RX_BUFFER_SIZE 8 (adsbygoogle = window.adsbygoogle || []).push({});

char rx_buffer[RX_BUFFER_SIZE]; #if RX_BUFFER_SIZE<256

unsigned char rx_wr_index,rx_rd_index,rx_counter; #else

unsigned int rx_wr_index,rx_rd_index,rx_counter; #endif

// This flag is set on USART Receiver buffer overflow bit rx_buffer_overflow;

// USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) {

char status,data; status=UCSRA; data=UDR;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) {

rx_buffer[rx_wr_index]=data;

if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; rx_buffer_overflow=1; }; }; } #ifndef _DEBUG_TERMINAL_IO_

// Get a character from the USART Receiver buffer #define _ALTERNATE_GETCHAR_

( Word to PDF - Unregistered ) http://www.word-to-pdf.abdio.com/ char getchar(void) { char data; while (rx_counter==0); data=rx_buffer[rx_rd_index];

if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0; #asm("cli") --rx_counter; #asm("sei") return data; } #pragma used- #endif

// USART Transmitter buffer #define TX_BUFFER_SIZE 8

char tx_buffer[TX_BUFFER_SIZE]; #if TX_BUFFER_SIZE<256

unsigned char tx_wr_index,tx_rd_index,tx_counter; #else

unsigned int tx_wr_index,tx_rd_index,tx_counter; #endif

interrupt [USART_TXC] void usart_tx_isr(void) { if (tx_counter) { --tx_counter; UDR=tx_buffer[tx_rd_index];

if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0; };

}

#ifndef _DEBUG_TERMINAL_IO_

// Write a character to the USART Transmitter buffer #define _ALTERNATE_PUTCHAR_

#pragma used+ void putchar(char c) {

while (tx_counter == TX_BUFFER_SIZE); #asm("cli")

if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0)) {

tx_buffer[tx_wr_index]=c;

if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0; ++tx_counter;

} else

Một phần của tài liệu Nghiên cứu thiết kế và chế tạo robot vượt địa hình, bám đối tượng sử dụng công nghệ xử lý ảnh (Trang 82 - 124)