136
Gestió d’una Unitat d’Emmagatzematge integrada en una Cèl·lula de Fabricació Flexible TITULACIÓ: Enginyeria Tècnica Industrial en Electrònica Industrial AUTOR: Juan David Roig Mauri. DIRECTOR: Esteban del Castillo Pérez. DATA: setembre de 2006.

Gestió d’una Unitat d’Emmagatzematge integrada en una Cèl ...deeea.urv.cat/public/PROPOSTES/pub/pdf/740pub.pdf · Esquema general de la Cèl·lula de Fabricació Flexible •

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Gestió d’una Unitat d’Emmagatzematge integrada en una Cèl·lula de Fabricació Flexible

TITULACIÓ: Enginyeria Tècnica Industrial en Electrònica Industrial

AUTOR: Juan David Roig Mauri. DIRECTOR: Esteban del Castillo Pérez.

DATA: setembre de 2006.

1 Índex

3

2 Memòria .................................................................................................................. 7

2.1 Introducció ....................................................................................................... 8

2.1.1 Situació i Emplaçament............................................................................. 8

2.1.2 Titular, Autor i Director ............................................................................ 9

2.2 Objectiu............................................................................................................ 9

2.3 Descripció de la Cèl·lula de Fabricació Flexible ............................................ 10

2.4 Descripció de la Unitat d’Emmagatzematge .................................................. 12

2.5 Descripció del bus PROFIBUS...................................................................... 14

2.5.1 Introducció al Busos de Camp................................................................. 14

2.5.2 Característiques Bàsiques del PROFIBUS.............................................. 15

2.5.3 Protocols i Dispositius de SIMATIC pel PROFIBUS............................. 15

2.6 PLC Simatic S7-300....................................................................................... 16

2.7 Targeta de Comunicacions CP 5613 .............................................................. 16

2.8 Comunicació amb el sistema SCADA ........................................................... 17

2.8.1 Mode de comunicació amb el sistema SCADA ...................................... 17

2.8.2 Elecció del protocol d’accés al PLC S7-300 ........................................... 18

2.8.2.1 Protocol Fieldbus Message Specification (FMS) ............................. 18

2.8.2.2 Protocol S5 ....................................................................................... 18

2.8.2.3 Protocol S7 ....................................................................................... 18

2.9 Implementació amb Visual C++ de la Comunicació amb l’SCADA............. 19

2.9.1 Ole for Process Control (OPC)................................................................ 19

2.9.1.1 Introducció ........................................................................................ 19

2.9.1.2 Objectes COM.................................................................................. 20

2.9.1.3 OPC-DA (OPC Data Access)........................................................... 22

2.9.1.4 OPC en SIMATIC NET ................................................................... 24

2.9.2 Comunicació amb el protocol S7 utilitzant OPC..................................... 25

2.9.2.1 Serveis per comunicacions en el protocol S7 ................................... 25

2.9.2.2 Serveis de variables S7 en un servidor OPC .................................... 26

2.9.2.3 Sintaxi de la Connexió entre el Servidor OPC i la el PLC ............... 26

2.9.3 Creació d’una connexió S7 amb el servidor OPC de SIMATIC NET...... 28

2.9.3.1 Software SIMATIC necessari........................................................... 28

2.9.3.2 Configuració inicial.......................................................................... 28

2.9.3.3 Creació d’un projecte amb la utilitat SIMATIC Manager ................ 29

2.9.3.4 Traspàs de la xarxa creada cap al PC amb “Station Configurator”... 33

4

2.9.4 Elecció del tipus d’accés (sincrón/asíncron) a la memòria del PLC........ 34

2.9.4.1 Accés síncron ................................................................................... 34

2.9.4.2 Accés asíncron.................................................................................. 34

2.9.4.3 Elecció de l’accés Síncron................................................................ 35

2.9.5 Codi Visual C++ per accés Síncron a la memòria del PLC..................... 35

2.9.5.1 Seqüència d’operacions per realitzar l’accés .................................... 35

2.9.5.2 Creació i configuració d’objectes OPC ............................................ 36

2.9.5.3 Lectura o escriptura de valor de memòria ........................................ 39

2.9.5.4 Esborrat del objectes OPC i alliberament de recursos...................... 40

2.10 Codificació de la comunicació amb el sistema SCADA .............................. 40

2.10.1 Funcionament de la entrada i sortida de palets del magatzem.............. 40

2.10.2 Codificació del diferents tipus de palets ................................................ 41

2.10.3 Utilització de la memòria del PLC en la comunicació amb l’SCADA.. 43

2.10.4 Actuadors de la CFF controlats pel magatzem...................................... 44

2.10.4.1 Sensor d’arribada de palet .............................................................. 44

2.10.4.2 Topall per parar el palet................................................................. 44

2.10.4.3 Fixador del palet............................................................................. 44

2.11 Software de control de magatzem ................................................................ 45

2.11.1 Funcions per interactuar amb el magatzem ........................................... 45

2.11.2 Incorporació del software de control al software de gestió ................... 46

2.12 Gestió del magatzem.................................................................................... 46

2.12.1 Diagrama de Flux del Funcionament General del Magatzem................ 47

2.12.2 Bloc d’Inicialització .............................................................................. 48

2.12.2.1 Inicialització de variables global .................................................... 48

2.12.2.2 Comprovació de fitxer de dades ..................................................... 48

2.12.2.3 Inicialització OPC .......................................................................... 49

2.12.2.4 Traspàs del Contingut del Magatzem al PLC................................. 50

2.12.3 Bloc de Recepció i Lliurament de Palets ............................................... 51

2.12.4 Bloc d’Accions Automàtiques............................................................... 54

2.13 Interfície d’usuari ......................................................................................... 56

2.14 Resum del pressupost................................................................................... 57

2.15 Bibliografia .................................................................................................. 58

3 Pressupost ............................................................................................................. 59

3.1 Consideracions inicials................................................................................... 60

3.2 Preus unitaris .................................................................................................. 60

5

3.2.1 Material ................................................................................................... 60

3.2.2 Mà d’Obra ............................................................................................... 60

3.3 Descomposició de tasques.............................................................................. 61

3.4 Descomposició del projecte ........................................................................... 62

3.4.1 Creació d’Interfície d’Usuari.................................................................... 62

3.4.2 Comunicació amb el sistema SCADA..................................................... 62

3.4.3 Gestió del Magatzem............................................................................... 63

3.5 Resum del pressupost..................................................................................... 64

4 Plec de Condicions................................................................................................ 65

4.1 Generalitats ..................................................................................................... 66

4.1.1 Condicions Generals ............................................................................... 66

4.1.2 Reglaments i Normativa ........................................................................... 66

4.1.3 Execució del Programa............................................................................. 66

4.1.3.1 Inici ................................................................................................... 66

4.1.3.2 Termini d’execució ........................................................................... 66

4.1.4 Interpretació i Desenvolupament del Programa ....................................... 67

4.1.5 Treballs Complementaris ......................................................................... 67

4.1.6 Modificacions........................................................................................... 67

4.1.7 Programa Defectuós ................................................................................. 68

4.1.8 Mitjans Auxiliars...................................................................................... 68

4.1.9 Conservació del Programa........................................................................ 68

4.1.10 Recepció del Programa........................................................................... 68

4.1.10.1 Recepció provisional. ...................................................................... 68

4.1.l0.2 Llicència i drets ................................................................................ 68

4.1.10.3 Termini de garantia ......................................................................... 69

4.1.10.4 Recepció Definitiva ......................................................................... 69

4.1.11 Contractació de l’Empresa Programadora.............................................. 69

4.1.11.1 Mode de Contractació ..................................................................... 69

4.1.11.2 Presentació ...................................................................................... 69

4.1.11.3 Selecció ........................................................................................... 69

4.1.12 Fiança ..................................................................................................... 70

4.2 Condicions Econòmiques................................................................................ 70

4.2.1 Pagament del Programa............................................................................ 70

4.2.2 Preus......................................................................................................... 70

4.2.3 Revisió de Preus....................................................................................... 71

6

4.2.4 Penalitzacions........................................................................................... 71

4.2.5 Contracte .................................................................................................. 71

4.2.6 Responsabilitats........................................................................................ 71

4.2.7 Rescissió del Contracte ............................................................................ 72

4.2.7.1 Causes de Rescissió........................................................................... 72

4.2.8 Liquidació en el cas de Rescissió del Contracte ....................................... 72

4.3 Conclusions..................................................................................................... 73

5 Annexes................................................................................................................. 74

7

2 Memòria

2 Memòria

8

2.1 Introducció

El present projecte es composa dels següents apartats: Memòria, Pressupost, Plec de Condicions, Manual d’Usuari i Annexes.

- A la Memòria Descriptiva es realitza una descripció de tots els elements que han intervingut en la realització del projecte. També s’ha realitzat una explicació de les alternatives estudiades i de la solució adoptada en la realització del projecte. Així com un descripció detallada del funcionament del programa.

- Al Pressupost es realitza una valoració econòmica de la realització del projecte.

- El Plec de Condicions és el document on s’estableixen les condicions administratives, econòmiques, facultatives i tècniques per la realització del present projecte.

- El Manual d’Usuari presenta una manual per poder utilitzar el programa realitzat en el projecte.

- En els Annexes es mostra tot codi de programa realitzat, així com un manual del software de suport utilitzat en el projecte.

2.1.1 Situació i Emplaçament

El projecte ha estat realitzat al laboratori 113, dins les instal·lacions de la Escola Tècnica Superior d’Enginyeria de la Universitat Rovira i Virgili de Tarragona, ubicades al Campus Sescel·lades, amb adreça Av. Països Catalans 26 de Tarragona, CP: 43007. Telf. Secretaria: 977 559 708, Telf. Consergeria: 977 559 699

Figura 1. Imatge de la Cèl·lula de Fabricació Flexible

2 Memòria

9

2.1.2 Titular, Autor i Director

El titular del projecte és la Universitat Rovira i Virgili de Tarragona; amb adreça a C/ Escorxador, s/n de Tarragona (CP: 43003). Telèfon 977 588000 y Fax 977 588022.

L’autor del projecte és David Roig Mauri amb NIF: 52605217-P i amb domicili a Hernandez Sanahuja 15 7è 1à de Tarragona amb CP 43002

El director del projecte és Esteban del Castillo Pérez amb adreça a l’Escola Tècnica Superior d’Enginyeria de la Universitat Rovira i Virgili de Tarragona; situada al Campus Sescel·lades; amb adreça: Av. Països Catalans núm. 26; CP 43007 de Tarragona. Telèfon 977 559628.

2.2 Objectiu

L’objectiu del present projecte es la realització d’un software, les funcions del qual seran gestionar un magatzem, que està integrat en una Cèl·lula de Fabricació Flexible (CFF) i resoldre la comunicació amb el sistema SCADA que la controla, utilitzant el bus de comunicacions industrials PROFIBUS.

L’aplicació s’ha realitzat amb l’entorn de programació Microsoft Visual C++.

En el següent esquema es pot veure com estan connectats els components que intervenen en el projecte:

3/ &�6

