- Menghapus Tugas di FreeRTOS Arduino
- Apa itu Antrian di FreeRTOS?
- Membuat Antrian di FreeRTOS
- Diagram Sirkuit
- Menerapkan Antrian FreeRTOS di Arduino IDE
Dalam tutorial sebelumnya, kami memperkenalkan FreeRTOS di Arduino Uno dan membuat tugas untuk LED yang berkedip. Sekarang, dalam tutorial ini, kita akan mendalami lebih dalam konsep lanjutan dari API RTOS dan belajar tentang komunikasi antara tugas yang berbeda. Di sini kita juga belajar tentang Queue untuk mentransfer data dari satu tugas ke tugas lainnya dan mendemonstrasikan cara kerja API antrian dengan menghubungkan LCD 16x2 dan LDR dengan Arduino Uno.
Sebelum membahas tentang Queues, mari kita lihat satu lagi FreeRTOS API yang berguna untuk menghapus tugas ketika sudah selesai dengan pekerjaan yang ditugaskan. Terkadang tugas perlu dihapus untuk membebaskan memori yang dialokasikan. Sebagai kelanjutan dari tutorial sebelumnya, kita akan menggunakan fungsi API vTaskDelete () dalam kode yang sama untuk menghapus salah satu tugas. Sebuah tugas bisa menggunakan fungsi API vTaskDelete () untuk menghapus dirinya sendiri, atau tugas lainnya.
Untuk menggunakan API ini, Anda harus mengkonfigurasi file FreeRTOSConfig.h . File ini digunakan untuk menyesuaikan FreeRTOS sesuai dengan aplikasi. Ini digunakan untuk mengubah algoritma penjadwalan dan banyak parameter lainnya. File tersebut dapat ditemukan di Direktori Arduino yang umumnya tersedia di folder Dokumen PC Anda. Dalam kasus saya, ini tersedia di \ Documents \ Arduino \ libraries \ FreeRTOS \ src seperti yang ditunjukkan di bawah ini.
Sekarang, buka file ini menggunakan editor teks dan mencari yang # define INCLUDE_vTaskDelete dan pastikan nilainya adalah '1' (1 berarti mengaktifkan dan 0 berarti menonaktifkan). Ini adalah 1 secara default tetapi memeriksanya.
Kami akan sering menggunakan file konfigurasi ini di tutorial berikutnya untuk mengatur parameter.
Sekarang, mari kita lihat cara menghapus tugas.
Menghapus Tugas di FreeRTOS Arduino
Untuk menghapus tugas, kita harus menggunakan fungsi API vTaskDelete (). Hanya dibutuhkan satu argumen.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Ini adalah pegangan tugas yang akan dihapus. Ini sama dengan argumen ke- 6 dari xTaskCreate () API. Dalam tutorial sebelumnya, argumen ini disetel sebagai NULL tetapi Anda dapat meneruskan alamat konten tugas dengan menggunakan nama apa pun. Katakanlah jika Anda ingin mengatur pegangan tugas untuk Task2 yang dideklarasikan sebagai
TaskHandle_t any_name; Contoh: TaskHandle_t xTask2Handle;
Sekarang, dalam vTaskCreate () API setel argumen ke- 6 sebagai
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Konten tugas ini sekarang dapat diakses menggunakan pegangan yang Anda berikan.
Selain itu, tugas dapat menghapus dirinya sendiri dengan meneruskan NULL di tempat pegangan tugas yang valid.
Jika kita ingin menghapus Task 3 dari task 3 itu sendiri, Anda perlu menulis vTaskDelete (NULL); di dalam fungsi Task3 tetapi jika Anda ingin menghapus tugas 3 dari tugas 2, tulis vTaskDelete (xTask3Handle); di dalam fungsi task2.
Pada kode tutorial sebelumnya, untuk menghapus Task2 dari task2 itu sendiri, cukup tambahkan vTaskDelete (NULL); dalam fungsi void TaskBlink2 (void * pvParameters) . Maka fungsi di atas akan terlihat seperti ini
void TaskBlink2 (void * pvParameters) { Serial.println ("Task2 sedang berjalan dan akan dihapus"); vTaskDelete (NULL); pinMode (7, OUTPUT); sementara (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Sekarang, unggah kode dan amati LED dan monitor Serial. Anda akan melihat bahwa LED kedua tidak berkedip sekarang dan task2 dihapus setelah menemukan API hapus.
Jadi API ini dapat digunakan untuk menghentikan eksekusi tugas tertentu.
Sekarang, mari kita mulai dengan Antrian.
Apa itu Antrian di FreeRTOS?
Antrian adalah struktur data yang dapat menampung sejumlah elemen berukuran tetap dan dioperasikan dalam skema FIFO (First-in First-out). Antrian menyediakan mekanisme komunikasi tugas-ke-tugas, tugas-ke-interupsi, dan interupsi-ke-tugas.
Jumlah maksimum elemen yang dapat ditampung antrian disebut "panjang". Baik panjang dan ukuran setiap elemen ditetapkan saat antrean dibuat.
Contoh bagaimana antrian digunakan untuk transfer data diilustrasikan dengan baik dalam dokumentasi FreeRTOS yang dapat ditemukan di sini. Anda dapat dengan mudah memahami contoh yang diberikan.
Setelah memahami Queues, mari kita coba memahami proses pembuatan antrian dan mencoba menerapkannya dalam kode FreeRTOS kami.
Membuat Antrian di FreeRTOS
Pertama, jelaskan pernyataan masalah yang akan diimplementasikan dengan bantuan antrian FreeRTOS dan Arduino Uno.
Kami ingin mencetak nilai sensor LDR pada LCD 16 * 2. Jadi sekarang ada dua tugas
- Tugas1 mendapatkan nilai analog dari LDR.
- Tugas2 mencetak nilai analog pada LCD.
Jadi, di sini antrian berperan karena untuk mengirim data yang dihasilkan oleh task1 ke task2. Di task1, kami akan mengirim nilai analog ke antrian dan di task2, kami akan menerimanya dari antrian.
Ada tiga fungsi untuk bekerja dengan antrian
- Membuat Antrian
- Mengirim data ke Antrian
- Menerima data dari Antrian
Untuk membuat antrian, gunakan API fungsi xQueueCreate (). Ini membutuhkan dua argumen.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Jumlah maksimum item yang dapat ditampung oleh antrean dalam satu waktu.
uxItemSize: Ukuran dalam byte dari setiap item data yang dapat disimpan dalam antrian.
Jika fungsi ini mengembalikan NULL maka antrian tidak dibuat karena memori yang tidak mencukupi dan jika mengembalikan nilai non-NULL, antrian berhasil dibuat. Simpan nilai kembali ini ke variabel untuk digunakan sebagai pegangan untuk mengakses antrian seperti yang ditunjukkan di bawah ini.
QueueHandle_t queue1; queue1 = xQueueCreate (4, sizeof (int));
Ini akan membuat antrian 4 elemen dalam memori heap dengan ukuran int (2 byte dari setiap blok) dan menyimpan nilai yang dikembalikan ke variabel pegangan queue1 .
2. Mengirim Data ke Queue di FreeRTOS
Untuk mengirim nilai ke antrian, FreeRTOS memiliki 2 varian API untuk tujuan ini.
- xQueueSendToBack (): Digunakan untuk mengirim data ke belakang (ekor) antrian.
- xQueueSendToFront (): Digunakan untuk mengirim data ke depan (kepala) antrian.
Sekarang , xQueueSend () sama dengan, dan persis sama dengan, xQueueSendToBack ().
Semua API ini membutuhkan 3 argumen.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Pegangan antrian tempat data dikirim (ditulis). Variabel ini sama dengan yang digunakan untuk menyimpan nilai yang dikembalikan dari xQueueCreate API.
pvItemToQueue: Penunjuk ke data yang akan disalin ke antrian.
xTicksToWait: Jumlah waktu maksimum tugas harus tetap dalam keadaan Diblokir untuk menunggu ruang tersedia dalam antrian.
Menyetel xTicksToWait ke portMAX_DELAY akan menyebabkan tugas menunggu tanpa batas waktu (tanpa waktu habis), asalkan INCLUDE_vTaskSuspend disetel ke 1 di FreeRTOSConfig.h jika tidak, Anda bisa menggunakan makro pdMS_TO_TICKS () untuk mengubah waktu yang ditentukan dalam milidetik menjadi waktu yang ditentukan dalam tanda centang.
3. Menerima Data dari Queue di FreeRTOS
Untuk menerima (membaca) item dari antrian, xQueueReceive () digunakan. Item yang diterima dihapus dari antrian.
API ini juga membutuhkan tiga argumen.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Argumen pertama dan ketiga sama dengan mengirim API. Hanya argumen kedua yang berbeda.
const pvBuffer: Penunjuk ke memori tempat data yang diterima akan disalin.
Harap Anda memahami ketiga API tersebut. Sekarang, kami akan menerapkan API ini di Arduino IDE dan mencoba menyelesaikan pernyataan masalah yang telah kami jelaskan di atas.
Diagram Sirkuit
Ini adalah tampilannya di papan tempat memotong roti:
Menerapkan Antrian FreeRTOS di Arduino IDE
Mari mulai menulis kode untuk aplikasi kita.
1. Pertama, buka Arduino IDE dan sertakan file header Arduino_FreeRTOS.h . Sekarang, jika objek kernel seperti antrian digunakan, maka sertakan file header-nya. Karena kami menggunakan LCD 16 * 2 jadi sertakan juga pustaka untuk itu.
#include #include
2. Inisialisasi pegangan antrian untuk menyimpan isi antrian. Juga, inisialisasi nomor pin LCD.
QueueHandle_t queue_1; LCD LiquidCrystal (7, 8, 9, 10, 11, 12);
3. Dalam void setup (), inisialisasi LCD dan monitor serial dengan 9600 baud rate. Buat antrian dan dua tugas menggunakan API masing-masing. Di sini kita akan membuat antrian ukuran 4 dengan tipe integer. Buat tugas dengan prioritas yang sama dan kemudian cobalah bermain dengan nomor ini. Terakhir, jalankan penjadwal seperti yang ditunjukkan di bawah ini.
void setup () { Serial.begin (9600); lcd.begin (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Antrian tidak dapat dibuat"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Sekarang, buat dua fungsi yaitu TaskDisplay dan TaskLDR . Dalam fungsi TaskLDR , baca pin analog A0 dalam variabel karena LDR telah terhubung ke pin A0 dari Arduino UNO. Sekarang kirim nilai yang disimpan dalam variabel dengan meneruskannya di xQueueSend API dan mengirim tugas ke status blok setelah 1 detik menggunakan vTaskDelay () API seperti yang ditunjukkan di bawah ini.
void TaskLDR (void * pvParameters) { int current_intensity; sementara (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (intensitas_kini); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Demikian pula, buat fungsi untuk TaskDisplay dan terima nilai dalam variabel yang diteruskan ke fungsi xQueueReceive . Selain itu, xQueueReceive () mengembalikan pdPASS jika data berhasil diterima dari antrian dan mengembalikan errQUEUE_EMPTY jika antrian kosong.
Sekarang, tampilkan nilai ke LCD menggunakan fungsi lcd.print () .
void TaskDisplay (void * pvParameters) { int intensitas = 0; sementara (1) { Serial.println ("Task2"); if (xQueueReceive (queue_1, & intensitas, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensitas:"); lcd.setCursor (11, 0); lcd.print (intensitas); } } }
Itu dia. Kami telah menyelesaikan bagian pengkodean dari implementasi Antrian. Kode lengkap dengan Video yang berfungsi dapat ditemukan di bagian akhir.
Sekarang sambungkan LCD dan LDR dengan Arduino UNO sesuai diagram rangkaian unggah kodenya. Buka monitor serial dan amati tugasnya. Anda akan melihat tugas beralih dan nilai LDR berubah sesuai dengan intensitas cahaya.
CATATAN: Sebagian besar pustaka yang dibuat untuk sensor berbeda tidak didukung oleh kernel FreeRTOS karena implementasi fungsi penundaan di dalam pustaka. Delay membuat CPU berhenti sepenuhnya, oleh karena itu, kernel FreeRTOS juga berhenti bekerja dan kode tidak akan dieksekusi lebih lanjut dan mulai mengalami gangguan. Jadi, kami harus membuat perpustakaan bebas penundaan untuk bekerja dengan FreeRTOS.