Thư viện FreeRTOS

Một phần của tài liệu Nghiên cứu, phát triển hệ thống ĐIỀU KHIỂN ĐÈN GIAO THÔNG sử dụng hệ điều hành FreeRTOS (Trang 37)

CHƯƠNG 2 : THIẾT KẾ VÀ XÂY DỰNG HỆ THỐNG

2.3.2 Thư viện FreeRTOS

FreeRTOS là một hệ điều hành thời gian thực (RTOS) được thiết kế đủ nhỏ để chạy trên một vi xử lý. FreeRTOS chỉ cung cấp chức năng lập lịch thời gian thực lõi, truyền thông liên tác vụ, định thời và đồng bộ. Điều đó có nghĩa nó thực sự được mơ tả như một nhân thời gian thực, hoặc thực thi thời gian thực. FreeRTOS khả dụng với 35 kiến trúc xử lý, với hàng triệu nhà phát triển sản phẩm... Dự án khởi động cho LM3S811 có thể được biên dịch lại dễ dàng để chạy bất kì bộ vi điều khiển Cortex M nào của Texas Instruments.

FreeRTOS được thiết kế phù hợp cho nhiều hệ nhúng nhỏ gọn vì nó chỉ triển khai rất ít các chức năng như: Cơ chế quản lý bộ nhớ và tác vụ cơ bản, các hàm API quan trọng cho cơ chế đồng bộ. Nó khơng cung cấp sẵn các giao tiếp mạng, drivers, hay hệ thống quản lý tệp (file system) như những hệ điều hành khác. Tuy vậy, FreeRTOS có nhiều ưu điểm, hỗ trợ kiến trúc vi điều khiển khác nhau (PIC, AVR, MSP430, ARM…), kích thước nhỏ gọn, phát triển với nhiều trình biên dịch C khác nhau (GCC, OpenWatcom, Keil, IAR, Esclipse…), cho phép không giới hạn các tác vụ chạy đồng thời, không hạn chế quyền ưu tiên thực thi, khả năng khai thác phần cứng. Ngoài ra, nó cũng cho phép triển khai các cơ chế điều độ giữa các tiến trình như: hàng đợi (queue), cờ đếm (counting semaphore), loại trừ lẫn nhau (mutex).

FreeRTOS là một hệ điều hành nhúng thời gian thực (Real Time Operating System) mã nguồn mở được phát triển bởi Real Time Engineer Ltd, sáng lập và sở hữu bởi Richarf Barry.

FreeRTOS là một hệ điều hành nhúng rất phù hợp cho nghiên cứu, học tập về các kỹ thuật, công nghệ trong viết hệ điều hành nói chung và hệ điều hành nhúng thời gian thực nói riêng, cũng như việc phát triển mở rộng tiếp các thành phần cho hệ điều hành (bổ sung mơ-đun, trình điều khiển, chuyển đổi mơi trường thực hiện).

Cài đặt FreeRTOS trong Arduino IDE

Ở giao diện chính của Aruduino IDE, Sketch > Include Library > Manage

Libraries. Search từ khóa FreeRTOS và nhấn Install để cài đặt thư viện:

Hình 2. 28. Cài đặt thư viện FreeRTOS trong Arduino IDE

Một tác vụ là một chương trình, chương trình này chạy liên tục trong vịng lặp vơ tận và không bao giờ dừng lại. Trong FreeRTOS mỗi luồng thực thi được gọi là tác vụ. Một chương trình thường sẽ có nhiều tác vụ con khác nhau.

Hệ thống đèn giao thông gồm 3 chế độ chuyển đổi bình thường, giờ cao điểm, ban đêm. Để dễ dàng quản lý các chế độ nhóm chia hệ thống thành 3 tác vụ Task1 (chế độ bình thường), Task2 (chế độ giờ cao điểm), Task3 (chế độ ban đêm).

Tạo tác vụ

Nguyên mẫu hàm API xTaskCreate ()

