Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0
Wiki Markup
{code}
Code Block
// miniCANopen.cpp : Defines the entry point for the console application.
//


#include <stdio.h>
#include <math.h>
#include <string.h>
#include "can.h"
#include "kvaserdriver.h"
#include "inputevent.h"
#include "util/vt100.h"
#include "util/misc.h"

// Paletti luokan esittely
// Jokaista linjan palettia vastaan yksi tämän luokan instanssi
// Luokan metodeilla voidaan määrätä palettikohtaisesti palettien reitti ja kierrosten lukumäärä

class paletti
{
public:
		//int sijainti;
        void otettu();
        // Kun paletti otettu jollekkin asemalle, funktio muuttaa paletin vaihetta

        int kohde();
        // Lukijat tarkistavat minne paletin kuuluisi mennä
        // Funktio palauttaa seuraavana vuorossa olevan työpisteen numeron

        void aseta_reitti(int k0, int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, int k9);
        // Parametreiksi annetaan työkierto asemien numeroina
        // 1=manuaaliasema
        // 2=sr6
        // 3=sr60
        // Viimeisen vaiheen on oltava 0, jolloin työkierto palaa alkuun

	void aseta_tyovaihe(int k0, int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, int k9);
	//asetetaan työvaihe paleteille mahd. arvot 1-3

        void aseta_kierrosten_maara(int k);
        // Parametriksi annetaan kuinka monta kertaa työkierto halutaan suorittaa
        // Arvolla 0 työkiertoa ajetaan ikuisesti

        int kierros();
        // Palauttaa arvon joka kertoo kuinka monta kertaa työkierto on käyty läpi

        void aktivoi();
        void deaktivoi();
        // Paletti aktivoidaan tai deaktivoidaan. Deaktivoitu paletti kiertää linjaston keskellä

        void reset();
        // Kierrosten määrä ja työkierron vaihe nollataan

        bool aktiivisuus();
        // Palauttaa boolean arvon, joka kertoo onko paletti aktiivinen

        paletti();
        virtual ~paletti();

		int sijainti;	//1 = manuaali-asema, 2 = sr6, 3 = sr60
//pidetään lukua onko paletti otettu jollekkin roboteista, jotta sitten robotilla
//voidaan tarkistaa, että mikä paletti on tulossa robolle (voidaan lukea robon arvot). Arvo asetetaan rfid:n lukuhetkellä tila[0],[6],[10]:ssa
	
//Vai onko paletilla tieto siitä missä kohtaa linjalle paletti on menossa? --JH

private:
        int reitti[10];
		int tyovaihe[10];	//työvaiheen numerot eli mitä tehdään kyseisellä robolla.
        int vaihe;
        int kierrosten_maara;
        int kierroslaskuri;
        bool aktiivinen;
		int robotinOhjelma;
		int kuittausRobotilta;	//0 = susi, 1 = ok, 2 = aika ylitetty
	//asetetaan kuittaus-tyyppi. paletti odottaa tietyn ajan ja jos kuittausta ei siinä
	//ajassa ole tullut niin asetetaan tila '3' jolloin paletti siirtyy yleiseen kiertoon

};


// ************************
// 	Palettiluokan toteutus
// ************************

// Konstruktori
paletti::paletti()
{
}

// Destruktori
paletti::~paletti()
{
}

void paletti::otettu() {
        vaihe++;
        if(reitti[vaihe]==0) {
                vaihe=0;
                kierroslaskuri++;
        }
        if(kierroslaskuri>=kierrosten_maara && kierrosten_maara!=0) {
                deaktivoi();
        }

}

int paletti::kohde() {
        if(aktiivinen)
                return reitti[vaihe];
        else return 0;
}

void paletti::aseta_reitti(int k0, int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, int k9) {
        reitti[0]=k0;
        reitti[1]=k1;
        reitti[2]=k2;
        reitti[3]=k3;
        reitti[4]=k4;
        reitti[5]=k5;
        reitti[6]=k6;
        reitti[7]=k7;
        reitti[8]=k8;
        reitti[9]=k9;
}


void paletti::aseta_tyovaihe(int k0, int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, int k9) {
	tyovaihe[0] = k0;
	tyovaihe[1] = k0;
	tyovaihe[2] = k0;
	tyovaihe[3] = k0;
	tyovaihe[4] = k0;
	tyovaihe[5] = k0;
	tyovaihe[6] = k0;
	tyovaihe[7] = k0;
	tyovaihe[8] = k0;
	tyovaihe[9] = k0;
}

void paletti::aseta_kierrosten_maara(int k) {
        kierrosten_maara=k;
        kierroslaskuri=0;
        vaihe=0;
}

int paletti::kierros() {
        return kierroslaskuri;
}

void paletti::aktivoi() {
        aktiivinen=true;
}

void paletti::deaktivoi() {
        aktiivinen=false;
}

void paletti::reset() {
        kierroslaskuri=0;
        vaihe=0;
}

bool paletti::aktiivisuus() {
        return aktiivinen;
}

// ***********************************
// Globaalien apufunktioiden esittely
// ***********************************
void reittien_alustus();
void nodeon(int CANnode, int slave, int bitti);
void nodeoff(int CANnode, int slave, int bitti);
bool nodestate(int CANnode, int slave, int bitti);
//testiä: olivat ennen ..nodeon(int CAN_NodeID..)


// ***************************************
// Ohjelman Globaalit muuttujat ja luokat
// ***************************************

// Taulukko tilakoneille
int tila[24];
char tilan_viesti[20][50];

//Muuttujat rfid-lukijoille
unsigned char lukija[3];

//Luodaan 13 palettia
paletti p[13];
 
//Laskuri ohjelman nopeuden selvittämistä varten
int laskuri;

// Luodaan globaalit PDOt jotka sisältävät linjan inputtien tilat
PDO tpdo181(0x181); //Digitaali-inputit 1-15
PDO tpdo281(0x281); //Digitaali-inputit 16-31
PDO tpdo1c1(0x1c1); //RFID-lukija 1
PDO tpdo2c1(0x2c1); //RFID-lukija 2
PDO tpdo3c1(0x3c1); //RFID-lukija 3

//ASi node 2 transmit pdot
PDO tpdo381(0x381);	//Digitaali-inputit 1-15 ??? -JH

// Linjan outputit ovat näissä kahdessa RDPOssa
PDO rpdo201(0x201); //Digitaalioutputit 1-15
PDO rpdo301(0x301); //Digitaalioutputit 16-31

PDO rpdo401(0x401); //Digitaalioutputit 1-15 ASi Master 2

//testiä:
//uuden konfiguraation vaatimat muuttujat@14.4 -JH
//node 2:
PDO tpdo182(0x182);	//node 2, input 1-15
PDO tpdo282(0x282);	//input 1-15 //onko tätä? -JH
PDO rpdo202(0x202);	//node 2, output 1-15
PDO rpdo302(0x301);	//output 16-31	//onko tätä? -JH

int Run=1;
int LinjaAsiNode=1;
int RoboAsiNode=2;


// ***********
// Pääohjelma
// ***********

