Mô phỏng và kết quả

Một phần của tài liệu Giám sát và điều khiển thiết bị qua mạng ETHERNET trên nền FPGA luận văn tốt nghiệp đại học (Trang 79 - 106)

Để kiểm tra sự thông của mạng ta kết nối board với máy tính thông qua cổng ethernet. Trên máy trạm, mở ứng dụng Web browser(Internet Explorer, Firefox, Google chrome) và gõ địa chỉ IP của Web server thiết kế trên FPGA là 192.168.1.10 .

Hình 3.10: Hình test 2 Led tắt và trạng thái chuyển mạch là 1101. Một số bước thực hiện trong chương trình:

- Để load web server xuống board thì ta sẽ dịch web server này thành định dạng file .MFS và được lưu tại bộ nhớ DDRAM.

Trong bộ công cụ ISE có hỗ trợ biên dịch các file sang định dạng

.MFS.Để biên dịch ta thực hiện theo các bước sau:

+ Thứ nhất ta khởi động EDK Sell bằng cách vào Start Xilinx ISE Design Suite 10.1  EDK  Accessories  Launch EDK Shell

+ Tiếp theo ta gõ lệnh như sau:

- Nạp chương trình:+ Đầu tiên ta vào menu của phần mềm Xilinx Platform Studio ta vào Device Configuration  Download Bitstream. Bước này để nạp file .bit.

+ Để nạp các file tiếp theo ta thưc hiện như sau: ta vào Debug XMD Debug Options sau đó chọn kiểu cáp JTAG hay USB và click OK. + Ta chạy Debug  Launch XMD mở ra một hộp thoại command và chúng ta có thể giao tiếp với FPGA.

+ Ta gõ lệnh: dow –data image.mfs 0x87000000 để đưa web server vào bộ nhớ DDRAM tại vị trị đã được cài đặt sẵn trong software.

+ Ta gõi lệnh: dow lwip/executable.elf để đưa bitfile vào bộ nhớ DDRAM.

+ Ngoài ra ta có thể liệt kế các file hệ thống bằng lệnh ls và xóa các dòng lệnh bằng lệnh clear.

Kết luận chương

Trong chương này em đã trình bày sơ đồ khối của hệ thống điều khiển và giám sát thiết bị, các lưu đồ chính thực hiện chương trình. Đồng thời em cũng trình bày khái quát về ngôn ngữ JavaScript dùng để thiết kế web server và kiểm tra kiểm tra kết quả.

KẾT LUẬN

Ethernet là một chuẩn công nghiệp và hiện đang được sử dụng rộng rãi trên thế giới.Với nhưng tính năng vượt trội hơn các chuẩn giao tiếp khác như truyền được đi xa và không bị giới hạn bởi băng thông Ethernet sẽ còn được ứng dụng rộng rãi trong tương lai.

FPGA là một vi mạch lập trình có thể cấu hình lại được tức là nó có thể cấu hình thành lại thành một vi điều khiển thông thường và thực hiện các chức năng như các vi điều khiển đó hoặc nó có thể cấu hình lại để thực hiện các chức năng của một vi điều khiển DSP. Chính vì điều đó mà FPGA có đã và đang được sử dụng phổ biến trên thế giới và tại Việt Nam chúng ta.

Chính vì vậy nên em đã lưu chọn đề tài: “Giám sát và điều khiển thiết bị

qua mạng Ethernet trên nền FPGA” là cần thiết và có ý nghĩa thực tiễn.

Qua thời thực hiện đề tài em đã thực hiện thành công giám sát các Switch và điều khiển các Led trên board mạch Spartan-3E XC3S500E qua mạng LAN thông qua một Switch. Nhưng do thời gian thực hiện đề tài cũng như thời tiếp cận với công nghệ FPGA còn hạn chế nên em vẫn chưa điều khiển được các thiết bị ngoài thực tế như các thiết bị điện 220V,giám sát nhiệt độ, điện áp…, và cũng chưa điều khiển và giám sát được nhiều thiết bị. Ngoài ra em vẫn chưa điều khiển thiết bị qua mạng internet được, để khắc phục điều này ta cần một modem ADSL cấu hình Port Forwarding và đăng ký một tài khoản Open DNS để cập nhật IP của modem kết nối tới board cần điều khiển, lúc đó ta sẽ kết nối với board thông qua domain name thay vì IP.