( 7 6 ( 7 6 ( 7 6 ( 7 6 ( 7 6

&LQWD�WUDQVSRUWDGRUD

6ODYHV

0 DVWHU�6&$' $

0 DJDW] HP

3&�JHVWLy�6&$ ' $�DP E�&3

3&�JHVWLy�0 DJDW] HP �DP E�&3�

3URILEXV

3URILEXV

3URILEXV

&RQWURO�0 DJDW] HP

Figura 2. Esquema de connexió dels elements que intervenen en el projecte

2 Memòria

10

El sistema SCADA està format per un PLC S7-300 de Siemens que fa de mestre, una sèrie d’estacions ET que són esclaus i un PC que executa el software que ho gestiona. Tots aquest components comunicats mitjançant Profibus.

El PC que s’encarregarà de executar el software de gestió realitzat en el present projecte es comunica amb el sistema SCADA a través del PROFIBUS mitjançant la targeta de comunicacions SIMATIC CP 5613 de Siemens. El programa de gestió tindrà un comportament d’esclau dintre del sistema SCADA, es a dir rebrà ordres de les peces que ha d’emmagatzemar o lliurar i en cap moment ho podrà fer sense l’ordre prèvia del SCADA. En quant a l’organització interna del magatzem aquesta serà exclusiva del software de gestió del magatzem i no hi haurà cap intervenció del sistema SCADA.

Per altra banda, PC que gestiona el magatzem està connectat amb el magatzem a traves d’una targeta i una circuiteria li proporciona el control sobre aquest a través d’un software realitat amb Visual C++.

Finalment, el magatzem està comunicat amb la CFF mitjançant una cinta transportadora per la qual entraran i sortiran del magatzem les peces fabricades.

Per aconseguir l’objectiu del projecte s’han realitzats el següents passos:

- Coneixement del funcionament de tots el elements que hi intervenen, es a dir el bus PROFIBUS, la targeta de comunicacions CP 5613, el PLC S7-300 i el magatzem

- Resolució de la comunicació amb el sistema SCADA, a la seva implementació amb Visual C++.

- Codificació de la comunicació amb el sistema SCADA. Aquesta codificació s’ha realitzat conjuntament amb l’Enginyer Tècnic que realitza el projecte de gestió d’aquest sistema SCADA.

- Creació del software de gestió del magatzem amb una interfície d’ús amigable, mitjançant Visual C++. Aquest sofware incorpora les funcions de control del magatzem que han estat realitzades per l’Enginyer que ha realitzat el software de control del magatzem.

2.3 Descripció de la Cèl·lula de Fabricació Flexible

La CFF té com funcions realitzar la fabricació, verificació, classificació y emmagatzematge de cilindres pneumàtics de simple efecte.

Està composada de tres mòduls principals, com es pot veure en el següent esquema:

2 Memòria

11

Mòdul de Producció Mòdul d’Enllaç Mòdul d’Emmagatzematge

Figura 3. Esquema general de la Cèl·lula de Fabricació Flexible

• Mòdul de Producció

En aquest mòdul s’efectua la producció de cilindres de simple efecte amb retorn per molla. Primer s’identifiquen i s’introdueixen les camises al sistema; després són dipositades en un palet damunt d’una cinta transportadora que connecta els quatre submòduls. Després s’introdueixen l’èmbol corresponent i la molla; tot seguit és tapa amb una culata amb tancament mitjançant baioneta. Per últim, es verifica que el conjunt està correctament muntat.

Els cilindres que es fabricaran seran de tres tipus depenent del color i material de la camisa que s’ha utilitzat per fabricar-los, cilindres negres, vermells o metàl·lics.

Figura 4. Composició del cilindres fabricats

• Mòdul d’Enllaç

Un cop s’ha comprovat que el conjunt és correcte, es transporta cap a una estació en que es farà la seva identificació, classificació i emmagatzematge, fins que arribi la ordre de treball que indiqui el tipus de cilindre que cal subministrar.

2 Memòria

12

• Mòdul d’Emmagatzematge

Per últim, amb els cilindres procedents del mòdul d’enllaç es procedeix a la formació de palets de 1, 2 o 3 cilindres cadascun segons les ordres de treball assignades. Dins d’aquest mòdul tenim dues parts; la primera que forma els palets de 3 i la segona que és el magatzem on es guardaran el palets.

Figura 5. Imatge d’un palet amb cada un del 3 tipus de cilindres

2.4 Descripció de la Unitat d’Emmagatzematge

Aquesta unitat s’encarregarà d’emmagatzemar el palet fabricats pel mòdul de producció, que li arribaran a través de la cinta transportadora.

Figura 6. Imatge frontal del magatzem

2 Memòria

13

El magatzem està format per els següents elements:

• Dos panells de 36 caselles (6 files i 6 columnes) col·locats un en front l’altre. En total hi ha 72 caselles cada una del les quals pot emmagatzemar un palet.

Figura 7. Imatge d’un dels panells de 36 caselles

• Un capçal que està situat entre el dos panells de caselles, i es l’encarregat de desplaçar els palets en el magatzem. Aquest capçal es mogut per dos motors, un pel moviment de l’eix X i l’altre per l’eix Y, i es pot situar en qualsevol casella de cada panell. Esta format per una safata amb moviment horitzontal que és l’encarregada de recollir i deixar el palets a cada casella, així com a la unitat de recollida de palets.

Figura 8. Capçal utilitzat per desplaçar el palets dintre del magatzem

• Safata de recollida i lliurament de palets. S’encarrega de recollir o lliurar el palets a la cinta transportadora. El capçal hi te accés per tal d’agafar o deixar el palets.

2 Memòria

14

Figura 9. Imatge de la safata de recollida i lliurament de palets

• Panell de control. Està format per dues parts:

- Armari de connexions. On esta situades les dues fonts d’alimentació que utilitza el magatzem. També hi ha connectada la unitat externa que acondiciona la informació per als encoders del motors dels eixos X i Y de capçal, i que permet que el control del elements del magatzem es pugui fer des de un PC.

- Botonera de control. Hi ha una sèrie de botons per aturar i tornar a activar el funcionament del capçal , així com dues llums que indiquen si el sistema té alimentació o no.

Figura 10. Imatge del armari de connexions i la botonera de connexions

2.5 Descripció del bus PROFIBUS

2.5.1 Introducció al Busos de Camp

Actualment, les comunicacions són una part important en els sistemes de producció, en els que les xarxes industrials són una peça clau. En entorns industrials, els requisits de comunicacions són més restrictius quan s’està més a prop del procés. En les tasques d’adquisició de dades, el bus de camp (field bus) ha estat una revolució en contraposició a les tècniques de cablejat punt a punt. Els busos de camp, avui en dia, són emprats com a sistema de comunicació per intercanviar informació entre els sistemes d’automatització i dispositius de camp distribuïts.

2 Memòria

15

2.5.2 Característiques Bàsiques del PROFIBUS

PROFIBUS és un estàndard internacional per als nivells de cèl·lula i camp ( bus de camp), amb un elevat grau d’implementació. És una de les solucions més versàtil i flexible, emprada en una àmplia diversitat de processos productius. Compleix les normes internacionals EN 50170 i EC 61158.

PROFIBUS és un sistema de comunicacions industrial obert, indicat per a un ampli rang d’aplicacions a entorns de fabricació, processos i automatització. Ha estat desenvolupat sobre la base del model ISO/OSI (International Standards Organization / Open System Interconnect) per a serveis de comunicació de dades.

2.5.3 Protocols i Dispositius de SIMATIC pel PROFIBUS

Podem trobar dos tipus d’us del PROFIBUS per la comunicació de camp o procés, i per la comunicació de dades. En aquest projecte només s’utilitzarà el PROFIBUS per intercanviar dades amb l’SCADA, no s’ha de recollir cap dada de cap procés realitzat per la CFF, per tant el protocol DP ( distributed peripheral I/Os ) que és el utilitzat en aquest casos ( comunicació mestre/esclau ) no es pot utilitzar.

Siemens proporciona el següents protocols i dispositius per la comunicació de dades:

Protocol Mòduls per PC Descripció Dispositius de comunicació

SIMATIC mes usuals

FMS

CP 5613 CP 5614

Protocol obert per PLC’s amb xarxa, per diferents fabricants, a nivell de cèl·lula i per pocs nodes

CP 5613 CP 343-5 CP 443-5

CP 5431 FMS/DP

S7

CP 5613 CP 5614 CP 5511 CP 5611

Comunicació integrada i optimitzada per sistemes SIMATIC S7/C7,compatible amb un gran nombre d’aplicacions

CP 5611 CP 5613

CP 342-5, 343-5 CP 443-5

S5

CP 5613 CP 5614 CP 5511 CP 5611

Comunicació senzilla basada en PROFIBUS FDL per intercanviar dades entre dispositius S5 i S7

CP 5431 CP 5434

CP 342-4, 343-5 CP 443-5

Els mòduls per PC i dispositius de comunicació Siemens que es troben en aquest projecte són el següents:

- CP 342-5: Aquest mòdul de comunicacions es troba en el PLC Simatic S7-300 que controla la CFF.

- CP 5613: Aquesta targeta està en el PC que ha d’executar el programa de gestió del magatzem i en el PC que fa de mestre en el sistema SCADA

2 Memòria

16

2.6 PLC Simatic S7-300

Aquest autòmat programable pertany a la família S7-300. Està constituït per una font d’alimentació PS 307, una CPU 314C-2DP, mòduls d’entrades i sortides, tant analògiques com digitals. Per últim, tenim el mòdul de comunicacions CP 342-5, que ens servirà per connectar-nos a la CPU 314C-2DP via PROFIBUS.

Figura 11. Vista de l’autòmat amb font d’alimentació i mòduls E/S.

2.7 Targeta de Comunicacions CP 5613

La CP 5613 es una targeta PCI amb un microprocessador que es utilitzada per connectar PCs al PROFIBUS. Es pot instal·lar en el sistemes operatius: Windows NT, Windows 2000, Windows XP i Windows 2003 Server.

Aquesta targeta possibilita la comunicació del PC que gestionarà el magatzem amb qualsevol altre dispositiu de comunicacions de Siemens, en el cas d’aquest projecte poden ser la targeta CP 5613 del PC que fa la gestió del sistema SCADA o bé el PLC S7-300 ( a través del mòdul de comunicacions CP 342-5).

Figura 12. Imatge de la targeta CP 5613

2 Memòria

17

Aquesta CP 5613 utilitza per connectar amb el PROFIBUS un connector de tipus RS-485 amb 9 pins.

Figura 13. Cable i diferents connectors RS-485 per PROFIBUS

2.8 Comunicació amb el sistema SCADA

2.8.1 Mode de comunicació amb el sistema SCADA

Abans de decidir la manera d’establir la comunicació amb el sistema SCADA es va contactar amb l’Enginyer Tècnic que estava realitzant el projecte de la seva gestió, per saber de quina manera treballava aquest sistema a l’hora de gestionar les dades del procés.

El autòmat S7-300 disposa de una memòria de 256 bytes que es utilitzada per gestionar i emmagatzemar les variables del procés, que son consultades des de el programa que gestiona l’SCADA durant la realització del procés de fabricació.

En aquests 256 bytes de memòria hi ha reservats 72 bytes per guardar la informació del contingut de les caselles del magatzem (1 byte per cada una de les 72 caselles) i també hi ha sense utilitzar alguns bytes més que es podran utilitzar per realitzar la comunicació.

Llavors, la comunicació amb el sistema SCADA es pot realitzar a través de la memòria del PLC, en aquesta memòria hi té accés de lectura i escriptura el software de gestió del SCADA, per tant si el software de gestió del magatzem hi pot accedir per escriure el contingut del magatzem i llegir les ordres, la comunicació estarà establerta.

Per tant, s’ha de decidir amb quin protocol de transmissió de dades s’accedeix a la memòria del PLC S7-300 i com es pot implementar aquest protocol des de el codi de Visual C++.

2 Memòria

18

2.8.2 Elecció del protocol d’accés al PLC S7-300

El PROFIBUS proporciona tres possibles protocols de transmissió de dades FMS, S5 i S7, tal i com s’ha descrit en el apartat 2.5.3 d’aquest projecte. En els següents punts, s’ha realitzat un estudi de cada un per tant d’escollir el més adequat.

2.8.2.1 Protocol Fieldbus Message Specification (FMS)

El FMS es un protocol de comunicacions definit en l’estàndard EN 50170 en la capa 7 del model ISO/OSI . És apropiat per comunicacions entre sistemes d’automatització heterogenis, es a dir de diferents fabricants. Té una velocitat de procés bastant limitada degut al seu complexa funcionalitat, per això només s’utilitza a nivell de cèl·lula en xarxes amb poc nodes.

En aquest protocol s’estableix la comunicació entre dos nodes, un actua de servidor i l’altre de client. El servidor proporciona les variable que seran accessibles pel client.

Aquest protocol s’ha descartat degut a està pensat per sistemes amb autòmats de diferents fabricants, en el cas de la CFF on només hi ha un autòmat SIMATIC S7, es més adequat utilitzar el protocol S7, que està creat per la comunicació amb aquest sistema. I per tant ens oferirà una comunicació menys complexa, amb més funcionalitats i amb millor rendiment.

2.8.2.2 Protocol S5

La comunicació S5 està basada en la transmissió de dades en una trama Fieldbus Data Link (FDL). Durant la transmissió el receptor proporciona un buffer al qual el emissor envia la trama de dades.

Permet el intercanvi de dades entre autòmats SIMATIC S5, SIMATIC S7 i PCs.

Si la comunicació s’estableix entre un PC i un PLC S7, com es el cas d’aquest projecte, aquest protocol no és el més adequat ja està pensat per la comunicació amb autòmats S5, s’hauria de utilitzar S7 que es un protocol que ens ofereix les mateixes característiques i moltes altres funcionalitats, ja que es tracta d’un protocol més evolucionat.

2.8.2.3 Protocol S7

El protocol S7 és utilitzat per la comunicació amb PLCs SIMATIC S7. Les seves principals característiques són:

• Optimització en les comunicacions entre dispositius SIMATIC.

• Adaptació dels elements del protocol al requeriments SIMATIC.

• Gran velocitat de transmissió de dades comparat en altres protocols.

• Facilita l’administració a nivell de camp mitjançant PROFIBUS.

2 Memòria

19

Un exemple de configuració de xarxa òptim per utilitzar S7 seria aquest:

Figura 14. Exemple de xarxa PROFIBUS

Com es pot veure, la xarxa que tenim a la CFF es la òptima per utilitzar el protocol S7. Per tant, el protocol S7 és l’adient per realitzar la comunicació amb el PLC S7-300. En el següents apartats s’han estudiat amb més profunditat els serveis per la comunicació que ens ofereix per tal decidir quin es el més adient per tal de utilitzar-lo en el projecte.

2.9 Implementació amb Visual C++ de la Comunicació amb l’SCADA

Una vegada s’ha determinat que la comunicació amb el sistema SCADA és realitzarà a través de la memòria del PLC i que el protocol utilitzat serà el S7, s’ha buscat la manera de realitzar-ho mitjançant Visual C++. La manera de fer-ho es utilitzar Ole for Process Control (OPC), que són una sèrie d’estàndards que permeten l’accés a PLCs de diferents fabricants utilitzant els entorns de programació més comuns, com per exemple Visual Basic o Visual C++, que és l’utilitza’t en el projecte.

2.9.1 Ole for Process Control (OPC) 2.9.1.1 Introducció

OPC són una sèrie d’estàndards de comunicació en el camp de l’automatització i la supervisió de processos. Aquests estàndards permeten que diferents fonts de dades envien dades a un servidor OPC, al s’hi poden connectar com clients diferents programes compatibles amb aquests estàndards. D’aquesta manera s’elimina la necessitat de que tots el programes tinguin controladors per dialogar amb múltiples fonts de dades, només cal

2 Memòria

20

que tinguin un controlador OPC per connectar amb el servidor que els hi proporcionarà les dades.

Tots aquests estàndards han estat creats i són mantinguts per la OPC Fundation. Aquesta fundació que va néixer el 1996 esta formada per més de 300 membres de tot el món, incloent casi tots el majors proveïdors de sistemes de control, instrumentació i control de processos.

En la realització d’aquest projecte s’ha emprat l’estàndard Data Access Specification (OPC-DA) que es el primer estàndard que es va realitzar. Es el fruit de la col·laboració entre els principals proveïdors de productes d’automatització a nivell mundial i Microsoft. Està basat en el components OLE COM (Component Object Model) de Microsoft i la tecnologia DCOM (Distributed Component Object Model). Les tecnologies COM/DCOM proporcionen el marc de treball adequat per a que es pugin desenvolupar programes en diferents entorns de programació, com el Visual C++.

Abans del OPC-DA, en el món de l’automatització industrial cada fabricant realitzava la seva pròpia interfície d’usuari i el seu propi controlador per a cada dispositiu. Windows ha proporcionat la infraestructura per poder estandarditzar el controladors, afegint les especificacions OPC a la tecnologia OLE de Microsoft.

Amb el OPC-DA un fabricant de dispositius industrials pot crear un servidor OPC-DA i qualsevol programa es pot convertir en client OPC d’aquest servidor, i pot accedir als dispositius d’aquest fabricant.

2.9.1.2 Objectes COM

Abans de parlar dels objectes COM, cal aclarir que el terme objecte al context COM no es correspon a la definició d’objecte dels llenguatges de programació orientats a objectes. Les propietats típiques dels llenguatges de programació orientats a objectes, com la herència, no són proporcionades per COM.

• Què són el objectes COM?

La base del mecanisme OPC és COM, el Component Object Model de Microsoft.

COM defineix un estàndard que permet tenir objectes definits com unitats separades a Windows , i accedir a aquestes unitats travessant la frontera que suposa el procés.

Els objectes poden ser entesos com extensions del sistema operatiu. No són dependents del llenguatge de programació i estan disponibles des de totes les aplicacions.

Els objectes COM són components que es poden executar sota Windows , i aquest defineix funcionalitats que altres components podran utilitzar a través de la seva pròpia interfície. Un objecte COM pot ser utilitzat simultàniament per diferents aplicacions.

Les dades i el codi d’un objecte no són transparents per l’usuari del objectes COM.

Un exemple de l’estructura d’un objecte COM amb 4 interfícies, es troben en la següent figura . L’accés és controlat per 4 mètodes. I no es possible accedir a les dades i codi d’aquest objecte si no és a través d’una interfície.

2 Memòria

21

Figura 15. Estructura d’un objecte COM

• Representació gràfica dels objectes COM

Ja que els objectes COM son utilitzats en molts documents s’ha buscat una

representació gràfica.

La objecte COM es dibuixa com un rectangle, la interfície especifica del objecte es representa a un costat del objecte, i la interfície que no es coneix (IDesconeguda) que proporcionen tots el objectes es mostrada a la part superior del objecte.

Els mètodes que hi ha per sota de les interfícies no són representats.

,' HVFRQHJXGD

2 EMHFWH�;

,QWHUItFLH�$

,QWHUItFLH�%

,QWHUItFLH�&

,QWHUItFLH�'

Figura 16. Representació d’un objecte COM

• La interfície COM per OPC

Una interfície COM és una col·lecció definida de mètodes per fer crides a les

funcionalitats dels objectes COM. Consisteix en una taula de punters que fan referència als mètodes.

Una interfície COM encapsula les funcionalitats dels objectes COM i assegura que al objecte només s’hi pugui accedir de manera correcta.

Les interfícies COM tenen assignat un únic identificador, d’aquesta manera una aplicació que vol accedir al objecte COM pot verificar que l’objecte suporta la interfície abans d’accedir-hi.

En el següent esquema es mostra l’estructura bàsica d’una interfície.

2 Memòria

22

Figura 17. Estructura d’una interfície

• Tipus d’interfície per OPC

Cada interfície té un mètode intern de crida diferent. Per cada interfície hi ha

especificacions d’interfície separades.

COM proporciona els següents tipus d’interfície:

- Interfície d’automatització, l’han d’utilitzar els clients OPC basats en llenguatges de “scripts” com Visual Basic o VBA

- Interfície a mida (custom), l’han d’utilitzar les aplicacions realitzades en C i C++.

Figura 18. Exemple d’assignació entre Interfície i Aplicació.

2.9.1.3 OPC-DA (OPC Data Access)

OPC-DA és un especificació per accedir a les dades del procés utilitzant variables. Un servidor OPC-DA gestiona les variables de procés i les diferents vies des de les que es pot accedir a aquestes variables.

El servidor pot efectuar les següents accions:

- Llegir el valor d’una o més variables de procés.

- Modificar el valor d’una o varies variables de procés, escrivint un nou valor.

- Monitoritzar el valor d’una o més variables de procés.

2 Memòria

23

• Estructura jeràrquica del model de classes de OPC-DA

L’accés a dades pot ser dividit en tres classes:

• OPC Server

• OPC Group

• OPC Item

2 3 &�6HUYHU

23&�* URXS V 23&�* URXS V 23&�* URXS V

23&�,WHP V 23&�,WHP V 23&�,WHP V

Figura 19. Model de classes de d’interfície Data Access (DA)

L’aplicació client utilitza les crides COM del sistema operatiu només per crear un objecte de la classe OPC Server.

Aquest model de classes es pot aplicar tant a la interfície d’automatització com a la interfície “custom”.

• Classe OPC Server

Es la classe principal, cada servidor OPC pertany a aquesta classe. Representa el punt

d’accés per tots els serveis del servidor OPC-DA.

Amb l’ajuda dels atributs específics de classe i els mètodes, es pot obtenir informació del estat, versió i nom, de les variables de procés disponibles.

Els objectes de la classe OPC Server gestionen les instancies de la classe inferior, OPC Group.

• Classe OPC Group

La classe OPC Group està per baix de la classe OPC Server i de les estructures de les

variables de procés utilitzades pel servidor OPC. Un client OPC pot utilitzar diferents objectes d’aquesta classe al mateix temps. Utilitzant objectes d’un OPC Group un client pot formar unitats de variables de procés i executar operacions amb elles.

La classe OPC Group defineix mètodes amb els quals els valors de les variables de procés poden ser escrites i llegides. I utilitzant aquest mètodes diverses variables poden ser agrupades i transferides al mateix temps d’una manera ràpida.

2 Memòria

24

• Classe OPC Item

Els objectes d’aquesta classe representen les variables de procés actualitzades i

permeten l’adquisició de la dada requerida. Cada variable és un element (item) en l’espai de noms del servidor OPC i es identificat per un Item ID. L’Item ID és especificada pel fabricant del servidor i ha de ser única dintre de l’espai de noms del servidor. Les propietats de cada item son les següents:

- Valor: És l’últim valor que s’ha adquirit de la variable.

- Qualitat: Fiabilitat del valor . Si la qualitat és bona el valor adquirit és correcte.

- Marca temporal: Indica la data i l’hora en que la variable s’ha adquirit per última vegada. Cada vegada que el client adquireix el valor la data i l’hora s’actualitza. Si el valor d’una variable canvia la marca temporal tampoc ho fa.

2.9.1.4 OPC en SIMATIC NET

El servidor OPC de SIMATIC NET (xarxes de productes SIMATIC de Siemens) suporta la interfície OPC-DA per tots el protocols SIMATIC.

El servidor OPC de SIMATIC NET permet l’accés a les xarxes PROFIBUS i les Industrial Ethernet de SIMATIC NET. Proporciona als clients OPC accés als valors de les variables de procés dels dispositius vinculats en el cas del present projecte el PLC S7-300.

El servidor OPC accedeix al dispositiu vinculat utilitzant el software del protocol i el processador de comunicacions de SIMATIC NET a través de la xarxa de comunicacions, com es pot veure en la següent figura:

Figura 20. Servidor OPC de SIMATIC NET amb client OPC

L’ús del servidor OPC de SIMATIC NET, proporcionarà grans avantatges en el desenvolupament de programes ja que:

2 Memòria

25

- Permet operar amb una interfície “multi-fabricant”. Això vol dir que l’aplicació

desenvolupada en un futur es podrà utilitzar amb altres dispositius d’altres fabricants.

- Les aplicacions desenvolupades no depenen del sistema de comunicacions d’un fabricant, i sense fer cap canvi podran comunicar amb servidor OPC d’altres fabricants.

- OPC proporciona una interfície amb grans prestacions pel llenguatges de programació C i C++.

- Es possible l’accés de manera adequada i fàcil a les dades de procés amb entorns de desenvolupament com Visual Basic i Visual C++.

- Es pot desenvolupar el programa sense tenir els dispositius instal·lats, ja que els dispositius vinculats poden ser simulats. Per això es pot utilitzar el software OPC Scout.

2.9.2 Comunicació amb el protocol S7 utilitzant OPC

2.9.2.1 Serveis per comunicacions en el protocol S7

El protocol S7 ens ofereix el següents serveis per comunicacions, tots són accessibles des de el client OPC, es a dir el programa realitzat, utilitzant el servidor OPC-DA de SIMATIC.

Servei Descripció

Serveis d’informació Dóna informació de l’estat de la connexió establerta. Mostra l’estat del dispositiu amb el que s’ha establert la comunicació

Serveis de variables Funcions per llegir i escriure a la memòria dels dispositius SIMATIC S7

Serveis d’enviament i recepció d’un buffer

Transferència programada i controlada de grans paquets de dades

Servies d’administració de blocs

Permet la descarrega, actualització, esborrat i enllaç de blocs del programa que està guardat en el PLC mentre aquest està funcionant. Això permet la modificació dinàmica de seqüències de programa i de paràmetres.

Serveis d’esdeveniments S’utilitza per rebre i processar missatges dels controladors programables SIMATIC S7, com per exemple alarmes

Serveis de seguretat Permet posar contrasenyes d’accés als objectes amb dades dels dispositius SIMATIC S7

D’aquests serveis el que s’ha utilitzat en el projecte es el servei a variables, aquestes variables poden accedir a qualsevol objecte del PLC S7/300, incloent els 256 bytes de memòria del PLC S7/300 que s’utilitzen per guardar els valors del procés.

2 Memòria

26

Aquesta memòria es la utilitzada en la comunicació amb l’SCADA, és aquest sistema SCADA qui defineix els valors que contindrà, i les pot llegir i escriure a través d’un software de gestió.

Per altra banda, aquest serveis a variables permeten llegir i escriure a la memòria del PLC directament des de l’ordinador que executa el programa de gestió. Per tant, serà aquests servei de variables els que s’utilitzaran en el projecte per realitzar l’intercanvi d’informació entre el programa realitzat i el sistema SCADA.

2.9.2.2 Serveis de variables S7 en un servidor OPC

El serveis de variables permeten accedir i monitoritzar les variables S7 d’un controlador programable, aquestes variables estan adreçades simbòlicament i representen el objectes del controlador accessibles des de el servidor OPC. Són les següents:

• Blocs de dades

• Entrades

• Sortides

• Entrades dels dispositius perifèrics

• Sortides dels dispositius perifèrics

• Bits de Memòria (en el S7-300 hi ha 256 bytes)

• Timers

• Comptadors

En el cas de l’aplicació realitzada, la comunicació amb l’SCADA es realitza utilitzant aquets Bits de Memòria (256 bytes).

2.9.2.3 Sintaxi de la Connexió entre el Servidor OPC i la el PLC

La sintaxi de la connexió per accedir a la memòria del PLC des de el servidor OPC, és la següent:

S7:[<nom_connexió>]<objecte>{<tipus>}<adreça>{,<quantitat>}

On cada element significa:

S7

S’està utilitzant el protocol S7 per accedir a les variables.

2 Memòria

27

<nom_connexió>

Nom de la connexió S7. Aquest nom es configura quan es crea el servidor OPC.

<objecte>

Per accedir a la memòria tindrà un valor M.

Per els altres objectes seria I per entrades, Q per sortides, PI per entrades dels perifèrics, PQ per sortides del perifèrics, T pels timers i C pels comptadors.

<tipus>

Tipus de dades S7. Un tipus de dades S7 es converteix al seu corresponent tipus OLE. Tots el formats de dades OLE es poden llegir a través de OPC.

En la següent taula es mostren els tipus de dades S7 i el seu corresponents tipus a Visual C++.

Identificador de tipus S7

Descripció Tipus de dada OLE

Tipus de dada Visual C++

X

Bit (boleia) S’ha d’especificar la posició ( de 0 a 7)

VT_BOOL Bool

B Byte (sense signe) VT_UI1 Byte W Word (sense signe) VT_UI2 Long

DW Doble Word (sense signe) VT_UI4 Double

STRING Cadena. S’ha d’especificar la seva longitud VT_BSTR String

DT Data i hora, 8 bytes amb format BCD VT_DATE Date

TIME Valor d’hora (amb signe). Format IEC en ms VT_I4 Long

TOD Hora dins del dia(sense signe).De 0 a 86399999 ms VT_UI4 Double

<adreça>

Adreça de memòria de la primera variable. Els valors possibles són:

• Byte : Indica el byte d’inici de la variable (del byte 0 fins al 255).

• Byte.Bit : Només pel tipus de dades X. Indica el bit al que es vols accedir.

<quantitat>

Quantitat de variables d’un determinat tipus que s’adreçaran a partir del valor indicat en el paràmetre adreça.

Pel tipus de dades X, la quantitat només es pot entrar en múltiples de 8. En aquest cas l’adreça del bit inicial ha de ser 0.

2 Memòria

28

Exemples de connexions:

S7:[DEMO_S7]MX19.5 ⇒ Accés al bit 5 del byte 19, el nom de la connexió es DEMO_S7, i el protocol utilitzat es S7.

S7:[DEMO_S7]MB224 ⇒ Accés al byte 224.

S7:[DEMO_S7]MB160,8 ⇒ Accés a 8 bytes a partir del byte 160.

S7:[DEMO_S7]MW114 ⇒ Accés a un WORD (2 bytes) a partir del byte 114.

S7:[DEMO_S7]MDWORD7,3 ⇒ Accés a 3 DWORD (12 bytes) a partir del byte 7

2.9.3 Creació d’una connexió S7 amb el servidor OPC de SIMATIC NET

Tant el servidor OPC, com el programa realitzat (client OPC) estaran situats en el mateix ordinador. Per tant, el servidor OPC serà local.

2.9.3.1 Software SIMATIC necessari

Per la creació de la connexió s’han utilitzat dos paquets de software , el SIMATIC NET i el SIMATIC STEP7.

• Software SIMATIC NET: Es distribueix amb la targeta de comunicacions CP 5613, la dota dels controladors i eines per configurar-la i per facilitar el seu accés als diferents protocols, com per exemple S7 i OPC

• Software SIMATIC STEP 7: És el paquet de software utilitzat per configurar i programar els PLCs SIMATIC. Inclou eines i funcions per les diferents tasques involucrades en un projecte d’automatització. El seu principal component es SIMATIC Manager que permet una gestió integrada de totes les eines i dades d’una projecte d’automatització.

Ambdós paquets de software, una vegada instal·lats apareixen al menú “Inicio” de Windows, en una entrada SIMATIC que ens permet l’accés a cada un.

2.9.3.2 Configuració inicial

S’ha de configurar el mode de funcionament de la CP 5613:

Anar a SIMATIC NET à Configuration Console à Modules à CP5613 à General. Aquí s’ha de marcar l’opció “Configured Mode”

2 Memòria

29

Figura 21. Configuració targeta CP 5613 des de Configuration Console

2.9.3.3 Creació d’un projecte amb la utilitat SIMATIC Manager

Obrir l’aplicació SIMATIC Manager, escollir el menú File à New.

S’ha de donar un nom i ubicació al nou projecte. Una vegada creat s’ha apretar el botó . Aquest botó ens obrirà l’aplicació NetPro.

Figura 22. Nou Projecte de SIMATIC Manager

L’aplicació NetPro ens permetrà afegir el components de xarxa i connexions el projecte.

Del catàleg s’ha d’escollir:

- Del directori “Subnets” s’ha d’escollir “PROFIBUS”

- Del directori “Station” una “Simatic PC Station”

2 Memòria

30

Figura 23. Introducció d’elements de xarxa des de NET PRO

Aquesta “Simatic PC Station” es crearà amb el nom “Simatic PC Station(1)”, aquest nom s’ha de canviar pel nom del ordinador del ordinador en el que s’està treballant. El nom es pot veure en les propietats de “Mi PC”. En aquest cas el seu nom és “cff02”.

Per canviar-lo s’ha de prémer el botó dret del ratolí damunt de la “Simatic PC Station” i en el menú contextual s’ha d’escollir “Object Properties”.

Per introduir el contingut de la “Simatic PC Station” s’ha de prémer al seu damunt el botó dret del ratolí i escollir “Open Object”.

Això ens obrirà l’aplicació HW Config que s’utilitza per introduir els elements següents:

- OPC Server: S’ha d’introduir en la posició 1. S’ha d’escollir dels elements de xarxa, User application à OPC Server à SW V6.0 SP5.

- CP 5613: S’ha de situar en la posició 2, escollint-la des de CP PROFIBUS à CP 5613 à SW V6.0 SP5. En el moment de situar-la en demanarà la seva configuració en la interfície PROFIBUS. S’ha posar l’adreça 30, s’ha d’escollir PROFIBUS i se li han de canviar les propietats, escollint Profile à Standard.

Figura 24. Configuració de CP 5613 des de HW Config

2 Memòria

31

Una vegada ja està definit el contingut de l’estació, tal com es veu en la següent imatge, ja pot guardar la configuració i tancar HW Config, tornant a NetPro.

Figura 25. Introducció de contingut d’estació des de HW Config

En el NetPro ja apareix l’estació amb el seus components i connectada a PROFIBUS per la adreça 30.

Figura 26. Estació amb OPC Server connectada a PROFIBUS mitjançant CP 5613

Ara ja es pot crear la connexió entre el OPC Server i el PLC S7-300. Per fer-ho se de prémer el botó dret del ratolí damunt del OPCServer, escollint l’opció “Insert New Connection”. Escollint Connection Partner à Unspecified i Connection Type à S7 connection.

2 Memòria

32

Figura 27. Configuració de connexió de tipus S7

En la següent finestra s’ha de posar la adreça del “partner” en aquest cas 1, que és l’adreça del PLC en el PROFIBUS. I després s’ha de prémer el botó “Adress Detail...”

Figura 28. Configuració de direcció del PLC en PROFIBUS

En la pantalla següent s’ha de configurar el Rack i el Slot on està el PLC, amb valors 0 i 2 respectivament.

2 Memòria

33

Figura 29. Configuració del Rack/Slot del PLC

Finalment, des de el menú Options à Set PG/PC Interface, s’ha d’escollir l’accés a l’aplicació de tipus “PC internal (local)”. Amb això ja es pot guardar la xarxa creada i tancar el NetPro i el SIMATIC Manager.

2.9.3.4 Traspàs de la xarxa creada cap al PC amb “Station Configurator”

Per accedir al “Station Configurator” s’ha d’executar l’accés que hi ha al menú “Inicio” o bé l’accés que hi ha al costat del rellotge del equip.

Apareix una finestra on s’ha d’escollir el botó “Import Station”. Aquí s’ha de buscar el fitxer .xdb que està associat al projecte creat en el SIMATIC Manager, en el directori on hem guardat el projecte, dintre una carpeta anomenada “XDBs”. Una vegada escollit el fitxer apareixen el OPC Server, la CP 5613 i la connexió S7 entre el OPC i el PLC (apareix un endoll).

Figura 30. Station Configurator

Després de totes aquestes configuracions, ja està creat el servidor OPC i la connexió S7 amb el PLC, en el PC on s’executa l’aplicació de gestió del magatzem

2 Memòria

34

2.9.4 Elecció del tipus d’accés (sincrón/asíncron) a la memòria del PLC

La accés de lectura i escriptura a la memòria del PLC amb els serveis de variables de OPC-DA des de Visual C++, es pot realitzar de manera síncrona o asíncrona.

2.9.4.1 Accés síncron

El programa fa una crida a una funció síncrona per accedir a les dades. Quan la funció s’executa el servidor OPC controla totes les comunicacions a través de la xarxa. El valor llegit es transfereix al programa del usuari amb el paràmetre que retorna la funció i l’aplicació en aquest moment pot continuar l’execució de la següent instrucció.

L’accés síncron és la forma més ràpida d’accedir a les dades del dispositiu vinculat.

En programes on una llarga interrupció no és acceptable, es poden utilitzar fils de treball (worker threads).

• Avantatges:

- Programació més senzilla.

- Gran taxa de transferència de dades ja que només hi ha un canvi de procés entre el client OPC i el servidor OPC.

• Desavantages:

L’aplicació s’interromp fins que l’accés síncron finalitza. L’aplicació només pot continuar quan totes les dades han estat llegides. Per exemple, si la funció no es crida en un fil separat, l’entorn d’usuari d’una aplicació interactiva es bloqueja durant la crida a la funció.

2.9.4.2 Accés asíncron

Quan un programa envia una crida a una funció asíncrona per accedir a les dades de procés, la funció retorna al programa immediatament indicant si el treball s’ha enviat correctament al servidor OPC. El programa pot continuar executant-se.

El servidor OPC assigna una TransactionID al treball, que el client pot identificar després per respondre al treball.

Al cap d’una estona, no determinada, el servidor OPC crida a la funció AsyncReadComplete o AsyncWritenoComplete del client OPC. El resultat de la crida prèvia (lectura o escriptura) i la TransactionID són enviades al client com paràmetres.

L’execució del programa del client OPC no rep cap influència en aquest accés.

L’accés síncron és útil quan s’han de llegir o escriure grans quantitats de dades.

Aquest accés provoca una gran carrega en el processador del ordinador que actua de servidor OPC, això és degut al procés d’intercanvi entre el client OPC i el servidor OPC.

2 Memòria

35

• Avantatges

- L’aplicació local és interrompuda només un petit instant ja que la comunicació corre paral·lela a l’aplicació.

• Desavantatges

- L’escriptura del codi de l’aplicació es mol més complexa, ja que un mecanisme de “callback” s’ha d’implementar en l’aplicació que ha de rebre el resultat del treball processat.

- Quan es transfereixen poques variables en un treball, hi ha una gran carrega en el processador degut als canvis de procés entre la crida i el “callback”. Aquesta carrega és el doble que en l’accés síncron.

2.9.4.3 Elecció de l’accés Síncron

S’ha escollit l’accés síncron a la memòria del PLC per la realització de projecte. El motius han estat:

- L’accés síncron es més fàcil de implementar en el programa.

- En el programa no s’accedirà a moltes variables a la vegada, per tan l’accés síncron no produirà tanta carrega en la CPU del ordinador que ha d’executar el programa i que també serà el servidor OPC. I també no carregarà tant la xarxa PROFIBUS.

- Per evitar que l’aplicació es quedi parada quan es realitza l’accés a memòria, s’ha creat un fil (thread) en el programa, que s’encarregarà de realitzar tots el accessos a la memòria.

2.9.5 Codi Visual C++ per accés Síncron a la memòria del PLC

Una vegada s’ha creat el servidor OPC i la connexió amb aquest s’ha establert, s’ha creat la funció bàsica amb Visual C++ per poder accedir a la memòria.

Aquesta funció ens permetrà escriure o llegir a qualsevol posició de memòria i amb qualsevol mida de dades (bit, byte, word o double word).

2.9.5.1 Seqüència d’operacions per realitzar l’accés

En la gràfica següent es mostra la seqüència bàsica de funcionament de la funció, en quant a la creació i esborrat d’objectes OPC. Els noms de variables utilitzats en la gràfica són els mateixos que s’utilitzen en la funció.

2 Memòria

36

2 3 &6HUYHU

2 3 &* URXS

2 3&,WHP

&R&UHDWH,QVWDQFH S2 3 & ! 5 HOHDVH

S2 3 & ! $GG* URXS S2 3 & ! 5 HP RYH* URXS

S,WHP 0 JW! $GG,WHP V S,WHP 0 JW! 5 HP RYH,WHP V

( [ HFXFLy�GH�O¶RSHUDFLy�GH�OHFWXUD�R�HVFULSWXUD�UHTXHULGD

Figura 31. Seqüència de instruccions creació i esborrat de objectes OPC

Per tant, la funció bàsica per realitzar l’accés a la memòria consta de 3 parts principals:

• Creació i configuració dels objectes OPC necessaris per l’execució de la funció

• Realització de la lectura o la escriptura del valor de memòria

• Esborrat dels objectes OPC utilitzats i alliberament dels recursos utilitzats

2.9.5.2 Creació i configuració d’objectes OPC

• Definició de la connexió S7:

Es crea un punter per accedir a la cadena que contindrà la connexió, d’aquesta manera a través del punter es pot modificar el contingut de la connexió per poder accedir a diferents posicions de memòria des de la mateixa funció. unsigned short *p_conexio; unsigned short conexio[]=L"S7:[S7 connection_1]MB114"; p_conexio=conexio;

En aquest cas l’accés es produeix a al byte 114, però utilitzant el punter es pot modificar, així es podrà accedir a diferents posicions de manera seqüencial, com per exemple en l’accés de tot el contingut del magatzem (72 bytes).

Després aquest punter es converteix a un punter a un string de caràcters Unicode (LPWSTR) que és el que s’utilitza en les següents funcions const LPWSTR szItemID=p_conexio;

2 Memòria

37

• Registre amb COM

Cada programa que ha d’utilitzar funcions de les llibreries COM primer s’ha de registrar amb COM. Això ho fa la funció CoInitialize( ): HRESULT r1; r1 = CoInitialize(NULL);

• Convertir el ProgID a CLSID

Per identificar-se , cada servidor COM té una “ProgID” que està assignada a única “CLSID” (codi de 128 bits). Com que el CLSID es requereix com a paràmetre per algunes funcions, aquest s’ha d’obtenir del ProgID amb la funció CLSIDFromProgID( ). El “ProgID” del servidor OPC de SIMATIC NET és L”OPC.SimaticNET” r1 = CLSIDFromProgID(L”OPC.SimaticNET”, &clsid);

• Establiment de la connexió amb el servidor OPC

La funció CoCreateInstance( ) crea una instancia de la classe sobre la que s’ha especificat el seu “CLSID”. r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER,

IID_IOPCServer, (void**)&m_pIOPCServer);

El resultat es un objecte de la classe OPC Server. CoCreateInstance també proporciona un punter a la interfície IOPCServer del objecte servidor (variable m_pIOPCServer )

• Creació d’un OPC group

La interfície IOPCServer té el mètode AddGroup( ) per crear grups:

r1 = m_pIOPCServer->AddGroup(L”grp1”, TRUE, 500, 1, &TimeBias, &PercentDeadband, LOCALE_ID, &m_GrpSrvHandle, &RevisedUpdateRate, IID_IOPCItemMgt, (LPUNKNOWN*)&m_pIOPCItemMgt);

El resultat és un group amb el nom específic i les propietats requerides. S’ha creat un punter a la interfície requerida del objecte group, que es retornat com paràmetre, el seu nom és IOPCItemMgt (variable m_pIOPCItemMagt):

2 Memòria

38

• Crear Items

La interfície IOPCItemMgt té el métode AddItems( ) per els OPC items:

r1 = pItemMgt->AddItems(1, m_Items, &m_pItemResult, &m_pErrors);

El resultat d’aquest pas són els items amb les propietats requerides. S’inicialitzen les variables de l’estructura que dóna el resultat, m_pItemResult.

• Crida a un punter de d’interfície IOPCSyncIO

El punter a la interfície IOPCSyncIO es necessari per permetre l’ús de mètodes per les escriptures i lectures síncrones. Es cridat utilitzant el punter existent a d’interfície IOPCItemMgt:

r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO,

(void**)&m_pIOPCSyncIO); Utilitzant els mètodes Read( ) i Write( ) d’aquesta interfície, els valors dels items

poden llegits i escrits:

2 Memòria

39

2.9.5.3 Lectura o escriptura de valor de memòria

• Lectura

El mètode que s’utilitza per la lectura síncrona dels OPC Items, és el següent: HRESULT Read (OPCDATASOURCE dwSource, DWORD dwNumItems, OPCHANDLE *phServer, OPCITEMSTATE **ppItemValues, HRESULT **ppErrors);

Read serà cridat amb les variables inicialitzades anteriorment com paràmetres: r1 = m_pIOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer,

&pItemValue, &pErrors);

El métode Read proporciona el valor que s’ha llegit en la taula pItemValue: Valor_llegit = pItemValue[0].vDataValue.lVal;

Aquest variable Valor_llegit conté el valor de la posició de memória que s’ha especificat.

• Escriptura

Es declara una variable de tipus VARIANT, aquest tipus de variable es una estructura que s’utilitzat específicament en el intercanvi de dades en automatització. VARIANT values[1]

Els dos valors que s’utilitzen de la variable values per guardar el valor que s’ha d’escriure són:

values[0].vt = VT_I2; El valor VT_I2 vol dir que guardarà un integer 2 de bytes values[0].iVal = Valor_escrit; El valor que s’escriurà a la memòria es el que conté Valor_escrit

El mètode per escriure el valor al OPC item és el següent: HRESULT Write (DWORD dwNumItems, OPCHANDLE *phServer, VARIANT *pItemValues, HRESULT **ppErrors);

La funció Write es crida les variables inicialitzades anteriorment com paràmetres: r1 = m_pIOPCSyncIO->Write(1, phServer, values, &pErrors);

2 Memòria

40

2.9.5.4 Esborrat del objectes OPC i alliberament de recursos

Abans de sortir de la funció, els objectes OPC que han estat creats han de ser esborrats i la memòria que se’ls ha reservat ha de ser alliberada. Les funcions principals formen part de les interfícies utilitzades anteriorment.

Els passos per fer-ho són:

• RemoveItems r1 = m_pIOPCItemMgt->RemoveItems(1, phServer, &pErrors); • RemoveGroup r1 = m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); • Alliberament de memòria CoTaskMemFree(m_pItemResult); m_pItemResult=NULL; CoTaskMemFree(m_pErrors); m_pErrors = NULL; m_pIOPCSyncIO->Release(); m_pIOPCSyncIO = NULL; m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; r1 = m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; • Tancament de la llibreria COM, això ho fa el mètode CoUninitialize( ) CoUninitialize();

