Prosty Paint napisany w Javie

Niestety nie dostałem treści zadania, ale kiedyś było takie zadanie, żeby zrobić Paint’a z rysowaniem kilku figur w tym kreski w różnych kolorach i z możliwością 'wypełniania’ figur. To było chyba na GUI.

Dostałem rozwiązanie bardzo proste:

Paint w Javie

Kod do przejrzenia i .zip wrzuciłem tu:
http://skalski.at/files/?dir=files/PJWSTK/java_paint

Zaszufladkowano do kategorii PJWSTK, PJWSTK - JAVA | 2 komentarze

Chat UDP w sieci lokalnej bez serwera

Temat: Rozproszony Chat
1. Zadanie polega na napisaniu rozproszonej aplikacji „Chat”, umożliwiającej komunikację
pomiędzy wieloma osobami w sieci lokalnej, z możliwością organizowania rozmów grupowych (w obrębie więcej niż pary uczestników).

Więcej informacji o zadaniu i rozwiązanie które przysłał kolega dostępne pod adresem:

http://skalski.at/files/?dir=files/PJWSTK/SKJ_chat_udp

Chat działa, sprawdziłem. Niestety do testów trzeba mieć parę komputerów (lub maszynę wirtualną na kompie), bo tylko jedna osoba się może podłączyć z 1 IP. Wygląda to tak:
Chat udp

Zaszufladkowano do kategorii PJWSTK, PJWSTK - SKJ | Dodaj komentarz

ZSO – Drugi projekt Justyny

Użyte:

– named-pipe

– sygnały

– pamięć dzielona (shared memory)

Treść:

Jeden proces (master) komunikuje się z wieloma innymi (slaves). Komunikacja jest periodyczna, ma charakter pytanie/odpowiedź, odbywa się za pomocą pamięci dzielonej. Master posiada listę podległych procesów. Wysłanie sygnału do slave’a powoduje, że ten powiadamia mastera poprzez named pipe, że kończy pracę. Master przestaje dalej zajmować się nim.

Rozwiązanie na ile poprawne nie wiem, ale chyba działa tak jak w poleceniu. Z tego co pamiętam to funkcja z obsługą sygnału powinna być 'krótka’, a tutaj w niej otwiera named-pipe, wysyła, czyta itd.:

/*Jeden proces (master) komunikuje się z wieloma innymi (slaves). Komunikacja jest periodyczna, ma charakter pytanie/odpowiedź, odbywa się za pomocą pamięci dzielonej. Master posiada listę podległych procesów. Wysłanie sygnału do slave’a powoduje, że ten powiadamia mastera poprzez named pipe, że kończy pracę. Master przestaje dalej zajmować się nim.*/
// szukanie PID slave: ps a | grep zso2 | grep S+
// kompilacja: g++ zso2.cpp -lstdc++ -o zso2

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <sys/signalfd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int N = 10; // ilosc slave
static void otrzymanoSygnal(int numerSygnalu);
int rodzic = 0; // czy rodzic
int czyOtrzymanoOdpowiedz=0;
int pipeOdbierajacy;
char buffer[20];
int i=0;
long int pid;
long int* dzieci;

int main()
{
	struct sigaction akcja;
	akcja.sa_handler = otrzymanoSygnal;
	akcja.sa_flags = 0;
	sigaction(SIGINT, &akcja, NULL);
	sigaction(SIGQUIT, &akcja, NULL);
	dzieci = (long int *) malloc(sizeof(long int) * N);
	for(i=0;i<N;i++)
	{
		dzieci[i] = 0;
	}
	int sms;
	key_t key = ftok(".", 666);
	char *segptr;
	pid = getpid();
	sprintf(buffer, "%ld.namedpipe", pid);
	printf("Tworze named-pipe %s do odbierania. \n", buffer);
	if(mkfifo(buffer,0666) != 0)
	{
		handle_error("Nie udalo sie utworzyc named-pipe'a do odbierania.");
	}
	rodzic=0;
	for(i=0; i<N; i++) // robienie dzieci
	{
		printf("FORK\n");
		dzieci[i] = fork();
		if (dzieci[i] > 0)
		{
			rodzic=1;
		}
		else
		{
			rodzic=0;
			break;
		}
	}

	sms = shmget(key, sizeof(char)*25, IPC_CREAT | 0660);
	// mapowanie pamieci
	segptr = (char*)shmat(sms, NULL, 0);
	if (rodzic == 1) 
	{
		while(1)
		{
			// czas pomiedzy seriami pytan/odpowiedzi
			sleep(2);
			for(i=0; i<N;i++)
			{
				if(dzieci[i] == 500)
				{
					continue;
				}
				// czas pomiedzy pytaniami do konkretnych dzieci
				usleep(200000);
				strcpy(segptr, "Ala ma kota.");
				printf("Master wysyla informacje %s do slave %d \n", segptr, i);
				int zwrot = kill(dzieci[i], SIGINT);  
				while(czyOtrzymanoOdpowiedz==0)
				{
					pause();
				}
				czyOtrzymanoOdpowiedz=0;
				printf("Master dostal informacje %s od dziecka %d. \n", segptr, i);
			}
		}
	}
	else
	{
		printf("DZIECKO: rusza %d \n", i);
		while(1)
		{
			pause();
			printf("Dziecko %d dostalo komunikat %s \n", i, segptr);
			strcpy(segptr, "Kot ma Ale.");
			printf("Dziecko %d wysyla informacje %s do mastera \n", i, segptr);
			int zwrot = kill(pid, SIGINT);
		}
	}
}