BaseType_t xTaskCreate (TaskFuntion_t task_function, const char *task_name,

uint16_t stack_depth, void *param,

UBaseType_t priority,

TaskHandle_t *task_handler); Trong đó:

o task_function: Con trỏ đến task function được dùng để tạo task mới. o task_name: Con trỏ đến string chứa tên của task. Kích thước tối đa của

task name được quy định trong hằng số

configMAX_TASK_NAME_LEN (trong file config của FreeRTOS) o stack_depth: Độ lớn của stack được cấp phát cho task, Idle task sử dụng

stack_depth được quy định bởi hằng số

configMINIMAL_STACK_SIZE và stack_depth của task tạo ra phải lớn hơn giá trị này.

o param: Con trỏ đến đối số được truyền cho task, kiểu pointer to void. priority: Mức độ ưu tiên của task được tạo, với 0 là mức thấp nhất (của Idle task) max là configMAX_PRIORITIES -1.

o task_handler: con trỏ đến task sẽ được tạo, được dùng để truyền vào các API như vTaskDelete (), vTaskPrioritySet (). Có thể truyền NULL nếu không sử dụng.

Kết quả trả về:

o pdPass: task được tạo thành công

o pdFAIL: task không được tạo do thiếu bộ nhớ heap.

Ban đầu tạo 3 tác vụ Task1, Task2, Task3 có mức ưu tiên là như nhau là 1. o Task1

o Task2

xTaskCreate (Task2, "CheDo2", 256, NULL, 1, &TaskHandle_2); o Task3

xTaskCreate (Task3, "CheDo3", 256, NULL, 1, &TaskHandle_3);  Thay đổi mức độ ưu tiên

Khi chuyển đổi hệ thống thực hiện một chế độ nào đó thì tác vụ của chế độ đó sẽ được thay đổi lên mức ưu tiên cao nhất để được thực hiện.

Nguyên mẫu hàm API vTaskPrioritySet ()

void vTaskPrioritySet (TaskHandle_t task_handler, UBaseType_t new_priority); Trong đó

o task_handler: con trỏ đến task sẽ được tạo, được dùng để truyền vào các API như vTaskDelete (), vTaskPrioritySet (). Có thể truyền NULL nếu khơng sử dụng.

o new_priority: Mức độ ưu tiên mới.

Khi số lần người điều khiển nhấn nút chia hết cho 3 thì Task1 thay đổi độ ưu tiên của chính nó lên mức cao nhất là 2 để hệ thống hoạt động chế độ bình thường. Khi số lần nhấn nút chia cho 3 dư 1 thì Task1 thay đổi độ ưu tiên của Task2 lên cao nhất là 2 và thay đổi độ ưu tiên của nó về 1 để hệ thống hoạt động chế độ giờ cao điểm.

Task1

void Task1(void* pvParameters) { while (1) { if (butPushCounterM%3==0) { vTaskPrioritySet (TaskHandle_2, 1); vTaskPrioritySet (NULL, 2); vTaskPrioritySet (TaskHandle_3, 1); } Serial.println("Vao che do 1");

For (long point=30; point>0; point--) { if (butPushCounterM%3! =0) break;

s2. write (90); s4. write (90);

s3. write (0);

HienThiLED7doan (point, 8,5);

DenSang(0b0101100,0b10110010,0b00001000); delay (1000);

}

for (long point=5; point>0; point--) { if (butPushCounterM%3! =0) break; s2. write (0); s4. write (0); s1. write (0); s3. write (0); HienThiLED7doan (point, 8, 0); DenSang(0b00101010,0b10101001,0b00000100); delay (1000); }

for (long point=20; point>5; point--) { if (butPushCounterM%3! =0) break; s1. write (90); s3. write (90); s2. write (0); s4. write (0); HienThiLED7doan (point, 8, -5); DenSang(0b10010001,0b01000101,0b00000110); delay (1000); }

for (long point=5; point>0; point--) { if (butPushCounterM%3! =0) break; s3. write (0); s2. write (0); s4. write (0); HienThiLED7doan (point, 8, 0); DenSang(0b01001001,0b00100101,0b00000101); delay (1000); }

if (butPushCounterM%3==1) { vTaskPrioritySet (TaskHandle_2, 2); vTaskPrioritySet (NULL, 1); vTaskPrioritySet (TaskHandle_3, 1); } } }