Chính vì khả năng của FPGA nên đề tài của em có thể phát triển hơn nữa để điều khiển một nhà thông minh, hoặc hệ thống thu thập dữ liệu trong quân sự…

Cuối cùng, dù đã cố gắng rất nhiều, nhưng em vẫn không tránh khỏi những sai sót, trong việc xây dựng hệ thống, trong việc trình bày đồ án. Nhưng em vẫn luôn ý thức được rằng, những sai sót ấy cũng là một cơ hội cho em rèn luyện kỹnăng của mình : kỹ năng sửa chữa những sai sót và khiếm khuyết, để thực hiện những đề tài, dự án về sau một cách hoàn chỉnh hơn. Đó tất cả là nhờ sự theo dõi, hướng dẫn, phản biện tận tình và nghiêm túc của các thầy, cô trong hội đồng bảo vệ.

TÀI LIỆU THAM KHẢO

[1] Jan Axelson,Embedded ethernet and internet complete Designing and

Programming Small Devices for Networking,2003.

[2] Xilinx, UG081, Microblaze Processor Reference Guide,2009. [3] Xilinx, UG230, Spartan-3E Starter KitBoard User Guide, 2009.

[4] Stephen MacMahon, Nan Zang, Anirudha Sarangi,LightWeight IP(LwIP)

Application Examples,2011

[5] http://www.es.ele.tue.nl/mamps/web_server/

[6] http://mp-fpga.blogspot.com/

[7] http://www.xilinx.com/ (adsbygoogle = window.adsbygoogle || []).push({});

PHỤ LỤC

Chương trình http_response.c

#include <string.h> #include "mfs_config.h" #include "lwip/inet.h" #include "lwip/sockets.h" #include "webserver.h" #include "platform_gpio.h" #include "platform_fs.h" char *notfound_header = "<html> \ <head> \ <title>404</title> \ <style type=\"text/css\"> \

div#request {background: #eeeeee} \ </style> \

</head> \ <body> \

<h1>404 Page Not Found</h1> \ <div id=\"request\">";

char *notfound_footer = "</div> \

</body> \ </html>";

