STM32F103 Blue Pill FreeRtos ile adım adım çalışma

M_B

Üye
Katılım
16 Şubat 2023
Mesajlar
93
Aşağıdaki özelliklere sahip kendi tasarladığım PCB de
FreeRtos yapısını kullanarak (öğrenerek )USART tan gelen acı bilgisine göre motoru
sağa - sola döndürmek ve istenilen acıda durdurmak. ( Motor Reduktorlu silecek motoru )

Motor sürmede PID kullanılacak.
Oled ekranda anlık acı bilgisi ve sağa sola donup donmediği.
İstenilen aciya gitme durumlarında buzzer kesik kesik ötmesi.
Acısına geldiğinde buzzer in devre dısı kalıp RGB ledin aktif olması.


input-1 bas bırak yapıldıgında sağa acılacak.
input-2 bas bırak yapıldıgında sola acılacak.

Not:
Motor başlangıc konumu 0 derece
input-1 bas bırak yapılınca 90 dereceye gidecek ve duracak
input-2 bas bırak yapılınca 90 dereceden -> 0 dereceye gidecek.

Not: İşin öetizi bir bakıma kanatlı turnike mantığı. Turnikelerde konum hareketi 0-90-180 derece olabiliyor.
Benim ekstradan eklediğim 0-360 derece dondurebilmek.

Not: Bu dediklerimin %80 'ni State machine yontemiyle yaptım. PID değerlerini deneme yanılma yontemleriyle buldum.
Şu an burda amac FreeRtos kullanarak yapmak ve öğrenmek. Bu aralar FreeRtos olayına kafayı taktım.

Şimdi burda nası bir yöntem hangi task yöntemini kullanmalıyım.


Kendi tasarladığım pcb özellikleri

1 tane STM32F103 Blue Pill
1 tane i2c SSD1306 Oled Ekran
1 tane i2c ASM5600 acı sensoru.
1 tane UART
2 adet BTS7960 motor sürücü entegresi.
4 adet input girişi.
1 tane RGB Led cıkısı ( R G B olarak )
1 Tane Buzzer
3 tane Role çıkışı
1 tane W5500 Ethernet modul.


Teşekkürler.
 
Eğer UART'tan veri alındığında bir kesmeye giriyorsan, kesme, gelen veriyi işlesin ve bir Queue'ya koysun (xQueueSendToBackFromISR()) Ana task da bu queue'yu beklesin, veri gelince de işlesin ve tekrar beklemeye başlasın (xQueueReceive()). Dikkat edersen yazma fonksiyonu, kesmeden çağrılmaya uygun olan varyant. Eğer UART verisi kesme ile alınmıyorsa o zaman artık nasıl alındığına göre uygun yöntem kullanmak lazım. Mesela UART verisini bir fonksiyon çağırarak beklemen mi gerekiyor? Bu beklemede task bloke mi oluyor, timeout verilebiliyor mu? Poll edilebiliyor mu?
 
@taydın hocam,
UART kısmını kesme ile alıp kuyruga koydum diyelim. O kısım tamam.
Diğer kısımlar kafamı karıştırıyor. Belki düşünce tarzım hatalı olduğu içindir.
Sensorden veri okuma
Ekrana veri gönderme.
PID hesaplama bunları Super Loop şeklinde yapınca hepsinin ayrı bir fonksiyonu vardı. scwitch case yapısı ile yapıyordum.

Hocam sizin mesajdan analadığım
Bir tane UART icin Task
Bir tane İnputlar için Task
Bir tanede ana dongu için Task oluştur.
Uart veriyi alınca kuyruğa İnputlar da değişim hareket olunca da event la ana taska veri gondersin ve ana task duruma göre davransın mı demek istiyorsunuz.
Ana task ta ekrana veri basma Led yakma Buzzer gibi aksiyonlar mı olsun.

Yukarda yazdığımdan önce ben Her olay için bir task düşünüyordum. Örnegin Ekran , PID , Buzzer , RGB Led gibi.

Hocam birde sormak istediğim FreeRtos ta dısardan eklediğim SSD1306 kutuphanesinde HAL_Delay(500) gibi fonksiyonlar var. Bu fonksiyonlar sistemi kitlermi ?
Kitlememesi için bunları devre dışı bırakıp FreeRtos a uygun nasıl bir zamanlayıcı eklemeliyim.

Yol ve yardımlarınız icin teşekkür ederim.