int main()
{
//Asetetaan paleteille reitit
reittien_alustus();

// Alustetaan näppäimistön käyttö
eventinit();

KvaserDriver driver;

// Avataan megabitin nopaudella
driver.open(1000000);
driver.set_debug(6);
decoder_openlog("\\temp\\canlog.txt");

// Luodaan CAN olio
CAN can;
can.set_debug(0); // Tulostetaan errorit ja ohjelma pysähtyy CAN-pinon virhetilanteisiin

// Ladataan CAN driver
can.load_driver(driver);
// Pysäytetään kaikien noodien toiminta

can.stop_node(0);
u_sleep(100000);

// Määritellään PDO:den pituudet
tpdo181.set_len(8);
tpdo281.set_len(8);
tpdo1c1.set_len(8);
tpdo2c1.set_len(8);
tpdo3c1.set_len(8);
//node 2
tpdo381.set_len(1);

rpdo201.set_len(8);
rpdo201.set_value(0); // Nollataan RDPOn kaikkien kahdeksan tavun sisältö
rpdo301.set_len(8);
rpdo301.set_value(0); // Nollataan RDPOn kaikkien kahdeksan tavun sisältö
//node 2
rpdo401.set_len(1);
rpdo401.set_value(0);

//testiä:
//asetetaan pituudet.
tpdo182.set_len(1);
rpdo202.set_len(8);	// pitäisikö olla ..(1)..?	--JH
rpdo201.set_value(0);

// Mapataan rfid-lukijoiden muuttujat oikeisii tpdo:hin.
tpdo1c1.mapcopy(0,lukija[1]);
tpdo2c1.mapcopy(0,lukija[2]);
tpdo3c1.mapcopy(0,lukija[3]);

// Lisätään TPDOt listaan
can.add_tpdo(tpdo181);
can.add_tpdo(tpdo281);
can.add_tpdo(tpdo1c1);
can.add_tpdo(tpdo2c1);
can.add_tpdo(tpdo3c1);

can.add_tpdo(tpdo381);

//testiä:
//lisätään luotujen tpdo182 + rpdo202 listaan. -- JH
can.add_tpdo(tpdo182);
can.add_rpdo(rpdo202);

// Lisätään RPDOt listaan
can.add_rpdo(rpdo201);
can.add_rpdo(rpdo301);

can.add_rpdo(rpdo401);

//SDO alustukset 

// Asetetaan CAN-noodi preoperational-tilaan
can.set_preoperational(0);
u_sleep(100000);


// IFM:n boksin alustukset
// Tarvitaan 5 TPDO:ta ja 2 RPDO:ta
// Määrätään PDO-viesteille COBID:t
// TDPO cobid konfigurointi 
can.sdo_write(1, 0x1800, 1, 4, 384+1);
can.sdo_write(1, 0x1801, 1, 4, 640+1);
can.sdo_write(1, 0x1802, 1, 4, 448+1);
can.sdo_write(1, 0x1803, 1, 4, 704+1);
can.sdo_write(1, 0x1804, 1, 4, 960+1);

can.sdo_write(1, 0x1805, 1, 4, 896+1);

// RDPO cobid konfigurointi 
can.sdo_write(1, 0x1400, 1, 4, 512+1);
can.sdo_write(1, 0x1401, 1, 4, 768+1);

can.sdo_write(1, 0x1402, 1, 4, 1024+1);


u_sleep(100000);
can.start_node(0);
u_sleep(100000);

VT100::clearscreen();

//luodaan globaali-tekstitiedosto, johon voi kirjoittaa halutussa kohtaa ohjelmaa tekstiä ---@7.4 JH
int iApu;	
//apumuuttuja (voidaan tallentaa tiloja esim. iApu = nodeon(x,x,x)
FILE *pFile;
pFile = fopen("debug_tekstia.txt", "w");
//"w" = kirjoita tiedostoon, ylikirjoita kaikki, luo tarvittavissa
//"a" = jatka jo olemassa olevan perään
if (pFile == NULL)
	perror("error opening file");
fprintf(pFile, "debug tekstiä\n*******************************\n");
//käytetään kirjoittamalla: "fprintf(pFile, "_teksti_tähän_, %d, %s", int_muuttuja, char_muuttuja);"

// Pääohjelma alkaa tästä ja suorittaa ikuista looppia

//tuleva valikko-ohjelma:
int valinta = 0;
//do{
	printf("This is the program for the production line!!\n\n");
	printf("\nWhen the line program is running you should stretch your terminal window downwards so that all information can be shown at the screen\n\n");
	printf("The following keys are valid:\n\n");
	printf("When the production line program is _running_ pressing '1' will activate the line. Pressing '0' will shutdown the line. Pressing 'ESC' will shutdown the line and exit\n\n");
	printf("What do you want me to do MASTER?\n");
	printf("Pressing number '1' will start the production-line program\n");
	printf("Any other button will end quit the program\n\n\n\n");
	printf("your selection: ");
	scanf("%d", &valinta);
	VT100::clearscreen();
	if (valinta == 1) {	
	
do{

	// Linjan moottorit päälle kun painetaan näppäintä '1'
	if (keydown('1'))
	{ 
		//moottorit käynnistetään yksi kerrallaan virtapiikin estämiseksi
		for(int i=1; i<=23; i++) {
			if(i==1) nodeon(1,17,1); //manuaalilinjan moottorit
			if(i==2) nodeon(1,27,1);
			if(i==3) nodeon(1,27,2);
			if(i==4) nodeon(1,6,1);
			if(i==5) nodeon(1,6,2);
			if(i==6) nodeon(1,6,3);
			if(i==7) nodeon(1,16,1);
			if(i==8) nodeon(1,16,2);
			// tehdään alustus, jossa '1' napin painalluksella jäämäpalettien poiston caset lähtevät käyntiin
			if(i==9) tila[0]=1;
			if(i==10) tila[1]=1;
			if(i==11) tila[2]=1;
			if(i==12) tila[3]=1;
			if(i==13) tila[6]=1;
			if(i==14) tila[7]=1;
			if(i==15) tila[8]=1;
			if(i==16) tila[11]=1;
			if(i==17) tila[12]=1;
			if(i==18) tila[13]=1;
			if(i==19) tila[14]=1;
			if(i==20) tila[16]=1;
			if(i==21) tila[17]=1;
			if(i==22) tila[18]=1;
			if(i==23) tila[19]=1;
			printf("Moottori :%d\n",i);
			u_sleep(500000); //500ms
			can.send_only_changed_rpdos();
	        
			}
	}

	// Linjan moottorit pois päältä kun painetaan näppäintä '0'
	if (keydown('0'))
	{
		//moottorit pysäytetään yksi kerrallaan virtapiikin estämiseksi
		for(int i=1; i<=8; i++) {
			if(i==1) nodeoff(1,17,1); //manuaalilinjan moottorit
			if(i==2) nodeoff(1,27,1);
			if(i==3) nodeoff(1,27,2);
			if(i==4) nodeoff(1,6,1);
			if(i==5) nodeoff(1,6,2);
			if(i==6) nodeoff(1,6,3);
			if(i==7) nodeoff(1,16,1);
			if(i==8) nodeoff(1,16,2);
			printf("Moottori :%d\n",i);
			u_sleep(500000); //500ms
			can.send_only_changed_rpdos();
		}
	}
//
	if (keydown('A'))
	{
		nodeoff(1,6,3);
		nodeoff(1,20,4);
	}

	//
	if (keydown('B'))
	{
		nodeon(1,6,3);
		nodeon(1,20,4);
	}


	if (keydown('C'))
	{
		int Tila;
	   Tila=nodestate(2,1,1);
	   printf("\ntila on %d",Tila);
	}

	if(keydown('D'))
	{
		//nodeon(2,3,1);
		//nodeon(2,3,2);
		/*nodeon(2,2,1);
		nodeon(2,2,2);*/
	//	nodeon(1,26,3);
		/*nodeon(2,4,3);
		nodeon(2,4,4);
		nodeon(2,3,3);
		nodeon(2,3,4);
		nodeon(2,3,3);
		nodeon(2,3,4);*/
		//nodeon(2,4,1);
		//nodeon(2,4,2);
		//nodeon(2,4,3);
		//nodeon(2,4,4);
		//nodeon(2,5,1);
		//nodeon(2,5,2);
		//fprintf(pFile, "näppäintä D painettu:\n");
		//fprintf(pFile, "nodestate(2,5,1): %d\nnodestate(2,5,2): %d\n", iApu = nodestate(2,5,1), iApu = nodestate(2,5,2));
		//rpdo401.set_value(15);
		if(nodestate(2, 2, 1))
			fprintf(pFile, "IFFIN SISässä***** D-nappi: noodi 2.2.1 päällä\n");
	}
	if(keydown('E'))
	{
		if (nodestate(2, 2, 2))
			fprintf(pFile, "E-nappi: noodi 2.2.2 päällä\n");
		//nodeoff(2,4,3);
		//nodeoff(2,4,4);
		//nodeoff(2, 2, 1);
		//nodeoff(2,4,1);
		//nodeoff(2,4,2);
		//nodeoff(2,5,1);
		//nodeoff(2,5,2);
		//fprintf(pFile, "näppäintä E painettu:\n");
		//fprintf(pFile, "nodestate(2,5,1): %d\nnodestate(2,5,2): %d\n", iApu = nodestate(2,5,1), iApu = nodestate(2,5,2));
		//nodeon(2,5,3);
		//nodeon(2,5,4);

//		nodeoff(1,26,3);
	}


if(Run==1)
{

// Varsinainen ohjelman logikka alkaa
// 20 tilakonetta seuraavat linjaston tapahtumia, ja ohjaavaat toimilaitteita 
// lisäksi neljä tilakonetta ohjaavat jäämäpalettien poistoa
switch(tila[0]) {
	
	// case 0-1 ovat jäämäpalettien poistamiseksi ajon alussa
	case 0:
	//tyhjä case anturien toiminnan parantamiseksiajon alussa
	break;

	case 1:
		if(nodestate(1,21,1))	  //Jos mekaaninen anturi 21,1 vaikuttuu, asetetaan hissi 20,3 yläasentoon.
			nodeon(1,20,3);
		if(timedelay(0,25000000)) //Ajastin laskee 25000ms, jonka jälkeen tila[0] siirtyy seuraavaan caseen.
			tila[0]++;
	break;

	case 2:
		strcpy(tilan_viesti[0],"20.1");
		nodeoff(1,20,4);		//Hissi asetetaan keskiasentoon.
		nodeoff(1,20,3);
		if(nodestate(1,20,1)) 	//Jos anturi 20,1 vaikuttuu, siirtyy tila[0] seuraavaan caseen.	
			tila[0]++;
	break;

	case 3:
		strcpy(tilan_viesti[0],"20.2");
		nodeon(1,21,3);			//Stoppari 21,3 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,20,2))	//Jos induktiivinen anturi 20,2 vaikuttuu, siirtyy tila[0] seuraavaan caseen.
			tila[0]++;
	break;
	
	case 4:
		strcpy(tilan_viesti[0],"21.1");
		nodeoff(1,21,3);		//Stoppari 21,3 menee poispäältä, estäen seuraavan paletin kulun.
		if(nodestate(1,21,1)) {		//Jos mekaaninen anturi 21,1 vaikuttuu, ja jos tila[1]=1, niin RFID-lukija[1] lukee paletin tagin. 
			strcpy(tilan_viesti[0],"tila[4], tila[12], tila[1]");
			if(tila[1]==1 && p[ lukija[1] ].kohde()==1 ) {		//Jos reitti paletille on 1 eli manuaaliasema, niin silta 20,3 vaikuttuu, tila[0] siirtyy seuraavaan caseen ja tila[1]=1.
				resettimedelay(0);
				nodeon(1,20,3);
				tila[0]++;
				tila[1]=1;
				p[lukija[1]].otettu(); //kuitataan että paletti otettiin
				p[lukija[1]].sijainti = 1;	//astetaan paletin sijainniksi 1, eli manuaaliasema
			}
			//Jos kohde ei ole manuaaliasema tai tunnistuksessa kestää yli sekunti
			//(paletti ilman tagia?), ajetaan suoraan
			else if((lukija[1]!=0 && p[ lukija[1] ].kohde()!=1) || timedelay(0,1000000)) {
				if(tila[4]==0 && tila[12]==1) {		//Jos tila[4]=0 ja tila[12]=1, vaikuttuu silta 20,4, tila[12]=2 ja tila[0] siirtyy seuraavaan caseen.
					resettimedelay(0);
					nodeon(1,20,4);
					tila[12]=2;
					tila[0]++;
				} 
			}			
		}
	break;
	
	case 5: //viive että paletti ehtii pois hissistä, sitten nollaus
		strcpy(tilan_viesti[0],"Ajastin 2s");
		if(timedelay(0,2000000)) //Kun ajastin on laskenut 2000ms, on tila[0]=2. 
			tila[0]=2; 
	break;
	
	
}

switch(tila[1]) {

	case 0:
	//tyhjä case anturien toiminnan parantamiseksi ajon alussa
	break;

	case 1:
		strcpy(tilan_viesti[1],"22.1");
		if(nodestate(1,22,1) && tila[2]==2)		//Jos induktiivinen anturi 22,1 vaikuttuu ja tila[2]=2, siirtyy tila[1] seuraavaan caseen.	
			tila[1]++;
	break;

	case 2:
		strcpy(tilan_viesti[1],"22.2");
		nodeon(1,22,3);			//Stoppari 22,3 menee päälle, päästäen paletin ylitseen.	
		if(nodestate(1,22,2))	//Jos induktiivinen anturi 22,2 vaikuttuu, siirtyy tila[1] seuraavaan caseen.
			tila[1]++;
	break;

	case 3:
		strcpy(tilan_viesti[1],"23.1");
		nodeoff(1,22,3);			//Stoppari 22,3 menee poispäältä, estäen seuraavan paletin kulun.
		if(nodestate(1,23,1)) {		//Jos  induktiivinen anturi 23,1 vaikuttuu, on tila[1]=1. 
			tila[1]=1;
		}
	break;
}

switch(tila[2]) {
	//Case 0…1 poistaa jäämäpaletit ennen kuin tila[2] aloittaa normaalin työkierron.
	case 0:
	//tyhjä case anturien toiminnan parantamiseksiajon alussa
	break;

	case 1:
	//if-lause yhden stopparin toiminnan parantamiseksi jäämäpaletteja poistettaessa ajon alussa
		if(tila[3]==1) {		//Jos tila[3]=1, niin stoppari 26,3 menee päälle, päästäen paletin ylitseen. 	
			nodeon(1,26,3);
			if(timedelay(2,500000)){	//Lisäksi ajastin laskee 500ms, jonka jälkeen stoppari 26,3 menee pois päältä, estäen seuraavan paletin kulun ja tila[2] siirtyy seuraavaan caseen.
					nodeoff(1,26,3);
					tila[2]++;
					}
					}
	break;

	case 2:
		
		strcpy(tilan_viesti[2],"23.1");
		if(nodestate(1,23,1))		//Jos induktiivinen anturi 23,1 vaikuttuu, siirtyy tila[2] seuraavaan caseen.
			tila[2]++;
	break;
	
	case 3:
		strcpy(tilan_viesti[2],"gut tai auto");
		nodeon(1,23,3);		//Pöytä asetetaan yläasentoon.
		nodeoff(1,23,4);	//Toimilaite 23,4 menee pois päältä.
		//kappale päästetään eteenpäin gut-napilla tai auto-valinnalla
		if(!nodestate(1,25,3) || nodestate(1,25,2))  //Jos painonappi auto/man ei ole painettuna tai gut nappi on painettuna, siirtyy tila[2] seuraavaan caseen.
			tila[2]++;	
	break;

	case 4:
		strcpy(tilan_viesti[2],"23.2");
		nodeon(1,22,4);		//Pöytä 22,4 asetetaan ala-asentoon.
		nodeoff(1,23,3);	//Toimilaite 23,3 menee pois päältä.
		nodeon(1,23,4);		//Toimilaite 23,4 menee päälle.
		if(nodestate(1,23,2)) 	//Jos induktiivinen anturi 23,2 vaikuttuu, siirtyy tila[2] seuraavaan caseen.	
			tila[2]++;
	break;
	
	case 5:
		strcpy(tilan_viesti[2],"tila[3]");
		nodeoff(1,22,4);	//Stoppari 22,4 menee pois päältä, estäen seuraavan paletin kulun.
		if(tila[3]==1) 		//Jos tila[3]=1, siirtyy tila[2] seuraavaan caseen.
			tila[2]++;	
	break;
	
	case 6:
		strcpy(tilan_viesti[2],"26.1");
		nodeon(1,26,3);			//Stoppari 26,3 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,26,1))	//Jos induktiivinen anturi 26,1 vaikuttuu, siirtyy tila[2] seuraavaan caseen.
			tila[2]++;
	break;
	
	case 7:
		nodeoff(1,22,4);	//Stopparit 22,4 ja 26,3 menevät pois päältä, estäen seuraavien palettien kulun.
		nodeoff(1,26,3);
		tila[2]=2;			//Tila[2]=2.
	break;
}

switch(tila[3]) {

	case 0:
		//tyhjä case anturien toiminnan parantamiseksi ajon alussa
	break;

	case 1:
		strcpy(tilan_viesti[3],"26.2");
		if(nodestate(1,26,2))	//Jos mekaaninen anturi 26,2 vaikuttuu, siirtyy tila[3] seuraavaan caseen.
			tila[3]++;
	break;
	
	case 2:
		strcpy(tilan_viesti[3],"ajastin 800ms");
		if(timedelay(3,800000)) //Ajastin laskee 800ms, jonka jälkeen tila[3] siirtyy seuraavaan caseen.
			tila[3]++; 
	break;
	
	case 3:
		strcpy(tilan_viesti[3],"24.2, tila[4]");
		nodeon(1,26,4);			//Hissi 26,4 asetetaan yläasentoon.
		if(nodestate(1,24,2) && tila[4]==0)		//Jos mekaaninen anturi 24,2 vaikuttuu ja tila[4]=0, siirtyy tila[3] seuraavaan caseen.
			tila[3]++;
	break;

	case 4:
		strcpy(tilan_viesti[3],"24.3");
		nodeoff(1,26,4);		//Hissi 26,4 asetetaan ala-asentoon.
		if(nodestate(1,24,3))	//Jos induktiivinen anturi 24,3 vaikuttuu, on tila[3]=1. 
			tila[3]=1;
	break;
}

switch(tila[4]) {
	case 0:
		strcpy(tilan_viesti[4],"28.1, tila[12]");
		if(nodestate(1,28,1) && tila[12]==1)	//Jos induktiivinen anturi 28,1 vaikuttuu ja tila[12]=1, siirtyy tila[4] seuraavaan caseen.
			tila[4]++;		
	break;

	case 1:
		strcpy(tilan_viesti[4],"28.2");
		nodeon(1,28,3);		//Stoppari 28,3 menee päälle, päästäen paletin ylitseen.
		nodeon(1,21,4);		//Hissi 21,4 asetetaan yläasentoon.
		if(timedelay(4,500000)){	//Ajastin laskee 500ms, jonka jälkeen stoppari 28,3 menee pois päältä, estäen seuraavan paletin kulun. Lisäksi tila[4]=0.
			nodeoff(1,28,3);
			tila[4]=0;
		}
	break;
	
}

switch(tila[5]){
	case 0:
		strcpy(tilan_viesti[5],"7.1");
		nodeon(1,7,3);		//Stoppari 7,3 menee päälle päästäen paletin ylitseen.
		if(nodestate(1,7,1))	//Jos induktiivinen anturi 7,1 vaikuttuu , siirtyy tila[5] seuraavaan caseen.
			tila[5]++;
	break;
	
	case 1:
		strcpy(tilan_viesti[5],"7.2");
		nodeoff(1,7,3);		//Stoppari 7,3 menee poispäältä, estäen seuraavan paletin kulun. 
		if(nodestate(1,7,2)) {		//Jos induktiivinen anturi 7,2 vaikuttuu, on tila[5]=0.
			tila[5]=0;
		}
	break;
}

switch(tila[6]) {
	//Case 0…1 poistaa jäämäpaletit ennen kuin tila[6] aloittaa normaalin työkierron.
	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		if(nodestate(1,8,2))	//Jos mekaaninen anturi 8,2 vaikuttuu, asetetaan hissi 9,3 ala-asentoon.
			nodeon(1,9,3);
		if(timedelay(6,3000000)) //Ajastin laskee 3000ms, jonka jälkeen tila[6] siirtyy seuraavaan caseen.
			tila[6]++;
	break;

	case 2:
		strcpy(tilan_viesti[6],"7.2");
		nodeoff(1,9,2);		//Hissi 9,2 ja 9,3 asetetaan keskiasentoon.
		nodeoff(1,9,3);
		if(nodestate(1,7,2))	//Jos induktiivinen anturi 7,2 vaikuttuu, siirtyy tila[6] seuraavaan caseen.
			tila[6]++;
	break;

	case 3:
		strcpy(tilan_viesti[6],"8.1");
		nodeon(1,9,1);		//Stoppari 9,1 menee päälle, päästäen paletin ylitseen. 
		if(nodestate(1,8,1))	//Jos induktiivinen anturi 8,1 vaikuttuu, siirtyy tila[6] seuraavaan caseen.
			tila[6]++;
	break;

	case 4:  
		strcpy(tilan_viesti[6],"8.2, tila[7]");
		nodeoff(1,9,1);		//Stoppari 9,1 menee poispäältä, estäen seuraavan paletin kulun
		
		if(nodestate(1,8,2)) {		//Jos mekaaninen anturi 8,2 vaikuttuu ja tila[7]=2, lukee RFID-lukija[2] paletin tagin.
			if(tila[7]==2 && p[lukija[2]].kohde()==2) { //Jos reitti paletille on 2 eli SR6-asema, niin tila[6]=5 ja paletti kuitataan otetuksi.
				resettimedelay(6);
				tila[6]=5;
				p[lukija[2]].otettu();
//testiä:
				p[lukija[2]].sijainti = 2;
				//asetetaan paletin-sijainniksi rfid:n numero
				//jotta tiedetään mikä paletti on tulossa kyseiselle robolle.
			}
			else if((lukija[2]!=0 && p[ lukija[1] ].kohde()!=2) || timedelay(6,1000000)) {	//Jos taas paletin retti on eri kuin 2 tai lukuaika on enemmän kuin 1000ms, on tila[6]=6. 
				resettimedelay(6);
				tila[6]=6;
			}
			tila[5]=0;	//Asetetaan tila[5]=0.
		}
	break;

	//Case 5 robotille, case 6 kiertoon
	case 5:
		//Tämä case ohjaa paletin SR6-robotille. 
		strcpy(tilan_viesti[6],"ajastin 2s");
		nodeon(1,9,2);	//Hissi 9,2 asetetaan yläasentoon. 
		if(timedelay(6,2000000)) //Kun ajastin on laskenut 2000ms kuluneeksi, on tila[6]=2.
			tila[6]=2;
	break;
	
	case 6:
		//Tämä case ohjaa paletin kiertoon. 
		strcpy(tilan_viesti[6],"ajastin 2s");
		nodeon(1,9,3);	//Hissi 9,3 asetetaan ala-asentoon.
		if(timedelay(6,2000000))  //Kun ajastin on laskenut 2000ms kuluneeksi, on tila[6]=2.
			tila[6]=2;
	break;
					
}

switch(tila[7]) { 
	//case 0-1 poistaa jäämäpaletit aluksi ennen kuin tila[7] aloittaa normaalin työkierron
	case 0:		
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:	
		//Tilakone tila[22] ohjaa jäämäpalettien poistoa ajon alussa tässä casessa.
		switch(tila[22]) {	//Tämä tilakone ohjaa tila[7]:n jäämäpalettien poistoa.
			
			case 0:
				nodeon(1,10,3);	//Stoppari 10,3 menee päälle, päästäen paletin ylitseen.
				nodeon(1,10,4);	//Hissi 10,4 asetetaan yläasentoon.
				tila[22]++;		//Tila[22] siirtyy seuraavaan caseen.
			break;

			case 1:	
				if(nodestate(1,10,1))	//Jos induktiivinen anturi 10,1 vaikuttuu, menee stoppari 10,3 pois päältä, estäen seuraavan paletin kulun.
					nodeoff(1,10,3);
				if(nodestate(1,10,2)){	//Jos mekaaninen anturi 10,2 vaikuttuu, asetetaan hissi 10,4 ala-asentoon ja tila[22] siirtyy seuraavaan caseen.
					nodeoff(1,10,4);
					tila[22]++;
				}
				if(timedelay(22,2000000)) //Ajastin laskee 2000ms, jonka jälkeen tila[22] siirtyy seuraavaan caseen.
					tila[22]++;
			break;

			case 2:	
				if(timedelay(22,4000000)){  //Ajastin laskee 4000ms, jonka jälkeen hissi 10,4 asetetaan yläasentoon ja stoppari 10,3 menee päälle, päästäen paletin ylitseen. Lisäksi tila[22] siirtyy seuraavaan caseen.
					nodeon(1,10,4);
					nodeon(1,10,3);
					tila[22]++;
					}
			break;

			case 3:	
				if(nodestate(1,10,1))	//Jos induktiivinen anturi 10,1 vaikuttuu, menee stoppari 10,3 pois päältä, estäen seuraavan paletin kulun.
					nodeoff(1,10,3);
				if(nodestate(1,10,2))	//Jos mekaaninen anturi 10,2 vaikuttuu, asetetaan hissi 10,4 ala-asentoon.
					nodeoff(1,10,4);

				if(timedelay(22,4000000))  //Ajastin laskee 4000ms, jonka jälkeen tila[22]=0.
					tila[22]=0;
			break;

		}
		if(timedelay(7,40000000)){ //Ajastin laskee 40000ms, jonka jälkeen jälkeen hissi 10,4 asetetaan ala-asentoon ja stoppari 10,3 menee päälle, estäen seuraavan paletin kulun.  Lisäksi tila[7] siirtyy seuraavaan caseen.
			nodeoff(1,10,4);		
			nodeoff(1,10,3);
			tila[7]++;
			}
	break;

	case 2:
		strcpy(tilan_viesti[7],"8.3");
		if(nodestate(1,8,3))	//Jos induktiivinen anturi 8,3 vaikuttuu, siirtyy tila[7] seuraavaan caseen. 
		tila[7]++;
		
	break;

	case 3:
		strcpy(tilan_viesti[7],"tila[16]");
		if(tila[16]==3)		//Jos tila[16]=3, siirtyy tila[7] seuraavaan caseen.
			tila[7]++;		
	break;
	
	case 4:
		strcpy(tilan_viesti[7],"10.1");
		nodeon(1,10,3);		//Stoppari 10,3 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,10,1))	//Jos induktiivinen anturi 10,1 vaikuttuu, tila[7] siirtyy seuraavaan caseen.
			tila[7]++;
	break;
			
	case 5:
		strcpy(tilan_viesti[7],"10.2");
		nodeon(1,10,4);		//Hissi 10,4 asetetaan yläasentoon.
		nodeoff(1,10,3);	//Stoppari 10,3 menee pois päältä, estäen seuraavan paletin kulun.

		if(nodestate(1,10,2)) //Jos mekaaninen anturi 10,2 vaikuttuu, siirtyy tila[7] seuraavaan caseen.
			tila[7]++;	
	break;
	
	case 6:
		strcpy(tilan_viesti[7],"ajastin 1s");
		nodeoff(1,10,4);	//Hissi 10,4 asetetaan ala-asentoon.
		if(timedelay(7,1000000)) //Ajastin laskee 1000ms, jonka jälkeen tila[7]=2.
			tila[7]=2; 	
	break;
}

switch(tila[8]){
	//case 0-1 poistaa jäämäpaletit aluksi ennen kuin tila[7] aloittaa normaalin työkierron
	case 0:		
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:	
		//Tilakone tila[23] ohjaa jäämäpalettien poistoa ajon alussa tässä casessa.
		switch(tila[23]) {	//Tämä tilakone ohjaa tila[8]:n jäämäpalettien poistoa.
			
			case 0:
				nodeon(1,5,3);	//Stoppari 5,3 menee päälle, päästäen paletin ylitseen.
				nodeon(1,5,4);	//Hissi 5,4 asetetaan yläasentoon.
				tila[23]++;		//Tila[23] siirtyy seuraavaan caseen.
			break;

			case 1:	
				if(nodestate(1,4,3))	//Jos induktiivinen anturi 4,3 vaikuttuu, menee stoppari 5,3 pois päältä, estäen seuraavan paletin kulun.
					nodeoff(1,5,3);
				if(nodestate(1,4,4)){	//Jos mekaaninen anturi 4,4 vaikuttuu, asetetaan hissi 5,4 ala-asentoon ja tila[23] siirtyy seuraavaan caseen.
					nodeoff(1,5,4);
					tila[23]++;
					}
				if(timedelay(23,4000000)) //Ajastin laskee 4000ms, jonka jälkeen tila[23] siirtyy seuraavaan caseen.
					tila[23]++;
			break;

			case 2:	
				if(timedelay(23,4000000)){  //Ajastin laskee 4000ms, jonka jälkeen hissi 5,4 asetetaan yläasentoon ja stoppari 5,3 menee päälle, päästäen paletin ylitseen. Lisäksi tila[23] siirtyy seuraavaan caseen.
					nodeon(1,5,4);
					nodeon(1,5,3);
					tila[23]++;
					}
			break;

			case 3:	
				if(nodestate(1,4,3))	//Jos induktiivinen anturi 4,3 vaikuttuu, menee stoppari 5,3 pois päältä, estäen seuraavan paletin kulun.
					nodeoff(1,5,3);
				if(nodestate(1,4,4))	//Jos mekaaninen anturi 4,4 vaikuttuu, asetetaan hissi 5,4 ala-asentoon.
					nodeoff(1,5,4);

				if(timedelay(23,4000000))  //Ajastin laskee 4000ms, jonka jälkeen tila[23]=0.
					tila[23]=0;
			break;

		}
		if(timedelay(8,40000000)){ //Ajastin laskee 40000ms, jonka jälkeen hissi 5,4 asetetaan ala-asentoon ja stoppari 5,3 menee päälle, estäen seuraavan paletin kulun.  Lisäksi tila[8] siirtyy seuraavaan caseen.
			nodeoff(1,5,4);
			nodeoff(1,5,3);
			tila[8]++;
			}
		break;

	case 2:
		strcpy(tilan_viesti[8],"29.1");
		if(nodestate(1,29,1)) tila[8]++;	//Jos induktiivinen anturi 29,1 vaikuttuu, tila[8] siirtyy seuraavaan caseen. 
	break;

	case 3:
		strcpy(tilan_viesti[8],"4.3");
		nodeon(1,5,3);		//Stoppari 5,3 menee päälle, päästäen paletin ylitseen. 
		if(nodestate(1,4,3)) 	//Jos induktiivinen anturi 4,3 vaikuttuu, siirtyy tila[8] seuraavaan caseen. 
			tila[8]++;
	break;
	
	case 4:
		strcpy(tilan_viesti[8],"4.4");
		nodeoff(1,5,3);		//Stoppari 5,3 menee poispäältä, estäen seuraavan paletin kulun. 
		nodeon(1,5,4);		//Hissi 5,4 asetetaan yläasentoon.
		if(nodestate(1,4,4) && tila[18]==3)		//Jos mekaaninen anturi 4,4 vaikuttuu ja tila[18]=3, tila[8] siirtyy seuraavaan caseen.
			tila[8]++;
	break;
	
	case 5:
		strcpy(tilan_viesti[8],"ajastin 1400ms");
		nodeoff(1,5,4);		//Hissi 5,4 asetetaan ala-asentoon. 
		if(timedelay(8,1400000)) tila[8]=2; //Ajastin laskee 1400ms, jonka jälkeen tila[8]=2.
	break;
}

switch(tila[9]) {
	case 0:
		nodeoff(1,14,2);	//Hissi 14,2 asetetaan ala-asentoon.
	break;
	
	case 1:
		strcpy(tilan_viesti[9],"13.2, tila[15]");
		if(nodestate(1,13,2) && tila[15]==0)	//Jos mekaaninen anturi 13,2 vaikuttuu ja tila[15]=0, siirtyy tila[9] seuraavaan caseen.
			tila[9]++;
	break;
	
	case 2:
		strcpy(tilan_viesti[9],"ajastin 1500ms");
		nodeoff(1,14,2);	//Hissi 14,2 asetetaan ala-asentoon.
		if(timedelay(9,2000000)){ //Ajastin laskee 2000ms, jonka jälkeen tila[9]=0.
			tila[9]=0; 
		}
	break;	
}

switch(tila[10]) {  
	case 0:
		strcpy(tilan_viesti[10],"31.4");
		nodeoff(1,30,3);	//Hissi asetetaan keskiasentoon. 
		nodeoff(1,30,4);
		if(nodestate(1,31,4))	//Jos mekaaninen anturi 31,4 vaikuttuu, siirtyy tila[10] seuraavaan caseen.
			tila[10]++;
	break;
	
	case 1:
		strcpy(tilan_viesti[7],"ajastin 400ms");
		 
		if(timedelay(10,800000)) tila[10]++; //Ajastin laskee 800ms paletin asettumiseksi hissille, minkä jälkeen tila[10] siirtyy seuraavaan caseen.

	break;
	
	case 2:
		strcpy(tilan_viesti[10],"31.4, tila[8]");
		if(nodestate(1,31,4)) { //Jos mekaaninen anturi 31,4 vaikuttuu ja tila[8]=2, lukee RFID-lukija[3] paletin tagin. 
			if(tila[8]==2 && p[lukija[3]].kohde()==3)  {
				resettimedelay(10);
				tila[10]=3;
				//testiä:
				p[lukija[3]].sijainti = 3;	//paletti otetaan robolle, joten sijainti asetetaan 3.
			}
			else if((lukija[3]!=0 && p[ lukija[3] ].kohde()!=3) || timedelay(10,2000000)) {	//Jos reitti paletille on 3 eli SR60-asema, niin tila[10]=3.
				resettimedelay(10);
				tila[10]=4;
			}
		}
	break;
	
	case 3:
		//Tämä case ohjaa paletin SR60-robotille.
		nodeon(1,30,3);		//Hissi  asetetaan yläasentoon.
		nodeoff(1,30,4);
		nodeon(1,5,3);		//Stoppari 5,3 menee päälle, päästäen paletin ylitseen.
		p[lukija[3]].otettu();	//Paletti kuitataan otetuksi.
		tila[10]=5;			//Tila[10]=5.
	break;
	
	case 4:
		//Tämä case ohjaa paletin kiertoon.
		nodeon(1,30,4);		//Hissi asetetaan ala-asentoon.
		nodeoff(1,30,3);
		tila[10]++;			//Tila[10] siirtyy seuraavaan caseen.
	break;
	
	case 5:
		strcpy(tilan_viesti[10],"ajastin 2s");
		// odotetaan ajastimella että hissi tyhjenee
		if(timedelay(10,4000000)) tila[10]=0; //Ajastin laskee 4000ms hissin tyhjentymistä varten, minkä jälkeen tila[10]=0.
	break;
		
	
}	

switch(tila[11]) {
	
	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		strcpy(tilan_viesti[11],"13.1, tila[9]");
	//odotetaan että tila[9] ja tila[19] ovat tyhjiä ennekuin päästetään paletti
		if(nodestate(1,13,1) && tila[9]==0 && tila[19]==1) {	//Jos induktiivinen anturi 13,1 vaikuttuu, tila[9]=0 ja tila[19]=1, niin tila[9]=1 ja tila[11] siirtyy seuraavaan caseen. 
			tila[9]=1;
			tila[11]++;
		}
	break;
	
	case 2:
		strcpy(tilan_viesti[11],"ajastin 500ms");
		nodeon(1,14,1);		//Stoppari 14,1 menee päälle, päästäen paletin ylitseen.
		nodeoff(1,14,2);	//Hissi 14,2 asetetaan ala-asentoon.
		if(timedelay(11,500000)){  //Ajastin laskee 500ms, jonka jälkeen stoppari 14,1 menee pois päältä, estäen seuraavan paletin kulun ja tila[11]=1.
			nodeoff(1,14,1);
			tila[11]=1; 
		}
	break;
}

switch(tila[12]) {
	//Hissin 21,4 lasku case 1:ssa on jäämäpaletteja varten
	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		strcpy(tilan_viesti[12],"28.2");
		if(nodestate(1,21,2))	//Jos mekaaninen anturi 21,2 vaikuttuu, asetetaan hissi 21,4 ala-asentoon.
			nodeoff(1,21,4);
		if(nodestate(1,28,2))	//Jos induktiivinen anturi 28,2 vaikuttuu, siirtyy tila[12] seuraavaan caseen.
			tila[12]++;
	break;
	
	case 2:
		strcpy(tilan_viesti[12],"21.2");
		if(nodestate(1,21,2)) {		//Jos mekaaninen anturi 21,2 vaikuttuu, asetetaan hissi 21,4 ala-asentoon ja tila[12] siirtyy seuraavaan caseen.
			nodeoff(1,21,4);
			tila[12]++;
		}
	break;
	
	case 3:
	
		strcpy(tilan_viesti[12],"ajastin 2s");
		if(timedelay(12,2000000))  tila[12]=1; //Ajastin laskee 2000ms, jonka jälkeen tila[12]=1.	
	break;	
}

switch(tila[13]) {
	
	
	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
	//odotetaan että tila[14] sekä tila[17] ovat tyhjiä ennen kuin päästetään paletti
		strcpy(tilan_viesti[13],"31.1, tila[14]");
		if(nodestate(1,31,1) && tila[14]==2 && tila[17]==1) { //Jos induktiivinen anturi 31,1 vaikuttuu, tila[14]=2 ja tila[17]=1, niin tila[14]=3 ja tila[13] siirtyy seuraavaan caseen. 
			tila[14]=3;
			tila[13]++;
		}
	break;
	
	case 2:
		strcpy(tilan_viesti[13],"ajastin 500ms");
		nodeon(1,29,3);		//Stoppari 29,3 menee päälle, päästäen paletin ylitseen.
		nodeoff(1,30,1);	//Hissi asetetaan keskiasentoon.
		nodeoff(1,30,2);
		if(timedelay(13,500000)) tila[13]++; //Ajastin laskee 500ms, jonka jälkeen tila[13] siirtyy seuraavaan caseen.
	break;
	
	case 3:
		nodeoff(1,29,3);	//Stoppari 29,3 menee pois päältä, estäen seuraavan paletin kulun.
		tila[13]=1;			//Tila[13]=1.
	break;
	
}

switch(tila[14]) {
	//caset 0-1 ovat jäämäpalettien poistoa varten ajon alussa
	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		if(nodestate(1,31,2) && tila[10]==0){	//Jos mekaaninen anturi 31,2 vaikuttuu ja tila[10]=0, niin hissi asetetaan ala-asentoon.
			nodeoff(1,30,1);
			nodeon(1,30,2);
			}
		if(timedelay(14,3000000))//Ajastin laskee 3000ms, jonka jälkeen tila[14] siirtyy seuraavaan caseen.
			tila[14]++;
	break;

	case 2:
		nodeoff(1,30,1);	//Hissi asetetaan keskiasentoon.
		nodeoff(1,30,2);
	break;
	
	case 3:
		strcpy(tilan_viesti[14],"31.2, tila[10]");
		if(nodestate(1,31,2) && tila[10]==0)	//Jos mekaaninen anturi 31,2 vaikuttuu ja tila[10]=0, niin tila[14] siirtyy seuraavaan caseen.
			tila[14]++;
	break;		
	
	case 4:
		strcpy(tilan_viesti[14],"ajastin 2s");
		nodeoff(1,30,1);	//Hissi asetetaan ala-asentoon.
		nodeon(1,30,2);
		if(timedelay(14,2000000)) //Ajastin laskee 2000ms, jonka jälkeen tila[14]=2.
			tila[14]=2;
	break;
}

switch(tila[15]) {
	case 0:
		strcpy(tilan_viesti[15],"12.1");
		nodeon(1,12,3);		//Stoppari 12,3 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,12,1))	//Jos induktiivinen anturi 12,1 vaikuttuu, siirtyy tila[15] seuraavaan caseen.
			tila[15]++;
	break;

	case 1:
		strcpy(tilan_viesti[15],"12.2");
		nodeoff(1,12,3);	//Stoppari 12,3 menee pois päältä, estäen seuraavan paletin kulun.
		if(nodestate(1,12,2))	//Jos induktiivinen anturi 12,2 vaikuttuu, on tila[15]=0.
			tila[15]=0;
	break;
}

switch(tila[16]) {
	//Case 0…2 poistaa jäämäpaletit ennenkuin tila[16] aloittaa normaalin työkierron.
	case 0:
			nodeon(1,11,3);	//Stopparit 11,3 ja 11,4 menevät päälle, päästäen paletin ylitseen.
			nodeon(1,11,4);
			nodeon(1,5,2); //Hissi 5,2 asetetaan yläasentoon.
			
	break;

	case 1:
	//Tila[20] ohjaa hissiä 5.2 jäämäpaletteja poistettaessa ajon alussa.
			switch(tila[20]) {	//Tämä tilakone ohjaa tila[16]:ta jäämäpalettien poistoa.

			case 0:
		
				if(timedelay(20,4500000)){ //Ajastin laskee 4500ms, jonka jälkeen hissi 5,2 asetetaan ala-asentoon ja stoppari 5,1 menee päälle, päästäen paletin ylitseen. Lisäksi tila[20] siirtyy seuraavaan caseen.
					resettimedelay(20);				
					nodeoff(1,5,2);
					nodeon(1,5,1);
					tila[20]++;
					}
				if(nodestate(1,4,2))	//Jos mekaaninen anturi 4,2 vaikuttuu, asetetaan hissi 5,2 yläasentoon.
					nodeon(1,5,2);	
			
			break;
		
			case 1:	
	//suljetaan tie seuraavalta paletilta, jotta hissillä oleva paletti ei puristuisi
				if(timedelay(25,500000)){	//Ajastin laskee 500ms, jonka jälkeen stoppari 5,1 menee pois päältä estäen seuraavan paletin kulun. Lisäksi tila[20]=0.
					resettimedelay(25);
					nodeoff(1,5,1);
					tila[20]=0;
					}
				
				
				
			break;
		}
		
		if(timedelay(16,40000000)) //Ajastin laskee 40000ms, jonka aikana jäämäpalettien poisto tapahtuu, minkä jälkeen tila[16] siirtyy seuraavaan caseen.
			tila[16]++;
	break;
	
	case 2:
			nodeoff(1,11,3);	//Stopparit 11,3, 11,4 ja 5,1 menevät pois päältä, estäen seuraavan paletin kulun.
			nodeoff(1,11,4);
			nodeoff(1,5,1);
			nodeoff(1,5,2);		//Hissi 5,2 asetetaan ala-asentoon.
			tila[16]=3;			//Tila[16]=3.
	break;

	case 3:
		strcpy(tilan_viesti[16],"11.1");
		nodeon(1,11,3);			//Stoppari 11,3 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,11,1))	//Jos induktiivinen anturi 11,1 vaikuttuu, tila[16] siirtyy seuraavaan caseen.
			tila[16]++;
	break;

	case 4:
		strcpy(tilan_viesti[16],"11.2");
		nodeoff(1,11,3);		//Stoppari 11,3 menee pois päältä, estäen seuraavan paletin kulun.
		if(nodestate(1,11,2))	//Jos induktiivinen anturi 11,2 vaikuttuu, siirtyy tila[16] seuraavaan caseen.
			tila[16]++;
	break;
//robotin toiminta:	
	case 5: 
		//Viive että robotti ehtii toimia
		strcpy(tilan_viesti[16],"ajastin 2s");
//testiä:
//onko tila 11.2 aktiivinen, ts. onko paletti tullut noodille
		if(nodestate(1,11,2)) {	
//koska robotti ei tiedä mikä paletti tulee pisteelle, niin katsotaan 
//millä paletilla sijainti = 2, sijainti asetetaan tila[6]:ssa			
			for (int i = 0; i <= 9; i++) {
				if (p[i].sijainti == 2) { //paletti on nyt robolla.
					//kommentoi if-lause pois jos et halua että paletti pysähtyy robolle:
					if (nodestate(2, 2, 1)) {
						//kun sr6:n työvaihe on valmis niin se kuittaa
						//noodin 2,2,1 päälle. Jolloin stopperi pois päältä ja kasvatetaan tilaa eteenpäin.
						nodeoff (1, 11, 2);
						tila[16]++;
					}
				}
			}

			/* vanha timerillä toimiva setti:
			for (int i = 0; i <= 9; i++) {
				if (p[i].sijainti == 2) {
					if (timedelay(16, 33000000)) {
					//nodeoff(1, 11, 2);
					tila[16]++;
					}
				}
			}*/
			
		}
			
/*		if(timedelay(16,2000000)) //2000ms 
			tila[16]++;	*/
	break;

	case 6:
		strcpy(tilan_viesti[16],"4.1");
		nodeon(1,11,4);	//Stoppari 11,4 menee päälle, päästäen paletin ylitseen.
		nodeoff(1,5,2); //Hissi asetetaan ala-asentoon.
		nodeon(1,5,1);	//Stoppari 5,1 menee päälle, päästäen paletin ylitseen.
		if(nodestate(1,4,1)) //Jos 4,1 on vaikuttunut, tila[16] siirtyy seuraavaan caseen.
			tila[16]++;
	break;

	case 7:
		strcpy(tilan_viesti[16],"4.2, tila[17]");
		nodeoff(1,11,4);	//Stopparit 11,4 ja 5,1 menevät pois päältä, estäen seuraavan paletin kulun.
		nodeoff(1,5,1);
		if(nodestate(1,4,2) && tila[17]==1)		//Jos mekaaninen anturi 4,2 vaikuttuu ja tila[17]=1, siirtyy tila[16] seuraavaan caseen.	
			tila[16]++;
	break;
	
	case 8: 
		strcpy(tilan_viesti[16],"ajastin 1400ms");
		nodeon(1,5,2);		//Hissi 5,2 asetetaan yläasentoon.
		if(timedelay(16,1400000)) tila[16]=3; //Ajastin laskee 1400ms, jonka jälkeen tila[16]=3.
	break;
}

switch(tila[17]) {

	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		strcpy(tilan_viesti[17],"31.1, tila[14]");
		if(nodestate(1,31,3) && tila[14]==2)	//Jos induktiivinen anturi 31,3 aktivoituu ja tila[14]=2, siirtyy tila[17] seuraavaan caseen.
			tila[17]++;
	break;
	
	case 2:
		strcpy(tilan_viesti[17],"31.2");
		nodeon(1,29,4);		//Stoppari 29,4 menee päälle, päästäen paletin ylitseen.
		nodeon(1,30,1);		//Hissi asetetaan yläasentoon.
		nodeoff(1,30,2);	
		tila[14]=3;			//Tila[14]=3.
		if(timedelay(17,500000)){		//Ajastin laskee 500ms, jonka jälkeen stoppari 29,4 menee pois päältä, estäen seuraavan paletin kulun ja tila[17] siirtyy seuraavaan caseen. 
			nodeoff(1,29,4);
			tila[17]++;
			}
	break;

	case 3:
		
		if(nodestate(1,31,2))	//Jos mekaaninen anturi 31,2 vaikuttuu, on tila[17]=1.
			tila[17]=1;
	break;


}

switch(tila[18]) {

	//Case 0…2 poistaa jäämäpaletit ennen kuin tila[18] aloittaa normaalin työkierron.
	case 0:
			nodeon(1,18,3);		//Stopparit 18,3 ja 18,4 menevät päälle, päästäen paletin ylitseen.
			nodeon(1,18,4);
			nodeon(1,15,4);		//Hissi 15,4 asetetaan yläasentoon.
	break;

	case 1:
	//Tila[21] ohjaa hissiä 15.4, jäämäpaletteja poistettaessa ajon alussa tässä casessa.
			switch(tila[21]) {	//Tämä tilakone ohjaa tila[18]:ta jäämäpalettien poistoa.

			case 0:
				if(timedelay(21,4500000)){	//Ajastin laskee 4500ms, jonka jälkeen hissi 15,4 asetetaan ala-asentoon ja stoppari 15,3 menee päälle, päästäen paletin ylitseen. Lisäksi tila[21] siirtyy seuraavaan caseen.
					resettimedelay(21);				
					nodeoff(1,15,4);
					nodeon(1,15,3);
					tila[21]++;
					}
				if(nodestate(1,15,2))	//Jos mekaaninen anturi 15,2 vaikuttuu, asetetaan hissi 15,4 yläasentoon.
					nodeon(1,15,4);	
			
			break;
		
			case 1:	
			//suljetaan tie seuraavalta paletilta, jotta hissillä oleva paletti ei puristu. 
				if(timedelay(21,500000)){ //Ajastin laskee 500ms, jonka jälkeen stoppari 15,3 menee pois päältä estäen seuraavan paletin kulun. Lisäksi tila[21]=0.
					resettimedelay(21);
					nodeoff(1,15,3);
					tila[21]=0;
					}
				
				
				
			break;
		}

		if(timedelay(18,45000000)) //Ajastin laskee 45000ms, jonka aikana jäämäpalettien poisto tapahtuu. Lisäksi tila[18] siirtyy seuraavaan caseen.
			tila[18]++;
		break;


	case 2:
		nodeoff(1,18,3);	//Stopparit 18,3, 18,4 ja 15,3 menevät pois päältä, estäen seuraavan paletin kulun.
		nodeoff(1,18,4);
		nodeoff(1,15,3);
		nodeoff(1,15,4);	//Hissi 15,4 asetetaan ala-asentoon.
		tila[18]=3;			//Tila[18]=3.
	break;

	case 3:
		strcpy(tilan_viesti[18],"18.1");
		nodeon(1,18,3);		//Stoppari 18,3 menee päälle, päästäen paletin ylitseen.
		nodeoff(1,15,4);	//Hissi 15,4 asetetaan ala-asentoon.
		if(nodestate(1,18,1)) //Jos induktiivinen anturi 18,1 aktivoituu, siirtyy tila[18] seuraavaan caseen.
			tila[18]++;
	break;
	
	case 4:
		//Viive robotin toimintaa varten
		strcpy(tilan_viesti[18],"ajastin 2s");
		nodeoff(1,18,3);	//Stoppari 18,3 menee pois päältä, estäen seuraavan paletin kulun.
//testiä:
		//paletti robolla n+1 s.
		if(nodestate(1, 18, 2)) {
			for (int i = 0; i <= 9; i++) {	//tsekataan millä paletilla sijainti ==3
				if (p[i].sijainti == 3) {	//sijainti asetetaan rfid:llä 3, tila[10].
					if (timedelay(16, 33000000))
						tila[18]++;
				}
			}
		}
		
		/*if(timedelay(18,2000000)) //Ajastin laskee 2000ms, jonka jälkeen tila[18] siirtyy seuraavaan caseen.
			tila[18]++;
		*/
	break;
	
	case 5:	
		strcpy(tilan_viesti[18],"15.2");
		nodeon(1,18,4);		//Stoppari 18,4 ja 15,3 menevät päälle, päästäen seuraavan paletin ylitseen.
		nodeon(1,15,3);
		if(nodestate(1,15,2) && tila[19]==1)	//Jos mekaaninen anturi 15,2 aktivoituu ja tila[19]=1, siirtyy tila[18] seuraavaan caseen.
			tila[18]++;
	break;
	
	case 6:
		strcpy(tilan_viesti[18],"ajastin 2s");
		nodeon(1,15,4);		//Hissi 15,4 asetetaan yläasentoon.
		nodeoff(1,18,3);	//Stopparit 18,3, 18,4 ja 15,3 menevät pois päältä, estäen seuraavan paletin kulun.
		nodeoff(1,18,4);
		nodeoff(1,15,3);

		if(timedelay(18,2000000))  //Ajastin laskee 2000ms, jonka jälkeen tila[18]=3.
			tila[18]=3;
	break;
}

switch(tila[19]) {

	case 0:
	//Tämä tyhjä case on anturin toiminnan parantamiseksi, jos anturilla on paletti ajon alussa.
	break;

	case 1:
		strcpy(tilan_viesti[19],"13.3, tila[9]");
		if(nodestate(1,13,3) && tila[9]==0) {	//Jos induktiivinen anturi 13,3 aktivoituu ja tila[9]=0, niin tila[19] siirtyy seuraavaan caseen.
			tila[19]++;
		}
	break;
	
	case 2:
		strcpy(tilan_viesti[19],"ajastin 500ms");
		nodeon(1,14,3);		//Stoppari 14,3 aktiovoituu, päästäen paletin ylitseen.
		nodeon(1,14,2);		//Hissi 14,2 asetetaan yläasentoon.
		tila[9]=1;			//Tila[9]=1
		if(timedelay(19,500000)){ //Ajastin laskee 500ms, jonka jälkeen stoppari 14,3 menee pois päältä, estäen seuraavan paletin kulun ja tila[19]=1.
			nodeoff(1,14,3);
			tila[19]=1; 
		}
	break;
	
	case 3:
		strcpy(tilan_viesti[19],"ajastin 1500ms");
		if (nodestate(1,13,2))	//Jos mekaaninen anturi 13,2 vaikuttuu, niin tila[19]=1.
			tila[19]=1;
	break;
}



// Printataan tilakoneiden ja palettien tilat 
VT100::goxy(0,0);

for(int i=0;i<=19;i++) 
	printf("Tila[%d]: %d  ,Viesti :%s\n", i, tila[i],tilan_viesti[i]);

for(int i=1;i<=12;i++)
	printf("Paletti[%d]:  Kohde: %d  Kierrokset: %d Aktiivinen :%i\n",i,p[i].kohde(),p[i].kierros(),p[i].aktiivisuus());

// Printataan RFID-lukijoiden tilat
for(int i=1;i<=3; i++) printf("Lukija[%d]: %d \n",i, lukija[i]);

// Printataan ohjelman nopeus
if(!timedelay(31,1000000)) laskuri++;
else { printf("%d kierrosta/s\n",laskuri); laskuri=0;}

}
// Hoidetaan CAN-kommunikaatio
// Lähetetään kaikki RPDOt joiden tilat ovat muuttuneet
can.send_only_changed_rpdos();
can.sync();

// Käydään lukemassa kaikki meille lähtetyt CAN viestit.
// Nukumme hetken kierrosten välissä jos ei useita samoja TDPO paketteja.
// Jos on samoja käsittelemme ne heti uudestaan jotta eivät jää puskuriin ja käsittelemättä.
can.read_all_messages();
u_sleep(4000);

} 
while(!key(VK_ESCAPE)); // ESC näppäimen painallus lopettaa ohjelman suorituksen


VT100::clearscreen();
printf("\nSystem Shutdown !\n");
printf("Wait a few seconds for all devices to go down !\n");

// Ohjelma lopetaan.
// Asetetaan kaikki outputit nollatilaan. 
// Nollataan kaikki outputit yksi kerrallaan pienin väliajoin jotta ei tule sähköpiikkiä
for (int i=1 ; i<32 ; i++ )
	for (int j=1 ; j<5 ; j++ ) {
		if (nodestate(1,i,j)) { // Jos nodeon päällä niin
			nodeoff(1,i,j); // Node pois päältä
			can.send_only_changed_rpdos();
			u_sleep(100000);//ennen 100000
		}
	}
u_sleep(10000);
can.stop_node(0); // Lähetetään CAN-väylälle stop-paketti kaikille nodeille jolloin noodit menevät stopped tilaan
	
	} //if
	else
		VT100::clearscreen();
		printf("\n\n\n\n\n\n\n\n\n\n\t\t\tYou ended the program..");
		u_sleep(1000000);
	

//} while (valinta != 9);
/*//ehkis maailman hienoin "efekti"
printf("\n\n You ended the production line program. The application will now close");
for (int i = 0; i < 2; i++) {
	printf(".");
	u_sleep(1000000);
}*/
#ifdef LINUX
	VT100::terminalreset();
#endif // !LINUX

fclose(pFile);
//suljetaan avattu tiedosto

decoder_closelog();
}




