// 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 } */