Khi số lần người điều khiển nhấn nút chia cho 3 dư 1 thì Task2 thay đổi độ ưu tiên của chính nó lên mức cao nhất là 2 để hệ thống hoạt động chế độ giờ cao điểm. Khi số lần nhấn nút chia cho 3 dư 2 thì Task2 thay đổi độ ưu tiên của Task3 lên cao nhất là 2 và thay đổi độ ưu tiên của nó về 1 để hệ thống hoạt động chế độ ban đêm.

Task2 while (1) { if (butPushCounterM%3 ==1) { vTaskPrioritySet (TaskHandle_1, 1); vTaskPrioritySet (NULL, 2); vTaskPrioritySet (TaskHandle_3, 1); } Serial.println("Vao che do 2");

for (long point=40; point>0; point--) { if (butPushCounterM%3! =1) break; s2. write (90); s4. write (90); s1. write (0); s3. write (0); HienThiLED7doan (point, 8,5); DenSang(0b0101100,0b10110010,0b00001000); delay (1000); }

for (long point=5; point>0; point--) { if (butPushCounterM%3! =1) break; s2. write (0);

s1. write (0); s3. write (0); HienThiLED7doan (point, 8, 0); DenSang(0b00101010,0b10101001,0b00000100); delay (1000); }

for (long point=30; point>5; point--) { if (butPushCounterM%3! =1) break; s1. write (90); s3. write (90); s2. write (0); s4. write (0); HienThiLED7doan (point, 8, -5); DenSang(0b10010001,0b01000101,0b00000110); delay (1000); }

for (long point=5; point>0; point--) { if (butPushCounterM%3! =1) break; s3. write (0); s2. write (0); s4. write (0); HienThiLED7doan (point, 8, 0); DenSang(0b01001001,0b00100101,0b00000101); delay (1000); } if (butPushCounterM%3 ==2) { vTaskPrioritySet (TaskHandle_1, 1); vTaskPrioritySet (NULL, 1); vTaskPrioritySet (TaskHandle_3, 2); } } }

Khi số lần người điều khiển nhấn nút chia cho 3 dư 2 thì Task3 thay đổi độ ưu tiên của chính nó lên mức cao nhất là 3 để hệ thống hoạt động chế độ giờ cao điểm.

Khi số lần nhấn nút chia hết cho 3 thì Task3 thay đổi độ ưu tiên của Task1 lên cao nhất là 2 và thay đổi độ ưu tiên của nó về 1 để hệ thống hoạt động chế độ bình thường.

Task3

void Task3(void* pvParameters) { while (1) { Serial.println(butPushCounterM); if (butPushCounterM%3==2) { vTaskPrioritySet (TaskHandle_1, 1); vTaskPrioritySet (NULL, 2); vTaskPrioritySet (TaskHandle_2, 1); } Serial.println("Vao che do 3"); for (; ;) { if (butPushCounterM%3! =2) break; s1. write (90); s2. write (90); s3. write (90); s4. write (90); DenSang(0b01000010,0b00001000,0b00000001); HienThiLED7doan (0, 8, 0); delay (1000); DenSang(0b00000000,0b00000000,0b00000000); delay (1000); } if (butPushCounterM%3 ==0) { vTaskPrioritySet (TaskHandle_1, 2); vTaskPrioritySet (NULL, 1); vTaskPrioritySet (TaskHandle_2, 1); } } } b. Quản lý ngắt

Ngắt là sự kiện dừng công việc hiện tại của CPU, buộc CPU thực hiện một việc nào đó rồi mới quay trở lại thực hiện tếp công việc cũ. Trong hệ thống nhúng, khi có tín hiệu Interrupt, tác vụ đang chạy sẽ bị ngừng lại, thay vào đó Interrupt Service Routine (ISR) sẽ được thực thi. Sau khi ISR hồn thành cơng việc, tác vụ ban đầu sẽ được thực thi tiếp.