// *********************
// Globaalit apufunkiot
// *********************

//testiä:
// Asetetaan palettien reitit
void reittien_alustus() {
        p[1].aktivoi();
        p[2].aktivoi();
        p[3].aktivoi();
        p[4].aktivoi();
        p[5].aktivoi();
        p[6].aktivoi();
        p[7].aktivoi();
        p[8].aktivoi();
        p[9].aktivoi();
        p[10].aktivoi();
        p[11].aktivoi();
        p[12].aktivoi();

        p[1].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[2].aseta_reitti(0,0,0,0,0,1,0,0,0,0);
        p[3].aseta_reitti(0,0,0,0,1,0,1,0,0,0);
        p[4].aseta_reitti(2,1,0,0,0,0,0,0,0,0);
        p[5].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[6].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[7].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[8].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[9].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[10].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[11].aseta_reitti(0,0,0,0,0,0,0,0,0,0);
        p[12].aseta_reitti(0,0,0,0,0,0,0,0,0,0);

//asetetaan robojen tyovaiheet:
	p[1].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[2].aseta_tyovaihe(0,0,0,0,1,0,0,1,0,0);
	p[3].aseta_tyovaihe(0,0,0,0,0,0,1,0,1,0);
	p[4].aseta_tyovaihe(1,2,3,2,0,0,0,0,0,0);
	p[5].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[6].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[7].aseta_tyovaihe(0,0,0,0,1,0,0,1,0,0);
	p[8].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[9].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[10].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[11].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	p[12].aseta_tyovaihe(0,0,0,0,0,0,0,0,0,0);
	

        p[1].aseta_kierrosten_maara(2);
        p[2].aseta_kierrosten_maara(2);
        p[3].aseta_kierrosten_maara(2);
        p[4].aseta_kierrosten_maara(1);
        p[5].aseta_kierrosten_maara(2);
        p[6].aseta_kierrosten_maara(2);
        p[7].aseta_kierrosten_maara(2);
        p[8].aseta_kierrosten_maara(1);
        p[9].aseta_kierrosten_maara(2);
        p[10].aseta_kierrosten_maara(2);
        p[11].aseta_kierrosten_maara(2);
        p[12].aseta_kierrosten_maara(2);

		//laiskan miehen kierros lkm asetus, kommentoi jos et käytä
/*		for (int i = 1; i <= 12; i++) {
			p[i].aseta_kierrosten_maara(1);
			//i++;
		}*/
}