2.10 Codificació de la comunicació amb el sistema SCADA

El mestre SCADA és l’encarregat de fer les sol·licituds d’entrada i sortida de palets del magatzem depenent de la seva producció. El software de control no pot desar o treure cap palet del magatzem sense cap ordre prèvia del mestre del SCADA.

Tota la comunicació amb el sistema SCADA es realitzarà a través de la memòria del PLC, on hi han disponibles el bytes necessaris per fer-ho.

Per altra banda, en la CFF hi ha una sèrie d’actuadors que estan associats a diferents bits de memòria del PLC, i que seran controlats pel software de gestió del magatzem escrivint a la memòria. Aquest actuadors són un topall per parar el palet quan arriba per la cinta transportadora , una peça que fa de pinça per fixar-los i un sensor capacitiu per detectar l’arribada d’un palet

2.10.1 Funcionament de la entrada i sortida de palets del magatzem

2 Memòria

41

El magatzem contindrà en cada casella un palet, que pot estar buit o tenir un, dos o tres cilindres. A part, en el magatzem sempre hi haurà una casella buida, es a dir sense cap tipus de palet.

Aquesta casella sense palet es necessària ja que per la cinta transportadora sempre arribaran palets damunt del seu carro. En el cas de que aquests palets siguin plens amb cilindres, es a dir una entrada de palet, s’haurà d’agafar aquest palet ple i deixar-lo a la casella buida. Després s’ha d’agafar un palet buit, sense cilindres, i s’ha de deixar damunt del carro per a que marxi per la cinta transportadora, així es torna a generar una casella sense palet en el magatzem.

En el cas de que per la cinta transportadora arribi un palet buit, es a dir una sortida de palet, es recollirà el palet buit i es posarà en la casella buida. Llavors s’agafarà el palet sol·licitat i es deixarà en el carro, creant-se la casella buida en el magatzem .

2.10.2 Codificació del diferents tipus de palets

La CFF pot fabricar 63 tipus de palets depenent del tipus de cilindres que contenen i de la posició que aquest ocupen en el palet.

Cada palet pot contenir un, dos o tres cilindres. I a la vegada aquest cilindres poden ser de tres tipus, negres, vermells i metàl·lics.

En la taula següent es mostra la codificació numèrica (de 0 a 63) que rebrà cada tipus de palet, depenent de tipus de cilindre i la seva posició.

Posició del cilindre al palet Tipus de cilindre

A CB

Negre

Vermell

Metàl·lic

Sense cilindre

2 Memòria

42

TIPUS DE PALET POSICIÓ CILINDRE DEC BINARI A B C

0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 1 0 3 0 0 0 0 0 0 1 1 4 0 0 0 0 0 1 0 0 5 0 0 0 0 0 1 0 1 6 0 0 0 0 0 1 1 0 7 0 0 0 0 0 1 1 1 8 0 0 0 0 1 0 0 0 9 0 0 0 0 1 0 0 1

10 0 0 0 0 1 0 1 0 11 0 0 0 0 1 0 1 1 12 0 0 0 0 1 1 0 0 13 0 0 0 0 1 1 0 1 14 0 0 0 0 1 1 1 0 15 0 0 0 0 1 1 1 1 16 0 0 0 1 0 0 0 0 17 0 0 0 1 0 0 0 1 18 0 0 0 1 0 0 1 0 19 0 0 0 1 0 0 1 1 20 0 0 0 1 0 1 0 0 21 0 0 0 1 0 1 0 1 22 0 0 0 1 0 1 1 0 23 0 0 0 1 0 1 1 1 24 0 0 0 1 1 0 0 0 25 0 0 0 1 1 0 0 1 26 0 0 0 1 1 0 1 0 27 0 0 0 1 1 0 1 1 28 0 0 0 1 1 1 0 0 29 0 0 0 1 1 1 0 1 30 0 0 0 1 1 1 1 0 31 0 0 0 1 1 1 1 1 32 0 0 1 0 0 0 0 0 33 0 0 1 0 0 0 0 1 34 0 0 1 0 0 0 1 0 35 0 0 1 0 0 0 1 1 36 0 0 1 0 0 1 0 0 37 0 0 1 0 0 1 0 1 38 0 0 1 0 0 1 1 0 39 0 0 1 0 0 1 1 1 40 0 0 1 0 1 0 0 0 41 0 0 1 0 1 0 0 1 42 0 0 1 0 1 0 1 0 43 0 0 1 0 1 0 1 1 44 0 0 1 0 1 1 0 0 45 0 0 1 0 1 1 0 1 46 0 0 1 0 1 1 1 0 47 0 0 1 0 1 1 1 1 48 0 0 1 1 0 0 0 0 49 0 0 1 1 0 0 0 1 50 0 0 1 1 0 0 1 0 51 0 0 1 1 0 0 1 1 52 0 0 1 1 0 1 0 0 53 0 0 1 1 0 1 0 1 54 0 0 1 1 0 1 1 0 55 0 0 1 1 0 1 1 1 56 0 0 1 1 1 0 0 0 57 0 0 1 1 1 0 0 1 58 0 0 1 1 1 0 1 0 59 0 0 1 1 1 0 1 1 60 0 0 1 1 1 1 0 0 61 0 0 1 1 1 1 0 1 62 0 0 1 1 1 1 1 0 63 0 0 1 1 1 1 1 1

2 Memòria

43

Finalment s’ha de destacar que la casella buida, sense cap tipus de palet, que es necessària per l’entrada i sortida de palets, es guardarà amb el codi 64

2.10.3 Utilització de la memòria del PLC en la comunicació amb l’SCADA

Dels 256 bytes de memòria que disposa el PLC, s’han utilitzats els següents per la comunicació entre programa de gestió del magatzem i el mestre del SCADA:

• Contingut de magatzem (72 bytes). El programa de gestió tindrà accés de lectura i escriptura. Només lectura per l’SCADA.

− Del byte 114 fins el byte 146, en total 32 bytes. S’utilitzen per guardar el

contingut de la casella 1 fins la casella 31 del magatzem

− Del byte 168 fins el byte 168, en total 8 bytes. Guardaran el contingut de la casella 32 fins la casella 40 del magatzem.

− Del byte 224 fins el byte 256, en total 32 bytes. Contindran el tipus de palet de la casella 31 fins la casella 72.

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 % 0 % 0 %�

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %�

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %�

0 %� 0 %�

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 % 0 % 0 %�

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %�

0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %� 0 %�

0 %� 0 %�

3RVLFLRQV�GH�P HPzULD

&DVHOOHV

Figura 42. Correspondència entre memòria i caselles del magatzem

• Byte 56 (MB 56). Comunicació d’entrada o sortida. El magatzem només tindrà accés de lectura.

MB 56 = 1 à Entrada de palet al magatzem

MB 56 = 2 à Sortida de palet del magatzem

2 Memòria

44

• Byte 57 (MB57). Tipus de palet que arriba. El magatzem només tindrà accés de lectura. En aquest cas, el palet amb valor 64, significarà que és un palet que no s’ha d’emmagatzemar, per tant s’ha de deixar passar per la cinta sense tenir-lo amb compte.

2.10.4 Actuadors de la CFF controlats pel magatzem

2.10.4.1 Sensor d’arribada de palet

Aquest sensor indicarà que ha arribat un palet per la cintra transportadora. Per saber quin valor té s’ha de llegir el Bit 5 del Byte 19 (MX 19.5). El programa mirarà el seu valor per saber si ha arribat palet.

MX 19.5 = 0 à Indica que no hi ha cap palet a la zona de recepció/lliurament

MX 19.5 = 1 à Indica que hi ha un palet a la zona de recepció/lliurament

2.10.4.2 Topall per parar el palet

Aquest topall para el palet davant de la zona de recepció/lliurament quan arriba per la cinta. D’aquesta manera el palet es queda parat esperant alguna acció fins que aquest topall baixa i el palet pot seguir circulant. La seva posició en la memòria és el Bit 1 del Byte 111 (MX 111.1).

MX 111.1 = 0 à El topall està pujat i el palet es para

MX 111.1 = 1 à El topall està baixat el palet podrà circular

2.10.4.3 Fixador del palet

2 Memòria

45

Aquest peça mecànica realitza la fixació del carro damunt del qual circula el palet per la cinta. El carro ha d’estar fixat en el moment en que s’hi recull o s’hi deixa el palet a sobre. La seva posició en la memòria és el Bit 4 del Byte 111 (MX 111.4).

MX 111.4 = 0 à Carro sense fixar

MX 111.4 = 1 à Carro fixat

El sistema SCADA només tindrà accés de lectura sobre aquest bit, i aquest bit serveix per indicar a l’SCADA si l’operació sobre el magatzem ha començat o ha finalitzat.

Quan es fixa el carro, es a dir hi ha un flanc de pujada en el bit MX 111.4, l’SCADA sap que s’ha iniciat l’operació sobre el magatzem

Quan es treu la fixació, es a dir hi ha una flanc de baixada al bit MX 111.4, l’SCADA sap que ha finalitzat l’operació sobre el magatzem

2.11 Software de control de magatzem

Per tenir una interfície per poder transmetre les ordres de funcionament bàsic al magatzem, s’ha utilitzat un programa realitzat en un altre projecte. Aquest programa, també realitzat en Visual C++, proporciona una sèrie de funcions per poder interactuar amb el magatzem, que seran cridades des de el programa de gestió.

2.11.1 Funcions per interactuar amb el magatzem

Hi ha una funció bàsica per realitzar les accions al magatzem. La seva capçalera es la següent: void magatzem (unsigned short accio, unsigned short casella1, unsigned short casella2 );

On el paràmetres poden tenir el següents valors:

• accio à DESA, TREU, MOU

• casella1, casella2 à Poden tenir un valor de 1 a 72, que són el nombre de caselles que te el magatzem.

Els tres accions que es podran realitzar amb aquesta funció son les següents:

• DESA: És utilitzada per guardar un palet que ha arribat per la cinta transportadora a una determinada casella dintre del magatzem. Un exemple de la crida a la funció magatzem per fer guardar un palet a la casella 5 és: magatzem (DESA, 5, NULL);

2 Memòria

46

• TREU: S’utilitza per treure un palet des d’una casella determinada fins a deixar-la a la cinta transportadora. Un exemple de la seva crida per treure del magatzem el palet de la casella 72 , és el següent: magatzem (TREU, 72, NULL);

• MOU: Ens servirà per poder moure un palet des de una casella fins una altra dintre del mateix magatzem. La seva crida per moure un palet de la casella 58 fins a deixar-lo a la casella 14 seria la següent: magatzem (MOU, 58, 14);

L’altra funció que és utilitzada per interactuar amb el magatzem és la que realitza el calibratge de posició del capçal que recorre les caselles, aquesta funció fa que aquest capçal vagi fins el punt inicial del eixos de coordenades (x=0, y=0) per els que es mou el capçal, realitzi el calibratge i després torni a la posició central del magatzem. Aquesta funció que no rep cap paràmetre té la següent capçalera:

void calibra();

2.11.2 Incorporació del software de control al software de gestió

El funcionament del software de control està basat en un timer que cada 50ms realitza el control PID de la posició del capçal en els eixos X i Y. Llavors per realitzar qualsevol acció en el magatzem aquest software ha d’estar en funcionament.

Per tant, s’ha incorporat el programa de control en aquest projecte de manera que les crides a funcions de control es podran realitzar directament des de el programa realitzat., i l’execució del programa unificat es podrà realitzar des de un sol executable.

Per poder incorporar el programa de control s’han inclòs el seus fitxer .h, el fitxers de codi ( .cpp ), el fitxer de capçalera ( .h ) a l’espai de treball de Visual C++ . Així com tot el codi del fitxers “nom_projecteView.cpp” i “nom_projecteView.h”, que són el fitxer de la classe vista a Visual C++, que s’ha incorporat als fitxers de la classe vista del projecte

2.12 Gestió del magatzem

Per descriure el funcionament general del magatzem s’ha implementat un diagrama de flux, a partir d’aquest diagrama s’han establerts un blocs de funcionament diferenciats que es descriuran més detalladament i sobre els que es mostrarà el codi c++ utilitzat.

2 Memòria

47

2.12.1 Diagrama de Flux del Funcionament General del Magatzem

2 Memòria

48

2.12.2 Bloc d’Inicialització

En la inicialització de l’aplicació es realitzen les següents tasques:

,QFLDOLW] DFLy�GH�YDULDEOHV�JOREDOV