Hình 2. 29. Quy trình thực hiện ngắt

Trong Arduino Uno được hỗ trợ hai loại ngắt như sau:

o Ngắt số 0 được nối với chân số 2

o Ngắt số 1 được nối với chân số 3 Cấu trúc hàm ngắt trong Arduino

attachInterrupt (digitalPinToInterrupt (pin), ISR, mode) Trong đó:

o digitalPinToInterrupt (pin): Ngắt tại chân tương ứng với số pin muốn sử dụng để kích hoạt ngắt bên ngoài.

o ISR: Tên hàm ISR mà ta muốn gọi mỗi khi có ngắt

o mode: Kiểu ngắt đang sử dụng (Change, Rising, Falling, Low, High). Có năm loại kích hoạt ngắt Arduino:

o Change: Khi tín hiệu thay đổi ngay cả khi tín hiệu tăng hoặc tín hiệu giảm hoặc nếu tín hiệu ở trạng thái thấp ở 0 hoặc nếu tín hiệu ở trạng thái cao thì kích hoạt 5V.

o Rising: Trên một cạnh tăng, tín hiệu đi từ thấp đến cao có nghĩa là tín hiệu kích hoạt từ 0V đến 5V.

o Falling: Trên một cạnh giảm, tín hiệu đi từ cao xuống thấp có nghĩa là tín hiệu được kích hoạt từ 5V đến 0V.

o Low: Thấp là sự kích hoạt liên tục bất cứ khi nào tín hiệu ở mức thấp hay nói cách khác là tín hiệu trên 0V.

o High: Cao là sự kích hoạt liên tục bất cứ khi nào tín hiệu ở mức cao hay nói cách khác là tín hiệu trên 5V.

Trong hệ thống, nhóm sử dụng nút nhấn được nối với ngắt số 0 của chân số 2. int butM = 2;

int butPushCounterM =0; pinMode (butM, INPUT);

attachInterrupt (digitalPinToInterrupt (butM), button, RISING); void button () {

butPushCounterM++; }

Khi button được nhấn, tín hiêu đi từ thấp đến cao thì hàm button () được gọi và thực hiện tăng giá trị biến (butPushCounterM) lên 1.

2.4 Tổng kết chương 2

Trong chương 2, báo cáo đã nêu lên được các chức năng cần thiết của hệ thống là hiển thị đèn tín hiệu giúp phân luồng giao thơng tại ngã tư. Bên cạnh đó, chương 2 đã chỉ rõ sơ đồ nguyên lý, sơ đồ thiết kế các chức năng của hệ thống. Trình bày cụ thể cách kết nối giữa phần cứng và thiết kế thời gian chạy của từng đèn.

CHƯƠNG 3: KẾT QUẢ THỰC NGHIỆM3.1 Mơ hình hệ thống đèn tín hiệu giao thơng ở ngã tư 3.1 Mơ hình hệ thống đèn tín hiệu giao thơng ở ngã tư

Để thể hiện tính ứng dụng một cách trực quan của hệ thống vào thực tế nhóm đã tiến hành tiến hành thiết kế và thi công hệ thống đèn giao thơng như thực tế.

Hình 3. 1. Mơ hình hệ thống

3.2 Kết quả thực nghiệm

Tiến hành thực nghiệm 5 lần, mỗi lần thử nghiệm các đèn tín hiệu dành cho phương tiện giao thông, đèn dành cho người đi bộ và thanh chắn. Thời gian trễ cho phép của các đèn LED là 0.1 s đến 0.3 s và động cơ servo để điều khiển thanh chắn là 0.3 s đến 0.5 s.

Bảng 3. 1. Kết quả thử nghiệm của hệ thống

Số lần

thử Độ trễ của đèn tín hiệu (s) Độ trễ của thanh chắn (s)

2 0.3 1.625

3 0.5 2.125

4 0.3 2.75

5 0.2 4