static void otrzymanoSygnal(int numerSygnalu)
{
	if(rodzic==1)
	{
		if(numerSygnalu==SIGINT)
		{
			// przerywa pause()
			czyOtrzymanoOdpowiedz=1;
		}
		else if (numerSygnalu==SIGQUIT)
		{
			sprintf(buffer, "%ld.namedpipe", pid);
			printf("RODZIC: Otwieram named-pipe %s\n", buffer);
			pipeOdbierajacy = open(buffer, O_RDONLY);
			if(pipeOdbierajacy == -1)
			{
				printf("Nie udalo sie otworzyc fifo odbierajacego.\n");
				exit(1);
			}
			char b[10];
			int ret = read(pipeOdbierajacy, b, sizeof(b));
			if(ret <= 0)
			{
				printf("Funkcja read zwrocila error dla slave.\n");
				perror(NULL);
				exit(1);
			}
			// zamieniam ID dziecka przeslane jako char* 10 znakowy (np. "0000000003") na 'int' o wartosci '3' [funkcja 'atoi']
			int idDziecka = atoi(b);
			printf("RODZIC: Dziecko o numerze %d usuniete z listy\n", idDziecka);
			dzieci[idDziecka] = 500;
			close(pipeOdbierajacy);
		}
	}
	else
	{
		if(numerSygnalu==SIGINT)
		{
			// przerywa pause()
		}
		else if (numerSygnalu==SIGQUIT)
		{
			int zwrot = kill(pid, SIGQUIT);
			sprintf(buffer, "%ld.namedpipe", pid);
			printf("DZIECKO KAMIKAZE: Otwieram named-pipe %s\n", buffer);
			int pipeWysylajacy = open(buffer, O_WRONLY);
			if(pipeWysylajacy == -1)
			{
				printf("Nie udalo sie otworzyc fifo wysylajacego.\n");
				perror(NULL);
				exit(1);
			}
			// zamiana 'int' na 'char*' z dodaniem zer przed liczba jesli jest krotsza niz 10 znakow
			char b[10];
			sprintf(b, "%010d", i);
			// przepisujemy tresc z buffor na wyjscie do master
			int ret = write(pipeWysylajacy, b, sizeof(b));
			if(ret == -1)
			{
				printf("Funkcja write zwrocila error.\n");
				perror(NULL);
				exit(1);
			}
			close(pipeWysylajacy);
			exit(1);
		}
	}
}

 

 

Zaszufladkowano do kategorii PJWSTK, PJWSTK - ZSO | Dodaj komentarz

ZSO – Drugi projekt

Treść:
Jeden proces (master) oczekuje na pojawienie się podległych mu procesów (slaves). Za pomocą dodatkowego procesu możemy startować podległe procesy. Nowy proces wysyła masterowi sygnał, że się pojawił i poprzez kolejkę komunikatów przekazuje mu namiary na siebie. Od tego momentu master zaczyna komunikować się z nowopowstałym slave’wem periodycznie, według wzorca pytanie/odpowiedź poprzez named pipes, co slave uwidacznia.

Rozwiązanie składa się z dwóch programów: master.cpp i slave.cpp

Master musi być odpalony pierwszy (tworzy kolejkę komunikatów i czeka na sygnał). Master musi być odpalany z nazwą 'masterProcess’ – do procesu o takiej nazwie 'slave’ wysyła sygnał.

Dodałem sporo komentarzy tłumaczących co i jak działa.