// ***************************************************
// Funktiot Noodien tilan asettamiseen ja tutkimiseen
// ***************************************************

//ottavat vastaan cannoodin (1 tai 2), slave, bitti

//asetetaan haluttu noodi päälle:
void nodeon(int CANnode, int slave, int bitti) {
	if (CANnode == 1) {
		if ((slave >= 1 && slave <= 31) && (bitti >= 1 && bitti <= 4)) {
			if (slave < 16) {
				if (slave &1)
					rpdo201.set_bit((slave - 1) * 4 + bitti - 1);
				else
					rpdo201.set_bit((slave + 1) * 4 + bitti - 1);
			}
			else {
				if (slave &1)
					rpdo301.set_bit((slave - 17) * 4 + bitti - 1);
				else
					rpdo301.set_bit((slave - 15) * 4 + bitti - 1);
			}
		}

	}	
	else if (CANnode == 2) {
		if ((slave >= 1 && slave <= 31) && (bitti >= 1 && bitti <= 4)) {
			if (slave <16) {
				if (slave &1)
					rpdo202.set_bit((slave -1) * 4 + bitti - 1);
				else
					rpdo202.set_bit((slave + 1) * 4 + bitti - 1);
			}
			else {
				//outputteja 16-31 ei ole.
			}
		}
	}

}