Tiến hành chạy thử nghiệm các chế độ hoạt động đèn tín hiệu ở chế độ bình thường, chế độ giờ cao điểm và chế độ ban đêm thì hệ thống chạy theo các chế độ, hiển thị đèn tín hiệu và đèn đếm lùi đúng theo mục tiêu đề ra.

o Kết luận

o Đèn tín hiệu báo gần như đúng với khoảng thời gian cho phép, thời gian trễ trung bình của các lần thử nghiệm là 0,3 s.

o Thanh chắn hoạt động có độ trễ khá lớn, các lần thử nghiệm càng sau độ trễ càng lớn. Đỗ trễ này do tác động của khối lượng thanh chắn, môi trường bên ngồi, động cơ… Thời gian trễ trung bình của các lần thử nghiệm là 2,4 s. Như vậy vượt quá thời gian trễ cho phép của hệ thống. o Hệ thống đã điều chỉnh đúng các chế độ đèn tín hiệu bình thường, chế

độ ban đêm, chế độ giờ cao điểm.

3.3 Kết quả nhận được của hệ thống

Sau khi thực nghiệm xong thì nhóm đã thu được một số kết quả nhất định như sau:

 Mơ hình hóa cụ thể một hệ thống điều khiển đèn tín hiệu bao gồm: mơ hình thực nghiệm hệ thống. Cụ thể:

o Điều khiển đèn tín hiệu cho giao phương tiện giao thông và hiển thị đèn đếm giây 7 đoạn.

o Điều khiển đèn tín hiệu của người đi bộ và điều chỉnh thanh chắn.

o Điều chỉnh được các chế độ đèn tín hiệu bình thường, chế độ giờ cao điểm, chế độ ban đêm.

 Đối với cá nhân, đã nghiên cứu, áp dụng được nhiều kiến thức bổ ích như: o Hiểu và lập trình các Board Arduino thơng dụng trong các ứng dụng điều

khiển.

o Nguyên lý hoạt động và cách điều khiển động cơ servo.

o Hiểu và ứng dụng được FreeRTOS vào trong hệ thống đèn tín hiệu giao thơng.

3.4 Hạn chế của hệ thống

Bên cạnh đó do thời gian cũng như kiến thức cịn hạn hẹp nên cũng khơng tránh khỏi một số điều cần cải thiện như:

o Chưa có tính năng rẽ trái cho phương tiện tham gia giao thông.

o Thanh chắn thì vẫn chưa hoạt động hồn tồn đúng thời gian thực, cịn sai số làm cho thanh chắn kéo lên hoặc hạ xuống chậm.

3.5 Hướng phát triển của hệ thống

Qua các điểm cần cải thiện được nêu ra đề tài có thể được phát triển theo các hướng rộng hơn và hồn thiện hơn như:

 Tích hợp, thay thế thêm các động cơ để điều chỉnh thanh chắn cho ổn định.  Thiết lập thời gian hoạt động của đèn rẽ trái.

 Tích hợp thêm hệ thống điều khiển từ xa để thay đổi thời gian hoạt động của các đèn.

3.6 Tổng kết chương 3

Trong chương 3, đã mô tả và minh họa lại quá trình thực nghiệm hoạt động của hệ thống điều khiển đèn tín hiệu, thanh chắn và chức năng thay đổi chế độ đèn tín hiệu ở chế độ bình thường, chế độ giờ cao điểm và chế độ ban đêm. Tại đây, nhóm cũng đưa ra được kết quả thực nghiệm của của hệ thống và nêu ra các hạn chế cũng như hướng phát triển cho hệ thống sau này.

TÀI LIỆU THAM KHẢO

[1] Giáo trình “Cơng nghệ phần mềm nhúng – Nguyễn Ngọc Bình” – Nhà Xuất

Bản Đại Học Quốc Gia Hà Nội.

[2] Đồ án tốt nghiệp “Hệ thống điều khiển đèn tín hiệu giao thơng qua xử lý ảnh” – Trường Đại Học Sư Phạm Kĩ Thuật TP. Hồ Chí Minh.

