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

Crtanje zidova

Cilj

Ispisati zidove na 8x8 displeju.

Brisanje

void RobotMaze::wallsDisplay() {
	/* Contrary to the method used mostly here, this bitmap is not stored beforehand. There are too many combinations and that will not be feasible.
	So, it will be built on-line.*/

	// Clear red and green dots.
	uint8_t red[8];
	uint8_t green[8];
	for (uint8_t i = 0; i < 8; i++)
		red[i] = 0, green[i] = 0;

	...
}
U programu "mrm-robot-maze.cpp" postoji funkcija "wallsDisplay()".

Proučimo ju.

Na početku deklariramo 2 polja s po 8 elemenata: "red" i "green";

U njih ćemo upisivati točke koje želimo upaliti na 8x8 displeju.

Gornji red

void RobotMaze::wallsDisplay() {
	/* Contrary to the method used mostly here, this bitmap is not stored beforehand. There are too many combinations and that will not be feasible.
	So, it will be built on-line.*/

	// Clear red and green dots.
	uint8_t red[8];
	uint8_t green[8];
	for (uint8_t i = 0; i < 8; i++)
		red[i] = 0, green[i] = 0;

	//2 top sensors form top pixels' row.
	if (distance(rToM(Direction::UP), false) < NO_WALL_DISTANCE)
		red[0] |= 0b00001111;
	if (distance(rToM(Direction::UP), true) < NO_WALL_DISTANCE)
		red[0] |= 0b11110000;

	...
}
Funkcija "rToM()" prebacuje koordinatni sustav robota u koordinatni sustav labirinta.

Nećemo ju sad proučavati. Ona omogućava da uvijek gornji red displeja ispisuje gornji zid.

Uočite da robot može biti okrenut na 4 načina i da za svaki treba uzeti drugu stranu robota koja mjeri "gornji" zid.

Funkcija "distance()", u varijanti za robota za labirint, ima dva argumenta.

Prvi je smjer.

Drugi je "true", ako je to prvi senzor u smjeru suprotnom od kazaljke na satu za tu stranicu.

"false" ako je drugi.

Kad "if" ustanovi da je izraz "true" (zid je ispred tog senzora), doda jedinice u 4 bita bajta koji je u prvom redu (gornji red displeja).

Operacija je na bitovima: "|=", što znači da će izraz s lijeve strane ostati isti, osim što će se jedinice s desne strane prekopirati na odgovarajuća mjesta lijeve strane.

Na taj način će upaliti 4 LED diode ispred danog senzora.

Lijeva kolona

void RobotMaze::wallsDisplay() {
	/* Contrary to the method used mostly here, this bitmap is not stored beforehand. There are too many combinations and that will not be feasible.
	So, it will be built on-line.*/

	// Clear red and green dots.
	uint8_t red[8];
	uint8_t green[8];
	for (uint8_t i = 0; i < 8; i++)
		red[i] = 0, green[i] = 0;

	//2 top sensors form top pixels' row.
	if (distance(rToM(Direction::UP), false) < NO_WALL_DISTANCE)
		red[0] |= 0b00001111;
	if (distance(rToM(Direction::UP), true) < NO_WALL_DISTANCE)
		red[0] |= 0b11110000;

	//2 left sensors form left row.
	if (distance(rToM(Direction::LEFT), false) < NO_WALL_DISTANCE)
		for (uint8_t i = 0; i < 4; i++)
			red[i] |= 0b10000000;
	if (distance(rToM(Direction::LEFT), true) < NO_WALL_DISTANCE)
		for (uint8_t i = 4; i < 8; i++)
			red[i] |= 0b10000000;

	...
}
Na sličan način mjerimo lijevu stranu.

Ovaj put ne možemo mijenjati samo jedan element polja, nego ih moramo svih 8, jer se lijeva kolona proteže kroz najljevije bitove svih 8 bajtova (cijelo polje).

Ovo činimo u "for" petlji, opet koristeći istu bit-operaciju i na taj način palimo po 4 LEDa u gornja 4 ili donja 4 reda.

Preostale stranice