//sammutetaan haluttu noodi:
void nodeoff(int CANnode, int slave, int bitti) {
	if (CANnode == 1) {
		if((slave >= 1 && slave <= 31) && (bitti >= 1 && bitti <= 4)) {
			if (slave < 16) {
				if (slave &1)
					rpdo201.clear_bit((slave - 1) * 4 + bitti - 1);
				else
					rpdo201.clear_bit((slave + 1) * 4 + bitti - 1);
			}
			else {
				if (slave &1)
					rpdo301.clear_bit((slave - 17) * 4 + bitti - 1);
				else
					rpdo301.clear_bit((slave - 15) * 4 + bitti - 1);	
			}
		}
	}
	else if (CANnode == 2) {
		if ((slave >= 1 && slave <= 31) && (bitti >= 1 && bitti <= 4)) {	//joku mättää jossain koska virhe tulee '>=' kohdasta..
			if (slave < 16) {
				if (slave &1)
					rpdo202.clear_bit((slave - 1) * 4 + bitti - 1);
				else
					rpdo202.clear_bit((slave + 1) * 4 + bitti - 1);
			}
			else {
				//outputteja 16-31 ei ole
			}
		}
	}
}

//tarkistetaan halutun noodin inputin tila:
bool nodestate(int CANnode, int slave, int bitti) {
	bool retval;
	if (CANnode == 1) {
		if (slave < 16) {
			if (slave &1)
				retval = tpdo181.get_bit((slave - 1) * 4 + bitti - 1);
			else
				retval = tpdo181.get_bit((slave + 1) * 4 + bitti - 1);
		}
		else {
			if (slave &1)
				retval = tpdo281.get_bit((slave - 17) * 4 + bitti - 1);
			else
				retval = tpdo281.get_bit((slave - 15) * 4 + bitti - 1);
		}
		return(retval);
	}
	else if (CANnode == 2) {
		if (slave < 16) {
			if (slave &1)
				retval = tpdo182.get_bit((slave - 1) * 4 + bitti - 1);
			else
				retval = tpdo182.get_bit((slave + 1) * 4 + bitti - 1);
		}
		else {
			//inputteja 16-31 ei ole
		}
		return(retval);
	}	
}


