Hrvatsko društvo za robotiku - Uvod u robotiku - vježbe

Paralelni programi

Cilj

Kako izvršavati više programa odjednom.

Brzi program

void RobotLine::loop() {
	loop0();
	loop1();
	loop2();

	// Ovdje idu neke naredbe koje izvrše brzo.
}

Recimo da želimo izvršavati 3 programa usporedno s našim glavnim programom. Pretpostavimo da se nalaze u loop0(), loop1() i loop2(). Odgovor na pitanje je li to moguće je negativan. Mikrokontroleri to obično ne mogu napraviti.

Najbolje što se može je podijeliti vrijeme jednog mikrokontrolera na više funkcija.

Primjer je program lijevo. U ovom primjeru je loop() glavni program, ali može biti i neki drugi u općem slučaju.

Bitno je ograničenje da nijedna od 3 funkcije ne smije zadržavati vrijeme, nego se treba u svakom prolazu izvršiti praktički trenutno. Znači, ne smiju postojati lokalne petlje (loop, for), niti delayMs() naredbe. Isto tako loop() ne smije sadržavati ništa što se izvršava sporo. Svaki prolaz kroz petlju mora biti brz.

Ovakav je dizajn moguć, čak i vrlo dobar, ali izazovno je svaki put spremiti lokalna stanja u glavni program (ovdje: loop()) te ih u sljedećem prolazu opet pozvati.

Npr., recimo da je loop() podizanje lopte(). U svakom prolazu kroz loop() moramo na kraju zapamtiti u kojem su položaju servo motori, kako bi u novom prolasku počeli od te pozicije, ne opet od početka.

Spori program

void RobotLine::loop() {
	...

	while(...){
		...
		alwaysCallMe();
	}

	...

	while(...){
		...
		alwaysCallMe();
	}
}

void RobotLine::alwaysCallMe() {
	loop0();
	loop1();
	loop2();
	noLoopWithoutThis();
}

Lakši je dizajn putem spore funkcije. Recimo da je loop() ta spora funkcija, znači ne izvršava se brzo, jer npr. ima lokalne petlje.

Kako želimo da se loop0(), loop1() i loop2() stalno izvršavaju, moramo ih pozivati u svakoj lokalnoj petlji, kao što je u primjeru lijevo.

Dakle, sve funkcije koje se trebaju odvijati "paralelno" grupiramo u novu funkciju i nju pozivamo u svakoj petlji.

Dizajn programa je lakši jer npr. prva petlja (while) može izvršiti cijelu radnju i ne treba spremati stanja između svakog međukoraka. Na primjeru lopte, servo motori odrade sve što treba i onda se ide dalje.

delayMs()

void RobotLine::delayMsMy(uint32_t ms) {
	uint32_t startMs() = millis();
	while (millis() - startMs < ms)
		alwaysCallMe();
}

delayMs() je poseban problem. Ovu naredbu ne smijemo koristiti jer za to vrijeme ne rade loop0(), loop1() i loop2().

Možemo napraviti vlastu funkciju koja radi isto što i delayMs().

Primjer je na slici lijevo.

Zadatak: paralelni program.

Napišite funkciju loop0() koja provjerava ima li linije.

Napišite funkciju loop1() koja provjerava je li prepreka ispred robota.

Izvršavajte obadvije funkcije "odjednom" u loop().

Primjedbe



Projekt "Uvod u robotiku" sufinanciran je iz Europskog socijalnog fonda, poziv "Jačanje kapaciteta organizacija civilnoga društva za popularizaciju STEM-a". Relevantne stranice: Sadržaj vježbe za virtualne radionice isključiva je odgovornost Hrvatskog društva za robotiku.