int do_404(int sd, char *req, int rlen) {

int len, hlen;

int BUFSIZE = 1024; char buf[BUFSIZE];

hlen = generate_http_header(buf, "html", len); if (lwip_write(sd, buf, hlen) != hlen) {

xil_printf("error writing http header to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

lwip_write(sd, notfound_header, strlen(notfound_header)); lwip_write(sd, req, rlen);

lwip_write(sd, notfound_footer, strlen(notfound_footer)); return 0;

}

int do_http_post(int sd, char *req, int rlen) { int BUFSIZE = 1024; char buf[BUFSIZE]; int len = 0, n; char *p; if (is_cmd_led(req)) { n = toggle_leds(); len = generate_http_header(buf, "txt", 1); p = buf + len; *p++ = n?'1':'0'; *p = 0; len++;

xil_printf("http POST: ledstatus: %x\n\r", n); } else if (is_cmd_switch(req)) {

xil_printf("http POST: switch state: %x\n\r", s);

len = generate_http_header(buf, "txt", n_switches); p = buf + len; for (n = 0; n < n_switches; n++) { *p++ = '0' + (s & 0x1); s >>= 1; } *p = 0; len += n_switches; } else {

xil_printf("http POST: unsupported command\n\r"); }

if (lwip_write(sd, buf, len) != len) {

xil_printf("error writing http POST response to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

return 0; }

int do_http_get(int sd, char *req, int rlen) {

int BUFSIZE = 1024;

char filename[MAX_FILENAME]; char buf[BUFSIZE];

int fsize, hlen, n; int fd; (adsbygoogle = window.adsbygoogle || []).push({});

if (mfs_exists_file(filename) == 0) {

xil_printf("requested file %s not found, returning 404\n\r", filename); do_404(sd, req, rlen);

return -1; }

xil_printf("http GET: %s\n\r", filename); fext = get_file_extension(filename);

fd = mfs_file_open(filename, MFS_MODE_READ); fsize = mfs_file_lseek(fd, 0, MFS_SEEK_END); hlen = generate_http_header(buf, fext, fsize); if (lwip_write(sd, buf, hlen) != hlen) {

xil_printf("error writing http header to socket\n\r"); xil_printf("http header = %s\n\r", buf);

return -1; }

while (fsize) { int w;

n = mfs_file_read(fd, buf, BUFSIZE); if ((w = lwip_write(sd, buf, n)) != n) {

xil_printf("error writing file (%s) to socket, remaining unwritten bytes = %d\n\r",

filename, fsize - n);

xil_printf("attempted to lwip_write %d bytes, actual bytes written = %d\n\r", n, w);

break; }

fsize -= n; }

return 0; }

enum http_req_type { HTTP_GET, HTTP_POST, HTTP_UNKNOWN }; enum http_req_type decode_http_request(char *req, int l)

{

char *get_str = "GET"; char *post_str = "POST";

if (!strncmp(req, get_str, strlen(get_str))) return HTTP_GET;

if (!strncmp(req, post_str, strlen(post_str))) return HTTP_POST;

return HTTP_UNKNOWN; }

/* generate and write out an appropriate response for the http request */ int generate_response(int sd, char *http_req, int http_req_len)

{

enum http_req_type request_type = decode_http_request(http_req, http_req_len); switch(request_type) {

case HTTP_GET:

return do_http_get(sd, http_req, http_req_len); case HTTP_POST:

return do_http_post(sd, http_req, http_req_len); default:

return do_404(sd, http_req, http_req_len); }

Chương trình main.c #include <stdio.h> #include "xmk.h" #include "xenv_standalone.h" #include "xparameters.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include "netif/xadapter.h" #include "utils.h" #ifdef XPAR_ETHERNET_MAC_BASEADDR

#define EMAC_BASEADDR XPAR_ETHERNET_MAC_BASEADDR (adsbygoogle = window.adsbygoogle || []).push({});

#else #error #endif

struct netif server_netif; void print_web_app_header(); void web_application_thread(void *); void print_ip(char *msg, struct ip_addr *ip);

void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw); int main_thread();

void network_thread(void *p); void console_thread (void *p); int main()

{ /* enable caches */

/*Bat dau voi kenel va khong tra ve gia tri*/ xilkernel_main();

return 0; }

void print_ip(char *msg, struct ip_addr *ip) {

print(msg);

xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip));

}

void print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw) {

print_ip("Board IP: ", ip); print_ip("Netmask : ", mask); print_ip("Gateway : ", gw); }

void network_thread(void *p) {

struct netif *netif;

struct ip_addr ipaddr, netmask, gw;

/* the mac address of the board. this should be unique per board */

unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; netif = &server_netif;

/* initliaze IP addresses to be used */ IP4_ADDR(&ipaddr, 192, 168, 1, 10); IP4_ADDR(&netmask, 255, 255, 255, 0);

/* print application headers */ print_web_app_header();

/* print out IP settings of the board */ print("\n\r\n\r");

print_ip_settings(&ipaddr, &netmask, &gw);

if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, EMAC_BASEADDR)) {

xil_printf("Error adding N/W interface\n\r"); return;

}

netif_set_default(netif);

/* specify that the network if is up */ netif_set_up(netif);

/* start packet receive thread - required for lwIP operation */

sys_thread_new((void(*)(void*))xemacif_input_thread, netif, DEFAULT_THREAD_PRIO);

/* Khoi tao lop file he thong cho web servers */ platform_init_fs(); (adsbygoogle = window.adsbygoogle || []).push({});

/*bat dau thread web server */

sys_thread_new(web_application_thread, 0, DEFAULT_THREAD_PRIO);

return; }

void console_thread (void *p) {

while (1) { get_line (line); xil_printf ("%s\n\r", line); if (strcmp (line, "ls") == 0) { mfs_ls (); } if (strcmp (line, "clear") == 0) { clear_console (); } } return; } int main_thread() {

/* Khoi tao Lwip truoc khi goi phuong thuc sys_thread_new */ lwip_init();

/*Bat ky thread nao su dung lwIP nen duoc tao ra bang cach su dung phuong thuc sys_thread_new*/

sys_thread_new (network_thread, NULL, DEFAULT_THREAD_PRIO); sys_thread_new (console_thread, NULL, DEFAULT_THREAD_PRIO); return 0;

}

#include "mfs_config.h" int platform_init_fs() {

/* initialize the memory file system (MFS) image pre-loaded into memory */

mfs_init_fs(MFS_NUMBYTES, (char *)(MFS_BASE_ADDRESS+4), MFS_INIT_TYPE); /* check if we can access index.html */

