KHẢO SÁT VÀ XÂY DỰNG BÀI TOÁN
Khảo sát bài toán thực tế
Hiện nay cùng với sự phát triển của khoa học công nghệ cũng như nhu cầu về chất lựng thực phẩm của con người ngày một tăng cao
Việc tích hợp cảm biến nhiệt độ và độ ẩm vào hệ thống vườn thông minh là rất quan trọng Hệ thống tưới phun nước giúp duy trì độ ẩm cho cây trồng, đồng thời tiết kiệm nước và ngăn ngừa ô nhiễm môi trường Hơn nữa, thiết kế hệ thống tưới cây tự động không chỉ giảm chi phí nhân công mà còn tối ưu hóa thời gian tưới, phù hợp với từng giai đoạn phát triển của cây trồng.
Dưới sự hướng dẫn của cô Lê Thị Hồng Vân, nhóm chúng em đã nỗ lực hoàn thành đề tài "Ứng dụng cảm biến nhiệt độ, độ ẩm trong vườn thông minh sử dụng hệ điều hành FreeRTOS".
Xây dựng bài toán
Yêu cầu đối với các thiết bị đo nhiệt độ và độ ẩm là cảm biến phải hoạt động chính xác và có tốc độ phản hồi nhanh, đặc biệt khi hoạt động trong các điều kiện khác nhau.
Hệ thống có 2 chức năng chính:
+ Tự động bật đèn,tưới cây khi nhiệt độ, độ ẩm xuông thấp
+ Ứng dụng IOT giám sát , gửi nhiệt độ độ ẩm lên Blynk
Hệ thống chính sẽ bao gồm :
Một số linh kiện khác
Sử dụng FreeRTOS vào đề tài
FreeRTOS là hệ điều hành nhúng thời gian thực mã nguồn mở, ra đời từ năm 2003, và đã phát triển mạnh mẽ với sự ủng hộ lớn từ cộng đồng lập trình viên Hệ điều hành này có tính khả chuyển cao, cho phép sử dụng miễn phí hoặc cho mục đích thương mại Với kích thước nhỏ gọn, FreeRTOS rất phù hợp cho các hệ nhúng thời gian thực hạn chế về tài nguyên Được viết bằng ngôn ngữ C, FreeRTOS đảm bảo tính tương thích cao với nhiều nền tảng phần cứng khác nhau.
FreeRTOS hỗ trợ tạo ra số lượng task và coroutines không giới hạn, phụ thuộc vào tài nguyên phần cứng Nó cung cấp cơ chế truyền thông đồng bộ giữa các task, cũng như giữa task và ngắt, thông qua hàng đợi, semaphore nhị phân, semaphore đếm và mutex Hệ thống cũng có khả năng nhận biết khi ngăn xếp bị tràn Ngay cả trong các hệ thống nhúng lớn, FreeRTOS giúp tiết kiệm dung lượng bộ nhớ và giảm thiểu quá tải cho hệ thống.
CƠ SỞ LÝ THUYẾT
Tổng quan Hệ điều hành Nhúng thời gian thực FreeRTOS
1.1 Lịch sử phát triển của hệ điều hành nhúng thời gian thực FreeRTOS
FreeRTOS là một hệ điều hành thời gian thực miễn phí, được phát triển từ năm 2003 bởi Richard Barry và nhận được sự ủng hộ mạnh mẽ từ cộng đồng mã nguồn mở Với tính khả chuyển và mã nguồn mở, FreeRTOS có thể được tải xuống miễn phí và áp dụng cho các ứng dụng thương mại, đặc biệt là cho các hệ nhúng thời gian thực nhỏ Được viết chủ yếu bằng ngôn ngữ C, FreeRTOS tương thích cao với nhiều nền tảng khác nhau, nổi bật với dung lượng nhỏ gọn và khả năng hoạt động trên các hệ thống mà nhiều hệ điều hành khác không thể FreeRTOS có thể được port cho nhiều kiến trúc vi điều khiển và công cụ phát triển khác nhau, với mỗi port chính thức đi kèm các ứng dụng ví dụ để minh họa tính năng và sự phát triển của lõi Cộng đồng mạng cung cấp hỗ trợ miễn phí, đồng thời cũng có sẵn dịch vụ hỗ trợ thương mại với các dịch vụ phát triển toàn diện.
FreeRTOS được cấp giấy phép bởi bản đã được chỉnh sửa bởi GPL (
Giấy phép General Public License (GPL) cho phép sử dụng FreeRTOS trong các ứng dụng thương mại Bên cạnh FreeRTOS, còn có OpenRTOS và SafeRTOS OpenRTOS là phiên bản thương mại của FreeRTOS.org và không thuộc GPL Trong khi đó, SafeRTOS được phát triển dựa trên FreeRTOS nhưng đã trải qua quá trình phân tích, chứng minh tài liệu và kiểm tra nghiêm ngặt theo tiêu chuẩn IEC61508 Tiêu chuẩn IEC61508 SIL3 đã được tạo ra độc lập nhằm hoàn thiện tài liệu cho SafeRTOS.
Hình 2.1: Sơ đồ phát triển của FreeRTOS
1.2 Các đặc điểm của FreeRTOS
Các chức năng được cung cấp trong FreeRTOS
FreeRTOS.org là lõi của hệ điều hành thời gian thực được thiết kế cho các hệ thống nhúng nhỏ, với các chức năng chính sau:
- Lõi FreeRTOS hỗ trợ cả preemptive, cooperative và các lựa chọn cấu hình lai giữa hai phần
- SafeRTOS là sản phẩm dẫn xuất, cung cấp mã nguồn riêng ở mức độ cao
- Được thiết kế nhỏ, đơn giản và dễ sử dụng
- Cấu trúc mã nguồn rất linh động được viết bằng ngôn ngữ C
- Hỗ trợ cả task và co-routine
- Mạnh về hàm theo vết
- Có lựa chọn nhận biết tràn ngăn xếp
- Không giới hạn số task có thể tạo ra, phụ thuộc vào tài nguyên của chip
- Không giới hạn số mức ưu tiên được sử dụng
- Không giới hạn số task cùng một mức ưu tiên
- Hỗ trợ truyền thông và đồng bộ giữa các task hoặc giữa task và ngắt: queues, binary semaphores, counting semaphores and recursive mutexes
- Mutexes với ưu tiên kế thừa
- Các công cụ phát triển miễn phí, port cho Cortex -M3, ARM7,
PIC,MSP430, H8/S, AMD, AVR, x86 và 8051
- Miễn phí mã nguồn phần mềm nhúng Miễn phí trong ứng dụng thương mại
- Tiền cấu hình cho các ứng dụng demo, từ đó dễ dàng tìm hiểu và phát triển
1.3 Các vi điều khiển và trình dịch đã được hỗ trợ port FreeRTOS
- Vi điều khiển ST STM32 Cortex -M3
- ARM Cortex-M3 d ựa trên vi điều khiển sử dụng ARM Keil
(RVDS), IAR, Rowley và công c ụ GCC
- Atmel AVR32 A T32UC3A: vi điều khiển flash sử dụng GCC và IAR
- Các vi điện tử ST: STR71x (ARM7), STR75x( ARM7), STR9 (ARM9) (STR711F, STR712F, … )
- LPC2106, LPC2124 và LPC2129 (ARM7) G ồm mã nguồn cho I2C driver H8S2329 (Hitachi H8/S) v ới EDK2329 demo
- AtmelAT91SAM7family(AT91SAM7X256,AT91SAM7X128,AT9 1SAM7S32,AT91SAM7S64, AT91SAM7S128, AT91SAM7S256)
- Bao gồm mã nguồn USB driver cho IAR Kickstart, uIP và lwIP nhúng vào Ethernet TCP/IP
- AT91FR40008 v ới Embest ATEB40X demo
- MSP430 v ới demo cho LCD driver
- MSPGCC and Rowley CrossWorks được hỗ trợ
- HCS12 (MC9S12C32 lo ại bộ nhớ nhỏ và MC9S12DP256B kiểu bank nhớ) Fujitsu MB91460 series (32bit) and MB96340 series (16FX 16bit) s ử dụng trình d ịch Softune và Euroscope debugger
- Microchip PICMicro PIC18 (8 bit), PIC24 (16bit MCU) và dsPIC (16bitDSC) và PIC32 (32bit)
- Atmel AVR (MegaAVR) v ới STK500 demo
- Vi điều khiển RDC8822 với demo cho Flashlite 186 SBC
- PC (chạy ở FreeDOS hoặc DOS khác)
- ColdFire, chú ý r ằng port nàyko được hỗ trợ
- Zilog Z80, chú ý r ằng port nàyko được hỗ trợ
- Xilinx Microblaze ch ạy trên Virtex4 FPGA
- Xilinx PowerPC (PPC405) ch ạy trên Virtex4 FPGA
Ngoài ra các trình dịch đã hỗ trợ port: Rowley CrossWorks, Keil,
CodeWarrior, IAR, GNU GCC (nhiều loại), MPLAB, SDCC, Open Watcom, Paradigm và Borland.
Lựa chọn linh kiện
Mạch Arduino Uno là một trong những dòng mạch phổ biến nhất, đặc biệt dành cho những người mới bắt đầu làm quen và lập trình với Arduino Hiện tại, dòng mạch này đã phát triển đến thế hệ thứ ba, mang đến nhiều cải tiến và tính năng hữu ích cho người dùng.
Arduino Uno R3 là một bo mạch linh hoạt và cơ bản, lý tưởng cho người mới bắt đầu Mặc dù có nhiều lựa chọn khác như Arduino Mega, Arduino Nano và Arduino Micro, nhưng Arduino Uno vẫn là sự lựa chọn tối ưu cho các ứng dụng cơ bản.
Arduino UNO R3 là phiên bản thứ ba của kit Arduino UNO, được thiết kế để lập trình các ứng dụng điều khiển phức tạp Với cấu hình mạnh mẽ, Arduino UNO R3 sở hữu bộ nhớ ROM, RAM và Flash lớn, cùng với nhiều ngõ vào ra digital I/O, trong đó có các ngõ hỗ trợ xuất tín hiệu PWM Ngoài ra, nó còn tích hợp khả năng đọc tín hiệu analog và hỗ trợ các chuẩn giao tiếp đa dạng như UART, SPI và TWI (I2C).
Vi điều khiển ATmega328 họ 8bit Điện áp hoạt động 5V DC (chỉ được cấp qua cổng
Tần số hoạt động 16 MHz
Dòng tiêu thụ khoảng 30mA Điện áp vào khuyên dùng 7-12V DC Điện áp vào giới hạn 6-20V DC
Số chân Digital I/O 14 (6 chân hardware PWM)
Số chân Analog 6 (độ phân giải 10bit)
Dòng tối đa trên mỗi chân I/O 30 mA
Dòng ra tối đa (5V) 500 mA
Dòng ra tối đa (3.3V) 50 mA
Bộ nhớ flash 32 KB (ATmega328) với 0.5KB dùng bởi bootloader
Bảng 2.1 Các thông số kỹ thuật của Arduino UNO R3 b Sơ đồ chân
Hình 2.2 Sơ đồ chân Arduino Uno R3
GND (Ground) là cực âm của nguồn điện cấp cho Arduino UNO Khi sử dụng các thiết bị với nguồn điện riêng biệt, cần phải kết nối các chân GND này với nhau để đảm bảo hoạt động ổn định.
- 5V: cấp điện áp 5V đầu ra Dòng tối đa cho phép ở chân này là 500mA
- 3.3V: cấp điện áp 3.3V đầu ra Dòng tối đa ở chân này là 50mA
- Vin (Voltage Input): để cấp nguồn ngoài cho Arduino UNO, ta nối cực dương của nguồn với chân này và cực âm với chân GND
IOREF là chân trên Arduino UNO cho phép đo điện áp hoạt động của vi điều khiển, thường là 5V Tuy nhiên, không nên lấy nguồn 5V từ chân này vì chức năng chính của nó không phải là cung cấp nguồn.
- RESET: việc nhấn nút Reset trên board để reset vi điều khiển tương đương với việc chân RESET được nối với GND qua 1 điện trở 10KΩ
Arduino UNO có 14 chân digital dùng để đọc hoặc xuất tín hiệu Chúng chỉ có 2 mức điện áp là 0V và 5V với dòng tối đa trên mỗi chân là 40mA
Một số chân digital có các chức năng đặc biệt như sau:
Chân Serial 0 (RX) và 1 (TX) trên Arduino Uno được sử dụng để gửi (TX) và nhận (RX) dữ liệu TTL Serial, cho phép giao tiếp với các thiết bị khác Kết nối Bluetooth thường được coi là một hình thức kết nối Serial không dây Nếu không cần giao tiếp Serial, nên tránh sử dụng hai chân này để tiết kiệm tài nguyên.
Chân PWM (~) 3, 5, 6, 9, 10, và 11 cho phép xuất xung PWM với độ phân giải 8 bit, với giá trị từ 0 đến 255 tương ứng với điện áp từ 0V đến 5V thông qua hàm analogWrite() Điều này có nghĩa là điện áp đầu ra có thể được điều chỉnh linh hoạt từ 0V đến 5V, khác biệt so với các chân khác chỉ có mức điện áp cố định.
Chân giao tiếp SPI bao gồm 10 (SS), 11 (MOSI), 12 (MISO) và 13 (SCK), không chỉ thực hiện các chức năng thông thường mà còn hỗ trợ truyền phát dữ liệu qua giao thức SPI với các thiết bị khác.
Trên board Arduino UNO, có một đèn LED màu cam được ký hiệu bằng chữ L Khi nhấn nút Reset, đèn LED này sẽ nhấp nháy để báo hiệu, và nó được kết nối với chân số.
13 Khi chân này được người dùng sử dụng, LED sẽ sáng
Arduino UNO có 6 chân analog (A0 → A5) cung cấp độ phân giải tín hiệu 10bit (0 → 210-1) để đọc giá trị điện áp trong khoảng 0V → 5V Với chân
Khi sử dụng các chân analog trên board AREF, việc cấp điện áp tham chiếu 2.5V cho phép chúng ta tận dụng các chân này hiệu quả hơn Đặc biệt, Arduino UNO được trang bị hai chân A4 (SDA) và A5 (SCL) hỗ trợ giao tiếp I2C/TWI với các thiết bị khác, mở rộng khả năng kết nối và tương tác.
2.2 Tổng quan về ESP8266 nodeMCU
ESP8266 là một mạch vi điều khiển mạnh mẽ, cho phép người dùng điều khiển các thiết bị điện tử một cách linh hoạt Đặc biệt, nó được tích hợp Wi-Fi 2.4GHz, hỗ trợ lập trình và kết nối mạng dễ dàng.
Hình 2.5 Mô hình ESP8266 NodeMCU
-WiFi: 2.4 GHz hỗ trợ chuẩn 802.11 b/g/n
-Điện áp vào: 5V thông qua cổng USB
-Số chân I/O: 11 (tất cả các chân I/O đều có Interrupt/PWM/I2C/One-wire, trừ chân D0)
-Số chân Analog Input: 1 (điện áp vào tối đa 3.3V)
-Giao tiếp: Cable Micro USB ( tương đương cáp sạc điện thoại )
-Hỗ trợ bảo mật: WPA/WPA2
-Tích hợp giao thức TCP/IP
-Lập trình trên các ngôn ngữ: C/C++, Micropython,…
Một số ứng dụng cơ bản khi sử dụng ESP8266 trên Ubuntu
-Đọc nhiệt độ trên cảm biến DHT11 bằng openHAB
-Điều khiển bật/tắt Led bằng giọng nói sử dụng ứng dụng openHAB
STM32 là một trong những dòng chip phổ biến của ST với nhiều họ thông dụng như F0,F1,F2,F3,F4… Stm32f407 thuộc họ F1 với lõi là ARM COTEX M4
- Vi điều khiển chính: STM32F407VGT6 32-bit ARM Cortex-M4 core, 1
- Nguồn cấp từ cổng Mini USB qua các IC nguồn chuyển thành 3V3 để cấp cho MCU
- Flexible power-supply options: có các chân nguồn 3 V và 5 V để lựa chọn cấp nguồn
- Có 4 Led và 2 nút nhấn trong đó có một nút Reset
- Có led thông báo trạng thái nguồn và led báo trạng thái kết nôi USB
- Hỗ trợ Audio DAC tích hợp class D speaker driver
- Có chân cắm cho jack audio 3.5mm
- Hỗ trợ cổng cắm cho ứng dụng USB OTG FS
- Onboard Debugger interface: mạch nạp và mạch debugger đã được thiết kế trực tiếp trên KIT
Hình 2.6 Sơ đồ chân STM32F407 Discovery Board
2.4 Một số linh kiện khác
3 Phần mềm và giao tiếp được sử dụng
Blynk là một nền tảng với các ứng dụng iOS và Android để điều khiển
Arduino, Raspberry Pi và các ứng dụng tương tự qua Internet
Bảng điều khiển kỹ thuật số cho phép bạn tạo giao tiếp đồ họa cho dự án của mình thông qua việc kéo và thả các widget một cách dễ dàng.
Việc thiết lập Blynk rất dễ dàng và chỉ mất chưa đầy 5 phút Blynk không giới hạn với các bo mạch hoặc shield cụ thể, mà kết nối qua Internet bằng Wi-Fi, Ethernet hoặc chip ESP8266, giúp bạn sẵn sàng cho IoT.
Hình 2.7 Giao tiếp app Blynk
Có ba thành phần chính trong nền tảng:
Blynk App - cho phép tạo giao tiếp cho sản phẩm của bạn bằng cách kéo thả các widget khác nhau mà nhà cung cấp đã thiết kế sẵn
Blynk Server là trung tâm xử lý dữ liệu giữa điện thoại, máy tính bảng và phần cứng Người dùng có thể lựa chọn sử dụng Blynk Cloud hoặc tự tạo máy chủ Blynk riêng Với mã nguồn mở, Blynk cho phép dễ dàng tích hợp vào các thiết bị, bao gồm cả việc sử dụng Raspberry Pi làm máy chủ.
Thư viện Blynk hỗ trợ hầu hết các nền tảng phần cứng phổ biến, cho phép giao tiếp hiệu quả với máy chủ và xử lý mọi lệnh gửi đi và nhận về.
XÂY DỰNG HỆ THỐNG
Giải pháp thiết kế
- Cấp nguồn cho khác khối khác hoạt động
- Gửi các giá trị từ cảm biến trả về cho Khối xử lý tính toán
Tính toán các giá trị cảm biến và gửi kết quả đã xử lý đến Khối hiển thị, đồng thời truyền tín hiệu điều khiển đến Khối động cơ và đèn.
- Hiển thị các giá trị lên phần mềm Blynk
- Hoạt động khi có tín hiệu điều khiển
Hình 3.2 Sơ đồ nguyên lý
Arduino ESP8266 Relay Cảm biến độ ẩm đất 1
Cảm biến độ ẩm đất 2
Cảm biến nhiệt độ kk
VCC VCC VCC VCC VCC VCC
GND GND GND GND GND GND
Bảng 3.1 Sơ đồ nối chân
Thiết kế phần mềm
Hình 3.3 Lưu đồ thuật toán Arduino
Hình 3.4 Lưu đồ thuật toán ESP8266
TaskHandle_t SendTaskHandle; int doc_cb,TBcb,value1,value2; char t;
SoftwareSerial CBR(12,13);// RX, TX void Vuon1Task(void* pvParameters); void Vuon2Task(void* pvParameters); void SendTask(void* pvParameters); void setup() {
The code initializes a communication baud rate of 115200 and sets up two input pins (CB1 and CB2) and two output pins (MayBom1 and MayBom2) It records the current time using `millis()` and creates a mutex for synchronization Three tasks are then created: "Vuon1Task," "Vuon2Task," and "SendTask," each allocated 128 bytes of stack space and given a priority level of 1 Finally, the task scheduler is started to manage the execution of these tasks.
} void Vuon1Task(void* pvParameters)
Sử dụng lệnh xSemaphoreTake(xMutex, portMAX_DELAY) để đảm bảo truy cập an toàn vào tài nguyên chia sẻ Tiếp theo, chúng ta sẽ tạo một vòng lặp for để đọc giá trị cảm biến 10 lần, từ đó tính toán giá trị trung bình nhằm đạt được độ chính xác cao nhất.
TBcb=doc_cb/10; //Tính giá trị trung bình int phantramao = map(TBcb, 0, 1023, 0, 100); //Chuyển giá trị Analog thành giá trị % value1 = 100 - phantramao; //Tính giá trị phần trăm thực, chuyển
Serial print(" Do am dat vuon 1 : ");
Serial.println('%'); vTaskDelay(pdMS_TO_TICKS(1000)); doc_cb=0;
Serial.println(" ====> DAT KHO THIEU NUOC");
Serial.println(" ====> MAY BOM 1 CHAY "); digitalWrite(MayBom1, HIGH);
Serial.println(" ====> DO AM DAT BINH THUONG");
Serial.println(" ====> MAY BOM 1 TAT "); digitalWrite(MayBom1, LOW);
} vTaskDelay(pdMS_TO_TICKS(1000)); xSemaphoreGive( xMutex ); taskYIELD();
} void Vuon2Task(void* pvParameters)
Sử dụng xSemaphoreTake(xMutex, portMAX_DELAY) để đảm bảo an toàn khi truy cập tài nguyên Chúng ta sẽ tạo một vòng lặp for để đọc giá trị cảm biến 10 lần, sau đó tính giá trị trung bình để đạt được độ chính xác cao nhất.
Để tính giá trị trung bình, sử dụng công thức TBcb=doc_cb/10 Giá trị Analog được chuyển đổi sang phần trăm với phantramao = map(TBcb, 0, 1023, 0, 100) Cuối cùng, để xác định giá trị phần trăm thực, ta tính value2 = 100 - phantramao, chuyển đổi điện thế khô thành ẩm.
Serial print(" Do am dat vuon 2 : ");
Serial.println('%'); vTaskDelay(pdMS_TO_TICKS(1000)); doc_cb=0;
Serial.println(" ====> DAT KHO THIEU NUOC");
Serial.println(" ====> MAY BOM 2 CHAY "); digitalWrite(MayBom2, HIGH);
Serial.println(" ====> DO AM DAT BINH THUONG");
Serial.println(" ====> MAY BOM 2 TAT "); digitalWrite(MayBom2, LOW);
} vTaskDelay(pdMS_TO_TICKS(1000)); xSemaphoreGive( xMutex ); taskYIELD();
{ long v 34; xSemaphoreTake( xMutex, portMAX_DELAY ); if(millis()-last > 00)
Serial.print(" -Gui du lieu cho ESP : ");
} vTaskDelay(pdMS_TO_TICKS(1000)); xSemaphoreGive( xMutex ); taskYIELD();
#define BLYNK_TEMPLATE_ID "TMPLKgKZQJSG"
#define BLYNK_DEVICE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "4gh5rT2o6bPauNDnS9LYi- xjheNPdvek"
#define BLYNK_PRINT Serial char auth[] = BLYNK_AUTH_TOKEN; char ssid[] = "Trieu Phu"; char pass[] = "trieuphu46";
String b= ""; int value1, value2,i; char c; int n1=0,n2=0,n3=0; void setup()
Blynk.begin(auth, ssid, pass, "64.225.16.22", 80); dht.begin(); timer.setInterval(1000L, loop); last = millis();
Serial.print(" Nhan gia tri DATA gui tu ARDUINO :"); Serial.println(""); delay(1000); for(i=0; iCTRL |= (1