( [ LVWHL[ � HO�ILW[ HU�RQ�HV�JXDUGD�HO�FRQWLQJXW�GH�

P DJDW] HP "

( V�FUHD�HO�ILW[ HU�DP E�HQWUDGD�GH�GDGHV�P DQXDO�R�

HV�FUHD�EXLW

,QLFLDOLW] DFLy�2 3&

) L�GH�OD�LQLFLDOLW] DFLy�L�&ULGD�DO�7KUHDG

1 2

6 ,

&RSLD�GH�GDGHV�GHVGH�ILW[ HU�DO�3/ &

2.12.2.1 Inicialització de variables global

En aquest punt es creen totes les variables globals de l’aplicació i s’inicialitzen al valor requerit.

2.12.2.2 Comprovació de fitxer de dades

Es verifica si existeix el fitxer que guarda el contingut del magatzem, el seu contingut es binari per tant no es pot consultar ni modificar des de un editor de text. Per modificar-lo s’ha de fer des de d’interfície d’usuari.

En el cas de que el fitxer no existeixi apareix un diàleg que permet crear-lo sense dades o bé obre el diàleg que te d’interfície d’usuari per poder entrar les dades manualment al fitxer.

La ubicació d’aquest serà el mateix directori on està situat el fitxer .exe que executa l’aplicació.

2 Memòria

49

El contingut del fitxer magatzem es copia a la taula de integers “almacen” que guardarà el contingut del magatzem durant l’execució del programa.

Funció que ho implementa

void CMagatzem003View::fitxer_dades() { fitxer_mag = fopen("magatzem.txt","rt+"); /*Es mira existència*/ CnofitxerDialog nofitxerdialog; /*Diàleg explicatiu*/ CDialogEntradaDades DialogEntradaDades; /*Diàleg entrada manual*/ if (fitxer_mag==NULL) /*Si el fitxer no existeix*/ { if (nofitxerdialog.DoModal()==IDOK) { DialogEntradaDades.DoModal(); /*Entrada dades manual*/ } else /*Creació fitxer buit*/ { fitxer_mag = fopen("magatzem.txt","at"); int i; for (i=0; i<72; i++) /*S'incialitza la taula almacen*/ almacen[i]=0; int num1; num1=sizeof(almacen); fwrite(almacen, sizeof(almacen), 1, fitxer_mag); /*Es copia tabla almacen al fitxero*/ fclose(fitxer_mag); } } else /*Si el fichero existe se copia su contenido a almacen*/ { fread(almacen, sizeof(almacen), 1, fitxer_mag); fclose(fitxer_mag); } }

2.12.2.3 Inicialització OPC

En aquesta funció el que es realitza és la creació dels objectes OPC per accedir a la memòria del PLC tal i com està descrit en l’apartat 2.3.7 del projecte. En aquest cas només es fa la inicialització d’aquest objectes, sense realitzar-se cap accés de lectura o escriptura.

En l’aplicació cada vegada que es fa un accés a la memòria del PLC es creen els objectes OPC i es tornen a esborrar, per tant es perd la connexió amb el servidor OPC.

Si abans s’ha fet una connexió amb el servidor OPC per part d’aquesta funció, i es manté oberta durant l’execució de l’aplicació, quan s’intenti accedir des de l’aplicació es és farà d’una manera més ràpida. Quan es tanqui la aplicació aquesta connexió es perdrà automàticament.

Les parts més importants del codi d’aquesta funció està exposats en el punt 2.9.5.

2 Memòria

50

2.12.2.4 Traspàs del Contingut del Magatzem al PLC

Degut a que la memòria del PLC es perd en el moment que aquest es apagat, el fitxer amb les dades que hi ha al PC serà el que tindrà el contingut actualitzat de les dades del magatzem. Cada vegada que s’inicia l’aplicació es copia el contingut d’aquest fitxer a la memòria del PLC per assegurar que aquest tingui les dades correctes.

Aquest fitxer local de dades també es pot modificar i traspassar al PLC durant l’execució de l’aplicació des de la interfície d’usuari.

La quantitat de dades que s’han de traspassar al PLC són 72 bytes, l’escriptura que s’ha utilitzat en aquesta funció es de 2 bytes (WORD), per tant es realitzen 36 accessos a la memòria del PLC per copiar les dades.

Per crear el WORD a escriure en el PLC s’ha fet amb aquesta formula:

Word (n)=byte( n)+byte(n+1)*256 . . . . . Word (n+2)=byte( n+2)+byte(n+3)*256

El codi de la funció traspas_dades_plc() és el següent:

void CMagatzem003View::traspas_dades_PLC() { CProgressWnd wndProgress(this, "Carrega de dades"); /*Barra progrés*/ wndProgress.GoModal(); /*Crida al diàleg barra progrés*/ wndProgress.SetRange(0,36); /*La barra creixerà amb 36 passos*/ wndProgress.SetText("Carregant dades al PLC. Espereu uns segons ..."); / * Missatge barra progrés*/ for (casella=1; casella<=72 ; casella=casella+2) /*Per 32 passos*/ { valor_dw=almacen[casella-1]*256 + almacen[casella]; /*Es crea el WORD word(n)=byte(n)*256+byte(n+1)*/ escriure_plc(casella,valor_dw); /*S'escriu Word al PLC*/ wndProgress.StepIt(); /*S'incrementa un pas la barra*/ wndProgress.PeekAndPump(); /*Es visualitza el increment*/ } }

2 Memòria

51

2.12.3 Bloc de Recepció i Lliurament de Palets

Aquest bloc s’encarregarà de rebre i lliurar els palets que arriben per la cinta. Tot aquest bloc s’executa dintre d’un thread, i dintre del thread s’espera en event cada 500ms. S’ha fet d’aquesta manera ja que cada 500ms s’ha de llegir el bit MX 19.5 per saber si ha arribat un palet. I una vegada ha arribat el palet s’han de realitzar una sèrie d’accions, fixar-lo, llegir a la memòria si es tracta d’una entrada o sortida del magatzem i quin tipus de palet. Tots aquest processos impliquen accessos continus a la memòria del PLC mitjançant OPC. Ja que aquests accessos són força lents, provocarien un mal funcionament de l’aplicació. Al utilitzar un thread separat aquesta problemàtica es veu solucionada.

D’utilització del thread per tots els accessos a memòria, també facilitarà el correcte funcionament de la part de control del magatzem. Cal recordar que el control del magatzem utilitza un timer que s’executa cada 50ms per realitzar el control PID dels motors X i Y del capçal del magatzem. Si s’utilitza el thread aquest timer sempre es podrà executar cada 50 ms , en el cas de que el bloc de recepció/lliurament no s’executés dintre del thread no es pot garantir que el timer sigui executat cada 50 ms.

S’han realitzats proves amb el programa utilitzant el thread i sense utilitzar-lo. En el programa s’executa el timer del control PID cada 50 ms, i l’event per llegir el bit del sensor d’arribada de palet (MX 19.5) cada 500ms.

Les proves realitzades han estat comptar el les vegades que s’ha executat el timer del PID i l’event de lectura del sensor durant 120 segons.

Si el funcionament del programa fos ideal, en 120s el timer PID s’hauria de executar 2.400 vegades, mentre que el event del sensor 240 vegades.

També s’ha de tenir en compte que un retràs en el timer PID és crític en quant al control del magatzem, mentre que l’event del sensor no ho és, ja que només provocaria un retràs de pocs milisegons en la detecció d’arribada del palet

En la següent taula es mostren el resultats:

Temps (s) Nombre Execucions Timer PID (50ms)

Nombre Execucions Event Sensor (500ms)

Programa amb Thread

120 2390 236

Programa sense Thread

120 1171 193

Com es pot veure, quan es funciona sense thread el nombre de vegades que es perd el timer PID és molt gran, 1219.

Quan el programa utilitza el thread nomes es perden 10 execucions del timer PID, que és un resultat molt proper al ideal i que no interfereix en el funcionament del control PID.

2 Memòria

52

El diagrama de flux d’aquest bloc de funcionament és el següent:

&UHDFLy�GHO�WKUHDG�L�GHO�HYHQW

/ OHJLU�0 ; �&DGD� P V

+D�DUULEDW�SDOHW "

� L[ DFLy�GHO�SDOHW

/ OHJLU�0 %�3DOHW�FRUUHFWH "

/ OHJLU�0 %�( V�OOHJHL[ � O¶DFFLR�( QWUDGD�R�6RUWLGD

( V�WUHX�IL[ DFLy�SDOHW( O�SDOHW�P DU[ D

( V�YH�GH�G¶XQD�DFFLy�DXWRP j WLFD�L�V¶KD�GH�

OOLEHUDU�SDOHW"

6,

1 2

6,

1 2

6,

1 2

( V�UHDOLW] D�DFFLy�DXWRP j WLFD( QWUDGD�R�6RUWLGD

( V�ILQDOLW] D�HO�7KUHDG

+L�KD�XQD�DFFLy�P DQXD�HQ�FXUV

1 2

6,

2 Memòria

53

A aquest bloc funcional, que està implementat en el thread, es cridarà des de la inicialització de l’aplicació i es crearà l’event que s’esperarà en el thread. Aquest thread es tanca en el moment que es comença l’entrada o sortida al magatzem.

Després el thread, es tornaràn a cridar des de el bloc que realitza la acció automàtica, per realitzar el lliurament del palet a la cinta transportadora. Una vegada s’hagi lliurat el palet , el thread es seguirà executant esperant l’arribada de un nou palet per la cinta.

La crida al thread i la creació del event són les següents: frame = CreateEvent(NULL,FALSE,FALSE,NULL); /*Creació del event frame*/ CreateThread(NULL,NULL,myThread,NULL,NULL,NULL); /*Creació al thread*/

El codi del thread és el següent: DWORD WINAPI myThread(LPVOID lpParameter) { DWORD ReturnInfo; int m_ReadVal; /*Variable per llegir MX19.5*/ const LPWSTR szItemID = L"S7:[S7 connection_1]MX19.5";/*Connexió MX19.5*/

Una vegada s’ha definit la connexió, es realitza la inicialització OPC. while(TRUE) /*Assegurem que el thread sempre existeixi*/ { ReturnInfo=WaitForSingleObject(frame,500); /*Cada 500ms es mira event*/ if(ReturnInfo==WAIT_TIMEOUT) /*Cada 500ms s’entra*/ { if (acabada_accio==1) /*Si es ve d’acció automatica*/

{ escriure_plc_palet(1114,0); //Es posa a 0 el bit MX 111.4 //per desclavar el palet

escriure_plc_palet(1111,1); //Es posa a 1 el bit MX 111.1 //per treure el tope del palet acabada_accio=2; /*S’utilitza per pujar el tope*/ } if (acabada_accio==2) /*Es puja el tope al cap de 1 s*/ { cnt1++; if (cnt1>=2) /*S’entra al cap de 1 s*/ { cnt1=0; escriure_plc_palet(1111,0); /*Es puja el tope*/ acabada_accio=0; /*Palet alliberat*/ } } else /*Quan s’alliberà palet es continua esperant*/ { if(ReturnInfo==WAIT_TIMEOUT) {

S’està esperant l’arribada del palet. Es produeix la lectura del MX 19.5 amb OPC. El valor es guarda a la variable m_ReadVal

if(m_ReadVal>0) /*Ha arrivat palet*/ { arriba_palet=1; escriure_plc_palet(1114,1); /*Es fixa palet*/ valor_e_s=llegir_plc_palet(56); /*Entrada o sortida*/ valor_palet=llegir_plc_palet(57); /*Tipus de palet*/ if (valor_palet==64) /*Palet incorrecte*/ { arriba_palet=0; //En la pròxima execució del

2 Memòria

54

acabada_accio=1; //thread es lliura el palet } } /*Si ha aribat palet i es entrada o sortida*/ if ( (arriba_palet==1) & ((valor_e_s==1)|(valor_e_s==2)) ) { passos_accio=1; /*Comença acció automàtica*/ ExitThread(NULL); /*Es tanca el thread*/ } } } } } return 0; /* Valor de retorn del thread,no s’utilitza*/ }

2.12.4 Bloc d’Accions Automàtiques

El seu diagrama de flux és:

2 Memòria

55

El primer que es realitzat en aquest bloc es la cerca del les caselles on es deixaran els palets en cada acció, si no hi ha caselles disponibles per realitzar l’acció es mostra un missatge per pantalla i s’allibera el palet. Es improbable que un arribi un palet que no es pugui emmagatzemar o es demani un palet que no està al magatzem, ja que l’SCADA revisa el contingut del magatzem que hi ha al PLC, abans de fer la comanda al magatzem.

L’algorisme de cerca de caselles sempre buscarà la casella més propera que conté el palet buscat a partir de la casella 1 del magatzem

L’algorisme de cerca de caselles funciona de la següent manera, es comença a buscar a partir d’una casella inicial, degut a que el capçal sempre el primer que fa es buscar un palet a la safata de recepció, la casella inicial sempre serà la primera del magatzem.

A partir d’aquí es cerca la casella més propera on està el palet buscat a partir de la casella 1 en diferents casos, tal i com es mostra en el següent gràfic:

La cerca es realitzarà simultàniament en el dos mòduls del magatzem, ja que com els dos mòduls estan un en front de l’altre, primer es busca en la casella del mòdul 1 i després es busca en la casella equivalent del mòdul 2.

D’aquesta manera s’assegura que la casella trobada sempre serà la més propera a la casella1.

La crida a la casella es fa de la següent manera

cerca_palet(int casella_inicial, int tipus_palet)

Per exemple, per buscar una casella sense palet la crida seria:

cerca_palet (1, 0)

I per buscar la casella sense palet, la crida seria:

cerca_palet (1, 64)

Finalment per guardar o treure cada palet es fa la crida a les funcions de control del magatzem explicades en l’apartat 2.11.1 del present projecte.

2 Memòria

56

2.13 Interfície d’usuari

La interfície del programa desenvolupat serà la típica d’una aplicació Windows.

L’aplicació s’executa en un finestra on hi ha:

• Una barra de menús on es pot accedir a les diferents opcions que faciliten la gestió del magatzem.

• La zona del document hi ha una representació gràfica del magatzem i del seu contingut, així com una barra horitzontal que donarà informació de les accions que es realitzen en el magatzem.

En cada casella es representa de manera gràfica i numèrica cada tipus de palet que conté. La casella sense palet es representa amb un aspa i les caselles amb palets buits es representen en blanc.

Aquesta interfície ens permetre realitzar les accions manuals, es a dir moure un palet d’una posició a una altra del magatzem. Per fer-ho, simplement s’haurà de prémer el botó esquerre del ratolí sobre la casella inicial i sense deixar-lo de prémer, s’ha d’arrossegar la casella inicial fins la casella que ha de rebre el palet. Amb això ja es realitzarà el moviment del palet de la casella inicial fins la final.

2 Memòria

57

2.14 Resum del pressupost

El preu total del pressupost resultant és de 19.277,29 € , tenint en compte despeses generals (13%), benefici industrial (6%) i I.V.A. (16%) , trobant-se detellat en el pressupost.

Tarragona, setembre de 2006

JUAN DAVID ROIG MAURI

Enginyer Tècnic Industrial en Electrònica Industrial

2 Memòria

58

2.15 Bibliografia

En quant a la programació amb Visual C++:

• Llibres:

Títol: Aprenda Microsoft Visual C++ 6.0 Ya Autor: Chuck Sphar Editorial: McGraw-Hill

Títol: Progrese con Visual C++ Autor: David Kruglinski Editorial: McGraw-Hill

• Adreces d’Internet:

- http://www.dcp.com.ar

Web dedicada a la programació amb Visual C++ amb nombrosos exemples de codi.

- http://www.codeguru.com

Web on espot trobar codi lliure per diversos llenguatges de programació

En quant a la comunicació amb el PLC S7-300 amb OPC través de PROFIBUS s’han utilitzat el manuals que proporciona Siemens pels seus components i aplicacions. Tots es poden trobar amb format PDF a la zona de documents i utilitzats de http://www.automation.siemens.com , utilitzant el seu nom o bé el número de ordre.

- Industrial Communication with PG/PC Release 11/2003 C79000-G8976-C172-03 - Industrial Communication with PG/PC Volume 2 - Interfaces Release 07/2004 C79000-G8976-C197 - Product Informatio/Installation Instructions CP5613/CP5614 Release 11/2003 S79220-A5814-X-03-7419 Adreces d’Internet:

- http://www.profibus.com

Web sobre l’estandard PROFIBUS

- http://www.opcfoundation.org

Web sobre la fundació OPC

- http://www.automation.siemens.com

Web de Siemens per als seus productes d’automatització amb molta informació.

59

3 Pressupost

3 Pressupost

60

3.1 Consideracions inicials

Cal tenir en compte que els preus que hi figuren en aquest pressupost són orientatius i que el número d’hores i els materials necessaris poden anar variant durant l’elaboració del projecte, provocant variacions en el pressupost.

Normalment l’elaboració d’un pressupost es veu afectat per la situació del mercat. La forta competència i la caiguda de la demanda en el sector informàtic ha provocat que els pressupostos siguin molt ajustats.

En els cas que estem tractant, l’empresa ja disposa de tot el material i infraestructures necessàries per realitzar aquests tipus de projectes. Per tant, en el pressupost no s’incorporarà l’adquisició del material, sinó l’amortització del mateix.

També cal destacar que l’empresa ja disposa del software necessari per desenvolupar aquest tipus de projectes i que per tant, les llicencies de software i tots els programes que s’utilitzaran només s’inclourà al pressupost la seva amortització.

3.2 Preus unitaris

3.2.1 Material

Codi Unitat Designació Preu (Eur)

101 h Amortització Equipament Hardware 1,00

102 h Amortització Equipament Software 1,00

3.2.2 Mà d’Obra

Codi Unitat Designació Preu (Eur)

201 h Enginyer Tècnic 15,00

3 Pressupost

61

3.3 Descomposició de tasques

Les diferents tasques que s’han realitzat per arribar a obtenir cada capítol de projecte són:

• T001 - Estudi del component

• T002 - Programació amb Visual C++

• T003 - Proves i validacions

• T004 - Documentació

S’ha establert que el cost d’execució es el mateix per cada una de les tasques :

Codi Partida Designació Unitat

T001, T002, T003, T004

Tasca genèrica per realitzar cada component del projecte un.

Unitat Quantitat Preu unitari Total (Eur)

Material: 101- Amortització Equip. Hardware h 2,00 1,00 2,00

102- Amortització Equip. Software h 2,00 1,00 2,00

Subtotal Material: 4,00 Mà d’obra:: 202- Analista Programador h 1,00 15,00 15,00

Subtotal Material: 15,00 Cost Execució : 19,00

3 Pressupost

62

3.4 Descomposició del projecte

El projecte s’ha descompost en els següents components:

• C001 - Creació de la interfície d’usuari

• C002 - Comunicació amb el sistema SCADA

• C003 - Gestió del magatzem

3.4.1 Creació d’Interfície d’Usuari

Codi Component Designació Unitat

C-001 Creació d’interfície d’usuari un.

Unitat Quantitat Preu unitari Total (Eur)

Tasques: T001 - Estudi del component h 10,00 19,00 190,00 T002 - Programació Visual C++ h 220,00 19,00 4.180,00 T003 - Proves i validacions h 15,00 19,00 285,00 T004 - Documentació h 10,00 19,00 190,00

Cost Execució : 4.845,00

3.4.2 Comunicació amb el sistema SCADA

Codi Component Designació Unitat

C-002 Comunicació amb el sistema SCADA un.

Unitat Quantitat Preu unitari Total (Eur)

Tasques: T001 - Estudi del component h 50,00 19,00 950,00 T002 - Programació Visual C++ h 120,00 19,00 2.280,00 T003 - Proves i validacions h 50,00 19,00 950,00 T004 - Documentació h 20,00 19,00 380,00

Cost Execució : 4.560,00

3 Pressupost

63

3.4.3 Gestió del Magatzem

Codi Component Designació Unitat

C-003 Gestió del magatzem un.

Unitat Quantitat Preu unitari Total (Eur)

Tasques: T001 - Estudi del component h 30,00 19,00 570,00 T002 - Programació Visual C++ h 150,00 19,00 2.850,00 T003 - Proves i validacions h 40,00 19,00 760,00 T004 - Documentació h 20,00 19,00 380,00

Cost Execució : 4.560,00

3 Pressupost

64

3.5 Resum del pressupost

Capítols Import (Eur) C001 - Creació de la interfície d’usuari 4.845,00 C002 - Comunicació amb el sistema SCADA 4.560,00 C003 - Gestió del magatzem 4.560,00

Total Pressupost d’execució material : 13.965,00

Despeses Generals 13% 1.815,45 Benefici Industrial 6% 837,90

Total Parcial : 16.618,35

I.V.A 16% 2.658,94 Total Pressupost : 19.277,29

El preu total és de DINOU MIL DOS-CENTS SETANTA SET EUROS AMB VINT-I-NOU CÈNTIMS.

Tarragona, setembre de 2006

JUAN DAVID ROIG MAURI Enginyer Tècnic Industrial en Electrònica Industrial

65

4 Plec de Condicions

4 Plec de Condicions

66

4.1 Generalitats

4.1.1 Condicions Generals

El present plec de condicions té com a objectiu definir a l’Empresa Programadora l’abast del treball i l’execució qualitativa del mateix.

• El treball consisteix en la creació d’una aplicació informàtica i totes les proves oportunes per assegurar la fiabilitat del mateix.

• L’Empresa Programadora s’encarregarà del disseny i la implantació del programa.

4.1.2 Reglaments i Normativa

Totes les unitats del programa s’executaran complint les prescripcions indicades als Reglaments i Normes Tècniques d’obligat compliment per a aquest tipus d’aplicacions, tant d’àmbit nacional, autonòmic com municipal, així com totes les altres que s’estableixin a la Memòria Descriptiva.

S’adaptaran, a més, a les presents condicions particulars que completaran les indicades pels Reglaments i Normes esmentats.

4.1.3 Execució del Programa

4.1.3.1 Inici

L’Empresa Programadora començarà a crear el programa dins el termini que figura al contracte establert amb l’Empresa Usuària, o en el seu defecte als quinze dies de l’adjudicació definitiva del contracte.

L’Empresa Programadora està obligada a notificar per escrit o personalment, de forma directa a l’Empresa Usuària la data de inici de realització del Programa.

4.1.3.2 Termini d’execució

El programa s’executarà dins el termini que s’estipuli al contracte subscrit amb l’Empresa Usuària o en el seu defecte el que figuri a les condicions d’aquest plec.

Quan l’Empresa Programadora, d’acord amb algun dels extrems continguts en el present plec, o bé, al contracte establert amb l’Empresa Usuària, sol·liciti una inspecció pera poder realitzar algun treball ulterior que estigui condicionat per la mateixa, vindrà

4 Plec de Condicions

67

obligada a tenir preparada per a l’esmentada inspecció, una programació que correspongui a un ritme normal de treball.

Quan el ritme de treball establert pel Contractista, no sigui normal, o be, a petició d’una de les parts, es podrà convenir una programació d’inspeccions obligatòries d’acord amb el pla de realització de la programació.

4.1.4 Interpretació i Desenvolupament del Programa

La interpretació tècnica del Programa, correspon al Tècnic Director. L’Empresa Programadora està obligada a sotmetre a aquest, qualsevol dubte, aclariment o contradicció que sorgeixi durant l’execució de l’obra per causa d’una mala interpretació, o circumstàncies alienes, sempre amb la suficient antelació en funció de la importància de l’assumpte.

L’Empresa Programadora es fa responsable de qualsevol error d’execució motivada per la omissió d’aquesta reglamentació i conseqüentment deurà refer a cost propi els treballs que corresponguin a la correcta interpretació del Projecte.

L’Empresa Programadora està obligada a realitzar tot el que sigui necessari per a la bona execució del Programa, encara que no es trobi explícitament expressat al Plec de Condicions del Projecte.

L’Empresa Programadora notificarà per escrit o personalment de forma directa al Tècnic Director i amb suficient antelació les dates en que quedaran preparades per a inspecció, cadascuna de les parts del Programa per a les quals s’ha indicat la necessitat o conveniència de les mateixes.

4.1.5 Treballs Complementaris

L’Empresa Programadora té l’obligació de realitzar tots els treballs complementaris que siguin indispensables per a executar qualsevol part del Programa especificades en qualsevol dels documents del Projecte, tot i que en aquest no figurin explícitament mencionats els esmentats treballs complementaris. Tot això sense variació del import contractat.

4.1.6 Modificacions

L’Empresa Programadora està obligada a realitzar els treballs que se li encarreguin resultants de modificacions del programa, tan en augment com disminució o simplement variacions, sempre i quan el import de les mateixes no alteri en més o menys d’un 25% del valor contractat.

La valoració de les mateixes es farà d’acord amb els valors establerts al Pressupost lliurat per l’Empresa Programadora i que ha estat agafat com a base del contracte. El Tècnic Director del Programa està facultat per a introduir les modificacions d’acord amb els seu criteri, en qualsevol part del Programa, durant la creació, sempre que es compleixin

4 Plec de Condicions

68

les condicions tècniques referides al Projecte i de forma que no variï del import total del Programa.

4.1.7 Programa Defectuós

Quan l’Empresa Programadora trobi qualsevol part del programa defectuós, que no s’ajusti a l’especificat al Projecte o en aquest Plec de Condicions, el Tècnic Director podrà acceptar-lo o refusar-lo. En el primer cas, aquest fixarà el preu que consideri just, estan l’Empresa Programadora obligada a acceptar l’esmentada valoració. En l’altre cas, es reconstruirà a costa de l’Empresa Programadora la part mal executada, sense que sigui motiu de reclamació econòmica o d’ampliació del termini d’execució.

4.1.8 Mitjans Auxiliars

Seran de l’Empresa Programadora els medis i maquinària auxiliar que siguin necessaris per a l’execució del Programa.

4.1.9 Conservació del Programa

Es obligació de l’Empresa Programadora la conservació en perfecte estat del programa fins a la data de recepció definitiva per la Empresa Usuària, i corren al seu càrrec les despeses.

4.1.10 Recepció del Programa

4.1.10.1 Recepció provisional.

Un cop finalitzat el programa, tindrà lloc la recepció provisional, i per a això es practicarà en aquestes un detingut reconeixement pel Tècnic Director i l’Empresa Usuària en presència de l’Empresa Programadora, aixecant acta i començant a córrer des de aquell dia el termini de garantia si es troba en estat de ser admès.

De no ser admès es farà constar al acta i es donaran instruccions a l’Empresa Programadora per a esmenar els defectes observats, fixant-se un nou termini per a tal efecte, expirant, expirant el qual es procedirà a un nou reconeixement a fi de procedir a la recepció provisional.

4.1.l0.2 Llicència i drets

Un cop efectuada la recepció provisional se li entregarà a l’Empresa Usuària una llicència amb dret d’us del programa, una còpia del Programa i un Manual d’Instal·lació i

4 Plec de Condicions

69

Ús. Està llicència dóna dret d’ús que es disposi, només pot haver una còpia en ús, és a dir, instal·lada en un ordinador. No es podrà copiar, instal·lar en un altre ordinador, executar en Públic o llogar la còpia entregada del programa sense la prèvia autorització de l’Empresa Programadora. Si es vol instal·lar el Programa en un altre ordinador caldrà desinstal·lar prèviament el primer.

Aquest document, i la informació continguda, així com la resta de documents són part integrant de la documentació que acompanya la Llicència d’ús d’aquest Programa informàtic , i de la que són inseparables.

4.1.10.3 Termini de garantia

El termini de garantia serà com a mínim d’un any, comptant des de la data de la recepció provisional, o bé el que s’estableixi al contracte, també comptant des de la mateixa data. Durant aquest període queda a càrrec de l’Empresa Programadora la conservació del Programa i l’esmena dels errors observats.

4.1.10.4 Recepció Definitiva

Es farà després de transcorregut el termini de garantia de forma anàloga a la provisional. A partir d’aquesta data cessa l’obligació de l’Empresa Programadora de conservar i reparar al seu càrrec els defectes observats.

4.1.11 Contractació de l’Empresa Programadora

4.1.11.1 Mode de Contractació

El conjunt del Programa el realitzarà l’empresa escollida per concurs – subhasta.

4.1.11.2 Presentació

Les empreses seleccionades per a l’esmentat concurs deuran presentar els seus projectes abans de la data fixada per la Universitat Rovira i Virgili, que serà la titular d’aquest projecte.

4.1.11.3 Selecció

L’empresa escollida serà anunciada a la setmana següent a la conclusió del plaça d’entrega. L’esmentada empresa serà escollida de mutu acord entre l’Empresa Usuària i el Tècnic Director, sense possible reclamació per part d’altres empreses concursants.

4 Plec de Condicions

70

4.1.12 Fiança

Al contracte s’establirà la fiança que l’Empresa Programadora deurà dipositar en garantia del compliment del mateix, o es convindrà una retenció sobre els pagaments realitzats a compte del Programa realitzat.

De no estipular-ne la fiança al contracte s’entén que s’adopta com garantia una retenció del 5% sobre els pagaments a compte esmentats.

En el cas que l’Empresa Programadora és negués a fer pel seu compte els treballs per ultimar el Programa en les condicions contractades, o a atendre la garantia, l’Empresa Usuària podrà ordenar executar-les a un tercer, abonant el import amb càrrec de retenció o fiança, sense prejudici de les accions legals a que tingui dret l’Empresa Usuària si amb el import de la fiança no n’hi hagués prou.

La fiança retinguda s’abonarà a l’Empresa Programadora en un termini no superior als trenta dies un cop firmada l’acta de recepció definitiva del Programa.

4.2 Condicions Econòmiques

4.2.1 Pagament del Programa

Al contracte es deuran fixar detalladament la forma i terminis que s’abonaran les parts realitzades del Programa. Les liquidacions parcials que puguin establir-se tindran caràcter de documents provisionals, subjectes a les certificacions que resultin de la liquidació final. No suposant, les esmentades liquidacions, aprovació ni recepció del treball que comprenen.

Un cop finalitzat el Programa es procedirà a la liquidació final que s’efectuarà d’acord amb els criteris establerts al contracte.

4.2.2 Preus

L’Empresa Programadora presentarà, al formalitzar el contracte, relació dels preus de les unitats del Programa que integren el Projecte, els quals, de ser acceptats, tindran valor contractual i s’aplicaran a les variacions que puguin haver-hi.

Aquests preus unitaris, s’entén que comprenen la execució total de la unitat del Programa, incloent tots els treballs, els complements i els materials, així com la part proporcional d’imposició fiscal, les carregues laborals i altres despeses a considerar.

En cas de tenir que realitzar-se unitats de Programa no previstes al Projecte, es fixarà el preu entre el Tècnic Director i l’Empresa Programadora abans d’iniciar el Programa i es presentarà a l’Empresa Usuària per a la seva acceptació o no.

4 Plec de Condicions

71

4.2.3 Revisió de Preus

Al contracte s’establirà si l’Empresa Programadora té dret a revisió de preus i a revisió de preus i la fórmula a aplicar per a calcular-la. En defecte d’aquesta última, s’aplicarà a judici del Tècnic Director algun dels criteris oficials acceptats.

4.2.4 Penalitzacions

Per retard als terminis d’entrega del Programa, es podran establir taules de penalització, les quanties i demores dels quals es fixaran al contracte.

4.2.5 Contracte

El contracte es formalitzarà mitjançant document privat, que podrà elevar-se a escriptura pública a petició de qualsevol de les parts. Comprendrà l’adquisició de tots els materials, transport, ma d’obra, mitjans auxiliars per a l’execució del Programa projectat en el termini estipulat, així com la reconstrucció de les unitats defectuoses, la realització de les parts complementaries i les derivades de les modificacions que s’introdueixin durant l’execució, aquestes últimes als terminis previstos.

La totalitat dels documents que componen el Projecte Tècnic del Programa seran incorporats al contracte i tan el contractista com la Empresa Usuària deuran firmar-los en testimoni de que els coneixen i accepten.

4.2.6 Responsabilitats

L’Empresa Programadora és la responsable en les condicions establertes al Projecte i al contracte. Com conseqüència d’això, estarà obligada a l’eliminació del que estes mal executat i a las seva reconstrucció correcta sense que serveixi d’excusa que el Tècnic Director hagi examinat i reconegut el Programa.

L’Empresa Programadora és la única responsable de totes les contravencions que aquesta o el seu personal cometin durant l’execució del Programa o operacions relacionades amb el mateix. També és responsable dels danys que, per errors, inexperiència o ús de mètodes inadequats es produeixin en l’Empresa Usuària.

L’Empresa Programadora és l’única responsable de l’incompliment de les disposicions vigents en la matèria laboral respecte del seu personal.

4 Plec de Condicions

72

4.2.7 Rescissió del Contracte

4.2.7.1 Causes de Rescissió

Es consideraran causes suficients per la rescissió del contracte les següents:

1. Mort o incapacitat de l’Empresa Programadora

2. Fallida de l’Empresa Programadora

3. Modificació del Projecte quan produeixi alteració en més o menys 25% del valor contractat.

4. Modificació de les unitats de Programa en nombre superior al 40% del original.

5. La no iniciació de la programació en el termini estipulat quan sigui per causes alienes a l’Empresa Programadora.

6. La suspensió de la programació ja iniciada, sempre que el termini de suspensió sigui major de sis mesos.

7. Incompliment de les condicions del Contracte quan impliqui mala fe.

8. Finalització del termini d’execució del Programa sense haver arribat a completar aquest.

9. Actuació de mala fe en la execució dels treballs.

10. Subcontractar la totalitat o part del Programa a tercers sense la autorització del Tècnic Director i de l’Empresa Usuària.

4.2.8 Liquidació en el cas de Rescissió del Contracte

Sempre que es rescindeixi el Contracte per alguna o varies causes anteriors, o bé, per acord d’ambdues parts, s’abonarà a l’Empresa Programadora les Unitats de Programa ja finalitzades.

Quan es rescindeixi el contracte portarà implícit la retenció de la fiança per a obtenir les possibles despeses e conservació del període de garantia i els derivats del manteniment fins la data de nova adjudicació.

4 Plec de Condicions

73

4.3 Conclusions

Les parts interessades manifesten conèixer els termes d’aquest plec de condicions i del Projecte Tècnic que s’adjunta.

Tarragona, setembre de 2006

JUAN DAVID ROIG MAURI

Enginyer Tècnic Industrial en Electrònica Industrial

74

5 Annexes

75

En l’Annex es mostra el codi del fitxer magatzem003View.cpp. Aquest fitxer conté tot el codi de l’aplicació, incloent el codi de la part de control del magatzem

magatzem003View.cpp Página:1/61C:\ Última modificación: 25/09/2006 06:08:22

// magatzem003View.cpp : implementation of the CMagatzem003View class//

#include "stdafx.h"#include <math.h>#include "magatzem003.h"

#include "magatzem003Doc.h"#include "magatzem003View.h"

#include "nofitxerDialog.h"#include "nohistorialDialog.h"#include "noestadistiquesDialog.h"

#include "entradaDialog.h"#include "sortidaDialog.h"#include "canviDialog.h"

#include "EntradaDirectaDialog.h"#include "SortidaDirectaDialog.h"#include "CanviDirectaDialog.h"

#include "automaticDialog.h"#include "DialogEntradaDades.h"

#include "OpcError.h"#include "opc.h"#include "opc_i.c"

#include "ProgressWnd.h"

/*********************************** Includes del programa de control/***********************************/#include "magatzem.h"#include "C:\MCC\CWIN\cbw.h"

#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif

/*************************************************** Capçalera de les funcions que s'utilitzen al thread ****************************************************/DWORD WINAPI myThread(LPVOID lpParameter); //ThreadHANDLE frame; //Eventvoid escriure_plc_palet(int casella, int valor_plc); //Per escriure al PLC des de threadint llegir_plc_palet(int casella); //Per lliegir al PLC des de thread

bool arriba_palet=0; static short arriba_palet2=0;static short acabada_accio;static short accio_manual;static short valor_palet, valor_e_s;int cnt1=0static short passos_accio;static bool no_palet,palet0,paletx; //Variables per quan no es troba // el palet en la funcio cerca_palet

static short casella_accio;static bool entra_linia;

/************************************ Variable del control del magatzem*************************************/#define REST 2047#define RANGO 2000#define RECOGIDO 1#define BAJADO 2#define EXTENDIDO 3#define ARRIBA 4

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:2/61C:\ Última modificación: 25/09/2006 06:08:22

#define TREU 0#define DESA 1#define MOU 2#define CALIBRA 3

#define MIG 5#define DRETA 6#define ESQUERRA 7

magatzem pid1, pid2; //Creación de objetos

static short auxpulsos,pulsos1, pulsos2, pulsos;static unsigned short bit,posi,costat,costat_d;static double wp_memo1, wp_memo2;static short pasos_x=0,pasos_y=0, cuenta=0, pd=0, pt=0, pm=0;//Vector para la calibración de cada posiciónstruct { int x, y;} pos[73];

/************************************ Funcions del control del magatzem*************************************//*********************************************************************************** Funció del control de magatzemRetorna 1 cuando la bandeja no està en ninguna de susposiciones de reposo por tanto en movimiento o error.Retorna 0 cuando se encuentra en una de las tres posiciones posibles.************************************************************************************/

bool CMagatzem003View::mou_safata (int costat){ unsigned short bit1,bit2, bit3; cbDBitOut(0,AUXPORT,costat,1); //Mueve hacia al lado indicado. cbDBitIn(0, FIRSTPORTA,MIG,&bit1); //Lectura de los sensores de posición cbDBitIn(0, FIRSTPORTA,DRETA,&bit2); //de la bandeja. cbDBitIn(0, FIRSTPORTA,ESQUERRA,&bit3); if ((bit1)&&(bit2)&&(bit3)){ //Cuando esten todos activos el relé cbDBitOut(0,AUXPORT,costat,0); //correspondiente estarà activo. Entonces return 1; //bandeja en movimiento. }

return 0;}

/***********************************************************************************Funció del control del magatzemRetorna 1 cuando la plataforma se encuentra en posición correctaRetorna 0 en caso contrario************************************************************************************/

bool CMagatzem003View::pos_ok(){static short compta; if (compta==1) { compta=0; return 1; } if ((pid1.error0==0)&&(pid2.error0==0)) { compta++; return 0; }

return 0;}

/**********************************************************************************Funció del control del magatzemRealiza la secuencia de la bandeja según el lado de extension y la acción de recogida o depósito.***********************************************************************************/

bool CMagatzem003View::seq_safata(unsigned short costat,unsigned short fer) { static short ps=1; switch (ps){ case 1: { if (pos_ok()) ps=2;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:3/61C:\ Última modificación: 25/09/2006 06:08:22

return 0; } break; case 2: { if (mou_safata(costat)) ps=3; return 0; }break; case 3:{ cbDBitIn(0, FIRSTPORTA,costat,&bit); if (!bit) { if (!fer) pid2.wishpos+=175; else pid2.wishpos-=175; ps=4; } return 0; }break; case 4:{ if (pos_ok()) ps=5; return 0; }break; case 5:{ if (costat==DRETA) { if (mou_safata(costat+1)) ps=6; } else { if (mou_safata (costat-1)) ps=6; } return 0; }break; case 6:{ cbDBitIn(0, FIRSTPORTA,5,&bit); //safata al mig if (!bit){ ps=1; return 1; } }break; }

return 0;}/*******************************Funció del control del magatzem********************************/bool CMagatzem003View::comprova_parametres (unsigned short cp_a, unsigned short cp_c, unsigned short cp_c_d) {

if ((cp_a<0)||(cp_a>3)) { return 1; MessageBox("Parametro incorrecto",NULL, MB_OK | MB_ICONEXCLAMATION); } else { switch (cp_a) { case TREU: { if ((cp_c_d!=NULL)||(cp_c<1)||(cp_c>72)){ MessageBox("Parametro incorrecto",NULL, MB_OK | MB_ICONEXCLAMATION); return 1; } }break; case DESA: { if ((cp_c_d!=NULL)||(cp_c<1)||(cp_c>72)) { MessageBox("Parametro incorrecto",NULL, MB_OK | MB_ICONEXCLAMATION); return 1; } }break; case MOU: { if ((cp_c_d<1)||(cp_c_d>72)||(cp_c<1)||(cp_c>72)||(cp_c==cp_c_d)) { MessageBox("Parametro incorrecto",NULL, MB_OK | MB_ICONEXCLAMATION); return 1; } } break;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:4/61C:\ Última modificación: 25/09/2006 06:08:22

case CALIBRA: { if ((cp_c!=NULL)||(cp_c_d!=NULL)) { MessageBox("Parametro incorrecto",NULL, MB_OK | MB_ICONEXCLAMATION); return 1; } } break; } }return 0;}

/*******************************Funció del control del magatzem********************************/void CMagatzem003View::magatzem(unsigned short accio, unsigned short casella1, unsigned short casella2 ){if (!comprova_parametres(accio,casella1,casella2)&&(!pt)&&(!pm)&&(!pd)) { //Verifica parametros y que no haya //ningún proceso en marcha if ((0<casella1)&&(casella1<37)) costat=ESQUERRA; if ((36<casella1)&&(casella1<73)) costat=DRETA; switch (accio) { case TREU:{ if (!SetTimer(4,500,NULL)) { MessageBox("ERROR starting Windows Timer",NULL, MB_OK | MB_ICONEXCLAMATION); break; } pid1.wishpos=pos[casella1].x; pid2.wishpos=pos[casella1].y; posi=casella1; pt=1; sortint=1;

}break; case DESA:{ if (!SetTimer(3,500,NULL)){ MessageBox("ERROR starting Windows Timer",NULL, MB_OK | MB_ICONEXCLAMATION); break; } pid1.wishpos=pos[0].x; pid2.wishpos=pos[0].y; posi=casella1; pd=1; entrant=1; }break; case MOU:{ if ((0<casella2)&&(casella2<37)) costat_d=ESQUERRA; if ((36<casella2)&&(casella2<73)) costat_d=DRETA; if (!SetTimer(5,500,NULL)) { MessageBox("ERROR starting Windows Timer",NULL, MB_OK | MB_ICONEXCLAMATION); break; } pid1.wishpos=pos[casella1].x; pid2.wishpos=pos[casella1].y; posi=casella2; pm=1; ordenant=1;

}break; case CALIBRA:{ calibra(); }break; } } else if ((pt)||(pm)||(pd)) MessageBox("ERROR Proceso Activo",NULL, MB_OK | MB_ICONEXCLAMATION);} /*******************************Funció del control del magatzem********************************/void CMagatzem003View::calibra () { if ((pt)||(pm)||(pd)) { MessageBox("ERROR Proceso Activo",NULL, MB_OK | MB_ICONEXCLAMATION);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:5/61C:\ Última modificación: 25/09/2006 06:08:22

} else { KillTimer(1); wp_memo1=pid1.wishpos; wp_memo2=pid2.wishpos; cbAOut(0,0,BIP10VOLTS,2047); cbAOut(0,1,BIP10VOLTS,2057); if (!SetTimer(2,50,NULL)) MessageBox("ERROR starting Windows Timer",NULL, MB_OK | MB_ICONEXCLAMATION); pasos_x=1; pasos_y=1; cbAOut(0,0,BIP10VOLTS,-RANGO+2047); cbAOut(0,1,BIP10VOLTS,-RANGO+2057); calibrant=1; }

}

/*******************************Funció del control del magatzem********************************/bool CMagatzem003View::recull_cinta(){static unsigned short bit,prc=1; switch (prc) { //pasos recoge cinta case 1:{ cbDBitOut(0,AUXPORT,2,1); //Extiende brazo cbDBitIn(0, FIRSTPORTA,RECOGIDO,&bit); if (bit) { prc=2; cbDBitOut(0,AUXPORT,2,0); } }break; case 2:{ cbDBitIn(0, FIRSTPORTA,EXTENDIDO,&bit); if (!bit) prc=3; }break;

case 3:{ cbDBitOut(0,AUXPORT,3,1); //sube brazo cbDBitIn(0, FIRSTPORTA,2,&bit); //lectura sensor abajo if (bit) { prc=4; cbDBitOut(0,AUXPORT,3,0); } }break; case 4:{ cbDBitIn(0, FIRSTPORTA,ARRIBA,&bit); if (!bit) prc=5; }break;

case 5:{ cbDBitOut(0,AUXPORT,4,1); //recoge brazo cbDBitIn(0, FIRSTPORTA,3,&bit); if (bit) { prc=6; cbDBitOut(0,AUXPORT,4,0); } }break; case 6:{ cbDBitIn(0, FIRSTPORTA,RECOGIDO,&bit); if (!bit) prc=7; }break; case 7:{ cbDBitOut(0,AUXPORT,5,1); //baja brazo cbDBitIn(0, FIRSTPORTA,4,&bit); if (bit) { prc=8; cbDBitOut(0,AUXPORT,5,0); } }break; case 8:{ cbDBitIn(0, FIRSTPORTA,BAJADO,&bit);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:6/61C:\ Última modificación: 25/09/2006 06:08:22

if (!bit){ prc=1; return 1; } }break;

}

return 0;}/*******************************Funció del control del magatzem********************************/bool CMagatzem003View::deposita_cinta(){

static unsigned short bit,pdc=1;switch (pdc) { //pasos deposita en cinta case 1:{ cbDBitOut(0,AUXPORT,3,1); //sube brazo cbDBitIn(0, FIRSTPORTA,2,&bit); //lectura sensor abajo if (bit) { pdc=2; cbDBitOut(0,AUXPORT,3,0); } }break; case 2:{ cbDBitIn(0, FIRSTPORTA,ARRIBA,&bit); if (!bit) pdc=3; }break;

case 3:{ cbDBitOut(0,AUXPORT,2,1); //Extiende brazo cbDBitIn(0, FIRSTPORTA,RECOGIDO,&bit); if (bit) { pdc=4; cbDBitOut(0,AUXPORT,2,0); } }break; case 4:{ cbDBitIn(0, FIRSTPORTA,EXTENDIDO,&bit); if (!bit) pdc=5; }break;

case 5:{ cbDBitOut(0,AUXPORT,5,1); //baja brazo cbDBitIn(0, FIRSTPORTA,4,&bit); if (bit) { pdc=6; cbDBitOut(0,AUXPORT,5,0); } }break; case 6:{ cbDBitIn(0, FIRSTPORTA,BAJADO,&bit); if (!bit) pdc=7; }break;

case 7:{ cbDBitOut(0,AUXPORT,4,1); //recoge brazo cbDBitIn(0, FIRSTPORTA,3,&bit); if (bit) { pdc=8; cbDBitOut(0,AUXPORT,4,0); } }break; case 8:{ cbDBitIn(0, FIRSTPORTA,RECOGIDO,&bit); if (!bit) { pdc=1;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:7/61C:\ Última modificación: 25/09/2006 06:08:22

return 1; } }break; }

return 0;}

//// Used by GetErrorString; Language code ////#define LOCALE_ID 0x409 // Code 0x409 = ENGLISH

//// ItemID used in this sample//const LPWSTR szItemID = L"S7:[DEMO]MB0";

// Prototype//CString GetQualityText(UINT qnr);

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View

IMPLEMENT_DYNCREATE(CMagatzem003View, CView)

BEGIN_MESSAGE_MAP(CMagatzem003View, CView) //{{AFX_MSG_MAP(CMagatzem003View) ON_COMMAND(ID_ACCIONS_ENTRADADEPALET, OnAccionsEntradadepalet) ON_COMMAND(ID_ACCIONS_SORTIDADEPALET, OnAccionsSortidadepalet) ON_COMMAND(ID_ACCIONS_CANVIUBICACIPALET, OnAccionsCanviubicacipalet) ON_COMMAND(ID_ACCIONS_ACTIVARDESACTIVARMDUSAUTMATIC, OnAccionsActivardesactivarmdusautmatic) ON_WM_TIMER() ON_COMMAND(ID_ARCHIVO_MODIFICARMAGATZEM, OnArchivoModificarmagatzem) ON_COMMAND(ID_ACCIONS_ENTRADADEDADES, OnAccionsEntradadedades) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_RBUTTONUP() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View construction/destruction

CMagatzem003View::CMagatzem003View(){/**************************************************** Inicialitzacio de variables del control de magatzem*****************************************************/int aux,eix_x,eix_y;

for (int i=1;i<73;i++) { if (i>36) aux=i-37; else aux=i-1; eix_x=(5-(aux%6)); eix_y=aux/6; if (i<37) pos[i].x=(eix_x*1304)+8; else pos[i].x=(eix_x*1304)-22; pos[i].y=(eix_y*1304)+680;}

pos[0].x=8102;pos[0].y=16;

pos[1].x+=0; pos[2].x+=0; pos[3].x+=0; pos[4].x+=0; pos[5].x+=0; pos[6].x+=0; pos[1].y+=0; pos[2].y+=0; pos[3].y+=-8; pos[4].y+=-10; pos[5].y+=-6; pos[6].y+=0; pos[7].x+=0; pos[8].x+=0; pos[9].x+=0; pos[10].x+=0; pos[11].x+=0; pos[12].x+=0;pos[7].y+=0; pos[8].y+=-4; pos[9].y+=-6; pos[10].y+=-4; pos[11].y+=0; pos[12].y+=-2;

pos[13].x+=0; pos[14].x+=0; pos[15].x+=0; pos[16].x+=0; pos[17].x+=0; pos[18].x+=0;pos[13].y+=2; pos[14].y+=2; pos[15].y+=2; pos[16].y+=4; pos[17].y+=4; pos[18].y+=6;

pos[19].x+=0; pos[20].x+=0; pos[21].x+=0; pos[22].x+=0; pos[23].x+=0; pos[24].x+=0;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:8/61C:\ Última modificación: 25/09/2006 06:08:22

pos[19].y+=-12; pos[20].y+=-8; pos[21].y+=-5; pos[22].y+=-4; pos[23].y+=-3; pos[24].y+=3;

pos[25].x+=0; pos[26].x+=0; pos[27].x+=0; pos[28].x+=0; pos[29].x+=0; pos[30].x+=0; pos[25].y+=-5; pos[26].y+=-4; pos[27].y+=-3; pos[28].y+=-2; pos[29].y+=1; pos[30].y+=3;

pos[31].x+=-1; pos[32].x+=-1; pos[33].x+=-1; pos[34].x+=-1; pos[35].x+=-1; pos[36].x+=-1; pos[31].y+=11; pos[32].y+=11; pos[33].y+=13; pos[34].y+=13; pos[35].y+=13; pos[36].y+=13;

//************************************************************************************************

pos[37].x+=0; pos[38].x+=0; pos[39].x+=0; pos[40].x+=0; pos[41].x+=0; pos[42].x+=0;pos[37].y+=0; pos[38].y+=0; pos[39].y+=0; pos[40].y+=0; pos[41].y+=0; pos[42].y+=0;

pos[43].x+=0; pos[44].x+=0; pos[45].x+=0; pos[46].x+=0; pos[47].x+=0; pos[48].x+=0;pos[43].y+=0; pos[44].y+=0; pos[45].y+=0; pos[46].y+=0; pos[47].y+=-2; pos[48].y+=0;

pos[49].x+=0; pos[50].x+=0; pos[51].x+=0; pos[52].x+=1; pos[53].x+=0; pos[54].x+=1;pos[49].y+=0; pos[50].y+=0; pos[51].y+=-1; pos[52].y+=0; pos[53].y+=0; pos[54].y+=0;

pos[55].x+=1; pos[56].x+=1; pos[57].x+=0; pos[58].x+=0; pos[59].x+=0; pos[60].x+=1;pos[55].y+=0; pos[56].y+=0; pos[57].y+=0; pos[58].y+=0; pos[59].y+=0; pos[60].y+=0;

pos[61].x+=0; pos[62].x+=0; pos[63].x+=0; pos[64].x+=0; pos[65].x+=0; pos[66].x+=0;pos[61].y+=0; pos[62].y+=0; pos[63].y+=0; pos[64].y+=0; pos[65].y+=0; pos[66].y+=0;

pos[67].x+=1; pos[68].x+=1; pos[69].x+=1; pos[70].x+=1; pos[71].x+=1; pos[72].x+=1;pos[67].y+=0; pos[68].y+=0; pos[69].y+=0; pos[70].y+=0; pos[71].y+=0; pos[72].y+=0; ///////////////////////////////////////////////////////////////////////// //Inicilitzacio de variables

automatic=0; calibrant=0; entrant=0, sortint=0; ordenant=0; //Variables utilitzades en la barra d'informació posicio.x=0; posicio.y=0; posicio.z=0;

casella_inicial=1; //S'utilitza en la funció cerca de palet primera_entrada=1; primera_lectura=1; primera_escriptura=1;

fitxer_dades (); //Comprobació i creació fitxer de dades fitxer_historial (); //Comprobació i creació fitxer d'historial

inicialitzacio_opc(); //Inicialitza l'OPC per facilitar un més rápid accés

// TODO: add construction code here}

CMagatzem003View::~CMagatzem003View(){}

BOOL CMagatzem003View::PreCreateWindow(CREATESTRUCT& cs){ // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs

return CView::PreCreateWindow(cs);}

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View drawing

void CMagatzem003View::OnDraw(CDC* pDC){ CMagatzem003Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

if (primera_entrada==1) { traspas_dades_PLC(); primera_entrada=0; primera_escriptura=0; }

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:9/61C:\ Última modificación: 25/09/2006 06:08:22

///////////////////////////////////// //Variables del control del magatzem //////////////////////////////////// static bool inicio=TRUE; if (inicio){ inicio=false; pid1.def_parametres(20,100,5,50); //proporcional,integrativo,derivativo,muestreo pid2.def_parametres(20,150,10,50); calibra(); wp_memo1=pos[16].x; wp_memo2=pos[16].y; }

////////////////////////////////// /// Representació dels mòdul ////////////////////////////////// dist1x=38; //Distancia X mòdul1 dist1y=75; //Distancia Y mòdul1 dist2x=532; //Distancia X mòdul2 dist2y=75; //Distancia Y mòdul2 costat1x=75; //Amplada de caselles mòdul1 costat1y=63; //Altura de caselles mòdul costat2x=75; //Amplada de caselles mòdul2 costat2y=63; //Altura de caselles mòdu2

ample_pesa=20; //Amaplada de cada cilindre POINT modul1[4*FIL*COL]; //Array de variables punts Modul1 POINT modul2[4*FIL*COL]; //Array de variables punts Modul2 int i; int j; int contx=0; int conty=0; int contyy=0; for (i=0; i<4*FIL*COL; i=i+4) // Es cren tots el punts de cada rectangle de cada // casella del Mòdul 1 { modul1[i].x=dist1x+costat1x*contx; modul1[i+1].x=dist1x+costat1x*(contx+1); modul1[i+2].x=dist1x+costat1x*(contx+1); modul1[i+3].x=dist1x+costat1x*contx; modul1[i].y=dist1y+costat1y*contyy; modul1[i+1].y=dist1y+costat1y*contyy; modul1[i+2].y=dist1y+costat1y*(contyy+1); modul1[i+3].y=dist1y+costat1y*(contyy+1);

contx++; conty++;

if (contx>=(COL)) contx=0; if (conty==(COL)) { contyy++; conty=0; } }

contx=0; conty=0; contyy=0;

for (i=0; i<4*FIL*COL; i=i+4) // Es cren tots el punts de cada rectangle de cada { // casella del Mòdul 1 modul2[i].x=dist2x+costat2x*contx; modul2[i+1].x=dist2x+costat2x*(contx+1); modul2[i+2].x=dist2x+costat2x*(contx+1); modul2[i+3].x=dist2x+costat2x*contx;

modul2[i].y=dist2y+costat2y*contyy; modul2[i+1].y=dist2y+costat2y*contyy;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:10/61C:\ Última modificación: 25/09/2006 06:08:22

modul2[i+2].y=dist2y+costat2y*(contyy+1); modul2[i+3].y=dist2y+costat2y*(contyy+1);

contx++; conty++;

if (contx>=(COL)) contx=0; if (conty==(COL)) { contyy++; conty=0; } } int casella1 [FIL*COL], *p_casella1; int casella2 [FIL*COL], *p_casella2; p_casella1=casella1; p_casella2=casella2;

for (i=0;i<FIL*COL;i++) { casella1[i]=4; casella2[i]=4; }

///////////////////////////////////////////// //Representació bases de les caselles ///////////////////////////////////////////// COLORREF clr20=RGB(150, 150, 150);

int ample_base=20; for (i=0; i<FIL*COL*4; i=i+(4*COL)) //Es crea les bases de cada casella Modul 1 { pDC->FillSolidRect(modul1[i].x, modul1[i].y+costat1y-19, costat1x*(FIL),ample_base, clr20); } for (i=0; i<FIL*COL*4; i=i+(4*COL)) //Es crea les bases de cada casella Modul 2 { pDC->FillSolidRect(modul2[i].x, modul2[i].y+costat2y-19, costat2x*(FIL),20, clr20); }

///////////////////////////////////////// //Linies separació bases de les caselles ///////////////////////////////////////// CPen* oldllapis1; //punter per guardar el llapis anterior CPen llapis1; //clase llapis

llapis1.CreatePen (PS_SOLID,2,RGB(150,150,150)); //llapis per linies oldllapis1 = pDC->SelectObject (&llapis1); //llapis anteriot guardat

for (i=0; i<FIL+1 ; i++) //linies verticals mòdul 1 { pDC->MoveTo(dist1x+costat1x*i,dist1y-1); pDC->LineTo(dist1x+costat1x*i,dist1y+costat1y*FIL-1); } for (i=0; i<FIL+1 ; i++) //linies verticals mòdul 2 { pDC->MoveTo(dist2x+costat2x*i,dist2y-1); pDC->LineTo(dist2x+costat2x*i,dist2y+costat2y*FIL-1); }

pDC->MoveTo(dist1x,dist1y); //linia horitzontal superior mòdul 1 pDC->LineTo(dist1x+costat1x*FIL,dist1y-1);

pDC->MoveTo(dist2x,dist2y); //linia horitzontal superior mòdul 2 pDC->LineTo(dist2x+costat2x*FIL,dist2y-1);

//////////////////////////////////////// //Numeració caselles //////////////////////////////////////// int k=0; int num_base1=31; //Pel mòdul1 int num_base2=72; //Pel mòdul2 char n_base1[1]; //S'utilitza per convertir el sencer a caracter per visualitzar per panatalla modul1 char n_base2[1]; //S'utilitza per convertir el sencer a caracter per visualitzar per panatalla modul2

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:11/61C:\ Última modificación: 25/09/2006 06:08:22

for (i=0; i<FIL; i++) { for (j=0; j< COL; j++, k=k+4) { itoa(num_base1,n_base1,10); //Es converteix el int a char per visualitzarlo Modul1 itoa(num_base2,n_base2,10); //Es converteix el int a char per visualitzarlo Modul2 if (num_base1<10) { //Es represnta cada numero de casella modul1 pDC->TextOut(modul1[k].x+costat1x/2-2,modul1[k].y+costat1y-17,n_base1); } else { //Es represnta cada numero de casella modul2 pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+costat1y-17,n_base1); } if (j==COL-1) { num_base1=num_base1-FIL*2; } pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+costat2y-17,n_base2); num_base1++; num_base2--; } }//////////////////////////////////////////////////////////////////////////////Dibuix del recuadre quan es posiciona el ratoli

CPen* oldllapis2; //punter per guardar el llapis anterior CPen llapis2; //clase llapis CPen* oldllapis3; //punter per guardar el llapis anterior CPen llapis3; //clase llapis if (ind_mod1==1) { llapis2.CreatePen (PS_SOLID,2,RGB(94,174,255)); //S'asigna el color del lalpis oldllapis2 = pDC->SelectObject (&llapis2); pDC->Rectangle(dist1x+nCol*costat1x+2, dist1y+nFil*costat1y+2, dist1x+costat1x+nCol*costat1x+1-1, dist1y+costat1y+nFil*costat1y+1-1-ample_pesa+2); pDC->SelectObject (oldllapis2); } if (ind_mod2==1) { llapis3.CreatePen (PS_SOLID,2,RGB(94,174,255)); //S'asigna el color del lalpis oldllapis3 = pDC->SelectObject (&llapis3); pDC->Rectangle(dist2x+nCol2*costat2x+2, dist2y+nFil2*costat2y+2, dist2x+costat2x+nCol2*costat2x+1-1, dist2y+costat2y+nFil2*costat2y+1-1-ample_pesa+2); pDC->SelectObject (oldllapis3); } ////////////////////////////////////////////////////////////////////////////// Representació de cada peça i el seu nombre

COLORREF negre_pesa=RGB(0,0,0); //Es defineix el color dels cilindres COLORREF roig_pesa=RGB(255,0,0); COLORREF gris_pesa=RGB(220,220,220);

COLORREF blanc=RGB(255,255,255); char tipus_pesa[1]; COLORREF color_num_palet=RGB(158,153,253); pDC->SetTextColor(color_num_palet);

k=168; for (j=0; j< 36; j++,k=k+4) { if(j%6==0) { k=k-48; } switch (almacen[j]) //Es representen les peces del mòdul 1 { case 0: break; case 1: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 2: itoa(almacen[j],tipus_pesa,10);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:12/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 3: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 4: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 5: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 6: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 7: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 8: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 9: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-1,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 10:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 11:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 12:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 13:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:13/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 14:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 15:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 16:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra break; case 17:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 18:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 19:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 20:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 21:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 22:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:14/61C:\ Última modificación: 25/09/2006 06:08:22

break; case 23:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 24:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 25:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 26:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 27:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 28:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 29:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 30:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 31:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:15/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 32:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra break; case 33:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 34:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 35:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 36:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 37:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 38:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 39:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 40:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:16/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 41:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 42:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 43:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 44:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 45:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 46:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 47:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 48:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra break;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:17/61C:\ Última modificación: 25/09/2006 06:08:22

case 49:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 50:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 51:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 52:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 53:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 54:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 55:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 56:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 57:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:18/61C:\ Última modificación: 25/09/2006 06:08:22

break; case 58:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 59:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 60:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 61:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 62:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 63:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul1[k].x+costat1x/2-6,modul1[k].y+3,tipus_pesa); pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2-ample_pesa-2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul1[k].x+costat1x/2-ample_pesa/2+ample_pesa+2, modul1[k].y+costat1y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 64: pDC->MoveTo(modul1[k].x,modul1[k].y); pDC->LineTo(modul1[k].x+costat1x,modul1[k].y+costat1y-ample_base); pDC->MoveTo(modul1[k].x+costat1x,modul1[k].y); pDC->LineTo(modul1[k].x,modul1[k].y+costat1y-ample_base); break; } } k=140; for (j=36; j<72; j++, k=k-4) { switch (almacen[j]) //Es representen les peces del mòdul 1 { case 0: break; case 1: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:19/61C:\ Última modificación: 25/09/2006 06:08:22

break; case 2: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 3: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 4: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 5: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 6: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 7: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 8: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 9: itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 10:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 11:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 12:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:20/61C:\ Última modificación: 25/09/2006 06:08:22

case 13:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 14:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 15:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 16:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra break; case 17:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 18:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 19:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 20:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 21:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 22:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:21/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 23:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 24:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 25:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 26:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 27:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 28:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 29:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 30:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:22/61C:\ Última modificación: 25/09/2006 06:08:22

case 31:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 32:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra break; case 33:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 34:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 35:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 36:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 37:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 38:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 39:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 40:itoa(almacen[j],tipus_pesa,10);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:23/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 41:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 42:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 43:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 44:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 45:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 46:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 47:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 48:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:24/61C:\ Última modificación: 25/09/2006 06:08:22

break; case 49:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 50:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 51:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 52:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central break; case 53:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 54:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 55:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 56:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central break; case 57:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:25/61C:\ Última modificación: 25/09/2006 06:08:22

break; case 58:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 59:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 60:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central break; case 61:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,roig_pesa); //posició dreta break; case 62:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,gris_pesa); //posició dreta break; case 63:itoa(almacen[j],tipus_pesa,10); pDC->FillSolidRect(0,900,1,1,blanc); //Està posat per que la numeració surti en blanc pDC->TextOut(modul2[k].x+costat2x/2-6,modul2[k].y+3,tipus_pesa); pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2-ample_pesa-2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició esquerra pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició central pDC->FillSolidRect(modul2[k].x+costat2x/2-ample_pesa/2+ample_pesa+2, modul2[k].y+costat2y-ample_base-ample_pesa-1,ample_pesa,ample_pesa,negre_pesa); //posició dreta break; case 64:pDC->MoveTo(modul2[k].x,modul2[k].y); pDC->LineTo(modul2[k].x+costat2x,modul2[k].y+costat2y-ample_base); pDC->MoveTo(modul2[k].x+costat2x,modul2[k].y); pDC->LineTo(modul2[k].x,modul2[k].y+costat2y-ample_base); } }

///////////////////////////////////////////////// //Representació del rectangle superior del mòduls ////////////////////////////////////////////////// COLORREF color_rectangles=RGB(74, 74, 255); //Color rectangles mòduls pDC->FillSolidRect(dist1x-2,dist1y-24,costat1x*COL+1+2,23, color_rectangles); //rectangle mòdul1 horinzontal pDC->FillSolidRect(dist2x-2,dist2y-24,costat2x*COL+1+2,23, color_rectangles); //rectangle mòdul2 horinzontal

///////////////////////////////////////////////////////////////////////////////////// // Contingut rectangles de color en cada mòdul COLORREF color_text_modul=RGB(0,0,0); pDC->SetTextColor(color_text_modul);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:26/61C:\ Última modificación: 25/09/2006 06:08:22

pDC->TextOut(dist1x+3, dist1y-20,"MÒDUL 1"); //Text MÒDUL 1 pDC->TextOut(dist2x+3, dist2y-20,"MÒDUL 2"); //Text MÒDUL 2

///////////////////////////////////////////////////////////////////////////////////// // Rectangle barra d'informació superior ///////////////////////////////////////////////////////////////////////////////////// COLORREF color_barra=RGB(150, 150, 255); //Color de la barra superior pDC->FillSolidRect(0,0,1400,30,color_barra); //Rectangle barra duperior

///////////////////////////////////////////////////////////// //Creació de linies de la barra d'informació ///////////////////////////////////////////////////////////// CPen* oldllapis; //punter per guardar el llapis anterior CPen llapis; //clase llapis

llapis.CreatePen (PS_SOLID,1,RGB(50,50,255)); //llapis per linies oldllapis = pDC->SelectObject (&llapis); //llapis anteriot guardat

pDC->MoveTo(146,3); //Linies de separació pDC->LineTo(146,27); //Linies de separació pDC->MoveTo(285,3); //Linies de separació pDC->LineTo(285,27); //Linies de separeció pDC->SelectObject (oldllapis); //Es torna a deixar el llapis anterior

///////////////////////////////////////////////////// // Missatges de la barra d'informació ///////////////////////////////////////////////////// COLORREF taronja_fosc=RGB(50,50,255); pDC->SetTextColor(taronja_fosc); pDC->TextOut(10,7,"Mòdus:"); pDC->TextOut(154,7,"Acció:"); pDC->TextOut(293,7,"Tipus palet:"); COLORREF negre=RGB(0,0,0); pDC->SetTextColor(negre); if (automatic==1) pDC->TextOut(62,7,"AUTOMÀTIC"); else pDC->TextOut(62,7,"MANUAL");

if (calibrant==1) pDC->TextOut(195,7,"CALIBRATGE"); if (entrant==1) { pDC->TextOut(195,7,"ENTRADA"); pDC->TextOut(375,7,valor_palet); } if (sortint==1) pDC->TextOut(195,7,"SORTIDA"); if (ordenant==1) pDC->TextOut(195,7,"ORDENACIÓ");

////////////////////////////////////////////////Representació palet que entra//////////////////////////////////////////////if ( arriba_palet==1){ int xpalet=460; int ypalet=550; int costatx_palet=100; int costaty_palet=50; int ample_cercle=12; int x1cercle1=xpalet+12; int y1cercle1=ypalet+28; int x1cercle2=xpalet+45; int y1cercle2=ypalet+10; int x1cercle3=xpalet+77; int y1cercle3=ypalet+28; short inte=val_palet; int nombre1, nombre2, nombre3; char buffer[6]; itoa (inte,buffer,2);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:27/61C:\ Última modificación: 25/09/2006 06:08:22

nombre1=(buffer[1]-48)+(buffer[0]-48)*2; nombre2=(buffer[3]-48)+(buffer[2]-48)*2; nombre3=(buffer[5]-48)+(buffer[4]-48)*2;

if(nombre1<=0) nombre1=0; if(nombre2<=0) nombre2=0; if(nombre3<=0) nombre3=0; pDC->FillSolidRect (xpalet+2, ypalet+2, costatx_palet+2, costaty_palet+2, gris_pesa); pDC->FillSolidRect (xpalet, ypalet, costatx_palet, costaty_palet, clr20);

//CPen cnegre; CPen* oldcnegre; CPen* oldcroig; CPen* oldcgris; CPen* oldcblanc;

CPen cnegre (PS_SOLID,12,RGB(0,0,0)); CPen croig (PS_SOLID,12,RGB(255,0,0)); CPen cgris (PS_SOLID,12,RGB(220,220,220)); CPen cblanc (PS_SOLID,12,RGB(255,255,255));

switch (nombre1) { case 1: { oldcroig = pDC->SelectObject (&croig); //Color roig pDC->Ellipse(x1cercle1, y1cercle1, x1cercle1+ample_cercle, y1cercle1+ample_cercle); //Cercle 1 - Esquerra }break; case 2: { oldcgris = pDC->SelectObject (&cgris); //Color Gris pDC->Ellipse(x1cercle1, y1cercle1, x1cercle1+ample_cercle, y1cercle1+ample_cercle); //Cercle 1 - Esquerra }break; case 3: { oldcnegre = pDC->SelectObject (&cnegre);//Color negre pDC->Ellipse(x1cercle1, y1cercle1, x1cercle1+ample_cercle, y1cercle1+ample_cercle); //Cercle 1 - Esquerra }break; case 0: { oldcblanc = pDC->SelectObject (&cblanc);//Color blanc pDC->Ellipse(x1cercle1, y1cercle1, x1cercle1+ample_cercle, y1cercle1+ample_cercle); //Cercle 1 - Esquerra }break; } switch (nombre2) { case 1: { oldcroig = pDC->SelectObject (&croig); //Color roig pDC->Ellipse(x1cercle2, y1cercle2, x1cercle2+ample_cercle, y1cercle2+ample_cercle); //Cercle 2 - Centre }break; case 2: { oldcgris = pDC->SelectObject (&cgris); //Color Gris pDC->Ellipse(x1cercle2, y1cercle2, x1cercle2+ample_cercle, y1cercle2+ample_cercle); //Cercle 2 - Centre }break; case 3: { oldcnegre = pDC->SelectObject (&cnegre);//Color negre pDC->Ellipse(x1cercle2, y1cercle2, x1cercle2+ample_cercle, y1cercle2+ample_cercle); //Cercle 2 - Centre }break; case 0: { oldcblanc = pDC->SelectObject (&cblanc);//Color blanc pDC->Ellipse(x1cercle2, y1cercle2, x1cercle2+ample_cercle, y1cercle2+ample_cercle); //Cercle 2 - Centre }break; } switch (nombre3) { case 1: { oldcroig = pDC->SelectObject (&croig); //Color roig pDC->Ellipse(x1cercle3, y1cercle3, x1cercle3+ample_cercle, y1cercle3+ample_cercle); //Cercle 3 - Dreta }break; case 2: { oldcgris = pDC->SelectObject (&cgris); //Color Gris pDC->Ellipse(x1cercle3, y1cercle3, x1cercle3+ample_cercle, y1cercle3+ample_cercle); //Cercle 3 - Dreta }break; case 3:

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:28/61C:\ Última modificación: 25/09/2006 06:08:22

{ oldcnegre = pDC->SelectObject (&cnegre);//Color negre pDC->Ellipse(x1cercle3, y1cercle3, x1cercle3+ample_cercle, y1cercle3+ample_cercle); //Cercle 3 - Dreta }break; case 0: { oldcblanc = pDC->SelectObject (&cblanc);//Color blanc pDC->Ellipse(x1cercle3, y1cercle3, x1cercle3+ample_cercle, y1cercle3+ample_cercle); //Cercle 3 - Dreta }break; }

////////////// //Linies moviment int inici_linia_x=xpalet+costatx_palet/2; int inici_linia_y=ypalet;

CPen* oldliniesmov; CPen liniesmov (PS_SOLID,2,RGB(173,173,173)); oldliniesmov = pDC->SelectObject (&liniesmov);

if (puja==1) { if ((casella_accio>=1)&(casella_accio<=36)) { pDC->MoveTo (inici_linia_x, inici_linia_y); pDC->LineTo (modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].x+33, modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].y+25);

pDC->FillSolidRect (inici_linia_x-conta*fletxax-50, inici_linia_y-conta*fletxay-50, 30, 15, negre_pesa); } else { pDC->MoveTo (inici_linia_x, inici_linia_y); pDC->LineTo (modul2[(36-(casella_accio-36))*4].x+33, modul2[(36-(casella_accio-36))*4].y+25); CRect rect1 (inici_linia_x-conta*fletxax, inici_linia_y-conta*fletxay, inici_linia_x-conta*fletxax+1, inici_linia_y-conta*fletxay+1); } }

if (baixa==1) { if ((casella_accio>=1)&(casella_accio<=36)) { pDC->MoveTo (modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].x+33, modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].y+25); pDC->LineTo (inici_linia_x, inici_linia_y); } else { pDC->MoveTo (modul2[(36-(casella_accio-36))*4].x+33, modul2[(36-(casella_accio-36))*4].y+25); pDC->LineTo (inici_linia_x, inici_linia_y); } } if (entra_linia==1) { entra_linia=0; RedrawWindow(); pDC->TextOut(100,500,"Hola"); fletxax=(inici_linia_x - modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].x+33)/40; fletxay=(inici_linia_y - modul1[((6-((casella_accio-1)/6)-1)*6+((casella_accio-1)%6))*4].y+33)/40; conta=0; }

if (conta==40) conta=0; else conta++;}

////////////////////////////////////////////Missatges quan no es troba el palet

if (no_palet==1)

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:29/61C:\ Última modificación: 25/09/2006 06:08:22

{ MessageBox("No hi ha una casella sense palet",NULL, MB_OK | MB_ICONEXCLAMATION); no_palet=0;}if (palet0==1){ MessageBox("No hi ha un palet buit per poder treure del magatzem",NULL, MB_OK | MB_ICONEXCLAMATION); palet0=0;}if (paletx==1){ MessageBox("No hi ha un palet de tipus XX en el magatzem",NULL, MB_OK | MB_ICONEXCLAMATION); paletx=0;}

// TODO: add draw code for native data here

}

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View printing

BOOL CMagatzem003View::OnPreparePrinting(CPrintInfo* pInfo){ // default preparation return DoPreparePrinting(pInfo);}

void CMagatzem003View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add extra initialization before printing}

void CMagatzem003View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add cleanup after printing}

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View diagnostics

#ifdef _DEBUGvoid CMagatzem003View::AssertValid() const{ CView::AssertValid();}

void CMagatzem003View::Dump(CDumpContext& dc) const{ CView::Dump(dc);}

CMagatzem003Doc* CMagatzem003View::GetDocument() // non-debug version is inline{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMagatzem003Doc))); return (CMagatzem003Doc*)m_pDocument;}#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////// CMagatzem003View message handlers

//////////////////////////////////////////////////////Opció de menu d'entrada de palet////////////////////////////////////////////////////void CMagatzem003View::OnAccionsEntradadepalet() { CentradaDialog entradaDialog; //entradaDialog.DoModal();

if (entradaDialog.DoModal()==IDOK) { moviment.inici=entradaDialog.m_filEnt; moviment.tipus=entradaDialog.m_tipEnt; almacen [moviment.inici-1]=moviment.tipus; guardar_magatzem(); escriure_plc(moviment.inici,moviment.tipus); } // TODO: Add your command handler code here

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:30/61C:\ Última modificación: 25/09/2006 06:08:22

}

//////////////////////////////////////////////////////Opció de menu sortida de palet////////////////////////////////////////////////////void CMagatzem003View::OnAccionsSortidadepalet() { CsortidaDialog sortidaDialog; //sortidaDialog.DoModal();

if (sortidaDialog.DoModal()==IDOK) { moviment.inici=sortidaDialog.m_filSor;//IMP// entrada_historial ("SORTIDA",magatzem [moviment.inici.x-1][moviment.inici.y-1][moviment.inici.z-1], // moviment.inici.x,moviment.inici.y,moviment.inici.z,0,0,0); almacen [moviment.inici-1]=0; escriure_plc(moviment.inici,0); guardar_magatzem(); } // TODO: Add your command handler code here}

//////////////////////////////////////////////////////Opció de menu activar o desactivar modus automatic////////////////////////////////////////////////////

void CMagatzem003View::OnAccionsCanviubicacipalet() { CcanviDialog canviDialog;

if (canviDialog.DoModal()==IDOK) { moviment.inici=canviDialog.m_filIni;

moviment.final=canviDialog.m_filFin;

almacen [moviment.final-1]=almacen [moviment.inici-1]; escriure_plc(moviment.final, almacen [moviment.inici-1]); almacen [moviment.inici-1]=0; escriure_plc(moviment.inici,0); guardar_magatzem(); }

// TODO: Add your command handler code here}

//////////////////////////////////////////////////////Opció de menu activar o desactivar modus automatic////////////////////////////////////////////////////void CMagatzem003View::OnAccionsActivardesactivarmdusautmatic() { CautomaticDialog automaticDialog;

CClientDC pantalla(this); char str[80]; if (automaticDialog.DoModal()==IDOK) { if (SetTimer(7,50, NULL)) { automatic=1; cont_timer=0; RedrawWindow(); frame = CreateEvent(NULL,FALSE,FALSE,NULL); CreateThread(NULL,NULL,myThread,NULL,NULL,NULL);

} else pantalla.TextOut(100,590,"Fallo en Timer"); } else { KillTimer(7); automatic=0; RedrawWindow();

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:31/61C:\ Última modificación: 25/09/2006 06:08:22

} // TODO: Add your command handler code here }

void CMagatzem003View::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default

char str[160]; char str1[80]; char str2[80]; int casella1; bool sortir=0; //CDC *pView= GetDC( ); CClientDC mostra(this); int contTimer=0; val_palet=valor_palet; //Ha arribat palet if(passos_accio==1) // Es verifica que el palet estigui al magatzem { if (valor_e_s==1) //Es una entrada { if (cerca_palet(1,0)==0) //Es cerca la casella amb palet buit { sortir=1; palet0=1; } if (cerca_palet(1,64)==0) //Es cerca la casella sense palet { sortir=1; no_palet=1; } } if (valor_e_s==2) { if (cerca_palet(1,valor_palet)==0) //Es cerca el palet especificat { sortir=1; paletx=1; } if (cerca_palet(1,64)==0) //Es cerca la casella sense palet { sortir=1; no_palet=1; } } if (sortir==1) // S'ha finalitzat la entrada de palet { passos_accio=0; acabada_accio=1; arriba_palet=0; CreateThread(NULL,NULL,myThread,NULL,NULL,NULL); //Es torna a crear el thread } }

if ((arriba_palet==1)&(passos_accio>=1)) // S'entrarà si ha arribat palet i si hi ha E/S { accio_magatzem(valor_e_s,valor_palet); //valor_e_s=llegir_plc_palet(51); arriba_palet2++; }

//////////////////////////////////////// //Codi pel timer del control del motor //////////////////////////////////////// static bool origen_x=false, origen_y=false; unsigned short origen1,origen2; static unsigned short Byte1H, Byte1L, Byte2H, Byte2L; static unsigned short ini=1;

//********************************************************************* //cbDBitOut(0, FIRSTPORTA, 16, 1); // * //cbDBitIn(0, FIRSTPORTA, 17, &Bit); * //cbDBitIn(0, AUXPORT, 0, &Bit); * //FIRSTPORTA 16 == bit 0 del FIRSTPORTCL => CLEAR_C* * //FIRSTPORTA 17 == bit 1 del FIRSTPORTCL => CAPTURE* * //FIRSTPORTA 18 == bit 2 del FIRSTPORTCL => OE* * //*********************************************************************

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:32/61C:\ Última modificación: 25/09/2006 06:08:22

cbDBitOut(0, FIRSTPORTA, 17, 1); //Bloqueo de cuenta (bit capture*) cbDBitOut(0, FIRSTPORTA, 20, 1 ); // encoder 1 eje x cbDBitOut(0, FIRSTPORTA, 18, 0); //Output Enable 1(bit OEL*) cbDIn(0, FIRSTPORTB, &Byte1L); //lectura 8 bits bajos encoder eje x cbDBitOut(0, FIRSTPORTA, 18, 1); //Output disable 1(bit OEL*='1') cbDBitOut(0, FIRSTPORTA, 19, 0); //Output enable 1(bit OEH*='0') cbDIn(0, FIRSTPORTB, &Byte1H); //lectura 8 bits altos encoder eje x cbDBitOut(0, FIRSTPORTA, 19, 1); //Output disable 1(bit OEH*='1') cbDBitOut(0, FIRSTPORTA, 17, 0); //Liberamos bloqueo (bit Capture*.)

cbDBitOut(0, FIRSTPORTA, 20, 0 ); // encoder 2 eje y cbDBitOut(0, FIRSTPORTA, 18, 0); //Output Enable 1(bit OEL*) cbDIn(0, FIRSTPORTB, &Byte2L); //lectura 8 bits bajos encoder 2 cbDBitOut(0, FIRSTPORTA, 18, 1); //Output disable 1(bit OEL*='1') cbDBitOut(0, FIRSTPORTA, 19, 0); //Output enable 1(bit OEH*='0') cbDIn(0, FIRSTPORTB, &Byte2H); //lectura 8 bits altos encoder 1 cbDBitOut(0, FIRSTPORTA, 19, 1); //Output disable 1(bit OEH*='1') cbDBitOut(0, FIRSTPORTA, 17, 0); //Liberamos bloqueo (bit Capture*.)

pulsos1=(Byte1H<<8)|Byte1L; //acondicionamos lectura encoder 1 a 16 bits pulsos1-=0x8000; //acondicionamiento de signo

pulsos2=(Byte2H<<8)|Byte2L; //acondicionamos lectura encoder 2 a 12 bits pulsos2-=0x8000; //acondicionamiento de signo

switch (nIDEvent){ case 1: { pid1.controlpid(pulsos1,77); //control pid eje x (posicion actual, incremento) cbAOut(0,0,BIP10VOLTS,pid1.control+2047); //Salida eje x

pid2.controlpid(pulsos2,78); //control pid eje y (posicion actual, incremento) cbAOut(0,1,BIP10VOLTS,pid2.control+2047); //Salida eje y

}break; case 2: { cbDBitIn(0,AUXPORT,0, &origen1); cbDBitIn(0,AUXPORT,1, &origen2);

if(pasos_x) { switch (pasos_x){ case 1:{ if (!origen1) { cbAOut(0,0,BIP10VOLTS,2047); //parar motor pid1.consigna_pulsos(pulsos1+2000); pid1.wp_temp=pulsos1; pid1.error0=0; pid1.error1=0; pid1.error2=0; pid1.control=0; pasos_x=2; } } break; case 2:{ if (origen1) { pid1.consigna_pulsos(pulsos1); pid1.controlpid(pulsos1,1); cbAOut(0,0,BIP10VOLTS,pid1.control+2047); origen_x=true; pasos_x=3; break; } pid1.controlpid(pulsos1,1); cbAOut(0,0,BIP10VOLTS,pid1.control+2047); } break; case 3:{ pid1.controlpid(pulsos1,1);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:33/61C:\ Última modificación: 25/09/2006 06:08:22

cbAOut(0,0,BIP10VOLTS,pid1.control+2047); }break; } } if (pasos_y){ switch (pasos_y){ case 1:{ if (!origen2) { cbAOut(0,1,BIP10VOLTS,2097); //parar motor pid2.consigna_pulsos(pulsos2+200); pid2.wp_temp=pulsos2; pid2.error0=0; pid2.error1=0; pid2.error2=0; pid2.control=0; pasos_y=2; } } break; case 2:{ if (origen2) { pid2.consigna_pulsos(pulsos2); pid2.controlpid(pulsos2,1); cbAOut(0,1,BIP10VOLTS,pid2.control+2047); pasos_y=3; origen_y=true; break; } pid2.controlpid(pulsos2,1); cbAOut(0,1,BIP10VOLTS,pid2.control+2047); } break; case 3:{ pid2.controlpid(pulsos2,77); cbAOut(0,1,BIP10VOLTS,pid2.control+2047); }break; }

}

if ((origen_y)&&(origen_x)){ if((pid1.error0==0.)&&(pid2.error0==0.)){ cuenta++; } else cuenta=0; }

if (cuenta==60) { cuenta=0; origen_y=false; origen_x=false; pid1.wishpos=wp_memo1; pid2.wishpos=wp_memo2; cbDBitOut(0, FIRSTPORTA, 16, 1); pid1.delay(); cbDBitOut(0, FIRSTPORTA, 16, 0); //clear_c* pid1.wishpos=wp_memo1; pid2.wishpos=wp_memo2;

pid1.wp_temp=0; pid1.error0=0.; pid1.error1=0.; pid1.error2=0.; pid1.control=0.;

pid2.wp_temp=0; pid2.error0=0.; pid2.error1=0.; pid2.error2=0.; pid2.control=0.;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:34/61C:\ Última modificación: 25/09/2006 06:08:22

KillTimer(2); if (!SetTimer(1,50,NULL)) MessageBox("ERROR starting Windows Timer",NULL, MB_OK | MB_ICONEXCLAMATION); calibrant=0; }

}break;

case 3:{ switch (pd) { //passes per a desar case 1:{ passos_accio=0; //Quan es comença a desar es possa a zero per a que no entri a accio_magatzem if (recull_cinta()) pd=2; }break; case 2:{ cbDBitIn(0, FIRSTPORTA,BAJADO,&bit); if ((pos_ok())&&(!bit)) pd=3; }break; case 3:{ if (seq_safata(DRETA,TREU)) { pid1.wishpos=pos[posi].x; //destinació pid2.wishpos=pos[posi].y+175; pd=4; //extracció de peça } }break; case 4:{if (pos_ok()) pd=5; }break; case 5:{ if (seq_safata(costat,DESA)) { KillTimer(3); pd=0; entrant=0; passos_accio=2; //Acaba de desar el palet que arriba i ara ha de treure el palet } }break; }

}break; case 4:{ switch (pt) { //passes per a treure case 1:{ passos_accio=0; //Quan es comença a treure es possa a zero per a que no entri a accio_magatzem if (pos_ok()) pt=2; }break; case 2:{ if (seq_safata(costat,TREU)) { pid1.wishpos=pos[0].x; pid2.wishpos=pos[0].y+175; pt=3; //extracció de peça } }break; case 3:{ cbDBitIn(0, FIRSTPORTA,BAJADO,&bit); if ((pos_ok())&&(!bit)) pt=4; }break; case 4:{ if (seq_safata(DRETA,DESA)) pt=5;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:35/61C:\ Última modificación: 25/09/2006 06:08:22

}break; case 5:{ if (deposita_cinta()) { KillTimer(4); pt=0; sortint=0;

acabada_accio=1; arriba_palet=0; CreateThread(NULL,NULL,myThread,NULL,NULL,NULL); //TextOut(100,590,"Creats Thread & Event"); } }break; }

}break; case 5:{ switch (pm) { //passes per a moure case 1:{ if (pos_ok()) pm=2; }break; case 2:{ if (seq_safata(costat,TREU)) { pid1.wishpos=pos[posi].x; pid2.wishpos=pos[posi].y+175; pm=3; } }break; case 3:{ if ((pos_ok())) pm=4; }break; case 4:{ if (seq_safata(costat_d,DESA)) { KillTimer(5); pm=0; calibrant=0; } }break;

}

}break;}

CView::OnTimer(nIDEvent);}

////////////////////////////////////////////////// Funció que repinta cada caselle del magatzem // quan es passa el ratoli per sobre////////////////////////////////////////////////

void CMagatzem003View::OnMouseMove(UINT nFlags, CPoint point) { //Repinta cada casella quan es passa per damunt // TODO: Add your message handler code here and/or call default CDC* pDC; pDC = GetDC();

CRect r1; CRect rAnt1; CRect r2; CRect rAnt2;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:36/61C:\ Última modificación: 25/09/2006 06:08:22

int nColAnt1; int nFilAnt1; int nColAnt2; int nFilAnt2; ind_mod1=0; ind_mod2=0; if ((nCol>=0)&(nCol<COL)&(nFil>=0)&(nFil<FIL)) { nColAnt1=nCol; nFilAnt1=nFil; } if ((nCol2>=0)&(nCol2<COL)&(nFil2>=0)&(nFil2<FIL)) { nColAnt2=nCol2; nFilAnt2=nFil2; }

if ((point.x>dist1x)&(point.x<dist1x+COL*costat1x)&(point.y>dist1y)&(point.y<dist1y+FIL*costat1y)) { ind_mod1=1; sortit_modul=1; nCol=(point.x-dist1x)/costat1x; nFil=(point.y-dist1y)/costat1y;

CRect r1(dist1x+nCol*costat1x, dist1y+nFil*costat1y, dist1x+nCol*costat1x+costat1x+1, dist1y+nFil*costat1y+costat1y+1-ample_pesa+2); CRect rAnt1(dist1x+nColAnt1*costat1x, dist1y+nFilAnt1*costat1y, dist1x+nColAnt1*costat1x+costat1x+1, dist1y+nFilAnt1*costat1y+costat1y+1-ample_pesa+2); RedrawWindow(r1); RedrawWindow(rAnt1); } if ((point.x>dist2x)&(point.x<dist2x+COL*costat2x)&(point.y>dist2y)&(point.y<dist2y+FIL*costat2y)) { ind_mod2=1; sortit_modul=1;

nCol2=(point.x-dist2x)/costat2x; nFil2=(point.y-dist2y)/costat2y;

CRect r2(dist2x+nCol2*costat2x, dist2y+nFil2*costat2y, dist2x+nCol2*costat2x+costat2x+1, dist2y+nFil2*costat2y+costat2y+1-ample_pesa+2); CRect rAnt2(dist2x+nColAnt2*costat2x, dist2y+nFilAnt2*costat2y, dist2x+nColAnt2*costat2x+costat2x+1, dist2y+nFilAnt2*costat2y+costat2y+1-ample_pesa+2); RedrawWindow(r2); RedrawWindow(rAnt2); } if ((sortit_modul==1)&(ind_mod1==0)&(ind_mod2==0)) { sortit_modul=0; if (ind_mod1==0) { CRect r3(dist1x+nCol*costat1x, dist1y+nFil*costat1y, dist1x+nCol*costat1x+costat1x+1, dist1y+nFil*costat1y+costat1y+1-ample_pesa+2); RedrawWindow(r3); } if (ind_mod2==0) { CRect r3(dist2x+nCol2*costat2x, dist2y+nFil2*costat2y, dist2x+nCol2*costat2x+costat2x+1, dist2y+nFil2*costat2y+costat2y+1-ample_pesa+2); RedrawWindow(r3); } } CView::OnMouseMove(nFlags, point);}

///////////////////////////////////////////////////// Funció que detecta quan s'ha pitjat el boto esquerre// del ratoli sobre una casella ///////////////////////////////////////////////////

void CMagatzem003View::OnLButtonDown(UINT nFlags, CPoint point) {

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:37/61C:\ Última modificación: 25/09/2006 06:08:22

// TODO: Add your message handler code here and/or call default CDC* pDC; pDC = GetDC();

if ((point.x>dist1x)&(point.x<dist1x+COL*costat1x)&(point.y>dist1y)&(point.y<dist1y+FIL*costat1y)) { if (almacen[nFil*COL+nCol+30-nFil*12]!=0) { ini_canvi_ubicacio=1; nPosIni=nFil*COL+nCol+30-nFil*12; nColIni=nCol; nFilIni=nFil; nModIni=0; tipPaletCanvi=almacen[nFil*COL+nCol+30-nFil*12]; } } if ((point.x>dist2x)&(point.x<dist2x+COL*costat2x)&(point.y>dist2y)&(point.y<dist2y+FIL*costat2y)) { if (almacen[FIL*(FIL-1-nFil2)+COL-1-nCol2+36]!=0) { ini_canvi_ubicacio=1; nPosIni=FIL*(FIL-1-nFil2)+COL-1-nCol2+36; nColIni=nCol2; nFilIni=nFil2; nModIni=1; tipPaletCanvi=almacen[FIL*(FIL-1-nFil2)+COL-1-nCol2+36]; } } CView::OnLButtonDown(nFlags, point); }

///////////////////////////////////////////////////// Funció que detecta quan s'ha soltat el boto esquerre// del ratoli sobre una casella. Això moura el aplet///////////////////////////////////////////////////

void CMagatzem003View::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC* pDC; pDC = GetDC(); if ((point.x>dist1x)&(point.x<dist1x+COL*costat1x)&(point.y>dist1y)&(point.y<dist1y+FIL*costat1y)) { if (almacen[nFil*COL+nCol+30-nFil*12]==0) { if (ini_canvi_ubicacio==1) { CCanviDirectaDialog CanviDirectaDialog; CanviDirectaDialog.m_PosIniDir=nPosIni+1; CanviDirectaDialog.m_PosFinDir=nFil*COL+nCol+30-nFil*12+1; CanviDirectaDialog.m_TipCanviDir=tipPaletCanvi;

if (CanviDirectaDialog.DoModal()==IDOK) { if (arriba_palet==0) { almacen [nFil*COL+nCol+30-nFil*12]=tipPaletCanvi; magatzem(MOU,nPosIni+1,nFil*COL+nCol+30-nFil*12+1); escriure_plc(nFil*COL+nCol+30-nFil*12+1,tipPaletCanvi); almacen [nPosIni]=0; escriure_plc(nPosIni+1,0); guardar_magatzem(); } else { accio_manual=1; MessageBox("No es pot moure el palet ja que hi ha una acció atomática en curs");

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:38/61C:\ Última modificación: 25/09/2006 06:08:22

} } } } } if ((point.x>dist2x)&(point.x<dist2x+COL*costat2x)&(point.y>dist2y)&(point.y<dist2y+FIL*costat2y)) { if (almacen[FIL*(FIL-1-nFil2)+COL-1-nCol2+36]==0) { if (ini_canvi_ubicacio==1) { CCanviDirectaDialog CanviDirectaDialog;

CanviDirectaDialog.m_PosIniDir=nPosIni+1; CanviDirectaDialog.m_PosFinDir=FIL*(FIL-1-nFil2)+COL-1-nCol2+36+1; CanviDirectaDialog.m_TipCanviDir=tipPaletCanvi; if (CanviDirectaDialog.DoModal()==IDOK) { if (arriba_palet==0) { almacen [FIL*(FIL-1-nFil2)+COL-1-nCol2+36]=tipPaletCanvi; magatzem(MOU,nPosIni+1,FIL*(FIL-1-nFil2)+COL-nCol2+36); escriure_plc(FIL*(FIL-1-nFil2)+COL-nCol2+36,tipPaletCanvi); almacen [nPosIni]=0; escriure_plc(nPosIni+1,0); guardar_magatzem(); } else { accio_manual=1; MessageBox("No es pot moure el palet ja que hi ha una acció atomática en curs"); } } } } } ini_canvi_ubicacio=0; CView::OnLButtonUp(nFlags, point);}

void CMagatzem003View::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CDC* pDC; pDC = GetDC();

if ((point.x>dist1x)&(point.x<dist1x+COL*costat1x)&(point.y>dist1y)&(point.y<dist1y+FIL*costat1y)) { if (almacen[nFil*COL+nCol+30-nFil*12]!=0) { CSortidaDirectaDialog SortidaDirectaDialog; SortidaDirectaDialog.m_FilSorDir=nFil*COL+nCol+30-nFil*12+1; SortidaDirectaDialog.m_TipSorDir=almacen [nFil*COL+nCol+30-nFil*12]; if (SortidaDirectaDialog.DoModal()==IDOK) { almacen [nFil*COL+nCol+30-nFil*12]=0; escriure_plc(nFil*COL+nCol+30-nFil*12+1,0); guardar_magatzem(); } } else { CEntradaDirectaDialog EntradaDirectaDialog; EntradaDirectaDialog.m_FilEntDir=nFil*COL+nCol+30-nFil*12+1; if (EntradaDirectaDialog.DoModal()==IDOK) { almacen [nFil*COL+nCol+30-nFil*12]=EntradaDirectaDialog.m_TipEntDir;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:39/61C:\ Última modificación: 25/09/2006 06:08:22

escriure_plc(nFil*COL+nCol+30-nFil*12+1,EntradaDirectaDialog.m_TipEntDir); guardar_magatzem(); magatzem(DESA,nFil*COL+nCol+30-nFil*12+1,NULL); } }

} if ((point.x>dist2x)&(point.x<dist2x+COL*costat2x)&(point.y>dist2y)&(point.y<dist2y+FIL*costat2y)) { if (almacen[FIL*(FIL-1-nFil2)+COL-1-nCol2+36]!=0) { CSortidaDirectaDialog SortidaDirectaDialog;

SortidaDirectaDialog.m_FilSorDir=FIL*(FIL-1-nFil2)+COL-1-nCol2+36+1; SortidaDirectaDialog.m_TipSorDir=almacen [FIL*(FIL-1-nFil2)+COL-1-nCol2+36]; if (SortidaDirectaDialog.DoModal()==IDOK) { almacen [FIL*(FIL-1-nFil2)+COL-1-nCol2+36]=0; escriure_plc(FIL*(FIL-1-nFil2)+COL-nCol2+36,0); guardar_magatzem(); } } else { CEntradaDirectaDialog EntradaDirectaDialog; EntradaDirectaDialog.m_FilEntDir=FIL*(FIL-1-nFil2)+COL-1-nCol2+36+1; if (EntradaDirectaDialog.DoModal()==IDOK) { almacen [FIL*(FIL-1-nFil2)+COL-1-nCol2+36]=EntradaDirectaDialog.m_TipEntDir; escriure_plc(FIL*(FIL-1-nFil2)+COL-nCol2+36,EntradaDirectaDialog.m_TipEntDir); guardar_magatzem(); } }

} RedrawWindow(); CView::OnRButtonDown(nFlags, point);}

/////////////////////////////////////////////////////////Cerca de palet///////////////////////////////////////////////////////int CMagatzem003View::cerca_palet(int casella_ini, int tipus_palet){ int cont; int i; int casella_fin=-1; bool sortir=0; casella_ini--;

for ( cont=0 ; (cont <=10)&(sortir==0) ; cont++ ) { if ( cont==0 ) { if (almacen[casella_ini]==tipus_palet) { sortir=1; casella_fin=casella_ini; } else { if (almacen[casella_ini+36]==tipus_palet) { sortir=1; casella_fin=casella_ini+36; } } } else { for ( i=0; (i<cont)&(sortir==0) ; i++) {

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:40/61C:\ Última modificación: 25/09/2006 06:08:22

if (((casella_ini+i*COL+i-cont)<=35)&((casella_ini+i*COL+i-cont)>=0) &((casella_ini+i*COL+i-cont)>=(casella_ini-(casella_ini%COL)+i*COL)) &((casella_ini+i*COL+i-cont)<=(casella_ini-(casella_ini%COL)+COL+i*COL))) { if (almacen[casella_ini+i*COL+i-cont]==tipus_palet) { sortir=1; casella_fin=casella_ini+i*COL+i-cont; } else { if (almacen[casella_ini+i*COL+i-cont+36]==tipus_palet) { sortir=1; casella_fin=casella_ini+i*COL+i-cont+36; } } } } for ( i=cont; (i>0)&(sortir==0) ; i--) { if (((casella_ini+i*COL-(i-cont))<=35)&((casella_ini+i*COL-(i-cont))>=0) &((casella_ini+i*COL-(i-cont))>=(casella_ini-(casella_ini%COL)+i*COL)) &((casella_ini+i*COL-(i-cont))<=(casella_ini-(casella_ini%COL)+COL+i*COL))) { if (almacen[casella_ini+i*COL-(i-cont)]==tipus_palet) { sortir=1; casella_fin=casella_ini+i*COL-(i-cont); } else { if (almacen[casella_ini+i*COL-(i-cont)+36]==tipus_palet) { sortir=1; casella_fin=casella_ini+i*COL-(i-cont)+36; } } } } for ( i=1; (i<=cont)&(sortir==0) ; i++) { if (((casella_ini-i*COL-(cont-i))<=35)&((casella_ini-i*COL-(cont-i))>=0) &((casella_ini-i*COL-(cont-i))>=(casella_ini-(casella_ini%COL)-i*COL)) &((casella_ini-i*COL-(cont-i))<=(casella_ini-(casella_ini%COL)+COL-i*COL))) { if (almacen[casella_ini-i*COL-(cont-i)]==tipus_palet) { sortir=1; casella_fin=casella_ini-i*COL-(cont-i); } else { if (almacen[casella_ini-i*COL-(cont-i)+36]==tipus_palet) { sortir=1; casella_fin=casella_ini-i*COL-(cont-i)+36; } } } } for ( i=cont-1; (i>=0)&(sortir==0) ; i--) { if (((casella_ini-i*COL+(cont-i))<=35)&((casella_ini-i*COL+(cont-i))>=0) &((casella_ini-i*COL+(cont-i))>=(casella_ini-(casella_ini%COL)-i*COL)) &((casella_ini-i*COL+(cont-i))<=(casella_ini-(casella_ini%COL)+COL-i*COL))) { if (almacen[casella_ini-i*COL+(cont-i)]==tipus_palet) { sortir=1; casella_fin=casella_ini-i*COL+(cont-i); } else { if (almacen[casella_ini-i*COL+(cont-i)+36]==tipus_palet) { sortir=1; casella_fin=casella_ini-i*COL+(cont-i)+36; }

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:41/61C:\ Última modificación: 25/09/2006 06:08:22

} } }

} }return (casella_fin+1);}///////////////////////////////////////////////////////// Funcio per realizar accions al magatzem// Accions a realitzar ( Entrada o Sortida )///////////////////////////////////////////////////////void CMagatzem003View::accio_magatzem(int accio,int palet) //tipus accio: 1=entrada 2=sortida { CClientDC pantalla(this); switch (accio) { case 1: { //Entrada de palet - Arriba palet ple switch (passos_accio) { case 1:{ // Agafar palet ple de l'entrada passos_accio=0; RedrawWindow(); entrant=1; casella_accio=cerca_palet(casella_inicial, 64); puja=1; entra_linia=1; magatzem(DESA,casella_accio,NULL); escriure_plc(casella_accio,valor_palet); //Treure funcionant motor almacen [casella_accio-1]=valor_palet; //Treure funcionant motor guardar_magatzem(); //Treure funcionant motor puja=0; RedrawWindow(); }break; case 2:{ // Deixar palet buit a l'entrada RedrawWindow(); casella_accio=cerca_palet(casella_inicial,0); // Es cerca el palet buit que ha de sortir baixa=1; entra_linia=1; magatzem(TREU,casella_accio,NULL); //Es treu el palet buit escriure_plc(casella_accio,64); //Treure funcionant motor almacen [casella_accio-1]=64; //Treure funcionant motor guardar_magatzem(); //Treure funcionant motor baixa=0; //Treure amb motor entrant=0; RedrawWindow(); passos_accio=0; } } }break; case 2: { //Sortida de palet - Arriba palet buit switch (passos_accio) { case 1:{ // Agafar palet buit de l'entrada RedrawWindow(); cnt3=3; sortint=1; casella_accio=cerca_palet(casella_inicial, 64); //Es cerca la casella sense palet puja=1;entra_linia=1; magatzem(DESA,casella_accio,NULL); //Primer es desa el palet buit passos_accio=0;

escriure_plc(casella_accio,0); almacen [casella_accio-1]=0; guardar_magatzem(); puja=0; RedrawWindow(); }break; case 2:{ // Deixar palet ple a l'entrada passos_accio=0; RedrawWindow(); cnt3=4; casella_accio=cerca_palet(casella_inicial,palet); // Es cerca el palet que ha de sortir baixa=1;entra_linia=1; magatzem(TREU,casella_accio,NULL); //Es treu el palet escriure_plc(casella_accio,64);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:42/61C:\ Última modificación: 25/09/2006 06:08:22

almacen [casella_accio-1]=64; guardar_magatzem(); sortint=1; RedrawWindow(); } } }break; }}

/////////////////////////////////////////////////////////Funcio per llegir qualsevol casella del PLC//////////////////////////////////////////////////////

int CMagatzem003View::llegir_plc(int casella){ unsigned short *p_conexio; int longitud=0; int valor_llegit; char p[3]; if (casella<100) //Per quan es vol llegir una posició memòria { if (casella<=32) casella=(casella-1)+114; if ((casella>32)&(casella<=40)) casella=(casella-1)+160-32;

if ((casella>40)&(casella<=72)) casella=(casella-1)+224-40;

} else casella=casella-100; itoa(casella,p,10); if (casella<100) p[2]=0; unsigned short conexio[]=L"S7:[S7 connection_1]MB114"; unsigned short conexio_dw[]=L"S7:[S7 connection_1]MDWORD114"; if (primera_lectura==false) { while (conexio[longitud]!=0) //Longitud de la cadena longitud++; p_conexio=conexio; } if (primera_lectura==true) { while (conexio_dw[longitud]!=0) //Longitud de la cadena longitud++; p_conexio=conexio_dw; } p_conexio[longitud-1]=p[2]; p_conexio[longitud-2]=p[1]; p_conexio[longitud-3]=p[0]; const LPWSTR szItemID=p_conexio; //////////////////////////////////////////////////////////////////////////////////// // OPC Inicialització

IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle; HRESULT *m_pErrors;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:43/61C:\ Última modificación: 25/09/2006 06:08:22

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL); // Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { MessageBox("Retrival of CLSID failed", "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR); CoUninitialize(); SendMessage(WM_CLOSE); //return; }

// Create the OPC server object and query for the IOPCServer interface of the object r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { MessageBox("Creation of IOPCServer-Object failed", "Error CoCreateInstance()", MB_OK+MB_ICONERROR); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR); m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:44/61C:\ Última modificación: 25/09/2006 06:08:22

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { MessageBox("AddItems failed!", "Error AddItems()", MB_OK+MB_ICONERROR); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; } else { m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr);

CoTaskMemFree(ErrorStr); // go on } // check if the Item is readable and writeable if (m_pItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE)){ MessageBox("Item is not readable and writeable. \nThis is esential for correct operation of this sample.", "Result AddItems()", MB_OK+MB_ICONEXCLAMATION); } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { MessageBox("No IOPCSyncIO found!", "Error QueryInterface()", MB_OK+MB_ICONERROR); CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); }

//////////////////////////////////////////////////7 // OPC Read

OPCHANDLE *phServer; OPCITEMSTATE *pItemValue; HRESULT *pErrors;

UINT qnr;

CString m_ReadQuality; CString m_ReadTS; if (m_pErrors[0] != S_OK) //Item not available { MessageBox("OPC Item not available!", "Error Read sync", MB_OK+MB_ICONERROR); } //Memory allocation really needed, if more than one item is to be read phServer = new OPCHANDLE[1]; //Select item by server handle, received at AddItem phServer[0] = m_pItemResult[0].hServer; r1 = m_pIOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors); delete [] phServer; if (r1 == S_OK) { m_ReadVal = pItemValue[0].vDataValue.lVal; qnr = pItemValue[0].wQuality; m_ReadQuality = "GOOD"; m_ReadTS = COleDateTime( pItemValue[0].ftTimeStamp ).Format();

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:45/61C:\ Última modificación: 25/09/2006 06:08:22

} if (r1 == S_FALSE) { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%S\n", ErrorStr); MessageBox(str, "Error Read()", MB_OK+MB_ICONERROR); CoTaskMemFree(ErrorStr); } if (FAILED(r1)) { MessageBox("Read failed!", "Error Read()", MB_OK+MB_ICONERROR); } else { // release out-parameters in case of not failed VariantClear(&pItemValue[0].vDataValue); CoTaskMemFree(pErrors); CoTaskMemFree(pItemValue); }

////////////////////////////////////////////////////////////// // OPC STOP phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer;

r1 = m_pIOPCItemMgt->RemoveItems(1, // [in] remove one item phServer, // [in] identified by server handle &pErrors); // [out] Errors for each item, returned by OPC server if ( (r1 != S_OK) && (r1 != S_FALSE) ) { MessageBox("RemoveItems failed!", "Error RemoveItems()", MB_OK+MB_ICONERROR); } else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr); CoTaskMemFree(ErrorStr); }

delete[] phServer; CoTaskMemFree(pErrors); CoTaskMemFree(m_pItemResult); m_pItemResult=NULL; CoTaskMemFree(m_pErrors); m_pErrors = NULL;

// Release interface for sync calls m_pIOPCSyncIO->Release(); m_pIOPCSyncIO = NULL;

// Release ItemManagement interface m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; // Remove Group r1=m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); if (r1 != S_OK) { MessageBox("RemoveGroup failed!", "Error RemoveGroup()", MB_OK+MB_ICONERROR); } m_GrpSrvHandle = NULL;

// Release OPC-Server m_pIOPCServer->Release(); m_pIOPCServer = NULL;

// Uninit COM CoUninitialize();

valor_llegit=m_ReadVal; return (valor_llegit);}

//////////////////////////////////////////////////////////////Funcio OPC per escriure el calor de la casella al PLC////////////////////////////////////////////////////////////void CMagatzem003View::escriure_plc(int casella, unsigned int valor){ unsigned short *p_conexio;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:46/61C:\ Última modificación: 25/09/2006 06:08:22

int longitud=0; char p[3]; if (casella<=32) casella=(casella-1)+114; if ((casella>32)&(casella<=40)) casella=(casella-1)+160-32;

if ((casella>40)&(casella<=72)) casella=(casella-1)+224-40;

itoa(casella,p,10); unsigned short conexio[]=L"S7:[S7 connection_1]MB114"; unsigned short conexio_w[]=L"S7:[S7 connection_1]MW114"; if (primera_escriptura==false) { while (conexio[longitud]!=0) //Longitud de la cadena longitud++; p_conexio=conexio; } if (primera_escriptura==true) { while (conexio_w[longitud]!=0) //Longitud de la cadena longitud++; p_conexio=conexio_w; }

p_conexio[longitud-1]=p[2]; p_conexio[longitud-2]=p[1]; p_conexio[longitud-3]=p[0]; if (casella==195) p_conexio=conexio1;

const LPWSTR szItemID=p_conexio; //////////////////////////////////////////////////////////////////////////////////// // OPC Inicialització

IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle; HRESULT *m_pErrors;

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL); // Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { MessageBox("Retrival of CLSID failed", "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR); CoUninitialize(); SendMessage(WM_CLOSE); return; }

// Create the OPC server object and query for the IOPCServer interface of the object

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:47/61C:\ Última modificación: 25/09/2006 06:08:22

r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { MessageBox("Creation of IOPCServer-Object failed", "Error CoCreateInstance()", MB_OK+MB_ICONERROR); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR); m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { MessageBox("AddItems failed!", "Error AddItems()", MB_OK+MB_ICONERROR); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; } else { m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr); CoTaskMemFree(ErrorStr); // go on } // check if the Item is readable and writeable if (m_pItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE)){ MessageBox("Item is not readable and writeable. \nThis is esential for correct operation of this sample.",

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:48/61C:\ Última modificación: 25/09/2006 06:08:22

"Result AddItems()", MB_OK+MB_ICONEXCLAMATION); } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { MessageBox("No IOPCSyncIO found!", "Error QueryInterface()", MB_OK+MB_ICONERROR); CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); return; }

////////////////////////////////////////////////////////////// // OPC WRITE OPCHANDLE *phServer; HRESULT *pErrors; VARIANT values[1]; //HRESULT r1; //LPWSTR ErrorStr; CString szOut;

if (m_pErrors[0] != S_OK) //Item not available { MessageBox("OPC Item not available!", "Error Write sync", MB_OK+MB_ICONERROR); return; } // Select item by server handle received at AddItem phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer; // Retrieve data from dialog //UpdateData(TRUE);

// Set Variant with datatype and received value values[0].vt = VT_I2; //values[0].iVal = m_WriteValue; values[0].iVal = valor; r1 = m_pIOPCSyncIO->Write(1, phServer, values, &pErrors); delete[] phServer; if (FAILED(r1)) { szOut.Format("Method call IOPCSyncIO::Write failed with error code %x", r1); MessageBox(szOut, "Error Writing Item", MB_OK+MB_ICONERROR); } else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); m_WriteRes = ErrorStr; m_WriteRes.Remove('\r'); m_WriteRes.Remove('\n'); UpdateData(FALSE); // release out-parameter in case of not failed CoTaskMemFree(pErrors); CoTaskMemFree(ErrorStr); }

////////////////////////////////////////////////////////////// // OPC STOP phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer;

r1 = m_pIOPCItemMgt->RemoveItems(1, // [in] remove one item phServer, // [in] identified by server handle &pErrors); // [out] Errors for each item, returned by OPC server if ( (r1 != S_OK) && (r1 != S_FALSE) ) { MessageBox("RemoveItems failed!", "Error RemoveItems()", MB_OK+MB_ICONERROR);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:49/61C:\ Última modificación: 25/09/2006 06:08:22

} else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr);//IMP///////////MessageBox(str, "Result RemoveItems()", MB_OK+MB_ICONEXCLAMATION); CoTaskMemFree(ErrorStr); }

delete[] phServer; CoTaskMemFree(pErrors); CoTaskMemFree(m_pItemResult); m_pItemResult=NULL; CoTaskMemFree(m_pErrors); m_pErrors = NULL;

// Release interface for sync calls m_pIOPCSyncIO->Release(); m_pIOPCSyncIO = NULL;

// Release ItemManagement interface m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; // Remove Group r1=m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); if (r1 != S_OK) { MessageBox("RemoveGroup failed!", "Error RemoveGroup()", MB_OK+MB_ICONERROR); } m_GrpSrvHandle = NULL;

// Release OPC-Server m_pIOPCServer->Release(); m_pIOPCServer = NULL;

// Uninit COM CoUninitialize();

//prova=m_ReadVal; }///////////////////////////////////////////Inicialització OPC/////////////////////////////////////////void CMagatzem003View::inicialitzacio_opc(){ const LPWSTR szItemID = L"S7:[DEMO]MB50"; IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle; HRESULT *m_pErrors;

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL); if (r1 != S_OK) { if (r1 == S_FALSE) { MessageBox("COM Library already initialized", "Error CoInitialize()", MB_OK+MB_ICONEXCLAMATION); } else { szErrorText.Format("Initialisation of COM Library failed. Error Code= %4x", r1); MessageBox(szErrorText,"Error CoInitialize()", MB_OK+MB_ICONERROR); SendMessage(WM_CLOSE);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:50/61C:\ Última modificación: 25/09/2006 06:08:22

} } // Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { MessageBox("Retrival of CLSID failed", "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR); CoUninitialize(); SendMessage(WM_CLOSE); }

// Create the OPC server object and query for the IOPCServer interface of the object r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { MessageBox("Creation of IOPCServer-Object failed", "Error CoCreateInstance()", MB_OK+MB_ICONERROR); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR); m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { MessageBox("AddItems failed!", "Error AddItems()", MB_OK+MB_ICONERROR); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:51/61C:\ Última modificación: 25/09/2006 06:08:22

//return; } else { m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr); CoTaskMemFree(ErrorStr); // go on } // check if the Item is readable and writeable if (m_pItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE)){ MessageBox("Item is not readable and writeable. \nThis is esential for correct operation of this sample.", "Result AddItems()", MB_OK+MB_ICONEXCLAMATION); } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { MessageBox("No IOPCSyncIO found!", "Error QueryInterface()", MB_OK+MB_ICONERROR); CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); SendMessage(WM_CLOSE); //return; }

}

///////////////////////////////////////////////////////////////////////////////Llegir PLC per saber quin tipus de palet arriba i si es Entrada o sortida////////////////////////////////////////////////////////////////////////////int llegir_plc_palet(int casella){ int m_ReadVal; unsigned short *p_conexio;

unsigned short conexio1[]=L"S7:[S7 connection_1]MB56"; //Entada o sortida unsigned short conexio2[]=L"S7:[S7 connection_1]MB57"; //Tipus de palet if (casella==56) p_conexio=conexio1; if (casella==57) p_conexio=conexio2;

const LPWSTR szItemID=p_conexio; //////////////////////////////////////////////////////////////////////////////////// // OPC Inicialització

IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle; HRESULT *m_pErrors;

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:52/61C:\ Última modificación: 25/09/2006 06:08:22

// Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { //MessageBox("Retrival of CLSID failed", // "Error CLSIDFromProgID()", MB_OK+MB_ICONERROR); CoUninitialize(); //SendMessage(WM_CLOSE); //return; }

// Create the OPC server object and query for the IOPCServer interface of the object r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { m_pIOPCServer = NULL; CoUninitialize(); }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ //MessageBox("Can't add Group to Server!", "Error AddGroup()", MB_OK+MB_ICONERROR); m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); //SendMessage(WM_CLOSE); //return; }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { //MessageBox("AddItems failed!", // "Error AddItems()", MB_OK+MB_ICONERROR); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); //SendMessage(WM_CLOSE); //return; } else

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:53/61C:\ Última modificación: 25/09/2006 06:08:22

{ m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr);//IMP///////MessageBox(str, "Result AddItems()", MB_OK+MB_ICONEXCLAMATION);////////////////////////// CoTaskMemFree(ErrorStr); // go on } // check if the Item is readable and writeable if (m_pItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE)){ //MessageBox("Item is not readable and writeable. \nThis is esential for correct operation of this sample.", // "Result AddItems()", MB_OK+MB_ICONEXCLAMATION); } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { //MessageBox("No IOPCSyncIO found!", // "Error QueryInterface()", MB_OK+MB_ICONERROR); CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); //SendMessage(WM_CLOSE); //return; }

//////////////////////////////////////////////////7 // OPC Read

OPCHANDLE *phServer; OPCITEMSTATE *pItemValue; HRESULT *pErrors; UINT qnr;

CString m_ReadQuality; CString m_ReadTS; //Memory allocation really needed, if more than one item is to be read phServer = new OPCHANDLE[1]; //Select item by server handle, received at AddItem phServer[0] = m_pItemResult[0].hServer; r1 = m_pIOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors); delete [] phServer; if (r1 == S_OK) { m_ReadVal = pItemValue[0].vDataValue.lVal; qnr = pItemValue[0].wQuality; m_ReadQuality = "GOOD"; m_ReadTS = COleDateTime( pItemValue[0].ftTimeStamp ).Format(); } if (r1 == S_FALSE) { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%S\n", ErrorStr); CoTaskMemFree(ErrorStr); } if (FAILED(r1)) { } else { // release out-parameters in case of not failed VariantClear(&pItemValue[0].vDataValue); CoTaskMemFree(pErrors); CoTaskMemFree(pItemValue); }

////////////////////////////////////////////////////////////// // OPC STOP

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:54/61C:\ Última modificación: 25/09/2006 06:08:22

phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer;

r1 = m_pIOPCItemMgt->RemoveItems(1, // [in] remove one item phServer, // [in] identified by server handle &pErrors); // [out] Errors for each item, returned by OPC server if ( (r1 != S_OK) && (r1 != S_FALSE) ) { } else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr);

CoTaskMemFree(ErrorStr); }

delete[] phServer; CoTaskMemFree(pErrors); CoTaskMemFree(m_pItemResult); m_pItemResult=NULL; CoTaskMemFree(m_pErrors); m_pErrors = NULL;

// Release interface for sync calls m_pIOPCSyncIO->Release(); m_pIOPCSyncIO = NULL;

// Release ItemManagement interface m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; // Remove Group r1=m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); if (r1 != S_OK) { } m_GrpSrvHandle = NULL;

// Release OPC-Server m_pIOPCServer->Release(); m_pIOPCServer = NULL;

// Uninit COM CoUninitialize();

return (m_ReadVal);}

/////////////////////////////////////////////////////////Escriure PLC per fixar el palet en el moment que arriba///////////////////////////////////////////////////////////void escriure_plc_palet(int casella, int valor_plc){ CString m_WriteRes;

unsigned short *p_conexio; unsigned short conexio1[]=L"S7:[S7 connection_1]MX111.4"; //Per fixar el palet unsigned short conexio2[]=L"S7:[S7 connection_1]MX111.1"; //Per treure o posar el tope if (casella==1114) p_conexio=conexio1; if (casella==1111) p_conexio=conexio2;

const LPWSTR szItemID=p_conexio; //////////////////////////////////////////////////////////////////////////////////// // OPC Inicialització

IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle;

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:55/61C:\ Última modificación: 25/09/2006 06:08:22

HRESULT *m_pErrors;

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL); // Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) { CoUninitialize(); }

// Create the OPC server object and query for the IOPCServer interface of the object r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { m_pIOPCServer = NULL; CoUninitialize(); }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { m_pIOPCItemMgt->Release();

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:56/61C:\ Última modificación: 25/09/2006 06:08:22

m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize();

} else { m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr);

CoTaskMemFree(ErrorStr); // go on } // check if the Item is readable and writeable if (m_pItemResult[0].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE)){ } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize();

}

////////////////////////////////////////////////////////////// // ESCRIPTURA OPC ///////////////////////////////////////////////////////////// OPCHANDLE *phServer; HRESULT *pErrors; VARIANT values[1]; CString szOut;

// Select item by server handle received at AddItem phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer; // Set Variant with datatype and received value values[0].vt = VT_I2; values[0].iVal = valor_plc; r1 = m_pIOPCSyncIO->Write(1, phServer, values, &pErrors); delete[] phServer; if (FAILED(r1)) { szOut.Format("Method call IOPCSyncIO::Write failed with error code %x", r1); } else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); m_WriteRes = ErrorStr; m_WriteRes.Remove('\r'); m_WriteRes.Remove('\n'); CoTaskMemFree(pErrors); CoTaskMemFree(ErrorStr); }

////////////////////////////////////////////////////////////// // OPC STOP phServer = new OPCHANDLE[1]; phServer[0] = m_pItemResult[0].hServer;

r1 = m_pIOPCItemMgt->RemoveItems(1, // [in] remove one item phServer, // [in] identified by server handle

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:57/61C:\ Última modificación: 25/09/2006 06:08:22

&pErrors); // [out] Errors for each item, returned by OPC server if ( (r1 != S_OK) && (r1 != S_FALSE) ) { } else { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr); CoTaskMemFree(ErrorStr); }

delete[] phServer; CoTaskMemFree(pErrors); CoTaskMemFree(m_pItemResult); m_pItemResult=NULL; CoTaskMemFree(m_pErrors); m_pErrors = NULL;

// Release interface for sync calls m_pIOPCSyncIO->Release(); m_pIOPCSyncIO = NULL;

// Release ItemManagement interface m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; // Remove Group r1=m_pIOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE); m_GrpSrvHandle = NULL;

// Release OPC-Server m_pIOPCServer->Release(); m_pIOPCServer = NULL;

// Uninit COM CoUninitialize();

//return (m_ReadVal);}

DWORD WINAPI myThread(LPVOID lpParameter) {DWORD ReturnInfo;

int m_ReadVal;const LPWSTR szItemID = L"S7:[S7 connection_1]MX19.5"; //////////////////////////////////////////// // OPC Inicialització //////////////////////////////////////////// IOPCServer *m_pIOPCServer; IOPCItemMgt *m_pIOPCItemMgt; IOPCSyncIO *m_pIOPCSyncIO; OPCITEMDEF m_Items[1]; OPCITEMRESULT *m_pItemResult; OPCHANDLE m_GrpSrvHandle; HRESULT *m_pErrors;

HRESULT r1; CLSID clsid; LONG TimeBias = 0; FLOAT PercentDeadband = 0.0; DWORD RevisedUpdateRate; LPWSTR ErrorStr; char str[100]; CString szErrorText;

m_pItemResult = NULL;

// Initialize the COM library r1 = CoInitialize(NULL); // Given a ProgID, this looks up the associated CLSID in the registry r1 = CLSIDFromProgID(L"OPC.SimaticNET", &clsid); if (r1 != S_OK) CoUninitialize();

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:58/61C:\ Última modificación: 25/09/2006 06:08:22

// Create the OPC server object and query for the IOPCServer interface of the object r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_pIOPCServer); if (r1 != S_OK) { m_pIOPCServer = NULL; CoUninitialize(); }

// Add a group object "grp1" and query for interface IOPCItemMgt r1=m_pIOPCServer->AddGroup(L"grp1", // [in] group name TRUE, // [in] active 500, // [in] request this Update Rate from Server 1, // [in] Client handle &TimeBias, // [in] no time interval to system UTC time &PercentDeadband, // [in] no deadband, so all data changes are reported LOCALE_ID, // [in] Server uses English language for text values &m_GrpSrvHandle, // [out] Server handle to identify this group in later calls &RevisedUpdateRate, // [out] the answer form the Server to the requested update rate IID_IOPCItemMgt, // [in] requested interface type of the group object (LPUNKNOWN*)&m_pIOPCItemMgt); // [out] pointer to the requested interface if (r1 == OPC_S_UNSUPPORTEDRATE) { szErrorText.Format ("Revised Update Rate %d is different from Requested Update Rate 500",RevisedUpdateRate ); AfxMessageBox(szErrorText); } else if (FAILED(r1)){ m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); }

// define an item table with one item as in-paramter for AddItem m_Items[0].szAccessPath = L""; // Accesspath not needed m_Items[0].szItemID = szItemID; // ItemID, see above m_Items[0].bActive = TRUE; m_Items[0].hClient = 1; m_Items[0].dwBlobSize = 0; m_Items[0].pBlob = NULL; m_Items[0].vtRequestedDataType = 0; // return values in native (cannonical) datatype // defined by the item itself

r1 = m_pIOPCItemMgt->AddItems(1, // [in] add one item m_Items, // [in] see above &m_pItemResult, // [out] array with additional information about the item &m_pErrors); // [out] tells which of the items was successfully added. // For any item which failed it provides a reason

if ( (r1 != S_OK) && (r1 != S_FALSE) ) { m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); } else { m_pIOPCServer->GetErrorString(m_pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%ls\n", ErrorStr); CoTaskMemFree(ErrorStr); } // query interface for sync calls on group object r1 = m_pIOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_pIOPCSyncIO); if (r1 < 0) { CoTaskMemFree(m_pItemResult); m_pIOPCItemMgt->Release(); m_pIOPCItemMgt = NULL; m_GrpSrvHandle = NULL; m_pIOPCServer->Release(); m_pIOPCServer = NULL; CoUninitialize(); }

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:59/61C:\ Última modificación: 25/09/2006 06:08:22

while(TRUE) // aseguramos que el thread siempre exista{ReturnInfo=WaitForSingleObject(frame,500);if(ReturnInfo==WAIT_TIMEOUT){ if (acabada_accio==1) { escriure_plc_palet(1114,0); //Es posa a 0 el bit MX 111.4 per desclavar el palet escriure_plc_palet(1111,1); //Es posa a 1 el bit MX 111.1 per baixar el tope de palet acabada_accio=2; }

if (acabada_accio==2) //Es puja el tope al cap de 1 segon { cnt1++; if (cnt1>=2) { acabada_accio=0; cnt1=0; escriure_plc_palet(1111,0); //Es posa a 0 el bit MX 111.1 per pujar el tope de palet } } else {

if(ReturnInfo==WAIT_TIMEOUT) {

////////////////////////////////////////////////// // OPC Lectura ////////////////////////////////////////////////// OPCHANDLE *phServer; OPCITEMSTATE *pItemValue; HRESULT *pErrors; UINT qnr; CString m_ReadQuality; CString m_ReadTS; //Memory allocation really needed, if more than one item is to be read phServer = new OPCHANDLE[1]; //Select item by server handle, received at AddItem phServer[0] = m_pItemResult[0].hServer; r1 = m_pIOPCSyncIO->Read(OPC_DS_DEVICE, 1, phServer, &pItemValue, &pErrors); delete [] phServer; if (r1 == S_OK) { m_ReadVal = pItemValue[0].vDataValue.lVal; qnr = pItemValue[0].wQuality; m_ReadQuality = "GOOD"; m_ReadTS = COleDateTime( pItemValue[0].ftTimeStamp ).Format(); } if (r1 == S_FALSE) { m_pIOPCServer->GetErrorString(pErrors[0], LOCALE_ID, &ErrorStr); sprintf(str, "%S\n", ErrorStr); //MessageBox(str, "Error Read()", MB_OK+MB_ICONERROR); CoTaskMemFree(ErrorStr); } if (FAILED(r1)) { //MessageBox("Read failed!", "Error Read()", MB_OK+MB_ICONERROR); } else { // release out-parameters in case of not failed VariantClear(&pItemValue[0].vDataValue); CoTaskMemFree(pErrors); CoTaskMemFree(pItemValue); } ////////////////////////////////////////////// //Fi lectura OPC

if(m_ReadVal>0) //El sensor detecta palet { arriba_palet=1; escriure_plc_palet(1114,1); //Es posa a 1 el bit MX 111.4 per fixar el palet valor_e_s=llegir_plc_palet(56); valor_palet=llegir_plc_palet(57);

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:60/61C:\ Última modificación: 25/09/2006 06:08:22

if (valor_palet==64) { arriba_palet=0; acabada_accio=1; } } if ( (arriba_palet==1) & ((valor_e_s==1)|(valor_e_s==2)) ) { passos_accio=1; ExitThread(NULL); } cnt2++; //contador per saber quantes vegades s'ha entrat al thread } } }} return 0;}

/***************************************************COMPROBACIÓ DE FITXER DE DADES DEL MAGATZEMEs verifica si exiteix el fitxer de dades locals al PC.Si no exiteix apareix un dialEG que permet crear-loEs crea sense dades***************************************************/

void CMagatzem003View::fitxer_dades (){ fitxer_mag = fopen("magatzem.txt","rt+"); //Es verificar si es pot obrir el fitxer en mode escriptura i lectura CnofitxerDialog nofitxerdialog; //Dialeg que s'obrirà en cas de que no hi e pugui obrir el fitxer CDialogEntradaDades DialogEntradaDades; //Dialeg per poder entrar les dades manualment

if (fitxer_mag==NULL) //Si el fitxer no existeix o no es pot obrir { if (nofitxerdialog.DoModal()==IDOK) //S'introdueixen les dades manualment { DialogEntradaDades.DoModal(); } else //Es crea fitxer buit { fitxer_mag = fopen("magatzem.txt","at"); //Si el fitxer no exiteix es crea int i; for (i=0; i<72; i++) // S'incialitza la taula almacen que tindrà el contingut del almacen[i]=0; // magatzem durant l'execució de l'aplicació int num1; num1=sizeof(almacen); fwrite(almacen, sizeof(almacen), 1, fitxer_mag); //Es copia el contingut de la taula de integers magatzem al fitxer fclose(fitxer_mag); } } else { //Si el fichero se ha podido abrir se copia su contenido fread(almacen, sizeof(almacen), 1, fitxer_mag); //a la taula almacen que s'utilitza durant l'execució de l'aplicació fclose(fitxer_mag); }}

/***************************************************TRASPAS DE DADES DESDE EL PC AL PLCS'utilitza una barra de progres mentre es va realitzantL'escriptura es realitza mitjançant WORD, es dir 2 bytes.Per tant es realitzan 36 accesos a memoria,ja que hi han 72 bytes a copiar ***************************************************/

void CMagatzem003View::traspas_dades_PLC(){ CProgressWnd wndProgress(this, "Carrega de dades"); //Barra de progres durant el traspás de dades al PLC wndProgress.GoModal(); // Crida barra progrés

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_

magatzem003View.cpp Página:61/61C:\ Última modificación: 25/09/2006 06:08:22

wndProgress.SetRange(0,36); //La barra creixerà mab 36 passos wndProgress.SetText("Carregant dades al PLC. Espereu uns segons ..."); //Missatge barra progrés for (casella=1; casella<=72 ; casella=casella+2) //Es fer per 72 caselles { valor_dw=almacen[casella-1]*256 + almacen[casella]; //Es crea el WORD suman els dos bytes, word(0)=byte(0)*256+byte(1) escriure_plc(casella,valor_dw); //S'ecriu el valor del word al PLC wndProgress.StepIt(); //S'incrementa un pas a la barra de progress wndProgress.PeekAndPump(); //Es visualitza l'increment }}

void CMagatzem003View::OnRButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default

CView::OnRButtonUp(nFlags, point);}

PSPad editor 4.5.1 (2207) www.pspad.com 25/09/2006 09:21:25 David_