//!vanhat node-funktiot!!!! (ennen 15.4)

/*
// Asete3tetaan jokin noodi päälle
// Parametreina ASI slaven numero ja slaven outputin numero 1-4
void nodeon(int ASiMasterID,int slave, int bitti) {
	if(ASiMasterID==1)
	{	
		if((slave>=1 && slave<=31) && (bitti>=1 && bitti<=4)) { 
			if(slave<16) {
				if(slave &1)
					rpdo201.set_bit((slave-1) * 4 + bitti -1);
				else 
					rpdo201.set_bit((slave+1) * 4 + bitti - 1);
			}
			else {
				if(slave &1)
					rpdo301.set_bit((slave-17) * 4 + bitti - 1);
				else
					rpdo301.set_bit((slave-15) * 4 + bitti - 1);
			}
		}
	}
	else if(ASiMasterID==2)
	{	
		if((slave>=1 && slave<=31) && (bitti>=1 && bitti<=4)) { 
			if(slave<16) {
				if(slave &1)
					rpdo401.set_bit((slave-1) * 4 + bitti -1);
				else 
					rpdo401.set_bit((slave+1) * 4 + bitti - 1);
			}
			else { 	//kommentoi-->
				if(slave &1)
					rpdo302.set_bit((slave-17) * 4 + bitti - 1);
				else
					rpdo302.set_bit((slave-15) * 4 + bitti - 1);
				//<---kommentoi
			}
		}
	}
}
*/