void RobotMaze::wallsDisplay() {
	/* Contrary to the method used mostly here, this bitmap is not stored beforehand. There are too many combinations and that will not be feasible.
	So, it will be built on-line.*/

	// Clear red and green dots.
	uint8_t red[8];
	uint8_t green[8];
	for (uint8_t i = 0; i < 8; i++)
		red[i] = 0, green[i] = 0;

	//2 top sensors form top pixels' row.
	if (distance(rToM(Direction::UP), false) < NO_WALL_DISTANCE)
		red[0] |= 0b00001111;
	if (distance(rToM(Direction::UP), true) < NO_WALL_DISTANCE)
		red[0] |= 0b11110000;

	//2 left sensors form left row.
	if (distance(rToM(Direction::LEFT), false) < NO_WALL_DISTANCE)
		for (uint8_t i = 0; i < 4; i++)
			red[i] |= 0b10000000;
	if (distance(rToM(Direction::LEFT), true) < NO_WALL_DISTANCE)
		for (uint8_t i = 4; i < 8; i++)
			red[i] |= 0b10000000;

	// 2 bottom sensors.
	if (distance(rToM(Direction::DOWN), false) < NO_WALL_DISTANCE)
		red[7] |= 0b11110000;
	if (distance(rToM(Direction::DOWN), true) < NO_WALL_DISTANCE)
		red[7] |= 0b00001111;

	// Finally, 2 right sensors.
	if (distance(rToM(Direction::RIGHT), false) < NO_WALL_DISTANCE)
		for (uint8_t i = 4; i < 8; i++)
			red[i] |= 0b00000001;
	if (distance(rToM(Direction::RIGHT), true) < NO_WALL_DISTANCE)
		for (uint8_t i = 0; i < 4; i++)
			red[i] |= 0b00000001;

	...
}
Na isti način ispišemo donju i desnu stranicu.

Ispis

void RobotMaze::wallsDisplay() {
	/* Contrary to the method used mostly here, this bitmap is not stored beforehand. There are too many combinations and that will not be feasible.
	So, it will be built on-line.*/

	// Clear red and green dots.
	uint8_t red[8];
	uint8_t green[8];
	for (uint8_t i = 0; i < 8; i++)
		red[i] = 0, green[i] = 0;

	//2 top sensors form top pixels' row.
	if (distance(rToM(Direction::UP), false) < NO_WALL_DISTANCE)
		red[0] |= 0b00001111;
	if (distance(rToM(Direction::UP), true) < NO_WALL_DISTANCE)
		red[0] |= 0b11110000;

	//2 left sensors form left row.
	if (distance(rToM(Direction::LEFT), false) < NO_WALL_DISTANCE)
		for (uint8_t i = 0; i < 4; i++)
			red[i] |= 0b10000000;
	if (distance(rToM(Direction::LEFT), true) < NO_WALL_DISTANCE)
		for (uint8_t i = 4; i < 8; i++)
			red[i] |= 0b10000000;

	// 2 bottom sensors.
	if (distance(rToM(Direction::DOWN), false) < NO_WALL_DISTANCE)
		red[7] |= 0b11110000;
	if (distance(rToM(Direction::DOWN), true) < NO_WALL_DISTANCE)
		red[7] |= 0b00001111;

	// Finally, 2 right sensors.
	if (distance(rToM(Direction::RIGHT), false) < NO_WALL_DISTANCE)
		for (uint8_t i = 4; i < 8; i++)
			red[i] |= 0b00000001;
	if (distance(rToM(Direction::RIGHT), true) < NO_WALL_DISTANCE)
		for (uint8_t i = 0; i < 4; i++)
			red[i] |= 0b00000001;

	// Send the result to mrm-8x8a.
	mrm_8x8a->bitmapCustomDisplay(red, green);
}
Zadnja naredba šalje polja u 8x8 displej, ispisujući ih.

Pokretanje programa

void RobotMaze::loop() {
	wallsDisplay();
}
Program pokrenite iz funkcije "loop()".

Zadatak: crtanje

Iscrtajte na isti način crvenom bojom bliske zidove, a zelenom daleke.

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.