Uygulamanın kalıp fonksiyonlarını ( Task'larını ) oluştursam inşaallah gerisi gelecektir.
 
Sırf RTOS kullanıyorsun diye herşeyi task yapmaya gerek yok. Doğru da olmaz. Multitasking ilave zorluklar yaratır. Bir task veri güncellerken diğerlerinin okuma yapması "race condition" dene sakatlıklara sebep olabilir. Mutex kullanarak çözmeye çalışırsan da, dikkat etmezsen "deadlock" denen olumsuzluklar ortaya çıkabilir. Multitasking problemlerde, sorunun çıkması bazan çok nadir olabilir. Sistem beş gün düzgün çalışır, altıncı günün sabahında sapıtmış olarak bulursun. O yüzden mümkün ise, RTOS da olsa HİÇ İLAVE TASK KULLANMAMAK en iyisidir. Ne zaman ilave task kullanacaksın, mecbur isen.

Senin program tek task ile halledilebilir. Kesme queue'ya veri yazacak, ana task da queue yu işleyecek. Ne zaman ilave tasklar gerekir? Mesela bir X sensörünü okuma 500 ms sürüyorsa (pek olası değil) o zaman ana task sürekli olarak 500 ms takılacak. O zaman sensör okumayı ayrı taska yaptırırsın ve sensör sonucunu da aynı queue'ya koyarsın. Veya ekrana bilgi yazıyorsun, çok uzun sürüyor, çok daha sıklıkla yapılması gereken işe ana task yeterince zaman ayıramıyor. O zaman ekran tazelemeyi ayrı taska yaptırırsın.

Ama burada tekrar belirteyim. Birden fazla task kullandığın zaman, disiplinli ve çok iyi düşünülmüş, sağlam bir yapı ortaya koyman lazım. Olabilecek bütün zamansal etkileşimleri kafanda tartıp her birisinde sistemin doğru çalışacağına dair bir öngörün olması lazım. Yoksa proje aylarca bitmez ve tehlikeye girer. Software işinde EN PİS buglar multitasking sistemlerde ortaya çıkan buglardır. En etkili çözüm, multitasking'den mümkün ise uzak durmak.

Her türlü bug ile sürünmüş birisi olarak bug çeşitleri ile ilgili bir konu açmıştım, fikir verebilir

 
Teşekkürler hocam detaylı acıklama icin. Verdiğiniz linki hemen okuyacağım.
Delay kısmı icin bir öneriniz varmıydı ? Programa eklenen kütüphanelerde HAL_Delay gibi fonksiyonlar mevcut.
Bunlara hiç dokunmamak en iyisi mi ?
 
STM kütüphanelerini kullanmadım şimdiye kadar, ama HAL_Delay'in sadece işlemciyi belli bir süre oyaladığını ve bunu yaparken de kesmeleri KAPATMADIĞINI düşünüyorum. Bu durumda bir task'ın HAL_Delay çağırması, diğer taskları veya FreeRTOS kernel'i etkilemez. Kernel çalışmaya devam eder, tasklar da olması gerektiği gibi, sahip oldukları "priority" değerine göre davranmaya devam ederler.
 
STM için HAL_Delay kodu bu, sadece tick counterdan değer okuyor ve bekliyor

1720613432364.png
 
"State Machine" ile çalışmak hem kontrol hem de basitlik açısından bence daha uygun.
Ayrıca bir çevrim süresi sizin kontrolünüzde değil.
 
"State Machine" ile çalışmak hem kontrol hem de basitlik açısından bence daha uygun.
Ayrıca bir çevrim süresi sizin kontrolünüzde değil.
Mehmet hocam Bir uygulamam da onuda kullandım memnunda kaldım. Neden freeRtos la uğraşıyorsun dersen merak ve karşıma devamlı cıkması.
O zaman foruma sorayım neden FreeRtos kullanmalıyım. Artısı ne olur. Teşekkürler
 
State machine yapısını da yaygın kullanıyorum. Ama eğer bir projede değişik sensör ve input sinyallerine çok kısa zamanda tepki verilmesi gerekiyorsa, bunu state machine yapısı ile yapamıyorsun. O yapıda döngü tamamlanmadan inputlar kontrol edilmemiş oluyor. Ha interrupt kullanırsın, ama bu da bir çeşit multitasking. Böyle bol interrupt'lı yapı kullanırsan, mayın tarlasında yürümek gibi oluyor. İnterrupt rutinlerini çok kısa tutman lazım, rutin içerisinde iken her fonksiyonu çağıramazsın, hardware'in getirdiği kısıtlamalar olabilir vs vs. Ama RTOS kullanırsan, her task bir interrupt gibi çalışır, ama kurallar basit ve nettir, çağrılacak fonksiyon kısıtlaması yoktur, hardware kısıtlaması yoktur, çok uzun da tutsan taskı sorun olmaz, çünkü task priority belirler neyin çalışacağını.

Eğer çok düşük gecikme ile dış dünya olaylarına tepki gerekiyorsa, RTOS kolaylık sağlıyor. Böyle bir ihtiyaç yoksa, state machine yapısı, deterministik çalışması, debug edilmesinin kolay olması ve çok yüksek oranda test edilebilmesi nedeniyle tercih edilebilir.

Ama şu da var, ya birisi ya diğeri diye de bakmamak lazım. Benim şu anda üzerinde çalıştığım firmware'de FreeRTOS var, 8 tane task çalışıyor. Mesela tasklardan birisi, motorlu bir potansiyometreyi kontrol ediyor. Bir çeşit pid kontrolü ile motoru önce maksimum hızda başlatıyorum, sonra hedef değere yaklaşırken hızını azaltıyorum. Bu motor taskı, kendi içinde state machine kullanıyor. State machine son derece faydalı ve temel bir yazılım yapı taşı.
 
State machine son derece faydalı ve temel bir yazılım yapı taşı.
Soruyu soran arkadaştan özür dileyerek sorunun asıl amacını saptırmadan bu konuyla alakalı bir soru sormak istiyorum. State machine için internette ciddi anlamda kaynak fazlalığı var ve ben hangi kaynağın state machine için uygun olduğuna karar veremiyorum. State machine'i güzel anlatan bildiğiniz bir kaynak var mı ? (Miro Samek'i biliyorum ama o da kendi frameworkunu kullanarak anlatıyor hep.)

