- Memadam Tugas di FreeRTOS Arduino
- Apakah Antrian di FreeRTOS?
- Membuat Antrian di FreeRTOS
- Rajah Litar
- Melaksanakan 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 menyelami lebih banyak konsep RTOS API terlebih dahulu dan belajar mengenai komunikasi antara tugas yang berbeza. Di sini kita juga belajar mengenai Antrian untuk memindahkan data dari satu tugas ke tugas yang lain dan menunjukkan cara kerja API antrian dengan menghubungkan LCD dan LDR 16x2 dengan Arduino Uno.
Sebelum membincangkan mengenai Antrian, mari kita lihat satu lagi API FreeRTOS yang berguna dalam menghapus tugas apabila selesai dengan kerja yang diberikan. Kadang-kadang tugas itu perlu dihapus untuk membebaskan memori yang diberikan. Sebagai lanjutan dari tutorial sebelumnya, kami akan menggunakan fungsi API vTaskDelete () dalam kod yang sama untuk menghapus salah satu tugas. Tugas boleh menggunakan fungsi API vTaskDelete () untuk memadamkannya sendiri, atau tugas lain.
Untuk menggunakan API ini, anda harus mengkonfigurasi fail FreeRTOSConfig.h . Fail ini digunakan untuk menyesuaikan FreeRTOS mengikut aplikasi. Ia digunakan untuk mengubah algoritma penjadualan dan banyak parameter lain. Fail boleh didapati di Arduino Directory yang biasanya terdapat di folder Dokumen pada PC anda. Dalam kes saya, ia boleh didapati di \ Documents \ Arduino \ library \ FreeRTOS \ src seperti gambar di bawah.
Sekarang, buka fail ini menggunakan mana-mana editor teks dan mencari yang # menentukan INCLUDE_vTaskDelete dan memastikan nilai ialah '1' (1 cara membolehkan dan 0 cara mematikan). Ini adalah 1 secara lalai tetapi memeriksanya.
Kami akan menggunakan fail konfigurasi ini dengan kerap dalam tutorial kami seterusnya untuk menetapkan parameter.
Sekarang, mari kita lihat cara menghapus tugas.
Memadam Tugas di FreeRTOS Arduino
Untuk menghapus tugas, kita harus menggunakan fungsi API vTaskDelete (). Hanya memerlukan satu hujah.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Ia adalah pengendalian tugas yang akan dihapuskan. Ia sama dengan argumen ke- 6 API xTaskCreate () . Dalam tutorial sebelumnya, argumen ini ditetapkan sebagai NULL tetapi anda boleh menyampaikan alamat isi tugas dengan menggunakan nama apa pun. Katakanlah jika anda ingin menetapkan tugas menangani untuk Task2 yang dinyatakan sebagai
TaskHandle_t any_name; Contoh: TaskHandle_t xTask2Handle;
Sekarang, dalam API vTaskCreate () menetapkan argumen ke- 6 sebagai
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Kandungan tugas ini kini dapat diakses menggunakan pegangan yang diberikan oleh anda.
Juga, tugas dapat menghapuskan dirinya dengan melewati NULL sebagai pengganti tugas yang sah.
Sekiranya kita mahu memadam Tugasan 3 dari tugas 3 itu sendiri, anda perlu menulis vTaskDelete (NULL); di dalam fungsi Task3 tetapi jika anda ingin menghapus tugas 3 dari tugas 2, kemudian tulis vTaskDelete (xTask3Handle); di dalam fungsi task2.
Dalam kod tutorial sebelumnya, untuk menghapus Task2 dari task2 itu sendiri, cukup tambahkan vTaskDelete (NULL); dalam fungsi TaskBlink2 (void * pvParameters) void . Maka fungsi di atas akan kelihatan seperti ini
batal TaskBlink2 (void * pvParameters) { Serial.println ("Task2 sedang berjalan dan akan dihapuskan"); vTaskDelete (NULL); pinMode (7, OUTPUT); sementara (1) { digitalWrite (7, TINGGI); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Sekarang, muat naik kod dan perhatikan LED dan Serial monitor. Anda akan melihat bahawa LED kedua tidak berkedip sekarang dan task2 dipadamkan setelah menemui API hapus.
Jadi API ini dapat digunakan untuk menghentikan pelaksanaan tugas tertentu.
Sekarang, mari kita mulakan dengan Antrian.
Apakah Antrian di FreeRTOS?
Antrian adalah struktur data yang dapat menahan bilangan elemen ukuran tetap yang terbatas dan ia dikendalikan dalam skema FIFO (First-in First-out). Antrean menyediakan mekanisme komunikasi task-to-task, task-to-interrupt, dan interrupt-to-task.
Jumlah maksimum elemen yang boleh ditahan oleh antrian disebut "panjangnya". Panjang dan ukuran setiap elemen ditetapkan semasa barisan dibuat.
Contoh bagaimana barisan digunakan untuk pemindahan data digambarkan dengan baik dalam dokumentasi FreeRTOS yang boleh didapati di sini. Anda dapat memahami contoh yang diberikan dengan mudah.
Setelah memahami Antrian, mari cuba memahami proses membuat barisan dan cuba menerapkannya dalam kod FreeRTOS kami.
Membuat Antrian di FreeRTOS
Pertama, terangkan pernyataan masalah yang akan dilaksanakan dengan bantuan barisan FreeRTOS dan Arduino Uno.
Kami mahu mencetak nilai sensor LDR pada LCD 16 * 2. Jadi ada dua tugas sekarang
- Task1 mendapatkan nilai analog LDR.
- Task2 mencetak nilai analog pada LCD.
Jadi, di sini barisan memainkan peranannya kerana untuk menghantar data yang dihasilkan oleh task1 ke task2. Dalam task1, kami akan menghantar nilai analog ke barisan dan di task2, kami akan menerimanya dari barisan.
Terdapat tiga fungsi untuk bekerja dengan barisan
- Membuat Antrian
- Menghantar data ke Antrian
- Menerima data dari Antrian
Untuk membuat barisan, gunakan fungsi API xQueueCreate (). Ia memerlukan dua hujah.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Jumlah maksimum item yang boleh ditahan oleh barisan dalam satu masa.
uxItemSize: Ukuran dalam bait setiap item data yang boleh disimpan dalam barisan.
Sekiranya fungsi ini mengembalikan NULL maka barisan tidak dibuat kerana memori tidak mencukupi dan jika mengembalikan nilai bukan NULL, barisan berjaya dibuat. Simpan nilai pulangan ini ke pemboleh ubah untuk menggunakannya sebagai pemegang untuk mengakses barisan seperti yang ditunjukkan di bawah.
QueueHandle_t beratur1; queue1 = xQueueCreate (4, sizeof (int));
Ini akan membuat barisan elemen 4 dalam memori timbunan saiz int (2 bait setiap blok) dan menyimpan nilai kembali ke pemboleh ubah pemegang queue1 .
2. Menghantar Data ke Antrian di FreeRTOS
Untuk menghantar nilai ke barisan, FreeRTOS mempunyai 2 varian API untuk tujuan ini.
- xQueueSendToBack (): Digunakan untuk menghantar data ke belakang (ekor) barisan.
- xQueueSendToFront (): Digunakan untuk menghantar data ke depan (kepala) barisan.
Sekarang , xQueueSend () bersamaan, dan sama dengan xQueueSendToBack ().
Semua API ini mengambil 3 argumen.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Pegangan barisan ke mana data dihantar (ditulis). Pemboleh ubah ini sama seperti yang digunakan untuk menyimpan nilai kembali API xQueueCreate.
pvItemToQueue: Penunjuk data yang akan disalin ke dalam barisan.
xTicksToWait: Jumlah masa maksimum tugas harus tetap dalam keadaan Disekat untuk menunggu ruang tersedia dalam barisan.
Menetapkan xTicksToWait ke portMAX_DELAY akan menyebabkan tugas menunggu selama-lamanya (tanpa tamat waktu), dengan syarat INCLUDE_vTaskSuspend ditetapkan ke 1 di FreeRTOSConfig. Jika tidak, anda boleh menggunakan makro pdMS_TO_TICKS () untuk menukar masa yang ditentukan dalam milisaat menjadi masa yang ditentukan dalam kutu.
3. Menerima Data dari Antrian di FreeRTOS
Untuk menerima (membaca) item dari barisan, xQueueReceive () digunakan. Item yang diterima dikeluarkan dari barisan.
API ini juga mengambil tiga hujah.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Argumen pertama dan ketiga sama dengan menghantar API. Cuma hujah kedua berbeza.
const pvBuffer: Penunjuk ke memori di mana data yang diterima akan disalin.
Harap anda memahami ketiga-tiga API tersebut. Sekarang, kami akan menerapkan API ini di Arduino IDE dan cuba menyelesaikan pernyataan masalah yang telah kami jelaskan di atas.
Rajah Litar
Beginilah rupanya di papan roti:
Melaksanakan Antrian FreeRTOS di Arduino IDE
Mari mula menulis kod untuk aplikasi kami.
1. Pertama, buka Arduino IDE dan sertakan fail tajuk Arduino_FreeRTOS.h . Sekarang, jika ada objek kernel seperti queue yang digunakan maka sertakan fail header daripadanya. Oleh kerana kami menggunakan LCD 16 * 2 jadi sertakan juga perpustakaan untuknya.
#sertakan #sertakan
2. Memulakan pemegang giliran untuk menyimpan kandungan barisan. Juga, mulakan nombor pin LCD.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. Dalam persediaan kosong (), mulakan monitor LCD dan bersiri dengan kadar baud 9600. Buat barisan dan dua tugas menggunakan API masing-masing. Di sini kita akan membuat barisan ukuran 4 dengan jenis bilangan bulat. Buat tugas dengan keutamaan yang sama dan kemudian cuba bermain dengan nombor ini. Akhirnya, mulakan penjadual seperti yang ditunjukkan di bawah.
persediaan tidak sah () { 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 TaskDisplay dan TaskLDR . Dalam fungsi TaskLDR , baca pin analog A0 dalam pemboleh ubah kerana kita telah menghubungkan LDR ke pin A0 Arduino UNO. Sekarang hantarkan nilai yang disimpan dalam pemboleh ubah dengan meneruskannya di API xQueueSend dan kirim tugas untuk menyekat keadaan setelah 1 saat menggunakan API vTaskDelay () seperti yang ditunjukkan di bawah.
void TaskLDR (void * pvParameters) { int current_intensity ; sementara (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (current_intensity); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Begitu juga, buat fungsi untuk TaskDisplay dan terima nilai dalam pemboleh ubah yang diteruskan ke fungsi xQueueReceive . Juga, xQueueReceive () mengembalikan pdPASS jika data dapat diterima dengan jayanya dari barisan dan mengembalikan errQUEUE_EMPTY jika barisan kosong.
Sekarang, paparkan nilai ke LCD menggunakan fungsi lcd.print () .
void TaskDisplay (void * pvParameters) { int intensiti = 0; sementara (1) { Serial.println ("Task2"); if (xQueueReceive (queue_1, & intensity, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensity:"); lcd.setCursor (11, 0); lcd.print (intensiti); } } }
Itu sahaja. Kami telah menyelesaikan bahagian pengekodan pelaksanaan Queue. Kod lengkap dengan Video yang berfungsi boleh didapati di hujungnya.
Sekarang, sambungkan LCD dan LDR dengan Arduino UNO mengikut gambarajah litar yang memuat naik kod. Buka monitor bersiri dan amati tugasnya. Anda akan melihat tugas beralih dan nilai LDR berubah mengikut intensiti cahaya.
CATATAN: Sebilangan besar perpustakaan yang dibuat untuk sensor yang berbeza tidak disokong oleh kernel FreeRTOS kerana kelewatan pelaksanaan fungsi di dalam perpustakaan. Kelewatan menjadikan CPU berhenti sepenuhnya, oleh itu, kernel FreeRTOS juga berhenti berfungsi dan kod tidak akan dijalankan lebih jauh dan ia mula tidak berfungsi. Oleh itu, kita harus menjadikan perpustakaan bebas untuk bekerja dengan FreeRTOS.