if (mfs_exists_file("index.html") == 0) {

xil_printf("%s: ERROR: unable to locate index.html in MFS\n\r", __FUNCTION__); xil_printf("Please check if Memory File System has been loaded, \

and it has index.html file in root directory\n\r"); return -1;

}

xil_printf("Memory File System initialized\n\r"); return 0;

}

Chương trinh platform_gpio.c #include "platform_gpio.h" #include "xparameters.h"

#if defined(XPAR_LEDS_8BIT_BASEADDR)

#define LED_BASE XPAR_LEDS_8BIT_BASEADDR #endif

#if defined(XPAR_DIP_SWITCHES_4BIT_BASEADDR)

#define DIP_BASE XPAR_DIP_SWITCHES_4BIT_BASEADDR #endif

{

/* set led gpio data direction to output */ *(volatile unsigned int*)(LED_BASE + 4) = 0; /* set dip switch gpio data direction to in */ *(volatile unsigned int*)(DIP_BASE + 4) = ~0; /* initialize leds to OFF */

*(volatile int *)(LED_BASE) = 0; }

int

toggle_leds() {

static int state = 0; state = ~state;

*(volatile int *)(LED_BASE) = state; return state; (adsbygoogle = window.adsbygoogle || []).push({});

}

unsigned int get_switch_state() {

return *(volatile unsigned int *)(DIP_BASE); }

Chương trinh utils.c #include <stdio.h>

#include "utils.h" #define ROW 50 #define COL 50

void get_line (char *line) {

int count = 0; char c;

memset (line, '\0', SIZE); while (1) { c = getchar (); if (count == (SIZE - 2) || c == 13) { return; } if (c >= 32) // visible character { line [count] = c; count++; } } } void clear_console () { int i,j; for (j = 0; j < ROW; j++) {

{ xil_printf (" "); } xil_printf ("\n\r"); } }

Chương trinh web_utils.c #include <string.h> #include <stdio.h> #include "mfs_config.h" #include "webserver.h" #include "platform_gpio.h" Int is_cmd_led(char *buf) {

/* skip past 'POST /' */ buf += 6;

/* then check for cmd/ledxhr */

return (!strncmp(buf, "cmd", 3) && !strncmp(buf + 4, "ledxhr", 6)); }

int

is_cmd_switch(char *buf) {

/* skip past 'POST /' */ buf += 6;

} void

extract_file_name(char *filename, char *req, int rlen, int maxlen) {

char *fstart, *fend;

/* first locate the file name in the request */

/* requests are of the form GET /path/to/filename HTTP... */ req += strlen("GET ");

if (*req == '/') req++;

fstart = req; /* start marker */

while (*req != ' ') /* file name finally ends in a space */ req++;

fend = req-1; /* end marker */ if (fend < fstart) {

strcpy(filename, "index.html"); return;

}

/* make sure filename is of reasonable size */ if (fend - fstart > maxlen) {

*fend = 0;

strcpy(filename, "404.html"); (adsbygoogle = window.adsbygoogle || []).push({});

printf("Request filename is too long, length = %d, file = %s (truncated), max = %d\n\r",

(fend - fstart), fstart, maxlen); return;

}

filename[fend-fstart+1] = 0;

/* if last character is a '/', append index.html */ if (*fend == '/')

strcat(filename, "index.html"); }

char *get_file_extension(char *fname) {

char *fext = fname + strlen(fname) - 1; while (fext > fname) {

if (*fext == '.') return fext + 1; fext--; } return NULL; }

int generate_http_header(char *buf, char *fext, int fsize) {

char lbuf[40];

strcpy(buf, "HTTP/1.0 200 OK\r\nContent-Type: "); if (fext == NULL)

strcat(buf, "text/html"); /* for unknown types */ else if (!strncmp(fext, "htm", 3))

strcat(buf, "text/html"); /* html */ else if (!strncmp(fext, "jpg", 3))

strcat(buf, "image/jpeg"); else if (!strncmp(fext, "gif", 3))

strcat(buf, "text/javascript"); else if (!strncmp(fext, "pdf", 2)) strcat(buf, "application/pdf"); else if (!strncmp(fext, "css", 2)) strcat(buf, "text/css"); else

strcat(buf, "text/plain"); /* for unknown types */ strcat(buf, "\r\n");

sprintf(lbuf, "Content-length: %d", fsize); strcat(buf, lbuf);

strcat(buf, "\r\n");

strcat(buf, "Connection: close\r\n"); strcat(buf, "\r\n"); return strlen(buf); } Chương trình webserver.c #include <stdio.h> #include <string.h> #include "xmk.h"