[3] Giáo trình “Hệ điều hành nhúng thời gian thực – Lê Thị Hồng Vân” – Học viện kĩ thuật Mật Mã.

PHỤ LỤC Chương trình hoạt động của hệ thống

#include <Arduino_FreeRTOS.h> #include <task.h>

void Task1 (void *pvParameters); void Task2 (void *pvParameters); void Task3 (void *pvParameters);

TaskHandle_t TaskHandle_1; // handler for Task1 TaskHandle_t TaskHandle_2; // handler for Task2 TaskHandle_t TaskHandle_3; // handler for Task3 #include <Servo.h> int latchPin = 8; //chân SH_CP của 74HC595 int clockPin = 12; //Chân DS của 74HC595 int dataPin = 11;

//74hc điều khiển đèn led int latch = 5;

int clock1 = 7; int data = 6; //button int butM = 2;

int butPushCounterM = 0; //biến đếm số lần nhấn button //servo den1, den2, den3, den4 lần lượt là s1, s2, s3, s4

Servo s1; Servo s2; Servo s3; Servo s4;

// Ta sẽ xây dựng mảng hằng số với các giá trị cho trước

// Các bit được đánh số thứ tự (0-7) từ phải qua trái (tương ứng với A-F, DP) // Vì ta dùng LED 7 đoạn chung cực dương nên với các bit 0

// thì các đoạn của LED 7 đoạn sẽ sáng // với các bit 1 thì đoạn ấy sẽ tắt

//mảng có 10 số (từ 0-9) const byte Seg [10] = {

0b11000000, //0 - các thanh từ a-f sáng 0b11111001, //1 - chỉ có 2 thanh b, c sáng 0b10100100, //2 0b10110000, //3 0b10011001, //4 0b10010010, //5 0b10000010, //6 0b11111000, //7 0b10000000, //8 0b10010000, //9 }; void setup () {

Serial.begin (9600);

//Bạn BUỘC PHẢI pinMode các chân này là OUTPUT pinMode (latchPin, OUTPUT);

pinMode (clockPin, OUTPUT); pinMode (dataPin, OUTPUT); pinMode (latch, OUTPUT); pinMode (clock1, OUTPUT); pinMode (data, OUTPUT); //servo s1. attach (10); s2. attach (4); s3. attach (9); s4. attach (13); // button

pinMode (butM, INPUT);

attachInterrupt (digitalPinToInterrupt(butM), button, RISING); xTaskCreate (Task1, "CheDo1", 256, NULL, 2, &TaskHandle_1); xTaskCreate (Task2, "CheDo2", 256, NULL, 1, &TaskHandle_2); xTaskCreate (Task3, "CheDo3", 256, NULL, 1, &TaskHandle_3); vTaskStartScheduler ();

}

//Điều khiển các đèn tín hiệu sáng

void DenSang (byte ic1, byte ic2, byte ic3) {//Khi dịch bit, byte đầu tiên sẽ //được chuyển đến ic cuối cùng (ic3)

byte array [] = {ic1, ic2, ic3}; //sau đó mới đến các ic trước nó (ic2) và đến //ic1 được nối trực tiếp với chân của arduino

digitalWrite (latch, LOW);

for (int i = 2; i >= 0; i--) {// có 3 ic dịch byte 3 lần từ i=2-> i=0 shiftOut (data, clock1, MSBFIRST, array[i]);

}

digitalWrite (latch, HIGH); }

//Đèn 7 đoạn hiển thị số

void HienThiLED7doan (unsigned long Giatri, byte SoLed = 8, int x = 5) {// //x là giá trị thời gian thay đổi của đèn 2,4 so với đèn 1,3

byte *array = new byte[SoLed];

Một phần của tài liệu Nghiên cứu, phát triển hệ thống ĐIỀU KHIỂN ĐÈN GIAO THÔNG sử dụng hệ điều hành FreeRTOS (Trang 37)

Tải bản đầy đủ (DOCX)

(63 trang)
w