/*
// Asetetetaan jokin noodi pois päältä
// Parametreina ASI slaven numero ja slaven outputin numero 1-4
void nodeoff(int ASiMasterID,int slave, int bitti) {
	if(ASiMasterID==1)
	{

		if((slave>=1 && slave<=31) && (bitti>=1 && bitti<=4)) { 
			if(slave<16) {
				if(slave &1)
					rpdo201.clear_bit((slave-1) * 4 + bitti -1);
				else 
					rpdo201.clear_bit((slave+1) * 4 + bitti - 1);
			}
			else {
				if(slave &1)
					rpdo301.clear_bit((slave-17) * 4 + bitti - 1);
				else
					rpdo301.clear_bit((slave-15) * 4 + bitti - 1);
			}
		}
	}
	else if(ASiMasterID==2)
	{

		if((slave>=1 && slave<=31) && (bitti>=1 && bitti<=4)) { 
			if(slave<16) {
				if(slave &1)
					rpdo401.clear_bit((slave-1) * 4 + bitti -1);
				else 
					rpdo401.clear_bit((slave+1) * 4 + bitti - 1);
			}
			else {	//kommentoi-->
				if(slave &1)
					rpdo302.clear_bit((slave-17) * 4 + bitti - 1);
				else
					rpdo302.clear_bit((slave-15) * 4 + bitti - 1);
					//<---kommentoi
			}
		}
	}

}
*/
/* 
// tarkistetaan halutun noodin inputin tila
// Parametreina ASI slaven numero ja slaven outputin numero 1-4
bool nodestate(int ASiMasterID,int slave, int bitti) { 
	bool retval;
	if(ASiMasterID==1)
	{
		if(slave<16) {
			if(slave &1)
				retval=tpdo181.get_bit((slave-1) * 4 + bitti -1);
			else 
				retval=tpdo181.get_bit((slave+1) * 4 + bitti - 1);
		}
		else {
			if(slave &1)
				retval=tpdo281.get_bit((slave-17) * 4 + bitti - 1);
			else
				retval=tpdo281.get_bit((slave-15) * 4 + bitti - 1);
		}
		return(retval);
	}
 //vanha-->
	else if (ASiMasterID==2)
	{
		if(slave<16) 
		{
			if(slave &1)
				retval=tpdo381.get_bit((slave-1) * 4 + bitti -1);
			else 
				retval=tpdo381.get_bit((slave+1) * 4 + bitti - 1);
		}
		else { //kommentoi -->
			if(slave &1)
				retval=tpdo281.get_bit((slave-17) * 4 + bitti - 1);
			else
				retval=tpdo281.get_bit((slave-15) * 4 + bitti - 1); // <--- kommentoi
		} 
	return(retval);	
	}//else if 
}
*/


{code}