- FreeRTOS Arduino'da bir Görevi Silme
- FreeRTOS'ta Sıra nedir?
- FreeRTOS'ta Sıra Oluşturma
- Devre şeması
- Arduino IDE'de FreeRTOS Kuyruğunun Uygulanması
Önceki eğitimde, Arduino Uno'da FreeRTOS'u tanıttık ve yanıp sönen LED için bir görev oluşturduk. Şimdi, bu eğiticide, RTOS API'lerinin gelişmiş kavramlarına daha fazla dalacağız ve farklı görevler arasındaki iletişimi öğreneceğiz. Burada ayrıca bir görevden diğerine veri aktarmak ve 16x2 LCD ve LDR'yi Arduino Uno ile arayüz oluşturarak kuyruk API'lerinin çalışmasını göstermek için Queue hakkında bilgi ediniyoruz.
Kuyruklar hakkında tartışmadan önce, atanan iş bittiğinde görevlerin silinmesine yardımcı olacak bir FreeRTOS API daha görelim. Bazen ayrılan hafızayı boşaltmak için görevin silinmesi gerekir. Önceki öğreticinin devamında, görevlerden birini silmek için aynı kodda vTaskDelete () API işlevini kullanacağız. Bir görev, kendisini veya başka bir görevi silmek için vTaskDelete () API işlevini kullanabilir.
Bu API'yi kullanmak için FreeRTOSConfig.h dosyasını yapılandırmanız gerekir. Bu dosya FreeRTOS'u uygulamaya göre uyarlamak için kullanılır. Programlama algoritmalarını ve diğer birçok parametreyi değiştirmek için kullanılır. Dosya, genellikle bilgisayarınızın Belgeler klasöründe bulunan Arduino Dizininde bulunabilir. Benim durumumda, aşağıda gösterildiği gibi \ Documents \ Arduino \ libraries \ FreeRTOS \ src içinde mevcuttur .
Şimdi, herhangi bir metin düzenleyicisi kullanarak bu dosyayı açmak ve aramak #define INCLUDE_vTaskDelete ve emin onun değerdir '1' yapmak (1 vasıta etkinleştirme ve 0 vasıta devre dışı). Varsayılan olarak 1'dir, ancak kontrol eder.
Bu yapılandırma dosyasını parametreleri ayarlamak için sonraki eğitimlerimizde sık sık kullanacağız.
Şimdi bir görevin nasıl silineceğini görelim.
FreeRTOS Arduino'da bir Görevi Silme
Bir görevi silmek için vTaskDelete () API fonksiyonunu kullanmalıyız. Yalnızca bir argüman gerektirir.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Silinecek görevin tanıtıcısıdır. Bu 6 ile aynıdır inci argüman xTaskCreate () API. Önceki öğreticide, bu bağımsız değişken NULL olarak ayarlanmıştır, ancak görevin içeriklerinin adresini herhangi bir ad kullanarak iletebilirsiniz. Diyelim ki, Task2 için görev tutamacını ayarlamak istiyorsanız
TaskHandle_t any_name; Örnek: TaskHandle_t xTask2Handle;
Şimdi, vTaskCreate () API 6 set inci argüman olarak
xTaskCreate (TaskBlink2, "görev2", 128, NULL, 1, & xTask2Handle);
Bu görevin içeriğine artık sizin tarafınızdan verilen tutamaç kullanılarak erişilebilir.
Ayrıca, bir görev, geçerli bir görev tutamacı yerine NULL geçirerek kendini silebilir.
Görev 3'ü görev 3'ten silmek istiyorsak, vTaskDelete (NULL) yazmanız gerekir ; Task3 işlevinin içinde, ancak görev 3'ü görev 2'den silmek istiyorsanız vTaskDelete (xTask3Handle) yazın; görev2 işlevinin içinde.
Önceki eğitim kodunda, Task2'yi task2'nin kendisinden silmek için, sadece vTaskDelete (NULL) ekleyin ; içinde boşluk TaskBlink2 (void * pvParameters) fonksiyonu. Sonra yukarıdaki işlev şöyle görünecek
void TaskBlink2 (void * pvParameters) { Serial.println (“Task2 çalışıyor ve silinmek üzere”); vTaskDelete (NULL); pinMode (7, ÇIKIŞ); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, DÜŞÜK); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Şimdi kodu yükleyin ve LED'leri ve Seri monitörü gözlemleyin. Silme API'siyle karşılaştıktan sonra ikinci LED'in şimdi yanıp sönmediğini ve task2'nin silindiğini göreceksiniz.
Dolayısıyla bu API, belirli bir görevin yürütülmesini durdurmak için kullanılabilir.
Şimdi Sıra ile başlayalım.
FreeRTOS'ta Sıra nedir?
Kuyruk, sınırlı sayıda sabit boyutlu öğeyi tutabilen veri yapısıdır ve FIFO şemasında (İlk Giren İlk Çıkar) çalıştırılır. Kuyruklar, görevden göreve, görevden kesmeye ve görevden görev arası iletişim mekanizmasını sağlar.
Kuyruğun tutabileceği maksimum öğe sayısına "uzunluk" denir. Her bir elemanın hem uzunluğu hem de boyutu, sıra oluşturulduğunda belirlenir.
Kuyruğun veri aktarımı için nasıl kullanıldığına dair bir örnek, burada bulabileceğiniz FreeRTOS belgelerinde iyi bir şekilde gösterilmiştir. Verilen örneği kolayca anlayabilirsiniz.
Kuyrukları anladıktan sonra, kuyruk oluşturma sürecini anlamaya çalışalım ve bunu FreeRTOS kodumuzda uygulamaya çalışalım.
FreeRTOS'ta Sıra Oluşturma
İlk olarak, FreeRTOS kuyruğu ve Arduino Uno yardımıyla uygulanacak problem ifadesini tanımlayın.
LDR sensörünün değerini 16 * 2 LCD ekrana yazdırmak istiyoruz. Yani şimdi iki görev var
- Task1, LDR'nin analog değerlerini alıyor.
- Görev2, analog değeri LCD'ye yazdırıyor.
Dolayısıyla, burada sıra rolünü oynar çünkü görev1 tarafından oluşturulan verileri görev2'ye gönderir. Görev1'de, analog değeri kuyruğa göndereceğiz ve görev2'de bunu kuyruktan alacağız.
Kuyruklarla çalışmak için üç işlev vardır
- Kuyruk Oluşturma
- Kuyruğa veri gönderme
- Kuyruktan veri alma
Sıra oluşturmak için xQueueCreate () işlev API'sini kullanın. İki argüman gerektirir.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Oluşturulan kuyruğun herhangi bir zamanda tutabileceği maksimum öğe sayısı.
uxItemSize: Kuyrukta saklanabilen her veri öğesinin bayt cinsinden boyutu.
Bu işlev NULL döndürürse, yetersiz bellek nedeniyle kuyruk oluşturulmaz ve NULL olmayan bir değer döndürürse, kuyruk başarıyla oluşturulur. Bu dönüş değerini, aşağıda gösterildiği gibi kuyruğa erişmek için bir tutamaç olarak kullanmak için bir değişkene kaydedin.
QueueHandle_t queue1; queue1 = xQueueCreate (4, sizeof (int));
Bu, int boyutlu (her bloğun 2 baytı) yığın hafızasında 4 elemanlı bir sıra oluşturacak ve dönüş değerini queue1 handle değişkenine depolayacaktır .
2. FreeRTOS'ta Verileri Kuyruğa Gönderme
Değerleri kuyruğa göndermek için, FreeRTOS bu amaçla 2 API varyantına sahiptir.
- xQueueSendToBack (): Bir kuyruğun arkasına (kuyruğuna) veri göndermek için kullanılır.
- xQueueSendToFront (): Bir kuyruğun önüne (başına) veri göndermek için kullanılır.
Artık xQueueSend () , xQueueSendToBack () 'e eşdeğerdir ve tam olarak aynıdır .
Tüm bu API'ler 3 argüman alır.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Verilerin gönderildiği (yazıldığı) kuyruğun tanıtıcısı. Bu değişken, xQueueCreate API'nin dönüş değerini depolamak için kullanılanla aynıdır.
pvItemToQueue: Kuyruğa kopyalanacak verilere bir işaretçi.
xTicksToWait: Görevin, kuyrukta kullanılabilir hale gelmesini beklemesi için Engellendi durumunda kalması gereken maksimum süre.
Ayar xTicksToWait için portMAX_DELAY görev (aşımına uğramadan olmaksızın) süresiz beklemesine neden olur, sağlanan INCLUDE_vTaskSuspend 1 olarak ayarlanır FreeRTOSConfig.h başka makro kullanabilirsiniz pdMS_TO_TICKS () keneler belirtilen süre milisaniyesinden belirtilen bir zaman dönüştürün.
3. FreeRTOS'ta Kuyruktan Veri Alma
Kuyruktan bir öğeyi almak (okumak) için xQueueReceive () kullanılır. Alınan öğe kuyruktan kaldırılır.
Bu API ayrıca üç argüman alır.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Birinci ve üçüncü argümanlar API gönderme ile aynıdır. Sadece ikinci argüman farklıdır.
const pvBuffer: Alınan verilerin kopyalanacağı belleğe bir işaretçi.
Umarım üç API'yi anladınız. Şimdi bu API'leri Arduino IDE'de uygulayacağız ve yukarıda anlattığımız problem ifadesini çözmeye çalışacağız.
Devre şeması
Devre tahtasında şu şekilde görünüyor:
Arduino IDE'de FreeRTOS Kuyruğunun Uygulanması
Uygulamamız için kod yazmaya başlayalım.
1. İlk olarak, Arduino IDE'yi açın ve Arduino_FreeRTOS.h başlık dosyasını dahil edin. Şimdi, queue gibi herhangi bir çekirdek nesnesi kullanılırsa, o zaman bunun başlık dosyasını dahil edin. 16 * 2 LCD kullandığımız için kitaplığı da dahil edin.
#include #include
2. Kuyruğun içeriğini saklamak için bir kuyruk tutamacını başlatın. Ayrıca, LCD pin numaralarını da başlatın.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. Geçersiz kurulumda (), LCD ve seri monitörü 9600 baud hızıyla başlatın. İlgili API'leri kullanarak bir sıra ve iki görev oluşturun. Burada tamsayı tipinde 4 boyutunda bir kuyruk oluşturacağız. Eşit önceliklere sahip bir görev oluşturun ve daha sonra bu sayıyla oynamaya çalışın. Son olarak, programlayıcıyı aşağıda gösterildiği gibi başlatın.
geçersiz kurulum () { Serial.begin (9600); lcd.begin (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); eğer (queue_1 == NULL) { Serial.println ("Sıra oluşturulamaz"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Şimdi, TaskDisplay ve TaskLDR olmak üzere iki işlev yapın . Gelen TaskLDR biz LDR Arduino UNO A0 bacağına bağlı gibi işlev, bir değişken analog pim A0 okuyun. Şimdi, değişkende depolanan değeri xQueueSend API'de geçirerek gönderin ve aşağıda gösterildiği gibi vTaskDelay () API'yi kullanarak görevi 1 saniye sonra blok durumuna gönderin.
void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Task1"); akım_ yoğunluğu = analogRead (A0); Serial.println (geçerli_ yoğunluk); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Benzer şekilde, TaskDisplay için bir işlev oluşturun ve xQueueReceive işlevine iletilen bir değişkendeki değerleri alın . Ayrıca xQueueReceive () döndürür pdPASS veri kuyruğundan başarılı bir şekilde alınan ve geri döndürür eğer errQUEUE_EMPTY bir sıra boş ise.
Şimdi, lcd.print () işlevini kullanarak değerleri LCD'de görüntüleyin.
void TaskDisplay (void * pvParameters) { intensity = 0; while (1) { Serial.println ("Task2"); if (xQueueReceive (queue_1, & intensity, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Yoğunluk:"); lcd.setCursor (11, 0); lcd.print (yoğunluk); } } }
Bu kadar. Queue uygulamasının kodlama kısmını bitirdik. Sonunda, çalışan bir Video ile eksiksiz kod bulunabilir.
Şimdi, LCD ve LDR'yi devre şemasına göre Arduino UNO ile bağlayın, kodu yükleyin. Seri monitörü açın ve görevleri izleyin. Işık yoğunluğuna göre görevlerin değiştiğini ve LDR değerlerinin değiştiğini göreceksiniz.
NOT: Farklı sensörler için yapılan kitaplıkların çoğu, kitaplıklar içindeki gecikme işlevi uygulaması nedeniyle FreeRTOS çekirdeği tarafından desteklenmez. Gecikme, CPU'nun tamamen durmasına neden olur, bu nedenle FreeRTOS çekirdeği de çalışmayı durdurur ve kod daha fazla çalışmaz ve hatalı davranmaya başlar. Bu nedenle, kütüphaneleri FreeRTOS ile çalışmak için gecikmesiz hale getirmeliyiz.