Benim aklıma takılan kısım neyi nereye yazacağım. Her şeyi super loop içine yazmak bana garip geliyor konuya hakim olmadığım için. Bu konuyla ilgili bir yönlendirme yapabilir misiniz ?
 
O konuda çok akademik düşünmeye gerek yok. Ben bir enum tanımlayıp değişik "state" leri belirliyorum. Sonra da switch/case içinde gereken davranışı gerçekleştiriyorum. Tabi bunu C/C++ alında minimum hata ile, bakımı kolay yapılabilecek şekilde, 1 sene sonra baktığında da rahatlıkla anlayacağın şekilde yapmanın püf noktaları var, onları da zamanla öğrenirsin. Ama temel mantıkta hiçbir karmaşıklık yok.
 
Teşekkürler hocam detaylı acıklama icin. Verdiğiniz linki hemen okuyacağım.
Delay kısmı icin bir öneriniz varmıydı ? Programa eklenen kütüphanelerde HAL_Delay gibi fonksiyonlar mevcut.
Bunlara hiç dokunmamak en iyisi mi ?
FreeRtos da delay kullanımında HAL_Delay ile osDelay arasında fark vardır. Birden fazla taskınız varsa ve task içerisinde delay kullanma ihtiyacınız varsa osDelay ı tercih etmeniz daha doğru bir yaklaşım olacaktır. HAL_Delay cpuyu bloke eder, osDelay tickcount yapısı ile çalışır, bu bekleme esnasında rtos diğer taskı / taskları yürütür, sistem kaynakları daha verimli kullanılır.

Yukarıda zaten gerekli uyarılar yapıldı, rtos iki tarafı keskin bıcak gibi. Özellikle karmaşık ve çok fazla işlemlerin birlikte veya paralel yapılması gereken durumlarda rtos hayat kurtarıyor, ama düzgün şekilde planlanmazsa sorun çıktığında nedenini bulmak saç baş yoldurur :)
 
ben basit projelerde state machine yapısı ile beraber birbirini kesmeyen ve farklı periyotlarda ardışık rutinler kullanıyorum. örneğin 10ms, 100ms ve 2000ms rutinler oluyor. 1ms timer kuruyorum ve bu timer değerine göre tasklara girmeye karar veriyor. tick timer ile de yapılabilir. bu rutinlerin içinde herhangi bir bekleme olmuyor en hızlı şekilde yapacağı işi yapıp çıkıyor. bunun dışında kritik işleri de interruptlar ve mümkünse dma ile yapıyor. örneğin uart bir satırı line idle olana kadar bir buffer içine atıyor ve işi bitince bir flag set ediyor. ben uygun task içinde bunu alıp işliyorum. 10ms içinde keypad okuyor, 100ms içinde flag set edilmiş ise gelen veriyi işliyor. 1000-2000ms rutinler de yanın sönen ledler buzzerlar vs türü işleri hallediyor.
 

Çevrimiçi üyeler

Çevrimiçi üye yok.

Forum istatistikleri

Konular
6,292
Mesajlar
106,771
Üyeler
2,605
Son üye
iceman

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top