#include "lwip/sockets.h" #include "lwipopts.h" #include "webserver.h" #include "platform_gpio.h"

/* thread spawned for each connection */ void

process_http_request(int sd) {

int read_len;

int RECV_BUF_SIZE = 600; unsigned char recv_buf[RECV_BUF_SIZE]; /* read in the request */

if ((read_len = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) return;

/* respond to request */

generate_response(sd, recv_buf, read_len); /* close connection */ close(sd); } /* http server */ int web_application_thread() {

int sock, new_sd;

struct sockaddr_in address, remote; int size; (adsbygoogle = window.adsbygoogle || []).push({});

/* create a TCP socket */

if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) return;

/* bind to port 80 at any interface */ address.sin_family = AF_INET; address.sin_port = htons(80);

address.sin_addr.s_addr = INADDR_ANY;

if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) return;

/* listen for incoming connections */ lwip_listen(sock, 5);

size = sizeof(remote); while (1) {

new_sd = lwip_accept(sock, (struct sockaddr *)&remote, &size); process_http_request(new_sd);

} }

void print_web_app_header() {

xil_printf("\n\r\n\r---DO AN TOT NGHIEP DAI HOC ---\n\r"); xil_printf("Open up your favorite browser and type: \n\r");

xil_printf("http://192.168.1.10\n\r"); }

Phụ lục 2:

Mã nguồn web server được thiết kế bằng ngôn ngữ JavaScript:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html> <head>

<script> </script> </head> <body> <center><td> <img src="index3.jpg"style="padding-center:100px"></img> </td></center> <div id="container"> <b class="rtop">

<b class="r1"></b> <b class="r2"></b> <b class="r3"></b> <b class="r4"></b> </b>

<center>

<b><font size=+2> TRƯỜNG ĐẠI HỌC VINH</font></b> </center>

<center>

<b><font size=+2>KHOA ĐIỆN TỬ VIỄN THÔNG</font></b> </center>

</center>

<center><p>--- </p></center>

<center><b> ĐỒ ÁN </b></center>

<center><b> TỐT NGHIỆP ĐẠI HỌC </b></center>

<center><h4><b>Đề tài: GIÁM SÁT VÀ ĐIỀU KHIỂN THIẾT BỊ QUA MẠNG ETHERNET TRÊN NỀN FPGA</b></h4></center>

<center><b><p>GVHD: ThS. Lê Đình Công </p></b></center> <center><b><p>SVTH: Nguyễn Hữu Tuyến </p></b></center> <center><b><p> LỚP: 48K-ĐTVT </p></b></center>

Tín hiệu điều khiển thiết bị từ máy tính xuống board thể hiện qua hàng Led </p>

<div id="led_results"> (adsbygoogle = window.adsbygoogle || []).push({});

<p><span style="background:#ffffaa">LEDs are now OFF.</span></p> </div>

<form class="forms" id="led_form" method="post" action="cmd/led"> <input type="submit" value="Toggle LEDs" disabled="true"></input> </form>

<h2> GIÁM SÁT THIẾT BỊ </h2> <p>

Máy tính giám sát thiết bị thể hiện qua việc giám sát các Switch </p>

<div id="switch_status">

<p><span style="background:#33ff00">1111</span></p> </div>

<form class="forms" id="switch_form" method="post" action="cmd/switch"> <input type="submit" value="Update Status" disabled="true"></input> </form>

<b class="rbottom">

<b class="r4"></b> <b class="r3"></b> <b class="r2"></b> <b class="r1"></b> </b>

</div>

<script type="text/javascript" src="yui/yahoo.js"></script> <script type="text/javascript" src="yui/dom.js"></script> <script type="text/javascript" src="yui/event.js"></script> <script type="text/javascript" src="yui/conn.js"></script> <script type="text/javascript" src="yui/anim.js"></script>

</body> </html>

Một phần của tài liệu Giám sát và điều khiển thiết bị qua mạng ETHERNET trên nền FPGA luận văn tốt nghiệp đại học (Trang 79 - 106)