master.cpp (do pobrania: http://paste.ots.me/404783 )

// Master
// kompilacja: g++ master.cpp -lstdc++ -o masterProcess && ./masterProcess
/*
Jeden proces (master) oczekuje na pojawienie się podległych mu procesów (slaves). Za pomocą dodatkowego procesu możemy startować podległe procesy. Nowy proces wysyła masterowi sygnał, że się pojawił i poprzez kolejkę komunikatów przekazuje mu namiary na siebie. Od tego momentu master zaczyna komunikować się z nowopowstałym slave’wem periodycznie, według wzorca pytanie/odpowiedź poprzez named pipes, co slave uwidacznia.
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/msg.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

// prosta funkcja zwracajaca czas
struct timeval czas;
int ret; // zmienna przyjmujaca zwracana wartosc z paru funkcji w programie
char* getTime()
{
	ret = gettimeofday(&czas, NULL);
	char* buffer = (char *) malloc(sizeof(char) * 18);
	if(ret == 0)
	{
		sprintf(buffer, "%ld.%06ld:", czas.tv_sec, czas.tv_usec);
	}
	else
	{
		strcpy(buffer, "Error:");
	}
	return buffer;
}

// funkcja obslugujaca przychodzace sygnaly (tylko SIGINT)
// sygnaly sa zliczane, a nie zapamietywane jako 0 lub 1 ('czy przyszedl'),
// bo moze przyjsc kilka zanim zacznie sie ich obsluga w 'main'
int otrzymalSygnalow = 0;
static void obslugaSygnalu(int signum)
{
	otrzymalSygnalow += 1;
	printf("Otrzymano sygnal SIGINT\n");
}

// struktura do przesylania przez kolejke komunikatow (FIFO)
struct Komunikat
{
	// pierwszy w strukturze MUSI byc 'long int' [o dowolnej nazwie],
	// w nim bedzie przechowywany 'typ' komunikatu
	// w funkcji ktora pobieramy komunikaty:
	// msgrcv(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 1, 0);
	// ta '1' to wlasnie typ komunikatu jaki chcemy otrzymac
	// (proces 'slave' przed wyslaniem komunikatu ustawia w strukturze typ na '1')
	long int typeKomunikatu;
	long int pid;
};

// limit obslugiwanych slave, tej wartosci uzywamy przy tworzeniu tablic z wejsciami i wyjsciami named-pipe
int iloscMaksymalnaSlave = 30;
// czas miedzy sprawdzeniami czy jest jakis sygnal
int czasPomiedzyObslugaSygnalow = 1000; // 0.001 sec - 1 ms
// czas pomiedzy obsluga sygnalow i periodyczna komunikacja w mikrosekundach
int czasPeriodycznejKomunikacji = 500000; // 0.5 sec

int main(int argc, char *argv[])
{
	int kolejkaKomunikatowID;
	int i; // iterator do 'for'
	Komunikat komunikat; // komunikat przesylany przez kolejke komunikatow
	char buffer [50]; // taki sam rozmiar jak w slave
	int iloscSlaveow = 0; // ilosc juz obslugiwanych slave
	int wejscie[iloscMaksymalnaSlave]; // named-pipe wejscia od slave
	int wyjscie[iloscMaksymalnaSlave]; // named-pipe wyjscia do slave
	int czasOdOstatniejPeriodycznejKomunikacji = 0; // zlicza czas od ostatniej periodycznej komunikacji z slave

	// ustawianie funkcji 'obslugaSygnalu' jako tej ktora obsluguje sygnal 'SIGINT' (ctrl+c)
	struct sigaction akcja;
	akcja.sa_handler = obslugaSygnalu;
	akcja.sa_flags = 0;
	sigaction(SIGINT, &akcja, NULL);
	// koniec ustawiania

	// tworze lub pobieram kolejke komunikatow o ID 123
	// jako, ze mogla juz istniec i cos w niej moglo byc to lepiej ja..
	if((kolejkaKomunikatowID = msgget(123, IPC_CREAT | 0660 )) == -1)
	{
		printf("Nie udalo sie utworzyc/pobrac ID kolejki o podanym kluczu.\n");
		return EXIT_FAILURE;
	}
	// ..usunac
	msgctl(kolejkaKomunikatowID, IPC_RMID, (struct msqid_ds *) NULL);
	// a potem stworzyc na nowo, teraz juz na 100% kolejka jest pusta
	if((kolejkaKomunikatowID = msgget(123, IPC_CREAT | 0660 )) == -1)
	{
		printf("Nie udalo sie utworzyc/pobrac ID kolejki o podanym kluczu.\n");
		return EXIT_FAILURE;
	}
	while(true)
	{
		// spimy okreslony czas
		usleep(czasPomiedzyObslugaSygnalow);
		czasOdOstatniejPeriodycznejKomunikacji += czasPomiedzyObslugaSygnalow;
		// sygnalow moglo przyjsc kilka lub w trakcie trwania petli mogl dojsc kolejny
		// wiec obslugujemy w petli 'while', a nie uzywajac 'if'
		while(otrzymalSygnalow > 0)
		{
   			printf("Obsluga sygnalu %d\n", iloscSlaveow);
			otrzymalSygnalow -= 1;
			// jesli limit slave przekroczony to wylecimy poza pamiec w tablicy!
			if(iloscSlaveow == iloscMaksymalnaSlave)
			{
   				printf("Przekroczono limit (%d) obslugiwanych slave!\n", iloscMaksymalnaSlave);
				// przerywamy obsluge 'sygnalu' - przechodzimy do komunikacji z juz znanymi slave
				break;
			}
			ret = msgrcv(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 1, 0);
   			printf("Odczytano komunikat\n");
			if(ret == -1)
			{
				// -1 = wystapil blad podczas odczytu komunikatu [np. usunieto kolejke komunikatow]
				handle_error("Wystapil blad podczas odczytu komunikatu.");
			}
			else if(ret != sizeof(struct Komunikat))
			{
				// rozmiar komunikatu jest inny, niz rozmiar naszej struktury
				// ktos inny, niz slave wyslal cos do naszej kolejki komunikatow?
				printf("Pobrany komunikat ma inny rozmiar, niz rozmiar struktury.\n");
				return EXIT_FAILURE;
			}
			// przygotowujemy nazwe named-pipe ktory chcemy otworzyc
			sprintf(buffer, "%ld.to_master", komunikat.pid);
			printf("Otwieram named-pipe z przychodzacymi wiadomosciami %s\n", buffer);
			wejscie[iloscSlaveow] = open(buffer, O_RDONLY);
			if(wejscie[iloscSlaveow] == -1)
			{
				printf("Nie udalo sie otworzyc named-pipe odbierajacego.\n");
				return EXIT_FAILURE;
			}
			// przygotowujemy nazwe named-pipe ktory chcemy otworzyc
			sprintf(buffer, "%ld.to_slave", komunikat.pid);
			printf("Otwieram named-pipe z wychodzacymi wiadomosciami %s\n", buffer);
			wyjscie[iloscSlaveow] = open(buffer, O_WRONLY);
			if(wyjscie[iloscSlaveow] == -1)
			{
				printf("Nie udalo sie otworzyc named-pipe wysylajacego.\n");
				return EXIT_FAILURE;
			}
			printf("Dodano slave o ID %d\n", iloscSlaveow);
			iloscSlaveow += 1;
		}
		// nie za kazdym obrotem petli chcemy wysylac/odbierac komunikaty
		// sprawdzamy czy od ostatniej komunikacji z slaveami minelo dosc czasu
		if(czasOdOstatniejPeriodycznejKomunikacji > czasPeriodycznejKomunikacji)
		{
			// zerujemy licznik czasu
			czasOdOstatniejPeriodycznejKomunikacji = 0;
			// lecimy petla przez wszystkich slave
			for(i = 0; i < iloscSlaveow; i++)
			{
				// wypelniamy buffer trescia z wejscia od konkretnego slave
				// jesli slave przestanie pisac to 'read' stanie w miejscu :(
				ret = read(wejscie[i], buffer, sizeof(buffer));
				if(ret <= 0)
				{
					printf("Funkcja read zwrocila error dla slave %d.\n", i);
					perror(NULL);
					return EXIT_FAILURE;
				}
		   		printf("%s Odczytano %d znakow od slave ID %d tresc: %s\n", getTime(), ret, i, buffer);

				// wstawiamy do buffer wysylany tekst
				strcpy(buffer,"DZIALA!");
				// przepisujemy tresc z buffer na wyjscie do konkretnego slave
				ret = write(wyjscie[i], buffer, sizeof(buffer));
				if(ret == -1)
				{
					printf("Funkcja write zwrocila error dla slave %d.\n", i);
					perror(NULL);
					return EXIT_FAILURE;
				}
				printf("%s Wyslano %d znakow do slave ID %d tresc: %s\n", getTime(), ret, i, buffer);
			}
		}
	}
}

slave.cpp (do pobrania: http://paste.ots.me/404784 )

// Slave
// kompilacja: g++ slave.cpp -o slave && ./slave
/*
Jeden proces (master) oczekuje na pojawienie się podległych mu procesów (slaves). Za pomocą dodatkowego procesu możemy startować podległe procesy. Nowy proces wysyła masterowi sygnał, że się pojawił i poprzez kolejkę komunikatów przekazuje mu namiary na siebie. Od tego momentu master zaczyna komunikować się z nowopowstałym slave’wem periodycznie, według wzorca pytanie/odpowiedź poprzez named pipes, co slave uwidacznia.
*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/msg.h>
#include <sys/stat.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

// prosta funkcja zwracajaca czas
struct timeval czas;
int ret; // zmienna przyjmujaca zwracana wartosc z paru funkcji w programie
char* getTime()
{
	ret = gettimeofday(&czas, NULL);
	char* buffer = (char *) malloc(sizeof(char) * 18);
	if(ret == 0)
	{
		sprintf(buffer, "%ld.%06ld:", czas.tv_sec, czas.tv_usec);
	}
	else
	{
		strcpy(buffer, "Error:");
	}
	return buffer;
}

// struktura do przesylania przez kolejke komunikatow (FIFO)
struct Komunikat
{
	// pierwszy w strukturze MUSI byc 'long int' [o dowolnej nazwie],
	// w nim bedzie przechowywany 'typ' komunikatu
	// w funkcji ktora pobieramy komunikaty:
	// msgrcv(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 1, 0);
	// ta '1' to wlasnie typ komunikatu jaki chcemy otrzymac
	// (proces 'slave' przed wyslaniem komunikatu ustawia w strukturze typ na '1')
	long int typeKomunikatu;
	long int pid;
};

int main(int argc, char *argv[])
{
	long int pid = (long int) getpid();
	char buffer [50];
	int kolejkaKomunikatowID;
	int pipeWysylajacy;
	int pipeOdbierajacy;
	Komunikat komunikat;
	// tworzymy named pipe do wysylania i odbierania
	sprintf(buffer, "%ld.to_master", pid);
	printf("Tworze named-pipe %s\n", buffer);
	if(mkfifo(buffer,0666) != 0)
	{
		handle_error("Nie udalo sie utworzyc named-pipe'a do wysylania.");
	}

	sprintf(buffer, "%ld.to_slave", pid);
	printf("Tworze named-pipe %s\n", buffer);
	if(mkfifo(buffer,0666) != 0)
	{
		handle_error("Nie udalo sie utworzyc named-pipe'a do odbierania.");
	}

	// wysylamy sygnal, zeby proces master zaczal czekac na nasz komunikat
	printf("Wysylam sygnal SIGINT do masterProcess\n");
	system("killall -2 masterProcess");

	// pobieramy ID kolejki komunikatow [utworzonej przez proces master]
	printf("Pobieram ID kolejki komunikatow\n");
	if((kolejkaKomunikatowID = msgget(123, 0660)) == -1)
	{
		printf("Nie udalo sie pobrac ID kolejki o podanym kluczu.\n");
		return EXIT_FAILURE;
	}
	// ustalamy typ komunikatu na 1, taki typ bedziemy pobierac w programie 'master' funkcja 'msgrcv'
	komunikat.typeKomunikatu = 1;
	// przesylamy PID aktualnego procesu,
	// bo utworzylismy named-pipe o nazwach zawierajacych pid 'slave'
	// ("tu_pid.to_master" i "tu_pid.to_slave") 
	komunikat.pid = pid;
	printf("Wysylam komunikat\n");
	if(msgsnd(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 0) == -1)
	{
		handle_error("Nie udalo sie wyslac komunikatu.");
	}

	// komunikat wyslany, sygnal wyslany, named-pipe utworzone [ale nie otwarte]
	// teraz otwieramy named-pipe
	sprintf(buffer, "%ld.to_master", pid);
	printf("Otwieram named-pipe %s\n", buffer);
	pipeWysylajacy = open(buffer, O_WRONLY);
	if(pipeWysylajacy == -1)
	{
		printf("Nie udalo sie otworzyc fifo wysylajacego.\n");
		return EXIT_FAILURE;
	}

	sprintf(buffer, "%ld.to_slave", pid);
	printf("Otwieram named-pipe %s\n", buffer);
	pipeOdbierajacy = open(buffer, O_RDONLY);
	if(pipeOdbierajacy == -1)
	{
		printf("Nie udalo sie otworzyc fifo odbierajacego.\n");
		return EXIT_FAILURE;
	}

	// teraz zaczynamy w petli wysylac 'DZIALA?' i odbierac co nam master napisze
	while(true)
	{
		// wstawiamy do buffer wysylany tekst
		strcpy(buffer,"DZIALA?");
		// przepisujemy tresc z buffor na wyjscie do master
		ret = write(pipeWysylajacy, buffer, sizeof(buffer));
		if(ret == -1)
		{
			printf("Funkcja write zwrocila error.\n");
			perror(NULL);
			return EXIT_FAILURE;
		}
		printf("Wyslano %d znakow do %ld tresc: %s\n", ret, komunikat.pid, buffer);

		// wypelniamy buffer trescia z wejscia od master
		// jesli master przestanie pisac to 'read' stanie w miejscu :(
		ret = read(pipeOdbierajacy, buffer, sizeof(buffer));
		if(ret <= 0)
		{
			printf("Funkcja read zwrocila error.\n");
			perror(NULL);
			return EXIT_FAILURE;
		}
   		printf("Odczytano %d znakow od %ld tresc: %s\n", ret, komunikat.pid, buffer);

		// petla nie ma zadnego 'sleep', bo funkcja 'read' zablokuje sie do czasu,
		// az master wpisze odpowiedz ('DZIALA!'), wiec to master odpowiada za 'periodycznosc'
	}
}

 

Zaszufladkowano do kategorii PJWSTK, PJWSTK - ZSO | Dodaj komentarz

ZSO – Pierwszy projekt Yuriego i mój w C/C++

Pierwszy projekt Yuri’ego:

/*
Zadanie 13. Problem orangutanów. Nad głębokim kanionem, gdzieś w Ameryce Południowej, rozpięta jest lina. Używają jej orangutany by przekroczyć kanion. Lina wytrzymuje ciężar pięciu małp a dwa orangutany nie mogą jednocześnie przechodzić po niej z przeciwnych stron kanionu. Po wejściu na linę nie można zawrócić z drogi. Każda małpa oczekująca na przejście musi kiedyś zostać obsłużona.
xubuntu: g++ o.cpp -pthread -std=c++0x -o zad01test
./zad01test
*/

#include <stdio.h>
#include <pthread.h> 
#include <errno.h>
#include <tr1/random>

int iloscOrangutanow = 90;

// tylko jeden orangutan moze wchodzic/schodzic z liny w danym momencie, ale moze byc kilka naraz na linie
pthread_mutex_t mutexLicznikaMalpNaLinie = PTHREAD_MUTEX_INITIALIZER;
// wysylany kiedy orangutan schodzi z liny do orangutanow oczekujacych na miejsce na linie
pthread_cond_t sygnal = PTHREAD_COND_INITIALIZER;
// jak 0 orangutanow na linie to mozna zmienic kierunek
int iloscOrangutanowNaLinie = 0;
// kierunek z ktorego ida to: 'A' lub 'B'
char kierunekOrangutanowNaLinie = 'A';
int przeszlo = 0;
// generator liczb losowych uzywajac algotymu Mersenne Twister
std::tr1::mt19937 losowacz;
// losowany 'int' od 0 do 1, czyli 0 lub 1
std::tr1::uniform_int<int> losowyInt_od_0_do_1(0,1);

void *orangutan(void *id)
{
	int idOrangutana = (int) id;

	pthread_mutex_lock(&mutexLicznikaMalpNaLinie);
	int kierunekWchodzacegoOrangutana;
	if(losowyInt_od_0_do_1(losowacz) == 1)
	{
		kierunekWchodzacegoOrangutana = 'A';
	}
	else
	{
		kierunekWchodzacegoOrangutana = 'B';
	}
	while(iloscOrangutanowNaLinie == 5 || (iloscOrangutanowNaLinie > 0 && kierunekWchodzacegoOrangutana != kierunekOrangutanowNaLinie))
	{
		pthread_cond_wait(&sygnal, &mutexLicznikaMalpNaLinie);
	}
	if(kierunekWchodzacegoOrangutana != kierunekOrangutanowNaLinie)
	{
		kierunekOrangutanowNaLinie = kierunekWchodzacegoOrangutana;
		printf("ZMIENIA SIE KIERUNEK ORANGUTANOW PRZECHODZACYCH PRZEZ LINE\n");
	}
	iloscOrangutanowNaLinie++;
	printf("Orangutan %d:	Wchodze %c, na linie: %d\n", idOrangutana, kierunekWchodzacegoOrangutana, iloscOrangutanowNaLinie);
	pthread_mutex_unlock(&mutexLicznikaMalpNaLinie);
	// czas przejscia przez line
	usleep(100000);
	pthread_mutex_lock(&mutexLicznikaMalpNaLinie);
	iloscOrangutanowNaLinie--;
	przeszlo++;
	printf("Orangutan %d:	Schodze %c, na linie: %d, przeszlo: %d\n", idOrangutana, kierunekWchodzacegoOrangutana, iloscOrangutanowNaLinie, przeszlo);
	pthread_cond_broadcast(&sygnal);
	pthread_mutex_unlock(&mutexLicznikaMalpNaLinie);
	pthread_exit(NULL);
}

int main()
{
	int idOrangutana=0;

	pthread_t tablicaWatkowOrangutanow[iloscOrangutanow];
	for(idOrangutana = 0; idOrangutana < iloscOrangutanow; idOrangutana++)
	{
		pthread_create(&tablicaWatkowOrangutanow[idOrangutana], NULL, orangutan, (void*) (idOrangutana+1));

	}
	for(idOrangutana = 0; idOrangutana < iloscOrangutanow; idOrangutana++)
	{
		pthread_join(tablicaWatkowOrangutanow[idOrangutana], NULL);
	}

	return EXIT_SUCCESS;
}

Tutaj moje rozwiązanie mojego zadania na 9/10, bo kanibal zabija kucharza exit(EXIT_SUCCESS);, a powinien wysłać mu sygnał po którym ten wykona pthread_kill:

#include <sys/time.h>
#include <stdio.h>
#include <pthread.h> 
#include <errno.h>
#include <time.h>
#include <stdlib.h>

int ilosc_misjonarzy = 200;
int ilosc_kanibali = 20;
int kociol_ilosc_misjonarzy = 0;
int kociol_limit_misjonarzy = 10;

pthread_mutex_t mutex_1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_3 = PTHREAD_MUTEX_INITIALIZER;
/*pthread_mutex_t mutex_4 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex_5 = PTHREAD_MUTEX_INITIALIZER; // jedzenie*/
pthread_mutex_t mutex_6 = PTHREAD_MUTEX_INITIALIZER; // wchodzenie

pthread_cond_t signal_1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_2 = PTHREAD_COND_INITIALIZER;
/*pthread_cond_t signal_3 = PTHREAD_COND_INITIALIZER;
pthread_cond_t signal_4 = PTHREAD_COND_INITIALIZER;
p	thread_cond_t signal_5 = PTHREAD_COND_INITIALIZER;*/

int kociolWejdz()
{
	int ret = 0;
	if(pthread_mutex_trylock(&mutex_6) == 0) // jesli odblokowane wchodzenie do gara
	{
		if(kociol_ilosc_misjonarzy < kociol_limit_misjonarzy)
		{
			kociol_ilosc_misjonarzy++;
			ret = 1;
		}
		pthread_mutex_unlock(&mutex_6);
	}
	return ret;
}
int kociolWyjmij()
{
	int ret;
	if(kociol_ilosc_misjonarzy > 0)
	{
		kociol_ilosc_misjonarzy--;
		ret = 1;
	}
	else
		ret = 0;
	return ret;
}
void* misjonarz()
{
	pthread_mutex_lock(&mutex_1);
	while (1)
	{
		pthread_cond_wait( &signal_1, &mutex_1 );
		if(kociolWejdz() == 1)
		{
			// misjonarz ginie
			break;
		}
	}
	pthread_mutex_unlock(&mutex_1);
	pthread_exit(NULL);
}

void* kucharz()
{
	int czas_koniec_czekania;
	pthread_mutex_lock(&mutex_6); // blokuje wchodzenie do gara
	printf("Blokuje gar\n");
	pthread_mutex_lock(&mutex_2);
	while (1)
	{
		printf("Ide spac\n");
		pthread_cond_wait( &signal_2, &mutex_2 ); // czeka na sygnal od kanibala
		printf("Ktos mnie obudzil\n");

		pthread_mutex_unlock(&mutex_6); // odblokowuje wchodzenie do gara
		pthread_cond_broadcast(&signal_1);
		czas_koniec_czekania = time(NULL) + 5;
		printf("Czekam az misjonarze wskocza do gara do %d jest %d\n", czas_koniec_czekania, (int) time(NULL));
		while(kociol_limit_misjonarzy != kociol_ilosc_misjonarzy && czas_koniec_czekania > time(NULL))
		{
			// czeka na napelnienie gara
			// pthread_cond_broadcast(&signal_1); czy bez tego 'signal' pozostanie zapamietany po broadcast??
		}
		printf("Misjonarze wskoczyli, jest ich %d\n", kociol_ilosc_misjonarzy);
		pthread_mutex_lock(&mutex_6); // blokuje wchodzenie do gara
		printf("Blokuje gar\n");

		pthread_cond_broadcast(&signal_2); // informuje kanibala, ze juz moze jesc
		printf("Informuje kanibala o napelnieniu gara\n");
	}
	pthread_mutex_unlock(&mutex_2);
}

void* kanibal()
{
	int ile_chce_zjesc;
	int i;
	while (1)
	{
		ile_chce_zjesc = (int)(rand() / (RAND_MAX + 1.0) * 10.0) + 1;
		printf("Chce zjesc %d\n", ile_chce_zjesc);
		pthread_mutex_lock(&mutex_3);
		pthread_mutex_lock(&mutex_2);
		printf("Przechodze do jedzenia\n");
		if(kociol_ilosc_misjonarzy >= ile_chce_zjesc)
		{
			printf("Jest dosc w garze\n");
// tylko jeden kanibal moze jesc naraz,
// wiec nie ma obaw,
// ze misjonarze znikna z kotla w inny sposob,
// nie trzeba sprawdzac co zwraca kociolWyjmij()
			for(i = 0; i < ile_chce_zjesc; i++)
			{
				kociolWyjmij();
			}
		}
		else
		{
			printf("Nie ma dosc w garze\n");
			pthread_cond_broadcast(&signal_2);
			printf("Czekam na kucharza\n");
			pthread_cond_wait( &signal_2, &mutex_2 );
			printf("Doczekalem sie na kucharza\n");
			while(ile_chce_zjesc > 0)
			{
				if(kociolWyjmij())
				{
			printf("!!!!!!!!!!!! Nie bylo dosc w garze, arg!\n");

// jesli udalo sie wyjac z kotla
// to znaczy, ze kucharz tam dolozyl misjonarza
					ile_chce_zjesc--;
				}
				else
					break;
			}
			if(ile_chce_zjesc > 0)
			{
			printf("!!!!!!!!!!!! Nie bylo dosc w garze, arg!\n");
// kanibal sie zdenerwowal, nie dostal w 5 sekund dosc misjonarzy
// zjedz kucharza
// koniec uczty
				exit(EXIT_SUCCESS);
			}
		}
		pthread_mutex_unlock(&mutex_2);
		pthread_mutex_unlock(&mutex_3);
	}
}

int main()  
{
	int i;
	pthread_t kucharz_t;
	pthread_t misjonarze_t[ilosc_misjonarzy];
	pthread_t kanibale_t[ilosc_kanibali];
	srand(time(NULL));

	pthread_create(&kucharz_t,NULL,kucharz,NULL);
	for(i = 0; i < ilosc_misjonarzy; i++)
	{
		pthread_create(&misjonarze_t[i],NULL,misjonarz,NULL);
	}
	for(i = 0; i < ilosc_kanibali; i++)
	{
		pthread_create(&kanibale_t[i],NULL,kanibal,NULL);
	}
	pthread_join(kucharz_t,NULL);
	for(i = 0; i < ilosc_misjonarzy; i++)
	{
		pthread_join(misjonarze_t[i],NULL);
	}
	for(i = 0; i < ilosc_kanibali; i++)
	{
		pthread_join(kanibale_t[i],NULL);
	}
	return EXIT_SUCCESS;
}
Czekam jeszcze na kod od Justyny.
Zaszufladkowano do kategorii PJWSTK, PJWSTK - ZSO | Dodaj komentarz

ZSO – Projekt 1 – Zadanie 4

Zadanie 4. Problem obiadujących kanibali.

Plemię kanibali spożywa wspólny posiłek z kotła mieszczącego M misjonarzy. Jeden z kanibali ustala liczbę m nie większą niż M misjonarzy, których chce zjeść i jeśli jest ich tylu w kotle to przystępuje do konsumpcji. W przeciwnym wypadku budzi wioskowego kucharza, który napełnia kocioł kolejnymi misjonarzami, o ile tylu misjonarzy jest dostępnych, a jak nie to czeka. Ja się plemię zdenerwuje bo za długo czeka na misjonarzy to dorzuca kucharza, spożywają  wszystkich obecnych w kotle i program się kończy.

ZADANIE MOŻNA RÓŻNIE ZINTERPRETOWAĆ, WIĘC NIE WIEM CZY TO JEST DOBRZE ZROBIONE.

W moim rozwiązaniu Kucharz działa w jednym wątku, a egzekutor ma pule Kanibali którzy pojedynczo (bo egzekutor jest ustawiony w tryb gdzie odpala jeden wątek naraz, a reszta czeka aż on się wykona)  próbują się najeść. Każdy patrzy czy jest tylu misjonarzy w kotle ilu chce zjeść, jak nie to budzi Kucharza i 'odchodzi’ (daje wait(), żeby nie blokować funkcji uzupełniania kotła, wtedy odpala się Kucharz). Kucharz napełnia kocioł i idzie znowu spać (daje wait(), żeby nie blokować kotła i pozwolić kanibalowi jeść) i tak do czasu aż się skończą misjonarze. Po za komentowaniu paru linii w Main.cpp i od komentowaniu paru program działa inaczej i wszyscy Kanibale chcą się naraz dorwać do kotła, ale wtedy nie ma pewności, że naje się ten który obudzi Kucharza, bo kto inny może podejść pierwszy do kotła po napełnieniu (losowo).

A od strony technicznej wygląda to tak, że kocioł ma funkcje 'wrzucDoKotla’ i 'zjedz’ które są synchronizowane, więc tylko jeden wątek z wszystkich działających może używać jednej z nich. Więc nie ma obaw, że kocioł będzie naraz opróżniany i napełniany. Jednak, żeby Kucharz nie napełniał kotła w losowych sytuacjach, a jedynie po tym jak inny wątek go obudzi dodałem obiekt public static Double budzik = 1d; w Kucharzu oraz funkcje do budzenia i przechodzenia w stan spoczynku (zablokowany / wait). Kucharz po napełnieniu kotła idzie spać (używa doWait() blokujące sie na budzik), a Kanibal używa 'doNotify()’ na Kucharzu kiedy w kotle nie ma dość misjonarzy, żeby odblokować wątek kucharza (używa doNotify() odblokowujące wątek zablokowany [który użył wait() ] na obiekcie budzik ).

Więcej na temat 'monitorowania’ (funkcje wait/notify ma każdy obiekt) można znaleźć na:
http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example

Dodam tylko, że monitorowania należy używać na utworzonych obiektach [ new Costam() ] , a nie NULLach i nie powinien to być obiekt o wartości domyślnej (podobno), czyli np. pusty string czy zero dla liczb.

Można pobrać pliki w .zip: ZSO_PROJEKT_1_ZADANIE_4

A obejrzeć tutaj:

Main.java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main
{
	static int iloscKanibali = 15;
	static int pojemnoscKotla = 10;
	static int iloscMisjonarzy = 100;
	static int czasZanimZjeKucharza = 3000;
	static KotloKlatka KotloKlatka = new KotloKlatka();
	static Kucharz Kucharz = new Kucharz();

	public static void main(String[] args) throws InterruptedException
	{
		KotloKlatka.setKlatkaIloscMisjonarzy(iloscMisjonarzy);
		KotloKlatka.setKociolPojemnosc(pojemnoscKotla);
		// WERSJA Z JEDNYM BUDZACYM

		// kucharz idzie spac, kociol jest pusty
		Kucharz.start();
		// kanibale zaczynaja uczte
		ExecutorService zarzadzcaUczty = Executors.newSingleThreadExecutor();

		// WERSJA Z WIELOMA BUDZACYMI
		/*
		ExecutorService zarzadzcaUczty = Executors.newFixedThreadPool(iloscKanibali+1);
		zarzadzcaUczty.submit(Kucharz);
		*/
		for(int i = 0; i < iloscKanibali; i++)
		{
			zarzadzcaUczty.submit(new Kanibal(i));
		}
		zarzadzcaUczty.shutdown();
		zarzadzcaUczty.awaitTermination(9999, TimeUnit.HOURS);
		System.out.println("KONIEC");
		Kucharz.interrupt();
		// BEZ SYSTEM EXIT: WTF
		//System.exit(1);
	}
}

KotloKlatka.java

public class KotloKlatka
{
	private int kociolIloscMisjonarzy = 0;
	private int kociolPojemnosc = 10;
	private int klatkaIloscMisjonarzy = 100;

	public synchronized void wrzucDoKotla()
	{
		System.out.println("KUCHARZ: DOKLADAM MISJONARZY");
		while(kociolIloscMisjonarzy < kociolPojemnosc)
		{
			if(klatkaIloscMisjonarzy == 0)
			{
				System.out.println("KUCHARZ: BRAK MISJONARZY");
				break;
			}
			klatkaIloscMisjonarzy--;
			kociolIloscMisjonarzy++;
		}
	}

	public synchronized void zjedz(int iloscDoZjedzenia, int idKanibala) throws InterruptedException
	{
		System.out.println("KANIBAL " + idKanibala + ": ZACZYNAM JESC " + iloscDoZjedzenia + " LUDZI");
		long start = System.currentTimeMillis();
		while(start + Main.czasZanimZjeKucharza > System.currentTimeMillis())
		{
			if(kociolIloscMisjonarzy >= iloscDoZjedzenia)
			{
				Thread.sleep(50 * iloscDoZjedzenia); // czas zjadania
				kociolIloscMisjonarzy -= iloscDoZjedzenia;
				System.out.println("KANIBAL " + idKanibala + ": ZJADLEM " + iloscDoZjedzenia);
				return;
			}
			else
			{
				Main.Kucharz.obudzKucharza(idKanibala);
				wait(200);
			}
		}
		System.out.println("KANIBAL " + idKanibala + ": " + Main.czasZanimZjeKucharza + " MS CZEKAM I NADAL PUSTY KOCIOL!");
		System.out.println("KANIBAL " + idKanibala + ": ZJADAM KUCHARZA");
		System.exit(1);
	}

	public int getKociolIloscMisjonarzy()
	{
		return kociolIloscMisjonarzy;
	}

	public void setKociolIloscMisjonarzy(int kociolIloscMisjonarzy)
	{
		this.kociolIloscMisjonarzy = kociolIloscMisjonarzy;
	}

	public int getKlatkaIloscMisjonarzy() {
		return klatkaIloscMisjonarzy;
	}

	public void setKlatkaIloscMisjonarzy(int klatkaIloscMisjonarzy)
	{
		this.klatkaIloscMisjonarzy = klatkaIloscMisjonarzy;
	}

	public int getKociolPojemnosc()
	{
		return kociolPojemnosc;
	}

	public void setKociolPojemnosc(int kociolPojemnosc)
	{
		this.kociolPojemnosc = kociolPojemnosc;
	}
}

Kanibal.java

import java.util.Random;

public class Kanibal implements Runnable
{
	public int id = -1;
	public static Random random = new Random();
	Kanibal(int id)
	{
		this.id = id;
	}

	@Override
	public void run()
	{
		try
		{
			Main.KotloKlatka.zjedz(random.nextInt(Main.KotloKlatka.getKociolPojemnosc()) + 1, this.id);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
}

Kucharz.java

public class Kucharz extends Thread
{
	public static Double budzik = 1d;
	@Override
	public void run()
	{

		while(true)
		{
			System.out.println("KUCHARZ: IDE SPAC");
			doWait(); // czekaj az ktos wysle info
			Main.KotloKlatka.wrzucDoKotla();
		}
	}
	  public void doWait(){
		    synchronized(budzik){
		        try{
		        	budzik.wait();
		         } catch(InterruptedException e){}
		    }
		  }

		  public void doNotify(){
		    synchronized(budzik){
		      budzik.notify();
		    }
		  }
	public void obudzKucharza(int idKanibala)
	{
		System.out.println("KUCHARZ: KANIBAL " + idKanibala + " MNIE BUDZI");
		doNotify();

	}
}

Zaszufladkowano do kategorii PJWSTK, PJWSTK - ZSO | Dodaj komentarz

ZSO 1

Mine.java

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Mine
{
	public static void main(String[] args) throws InterruptedException, ExecutionException
	{
		int cykli = 1000000000;
		int ilosc = 100; // ilosc wątków na które podzielimy cykle
		long s = System.currentTimeMillis();

		// tworze executor z okreslona iloscia watkow
		ExecutorService executorService = Executors.newFixedThreadPool(ilosc);
		// tworze zbior objektow do odpalenia
		Set<CallowalnaKlasa> callables = new HashSet<CallowalnaKlasa>();
		double step = 1.0 / (double)cykli;
		for(int i = 0; i < ilosc; i++)
		{
			// tworze obiekty ktore bede odpalal,
			// do konstruktora moge im przekazac jakies unikalne cechy
			CallowalnaKlasa x = new CallowalnaKlasa((cykli / ilosc) * i, cykli / ilosc, step);
			// dodaje je do listy
			callables.add(x);
		}
		// egzekutor odpala wszystkie objekty w watkach
		List<Future<Double>> x = executorService.invokeAll(callables);
		Double pi = 0.0;
		for(Future<Double> wynik : x)
		{
			// a tu pobieram wyniki obliczen jak sie skoncza
			pi += wynik.get();
		}

		long e = System.currentTimeMillis();
		// wylaczam egzekutor (kasuje watki)
		executorService.shutdown();

		System.out.println("Wartosc liczby PI wynosi " + pi);
		System.out.println("Czas przetwarzania wynosi " + ((double)(e - s) / 1000) + " sekund");
	}
}

CallowalnaKlasa.java

import java.util.concurrent.Callable;

public class CallowalnaKlasa implements Callable<Double>
{
	long iloscKrokowDlaDanegoWatka = 0;
	double krok;
	int odKtoregoKrokuZaczac = 0;

	CallowalnaKlasa(int od, long num, double step)
	{
		odKtoregoKrokuZaczac = od;
		iloscKrokowDlaDanegoWatka = num;
		krok = step;
	}

	@Override
	public Double call() throws Exception 
	{
		double x, pi, sum = 0.0;
		for(int i = odKtoregoKrokuZaczac; i < odKtoregoKrokuZaczac + iloscKrokowDlaDanegoWatka; i++)
		{
			x = (i + 0.5) * krok;
			sum = sum + 4.0 / (1.0 + x * x);
		}
		pi = sum * krok;
		return (Double) pi;
	}
}
Zaszufladkowano do kategorii PJWSTK, PJWSTK - ZSO | Dodaj komentarz

Czego tu szukasz? :)

#include <Servo.h>

Servo servo;
int dioda = 13;
int minimalnaOdleglosc = 0;
int katPrzyMinimalnejOdleglosci = 0;
int aktualnaOdleglosc = 0;
int aktualnyKat = 0;

// nie jestem pewien czy to znajdzie najblizsza czy najdalsza odleglosc,
// bo nie wiem czy dane z miernika rosna z odlegloscia czy maleja
// mozliwe, ze jest to odwrotnie niz w poleceniu!
// algorytm obroci servo w kierunku gdzie na wejsciu z miernika jest najnizsza wartosc (A TO MOZE BYC NAJWIEKSZA ODLEGLOSC!)

void setup() 
{
	servo.attach(9); // servo jest podlaczone do PIN 9
	servo.write(0); // ustawiamy servo na ustawienie poczatkowe
	pinMode(dioda, OUTPUT); // dodajemy diode
}

void loop()
{
	delay(500); // czekamy, az servo ustawi sie na pozycje poczatkowa
	// pelny obrot o 180 stopni powinien zajac 0.3 sec, a my damy 0.5 dla pewnosci
	aktualnaOdleglosc = analogRead(0); // wczytujemy aktualna odleglosc
	aktualnyKat = 1;// obracamy na kat 1 stopien [zakres serva jest od 0 do 180]
	// niech sie kreci, az obroci sie do 180 stopnia
	while(aktualnyKat <= 180)
	{
		servo.write(aktualnyKat);// obracamy na aktualny kat
		delay(20);// czekamy, az sie obroci, moze wymagac wiecej czasu!
		aktualnaOdleglosc = analogRead(0);// wczytujemy aktualna odleglosc
		if(aktualnaOdleglosc < minimalnaOdleglosc)// tu mozna odwrocic poszukiwanie na najwieksza wartosc
		{
			// jesli jest blizej niz dotychczas znana minimalna odeglosc to zapamietujemy kat
			minimalnaOdleglosc = aktualnaOdleglosc;
			katPrzyMinimalnejOdleglosci = aktualnyKat;
		}
		aktualnyKat += 1;// krecimy
	}
	// krecimy na ten kat przy ktorym odleglosc byla najmniejsza
	servo.write(katPrzyMinimalnejOdleglosci);
	// czekamy az sie obroci
	delay(500);
	// zapalamy diode na znak, ze teraz 'patrzy' na najblizszy punkt
	digitalWrite(dioda, HIGH);
	// TEGO NIE BYLO W POLECENIU! DAJCIE TU delay(9999999) i nie gascie diody!!
	// TEGO NIE BYLO W POLECENIU! DAJCIE TU delay(9999999) i nie gascie diody!!
	// TEGO NIE BYLO W POLECENIU! DAJCIE TU delay(9999999) i nie gascie diody!!
	// czekamy 5 sekund
        delay(5000);
        // gasimy diode
	digitalWrite(dioda, LOW);
	// jedziemy na pozycje startowa i 'loop' zaczyna szukanie od nowa najblizszej pozycji (mozemy przestawic arduino)
	servo.write(0);
}
Zaszufladkowano do kategorii PJWSTK, PJWSTK - SWB | Dodaj komentarz

Jeszcze więcej rzeczy jakich potrzebują studenci

SWB 12 (Komunikacja mikrokontrolera z urządzeniami zewnętrznymi):

http://www.technicana.com/physical-computing/73-connect-to-the-arduino-with-c-.html

Trzeba tylko trochę pozmieniać, żeby robiło to co jest w poleceniu, a nie jakieś durne maile wysyłało. Na dole jest link do pobrania projektu Visual Studio 🙂

POLECENIE:

Zadania na cwiczenia
1. Napisz programy, który od strony komputera PC wysyłac bedzie komunikat. Komunikat ten powinien zostac wyswietlony na wyswietlaczu LCD. Zwrotnie sterownik Arduino powinien wysłac jeden bajt sumy kontrolnej wyliczonej jako reszte z dzielenia sumy wszystkich kodów ASCII w odebranym komunikacie przez liczbe 2

2. Podobnie jak w poprzednim punkcie. Transmisje komunikatu rozpocznij po nacisnieciu przycisku. Wartosc sumy kontrolnej powinna byc wyswietlana automatycznie. Mozna wybrac dowolne srodowisko programistyczne (Java Swing, AWT, .Net, C++ etc.)

Zaszufladkowano do kategorii PJWSTK, PJWSTK - SWB | Dodaj komentarz

Wszystko czego potrzebują studenci

Plan zajęć dla grupy 424

i zadania na SWB 🙂

Ćwiczenia 10

Zadanie 2 i 3, zadania nr. 1 nie ma:

http://paste.ots.me/38704/text

Zadanie 2 (inne):

http://paste.ots.me/38870/text

Zadanie 3 (inne):

http://paste.ots.me/38871/text

Ćwiczenia 11

Zadanie 1:
http://paste.ots.me/38675/text

Zadanie 2:
http://paste.ots.me/38677/text

Zadanie 3:
http://paste.ots.me/38679/text

Zaszufladkowano do kategorii PJWSTK, PJWSTK - SWB | Dodaj komentarz